|
|
1.1 root 1: /* ftam-glob.c - interactive initiator FTAM -- globbing */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/ftam2/RCS/ftam-glob.c,v 7.0 89/11/23 21:54:19 mrose Rel $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/ftam2/RCS/ftam-glob.c,v 7.0 89/11/23 21:54:19 mrose Rel $
9: *
10: *
11: * $Log: ftam-glob.c,v $
12: * Revision 7.0 89/11/23 21:54:19 mrose
13: * Release 6.0
14: *
15: */
16:
17: /*
18: * NOTICE
19: *
20: * Acquisition, use, and distribution of this module and related
21: * materials are subject to the restrictions of a license agreement.
22: * Consult the Preface in the User's Manual for the full terms of
23: * this agreement.
24: *
25: */
26:
27:
28: /*
29: * C-shell glob for random programs.
30: *
31: * Modified for FTAM (and linted)
32: *
33: * Used by permission.
34: */
35:
36: #include <stdio.h>
37: #include <errno.h>
38: #include <pwd.h>
39: #include "ftamuser.h"
40:
41:
42: #define QUOTE 0200
43: #define TRIM 0177
44: #define eq(a,b) (strcmp(a, b)==0)
45: #define GAVSIZ (NCARGS/6)
46: #define isdir(d) ((d.st_mode & S_IFMT) == S_IFDIR)
47:
48: static char **gargv; /* Pointer to the (stack) arglist */
49: static int gargc; /* Number args in gargv */
50: static int gnleft;
51: static int gflag;
52: static int tglob();
53: char **glob();
54: char *globerr;
55: static char *home;
56: struct passwd *getpwnam();
57: extern int errno;
58: static char *strspl(), **copyblk(), *strend();
59: char *malloc(), *strcpy(), *strcat();
60:
61: static int globcnt;
62:
63: static
64: char *globchars = "`{[*?";
65:
66: static char *gpath, *gpathp, *lastgpathp;
67: static int globbed;
68: static char *entp;
69: static char **sortbas;
70:
71:
72: int chkldir (), chkrdir ();
73: static int (*chkdir) () = chkldir;
74:
75: int getldir (), getrdir ();
76: static int (*gethdir) () = getldir;
77:
78: int matchldir (), matchrdir ();
79: static int (*matchdir) () = matchldir;
80:
81:
82: static
83: char **
84: glob(v)
85: register char *v;
86: {
87: char agpath[BUFSIZ];
88: char *agargv[GAVSIZ];
89: char *vv[2];
90: vv[0] = malloc ((unsigned) (strlen (v) + 1));
91: if (vv[0] == (char *)0)
92: fatal("out of memory");
93: (void) strcpy (vv[0], v);
94: v = vv[0];
95: vv[1] = 0;
96: gflag = 0;
97: rscan(vv, tglob);
98: if (gflag == 0)
99: return (copyblk(vv));
100: free(v);
101:
102: globerr = 0;
103: gpath = agpath; gpathp = gpath; *gpathp = 0;
104: lastgpathp = &gpath[sizeof agpath - 2];
105: ginit(agargv); globcnt = 0;
106: collect(v);
107: if (globcnt == 0 && (gflag&1)) {
108: blkfree(gargv), gargv = 0;
109: return (0);
110: } else
111: return (gargv = copyblk(gargv));
112: }
113:
114: static
115: ginit(agargv)
116: char **agargv;
117: {
118:
119: agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
120: gnleft = NCARGS - 4;
121: }
122:
123: static
124: collect(as)
125: register char *as;
126: {
127: if (eq(as, "{") || eq(as, "{}")) {
128: Gcat(as, "");
129: sort();
130: } else
131: acollect(as);
132: }
133:
134: static
135: acollect(as)
136: register char *as;
137: {
138: register int ogargc = gargc;
139:
140: gpathp = gpath; *gpathp = 0; globbed = 0;
141: expand(as);
142: if (gargc != ogargc)
143: sort();
144: }
145:
146: static
147: sort()
148: {
149: register char **p1, **p2, *c;
150: char **Gvp = &gargv[gargc];
151:
152: p1 = sortbas;
153: while (p1 < Gvp-1) {
154: p2 = p1;
155: while (++p2 < Gvp)
156: if (strcmp(*p1, *p2) > 0)
157: c = *p1, *p1 = *p2, *p2 = c;
158: p1++;
159: }
160: sortbas = Gvp;
161: }
162:
163: static
164: expand(as)
165: char *as;
166: {
167: register char *cs,
168: *sgpathp,
169: *oldcs;
170: char *csstr;
171: struct stat stb;
172:
173: sgpathp = gpathp;
174: cs = csstr = strdup (as);
175: if (*cs == '~' && gpathp == gpath) {
176: addpath('~');
177: for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
178: addpath(*cs++);
179: if (!*cs || *cs == '/') {
180: if (gpathp != gpath + 1) {
181: *gpathp = 0;
182: if ((*gethdir) (gpath + 1))
183: globerr = "Unknown user name after ~";
184: (void) strcpy(gpath, gpath + 1);
185: } else
186: (void) strcpy(gpath, home);
187: gpathp = strend(gpath);
188: }
189: }
190: while (!any(*cs, globchars)) {
191: if (*cs == 0) {
192: if (!globbed)
193: Gcat(gpath, "");
194: else if (stat(gpath, &stb) >= 0) {
195: Gcat(gpath, "");
196: globcnt++;
197: }
198: goto endit;
199: }
200: addpath(*cs++);
201: }
202: oldcs = cs;
203: while (cs > as && *cs != '/')
204: cs--, gpathp--;
205: if (*cs == '/')
206: cs++, gpathp++;
207: *gpathp = 0;
208: if (*oldcs == '{') {
209: (void) execbrc(cs, ((char *)0));
210: return;
211: }
212: (*matchdir) (cs);
213: endit:
214: gpathp = sgpathp;
215: *gpathp = 0;
216:
217: if (csstr)
218: free (csstr);
219: }
220:
221: static
222: matchldir(pattern)
223: char *pattern;
224: {
225: char pat[MAXPATHLEN];
226: struct stat stb;
227: register struct dirent *dp;
228: DIR *dirp;
229:
230: (void) strcpy (pat, pattern);
231:
232: dirp = opendir(*gpath ? gpath : ".");
233: if (dirp == NULL) {
234: if (globbed)
235: return;
236: goto patherr2;
237: }
238: if (fstat(dirp->dd_fd, &stb) < 0)
239: goto patherr1;
240: if (!isdir(stb)) {
241: errno = ENOTDIR;
242: goto patherr1;
243: }
244: for (errno = 0; dp = readdir(dirp); errno = 0) {
245: if (dp->d_ino == 0)
246: continue;
247: if (match(dp->d_name, pat)) {
248: Gcat(gpath, dp->d_name);
249: globcnt++;
250: }
251: }
252: if (errno)
253: globerr = "corrupted directory";
254: (void) closedir(dirp);
255: return;
256:
257: patherr1:
258: (void) closedir(dirp);
259: patherr2:
260: globerr = "Bad directory components";
261: }
262:
263: static
264: execbrc(p, s)
265: char *p, *s;
266: {
267: char restbuf[BUFSIZ + 2];
268: register char *pe, *pm, *pl;
269: int brclev = 0;
270: char *lm, savec, *sgpathp;
271:
272: for (lm = restbuf; *p != '{'; *lm++ = *p++)
273: continue;
274: for (pe = ++p; *pe; pe++)
275: switch (*pe) {
276:
277: case '{':
278: brclev++;
279: continue;
280:
281: case '}':
282: if (brclev == 0)
283: goto pend;
284: brclev--;
285: continue;
286:
287: case '[':
288: for (pe++; *pe && *pe != ']'; pe++)
289: continue;
290: continue;
291: }
292: pend:
293: brclev = 0;
294: for (pl = pm = p; pm <= pe; pm++)
295: switch (*pm & (QUOTE|TRIM)) {
296:
297: case '{':
298: brclev++;
299: continue;
300:
301: case '}':
302: if (brclev) {
303: brclev--;
304: continue;
305: }
306: goto doit;
307:
308: case ','|QUOTE:
309: case ',':
310: if (brclev)
311: continue;
312: doit:
313: savec = *pm;
314: *pm = 0;
315: (void) strcpy(lm, pl);
316: (void) strcat(restbuf, pe + 1);
317: *pm = savec;
318: if (s == 0) {
319: sgpathp = gpathp;
320: expand(restbuf);
321: gpathp = sgpathp;
322: *gpathp = 0;
323: } else if (amatch(s, restbuf))
324: return (1);
325: sort();
326: pl = pm + 1;
327: if (brclev)
328: return (0);
329: continue;
330:
331: case '[':
332: for (pm++; *pm && *pm != ']'; pm++)
333: continue;
334: if (!*pm)
335: pm--;
336: continue;
337: }
338: if (brclev)
339: goto doit;
340: return (0);
341: }
342:
343: static
344: match(s, p)
345: char *s, *p;
346: {
347: register int c;
348: register char *sentp;
349: char sglobbed = globbed;
350:
351: if (*s == '.' && *p != '.')
352: return (0);
353: sentp = entp;
354: entp = s;
355: c = amatch(s, p);
356: entp = sentp;
357: globbed = sglobbed;
358: return (c);
359: }
360:
361: static
362: amatch(s, p)
363: register char *s, *p;
364: {
365: register int scc;
366: int ok, lc;
367: char *sgpathp;
368: struct stat stb;
369: int c, cc;
370:
371: globbed = 1;
372: for (;;) {
373: scc = *s++ & TRIM;
374: switch (c = *p++) {
375:
376: case '{':
377: return (execbrc(p - 1, s - 1));
378:
379: case '[':
380: ok = 0;
381: lc = 077777;
382: while (cc = *p++) {
383: if (cc == ']') {
384: if (ok)
385: break;
386: return (0);
387: }
388: if (cc == '-') {
389: if (lc <= scc && scc <= *p++)
390: ok++;
391: } else
392: if (scc == (lc = cc))
393: ok++;
394: }
395: if (cc == 0)
396: if (ok)
397: p--;
398: else
399: return 0;
400: continue;
401:
402: case '*':
403: if (!*p)
404: return (1);
405: if (*p == '/') {
406: p++;
407: goto slash;
408: }
409: s--;
410: do {
411: if (amatch(s, p))
412: return (1);
413: } while (*s++);
414: return (0);
415:
416: case 0:
417: return (scc == 0);
418:
419: default:
420: if (c != scc)
421: return (0);
422: continue;
423:
424: case '?':
425: if (scc == 0)
426: return (0);
427: continue;
428:
429: case '/':
430: if (scc)
431: return (0);
432: slash:
433: s = entp;
434: sgpathp = gpathp;
435: while (*s)
436: addpath(*s++);
437: addpath('/');
438: if ((*chkdir) (gpath, &stb))
439: if (*p == 0) {
440: Gcat(gpath, "");
441: globcnt++;
442: } else
443: expand(p);
444: gpathp = sgpathp;
445: *gpathp = 0;
446: return (0);
447: }
448: }
449: }
450:
451: static
452: chkldir (path, st)
453: char *path;
454: struct stat *st;
455: {
456: return (stat (path, st) == 0 && (st -> st_mode & S_IFMT) == S_IFDIR);
457: }
458:
459: static
460: Gmatch(s, p)
461: register char *s, *p;
462: {
463: register int scc;
464: int ok, lc;
465: int c, cc;
466:
467: for (;;) {
468: scc = *s++ & TRIM;
469: switch (c = *p++) {
470:
471: case '[':
472: ok = 0;
473: lc = 077777;
474: while (cc = *p++) {
475: if (cc == ']') {
476: if (ok)
477: break;
478: return (0);
479: }
480: if (cc == '-') {
481: if (lc <= scc && scc <= *p++)
482: ok++;
483: } else
484: if (scc == (lc = cc))
485: ok++;
486: }
487: if (cc == 0)
488: if (ok)
489: p--;
490: else
491: return 0;
492: continue;
493:
494: case '*':
495: if (!*p)
496: return (1);
497: for (s--; *s; s++)
498: if (Gmatch(s, p))
499: return (1);
500: return (0);
501:
502: case 0:
503: return (scc == 0);
504:
505: default:
506: if ((c & TRIM) != scc)
507: return (0);
508: continue;
509:
510: case '?':
511: if (scc == 0)
512: return (0);
513: continue;
514:
515: }
516: }
517: }
518:
519: static
520: Gcat(s1, s2)
521: register char *s1, *s2;
522: {
523: register int len = strlen(s1) + strlen(s2) + 1;
524:
525: if (len >= gnleft || gargc >= GAVSIZ - 1)
526: globerr = "Arguments too long";
527: else {
528: gargc++;
529: gnleft -= len;
530: gargv[gargc] = 0;
531: gargv[gargc - 1] = strspl(s1, s2);
532: }
533: }
534:
535: static
536: addpath(c)
537: char c;
538: {
539:
540: if (gpathp >= lastgpathp)
541: globerr = "Pathname too long";
542: else {
543: *gpathp++ = c;
544: *gpathp = 0;
545: }
546: }
547:
548: static
549: rscan(t, f)
550: register char **t;
551: int (*f)();
552: {
553: register char *p, c;
554:
555: while (p = *t++) {
556: if (f == tglob)
557: if (*p == '~')
558: gflag |= 2;
559: else if (eq(p, "{") || eq(p, "{}"))
560: continue;
561: while (c = *p++)
562: (*f)(c);
563: }
564: }
565:
566: #ifdef notdef
567: static
568: scan(t, f)
569: register char **t;
570: int (*f)();
571: {
572: register char *p, c;
573:
574: while (p = *t++)
575: while (c = *p)
576: *p++ = (*f)(c);
577: }
578: #endif
579:
580: static
581: tglob(c)
582: register char c;
583: {
584:
585: if (any(c, globchars))
586: gflag |= c == '{' ? 2 : 1;
587: return (c);
588: }
589:
590: #ifdef notdef
591: static
592: trim(c)
593: char c;
594: {
595:
596: return (c & TRIM);
597: }
598: #endif
599:
600: static
601: letter(c)
602: register char c;
603: {
604:
605: return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_');
606: }
607:
608: static
609: digit(c)
610: register char c;
611: {
612:
613: return (c >= '0' && c <= '9');
614: }
615:
616: static
617: any(c, s)
618: register int c;
619: register char *s;
620: {
621:
622: while (*s)
623: if (*s++ == c)
624: return(1);
625: return(0);
626: }
627: blklen(av)
628: register char **av;
629: {
630: register int i = 0;
631:
632: while (*av++)
633: i++;
634: return (i);
635: }
636:
637: char **
638: blkcpy(oav, bv)
639: char **oav;
640: register char **bv;
641: {
642: register char **av = oav;
643:
644: while (*av++ = *bv++)
645: continue;
646: return (oav);
647: }
648:
649: blkfree(av0)
650: char **av0;
651: {
652: register char **av = av0;
653:
654: while (*av)
655: free(*av++);
656: free((char *)av0);
657: }
658:
659: static
660: char *
661: strspl(cp, dp)
662: register char *cp, *dp;
663: {
664: register char *ep = malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
665:
666: if (ep == (char *)0)
667: fatal("out of memory");
668: (void) strcpy(ep, cp);
669: (void) strcat(ep, dp);
670: return (ep);
671: }
672:
673: static
674: char **
675: copyblk(v)
676: register char **v;
677: {
678: register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) *
679: sizeof(char **)));
680: if (nv == (char **)0)
681: fatal("out of memory");
682:
683: return (blkcpy(nv, v));
684: }
685:
686: static
687: char *
688: strend(cp)
689: register char *cp;
690: {
691:
692: while (*cp)
693: cp++;
694: return (cp);
695: }
696: /*
697: * Extract a home directory from the password file
698: * The argument points to a buffer where the name of the
699: * user whose home directory is sought is currently.
700: * We write the home directory of the user back there.
701: */
702: static
703: getldir(hdir)
704: char *hdir;
705: {
706: register struct passwd *pp = getpwnam(hdir);
707:
708: if (pp == 0)
709: return (1);
710: (void) strcpy(hdir, pp->pw_dir);
711: return (0);
712: }
713:
714: /* */
715:
716: #undef isdir
717:
718:
719: int xglobbed;
720:
721: static OID matchoid;
722:
723: /* */
724:
725: char *xglob1val (v, remote)
726: char *v;
727: int remote;
728: {
729: register char **gp;
730: char *cp,
731: *gb[2];
732:
733: gb[0] = v;
734: gb[1] = NULLCP;
735:
736: if ((gp = xglob (gb, remote)) == NULLVP)
737: return NULLCP;
738:
739: if (gp[1]) {
740: advise (NULLCP, "%s: ambiguous", v);
741: blkfree (gp);
742: return NULLCP;
743: }
744:
745: cp = *gp;
746: free ((char *) gp);
747:
748: return cp;
749: }
750:
751: /* */
752:
753: char **xglob (v, remote)
754: char **v;
755: int remote;
756: {
757: register int i;
758: register char *cp,
759: **gp,
760: **vp;
761: char *loses;
762:
763: xglobbed = 0;
764:
765: if (!globbing) {
766: register char *dp;
767:
768: for (gp = vp = copyblk (v); *gp; gp++) {
769: cp = remote ? str2file (*gp) : *gp;
770: if ((dp = malloc ((unsigned) (strlen (cp) + 1))) == NULLCP)
771: fatal ("out of memory");
772: (void) strcpy (dp, cp);
773: *gp = dp;
774: }
775:
776: return vp;
777: }
778:
779: if (remote) {
780: switch (realstore) {
781: case RFS_UNKNOWN:
782: advise (NULLCP, "%s", rs_unknown);
783: return NULLVP;
784:
785: case RFS_UNIX:
786: home = "~";
787: chkdir = chkrdir;
788: gethdir = getrdir;
789: matchdir = matchrdir;
790: break;
791:
792: default:
793: advise (NULLCP, "%s", rs_support);
794: return NULLVP;
795: }
796: }
797: else {
798: home = myhome;
799: chkdir = chkldir;
800: gethdir = getldir;
801: matchdir = matchldir;
802: }
803:
804: for (i = 0, loses = NULL, vp = NULLVP; cp = *v++; ) {
805: if ((gp = glob (remote ? str2file (cp) : cp)) == NULLVP) {
806: if (!loses && globerr)
807: loses = globerr;
808: continue;
809: }
810:
811: if (vp) {
812: register int j;
813: register char **xp,
814: **yp;
815:
816: if ((j = blklen (gp)) > 1)
817: xglobbed++;
818:
819: if ((vp = (char **) realloc ((char *) vp,
820: ((unsigned) (i + j + 1)) * sizeof *vp))
821: == NULLVP)
822: fatal ("out of memory");
823:
824: for (xp = vp + i, yp = gp; *xp = *yp; xp++, yp++)
825: continue;
826: i += j;
827:
828: free ((char *) gp);
829: }
830: else
831: if ((i = blklen (vp = gp)) > 1)
832: xglobbed++;
833: }
834:
835: if (vp == NULLVP || *vp == NULLCP) {
836: if (!loses)
837: loses = "no files match specification";
838: advise (NULLCP, "%s", loses);
839:
840: if (vp) {
841: blkfree (vp);
842: vp = NULLVP;
843: }
844: }
845:
846: if (vp && debug)
847: for (gp = vp; *gp; gp++)
848: printf ("%d: \"%s\"\n", gp - vp, *gp);
849:
850: return vp;
851: }
852:
853: /* */
854:
855: static matchrdir (pattern)
856: char *pattern;
857: {
858: register char *cp;
859: char cwd[MAXPATHLEN],
860: pat[MAXPATHLEN];
861: struct FADUidentity faduids;
862: register struct FADUidentity *faduid = &faduids;
863: register struct filent *fi, *gi;
864:
865: (void) strcpy (pat, pattern);
866:
867: switch (isdir (gpath, cwd, 1)) {
868: case NOTOK:
869: case OK:
870: if (!globbed)
871: globerr = "Bad directory components";
872: return;
873:
874: default:
875: if (cwd[0] == NULL)
876: (void) strcpy (cwd, gpath);
877: cp = cwd + strlen (cwd) - 1;
878: if (*cp == '/')
879: *cp = NULL;
880: else {
881: *++cp = '/';
882: *++cp = NULL;
883: }
884: cp = cwd;
885: break;
886: }
887:
888: faduid -> fa_type = FA_FIRSTLAST;
889: faduid -> fa_firstlast = FA_FIRST;
890:
891: (void) fdffnx (NOTOK, (struct PSAPdata *) 0, 1);
892: (void) getvf (cp, NULLCP, faduid, &vfs[VFS_FDF], fdffnx);
893:
894: fi = gi = filents, filents = NULL;
895: (void) fdffnx (NOTOK, (struct PSAPdata *) 0, 0);
896:
897: {
898: register int len = strlen (cp);
899:
900: for (fi = gi; fi; fi = fi -> fi_next)
901: if (strncmp (fi -> fi_name, cp, len) == 0)
902: fi -> fi_entry = fi -> fi_name + len;
903: }
904:
905: for (fi = gi; fi; fi = fi -> fi_next) {
906: matchoid = fi -> fi_oid;
907: if (match (fi -> fi_entry, pat)) {
908: Gcat (gpath, fi -> fi_entry);
909: globcnt++;
910: }
911: }
912:
913: filents = gi;
914: (void) fdffnx (NOTOK, (struct PSAPdata *) 0, 0);
915: }
916:
917: /* */
918:
919: /* ARGSUSED */
920:
921: static chkrdir (path, st)
922: char *path;
923: struct stat *st;
924: {
925: return (oid_cmp (vfs[VFS_FDF].vf_oid, matchoid) == 0);
926: }
927:
928: /* */
929:
930: static getrdir (hdir)
931: char *hdir;
932: {
933: char buffer[BUFSIZ];
934:
935: (void) sprintf (buffer, "~%s", hdir);
936:
937: return (isdir (buffer, hdir, 1) != DONE);
938: }
939:
940: /* */
941:
942: static int fatal (s)
943: char *s;
944: {
945: adios (NULLCP, "%s", s);
946: }
947:
948: /* */
949:
950: int f_echo (vec)
951: char **vec;
952: {
953: char **gb,
954: **gp,
955: *gs;
956:
957: if (*++vec && (gp = gb = xglob (vec, 1))) {
958: char *cp;
959:
960: for (cp = ""; *gp; gp++, cp = " "){
961: gs = rindex (*gp, '/');
962: if (gs == NULL)
963: printf ("%s%s", cp, *gp);
964: else
965: printf ("%s%s", cp, ++gs);
966: }
967: printf ("\n");
968:
969: blkfree (gb);
970: }
971:
972: return OK;
973: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.