rdist doesn't propagate sticky bits; bug report 4.3BSD/ucb/41
[unix-history] / usr / src / usr.bin / rdist / expand.c
index 6328bd3..593f1b4 100644 (file)
@@ -1,30 +1,46 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of California at Berkeley. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)expand.c    4.7 (Berkeley) 83/11/29";
-#endif
+static char sccsid[] = "@(#)expand.c   5.3 (Berkeley) %G%";
+#endif /* not lint */
 
 #include "defs.h"
 
 
 #include "defs.h"
 
+#define        GAVSIZ  NCARGS / 6
 #define LC '{'
 #define RC '}'
 
 static char    shchars[] = "${[*?";
 
 #define LC '{'
 #define RC '}'
 
 static char    shchars[] = "${[*?";
 
-static int     which;          /* bit mask of types to expand */
-static int     argc;           /* expanded arg count */
-static char    **argv;         /* expanded arg vectors */
-static char    *path;
-static char    *pathp;
-static char    *lastpathp;
-static char    *tilde;         /* null if expanding tilde */
-static char    *tpathp;
-static int     nleft;
+int    which;          /* bit mask of types to expand */
+int    eargc;          /* expanded arg count */
+char   **eargv;        /* expanded arg vectors */
+char   *path;
+char   *pathp;
+char   *lastpathp;
+char   *tilde;         /* "~user" if not expanding tilde, else "" */
+char   *tpathp;
+int    nleft;
 
 
-static int     expany;         /* any expansions done? */
-static char    *entp;
-static char    **sortbase;
+int    expany;         /* any expansions done? */
+char   *entp;
+char   **sortbase;
 
 char   *index();
 
 char   *index();
-struct block *copy();
+int    argcmp();
+
+#define sort() qsort((char *)sortbase, &eargv[eargc] - sortbase, \
+                     sizeof(*sortbase), argcmp), sortbase = &eargv[eargc]
 
 /*
  * Take a list of names and expand any macros, etc.
 
 /*
  * Take a list of names and expand any macros, etc.
@@ -32,13 +48,15 @@ struct block *copy();
  * wh = E_SHELL if expanding shell characters.
  * wh = E_TILDE if expanding `~'.
  * or any of these or'ed together.
  * wh = E_SHELL if expanding shell characters.
  * wh = E_TILDE if expanding `~'.
  * or any of these or'ed together.
+ *
+ * Major portions of this were snarfed from csh/sh.glob.c.
  */
  */
-struct block *
+struct namelist *
 expand(list, wh)
 expand(list, wh)
-       struct block *list;
+       struct namelist *list;
        int wh;
 {
        int wh;
 {
-       register struct block *bp, *prev;
+       register struct namelist *nl, *prev;
        register int n;
        char pathbuf[BUFSIZ];
        char *argvbuf[GAVSIZ];
        register int n;
        char pathbuf[BUFSIZ];
        char *argvbuf[GAVSIZ];
@@ -48,42 +66,41 @@ expand(list, wh)
                prnames(list);
        }
 
                prnames(list);
        }
 
-       if (wh == 0)
+       if (wh == 0) {
+               register char *cp;
+
+               for (nl = list; nl != NULL; nl = nl->n_next)
+                       for (cp = nl->n_name; *cp; cp++)
+                               *cp = *cp & TRIM;
                return(list);
                return(list);
+       }
 
        which = wh;
        path = tpathp = pathp = pathbuf;
        *pathp = '\0';
        lastpathp = &path[sizeof pathbuf - 2];
 
        which = wh;
        path = tpathp = pathp = pathbuf;
        *pathp = '\0';
        lastpathp = &path[sizeof pathbuf - 2];
-       tilde = NULL;
-       argc = 0;
-       argv = sortbase = argvbuf;
-       *argv = 0;
+       tilde = "";
+       eargc = 0;
+       eargv = sortbase = argvbuf;
+       *eargv = 0;
        nleft = NCARGS - 4;
        /*
        nleft = NCARGS - 4;
        /*
-        * Walk the block list and expand names into argv[];
+        * Walk the name list and expand names into eargv[];
         */
         */
-       for (bp = list; bp != NULL; bp = bp->b_next) {
-               expstr(bp->b_name);
-               free(bp->b_name);
-               free(bp);
-       }
+       for (nl = list; nl != NULL; nl = nl->n_next)
+               expstr(nl->n_name);
        /*
        /*
-        * Take expanded list of names from argv[] and build a block list.
+        * Take expanded list of names from eargv[] and build a new list.
         */
        list = prev = NULL;
         */
        list = prev = NULL;
-       for (n = 0; n < argc; n++) {
-               bp = ALLOC(block);
-               if (bp == NULL)
-                       fatal("ran out of memory\n");
-               bp->b_type = NAME;
-               bp->b_next = bp->b_args = NULL;
-               bp->b_name = argv[n];
+       for (n = 0; n < eargc; n++) {
+               nl = makenl(NULL);
+               nl->n_name = eargv[n];
                if (prev == NULL)
                if (prev == NULL)
-                       list = prev = bp;
+                       list = prev = nl;
                else {
                else {
-                       prev->b_next = bp;
-                       prev = bp;
+                       prev->n_next = nl;
+                       prev = nl;
                }
        }
        if (debug) {
                }
        }
        if (debug) {
@@ -97,10 +114,10 @@ expstr(s)
        char *s;
 {
        register char *cp, *cp1;
        char *s;
 {
        register char *cp, *cp1;
-       register struct block *tp;
-       char *tail, *opathp;
+       register struct namelist *tp;
+       char *tail;
        char buf[BUFSIZ];
        char buf[BUFSIZ];
-       int savec, oargc;
+       int savec, oeargc;
        extern char homedir[];
 
        if (s == NULL || *s == '\0')
        extern char homedir[];
 
        if (s == NULL || *s == '\0')
@@ -109,18 +126,18 @@ expstr(s)
        if ((which & E_VARS) && (cp = index(s, '$')) != NULL) {
                *cp++ = '\0';
                if (*cp == '\0') {
        if ((which & E_VARS) && (cp = index(s, '$')) != NULL) {
                *cp++ = '\0';
                if (*cp == '\0') {
-                       error("no variable name after '$'\n");
+                       yyerror("no variable name after '$'");
                        return;
                }
                if (*cp == LC) {
                        cp++;
                        if ((tail = index(cp, RC)) == NULL) {
                        return;
                }
                if (*cp == LC) {
                        cp++;
                        if ((tail = index(cp, RC)) == NULL) {
-                               error("unmatched %c\n", *cp);
+                               yyerror("unmatched '{'");
                                return;
                        }
                        *tail++ = savec = '\0';
                        if (*cp == '\0') {
                                return;
                        }
                        *tail++ = savec = '\0';
                        if (*cp == '\0') {
-                               error("no variable name after '$'\n");
+                               yyerror("no variable name after '$'");
                                return;
                        }
                } else {
                                return;
                        }
                } else {
@@ -131,9 +148,9 @@ expstr(s)
                tp = lookup(cp, NULL, 0);
                if (savec != '\0')
                        *tail = savec;
                tp = lookup(cp, NULL, 0);
                if (savec != '\0')
                        *tail = savec;
-               if ((tp = tp->b_args) != NULL) {
-                       for (; tp != NULL; tp = tp->b_next) {
-                               sprintf(buf, "%s%s%s", s, tp->b_name, tail);
+               if (tp != NULL) {
+                       for (; tp != NULL; tp = tp->n_next) {
+                               sprintf(buf, "%s%s%s", s, tp->n_name, tail);
                                expstr(buf);
                        }
                        return;
                                expstr(buf);
                        }
                        return;
@@ -161,7 +178,8 @@ expstr(s)
                        *cp1 = '\0';
                        if (pw == NULL || strcmp(pw->pw_name, buf+1) != 0) {
                                if ((pw = getpwnam(buf+1)) == NULL) {
                        *cp1 = '\0';
                        if (pw == NULL || strcmp(pw->pw_name, buf+1) != 0) {
                                if ((pw = getpwnam(buf+1)) == NULL) {
-                                       error("unknown user %s\n", buf+1);
+                                       strcat(buf, ": unknown user name");
+                                       yyerror(buf+1);
                                        return;
                                }
                        }
                                        return;
                                }
                        }
@@ -171,8 +189,10 @@ expstr(s)
                for (cp = path; *cp++ = *cp1++; )
                        ;
                tpathp = pathp = cp - 1;
                for (cp = path; *cp++ = *cp1++; )
                        ;
                tpathp = pathp = cp - 1;
-       } else
-               pathp = path;
+       } else {
+               tpathp = pathp = path;
+               tilde = "";
+       }
        *pathp = '\0';
        if (!(which & E_SHELL)) {
                if (which & E_TILDE)
        *pathp = '\0';
        if (!(which & E_SHELL)) {
                if (which & E_TILDE)
@@ -182,31 +202,20 @@ expstr(s)
                sort();
                return;
        }
                sort();
                return;
        }
-       oargc = argc;
+       oeargc = eargc;
        expany = 0;
        expsh(s);
        expany = 0;
        expsh(s);
-       pathp = opathp;
-       if (argc != oargc)
-               sort();
+       if (eargc == oeargc)
+               Cat(s, "");             /* "nonomatch" is set */
+       sort();
 }
 
 }
 
-/*
- * Bubble sort any new entries
- */
-sort()
+static
+argcmp(a1, a2)
+       char **a1, **a2;
 {
 {
-       register char **p1, **p2, *c;
-       char **ap = &argv[argc];
-
-       p1 = sortbase;
-       while (p1 < ap-1) {
-               p2 = p1;
-               while (++p2 < ap)
-                       if (strcmp(*p1, *p2) > 0)
-                               c = *p1, *p1 = *p2, *p2 = c;
-               p1++;
-       }
-       sortbase = ap;
+
+       return (strcmp(*a1, *a2));
 }
 
 /*
 }
 
 /*
@@ -285,7 +294,9 @@ matchdir(pattern)
 patherr1:
        closedir(dirp);
 patherr2:
 patherr1:
        closedir(dirp);
 patherr2:
-       error("%s: %s\n", path, sys_errlist[errno]);
+       strcat(path, ": ");
+       strcat(path, sys_errlist[errno]);
+       yyerror(path);
 }
 
 execbrc(p, s)
 }
 
 execbrc(p, s)
@@ -315,12 +326,14 @@ execbrc(p, s)
                        for (pe++; *pe && *pe != ']'; pe++)
                                continue;
                        if (!*pe)
                        for (pe++; *pe && *pe != ']'; pe++)
                                continue;
                        if (!*pe)
-                               error("Missing ]\n");
+                               yyerror("Missing ']'");
                        continue;
                }
 pend:
                        continue;
                }
 pend:
-       if (brclev || !*pe)
-               fatal("Missing }\n");
+       if (brclev || !*pe) {
+               yyerror("Missing '}'");
+               return (0);
+       }
        for (pl = pm = p; pm <= pe; pm++)
                switch (*pm & (QUOTE|TRIM)) {
 
        for (pl = pm = p; pm <= pe; pm++)
                switch (*pm & (QUOTE|TRIM)) {
 
@@ -359,7 +372,7 @@ doit:
                        for (pm++; *pm && *pm != ']'; pm++)
                                continue;
                        if (!*pm)
                        for (pm++; *pm && *pm != ']'; pm++)
                                continue;
                        if (!*pm)
-                               error("Missing ]\n");
+                               yyerror("Missing ']'");
                        continue;
                }
        return (0);
                        continue;
                }
        return (0);
@@ -415,8 +428,10 @@ amatch(s, p)
                                        if (scc == (lc = cc))
                                                ok++;
                        }
                                        if (scc == (lc = cc))
                                                ok++;
                        }
-                       if (cc == 0)
-                               fatal("Missing ]\n");
+                       if (cc == 0) {
+                               yyerror("Missing ']'");
+                               return (0);
+                       }
                        continue;
 
                case '*':
                        continue;
 
                case '*':
@@ -435,7 +450,7 @@ amatch(s, p)
                        return (scc == '\0');
 
                default:
                        return (scc == '\0');
 
                default:
-                       if (c != scc)
+                       if ((c & TRIM) != scc)
                                return (0);
                        continue;
 
                                return (0);
                        continue;
 
@@ -495,8 +510,10 @@ smatch(s, p)
                                        if (scc == (lc = cc))
                                                ok++;
                        }
                                        if (scc == (lc = cc))
                                                ok++;
                        }
-                       if (cc == 0)
-                               fatal("Missing ]\n");
+                       if (cc == 0) {
+                               yyerror("Missing ']'");
+                               return (0);
+                       }
                        continue;
 
                case '*':
                        continue;
 
                case '*':
@@ -531,10 +548,10 @@ Cat(s1, s2)
        register char *s;
 
        nleft -= len;
        register char *s;
 
        nleft -= len;
-       if (nleft <= 0 || ++argc >= GAVSIZ)
-               error("Arguments too long\n");
-       argv[argc] = 0;
-       argv[argc - 1] = s = malloc(len);
+       if (nleft <= 0 || ++eargc >= GAVSIZ)
+               yyerror("Arguments too long");
+       eargv[eargc] = 0;
+       eargv[eargc - 1] = s = malloc(len);
        if (s == NULL)
                fatal("ran out of memory\n");
        while (*s++ = *s1++ & TRIM)
        if (s == NULL)
                fatal("ran out of memory\n");
        while (*s++ = *s1++ & TRIM)
@@ -549,9 +566,11 @@ addpath(c)
 {
 
        if (pathp >= lastpathp)
 {
 
        if (pathp >= lastpathp)
-               fatal("Pathname too long\n");
-       *pathp++ = c;
-       *pathp = '\0';
+               yyerror("Pathname too long");
+       else {
+               *pathp++ = c & TRIM;
+               *pathp = '\0';
+       }
 }
 
 /*
 }
 
 /*
@@ -587,7 +606,7 @@ exptilde(buf, file)
                        s3 = NULL;
                if (pw == NULL || strcmp(pw->pw_name, file) != 0) {
                        if ((pw = getpwnam(file)) == NULL) {
                        s3 = NULL;
                if (pw == NULL || strcmp(pw->pw_name, file) != 0) {
                        if ((pw = getpwnam(file)) == NULL) {
-                               error("unknown user %s\n", file);
+                               error("%s: unknown user name\n", file);
                                if (s3 != NULL)
                                        *s3 = '/';
                                return(NULL);
                                if (s3 != NULL)
                                        *s3 = '/';
                                return(NULL);