BSD 1 development
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Wed, 25 Jan 1978 06:09:50 +0000 (22:09 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Wed, 25 Jan 1978 06:09:50 +0000 (22:09 -0800)
Work on file s6/chownall.c

Synthesized-from: 1bsd

s6/chownall.c [new file with mode: 0644]

diff --git a/s6/chownall.c b/s6/chownall.c
new file mode 100644 (file)
index 0000000..00bf2d4
--- /dev/null
@@ -0,0 +1,373 @@
+#
+#define isdir(a) ((a.flags & 060000) == 040000)
+/*
+ * chownall [ - ] [ -nname ] [ -a ] [ -g# ] [ -u# ] directory ...
+ *
+ * Author: Bill Joy (UCB) Oct 13, 1976
+ */
+char progname[] "chownall";
+char usagestr[] "usage: %s [ - ] [ -nname ] [ -a ] [ -g# ] [ -u# ] directory ...\n";
+
+struct dbuff {
+       int     ino;
+       char    name[14];
+};
+struct stbuff {
+       int     dev;
+       int     inumber;
+       int     flags;
+       char    nlinks;
+       char    uid;
+       char    gid;
+       char    size0;
+       int     size1;
+       int     addr[8];
+       int     actime[2];
+       int     modtime[2];
+};
+char *concat();
+int status;
+int terse;
+int lev;
+int all;
+int chggrp;
+int newuser;
+int newgid;
+char *newname;
+int chgusr;
+int newuid;
+int srcuid;
+int srcgid;
+
+char **xargv;
+
+main(argc,argv)
+char *argv[];
+{
+       register char *argp;
+       int *num;
+
+/*
+       if (getuid())
+               panic("NOT super-user");
+*/
+       argv++;
+       argc--;
+       while (argc && *(argp = *argv) == '-')
+       {
+               if (!*++argp)
+                       terse++;
+               else
+               {
+                       do
+                       {
+                               switch(*argp++)
+                               {
+                               case 'a':
+                                       all++;
+                                       break;
+                               case 'g':
+                                       if (chggrp)
+                                               goto usage;
+                                       chggrp++;
+                                       num = &newgid;
+                                       goto getnum;
+                               case 'u':
+                                       if (chgusr)
+                                               goto usage;
+                                       chgusr++;
+                                       num = &newuid;
+getnum:
+                                       *num = 0;
+                                       if (!(*argp >= '0' && *argp <= '9'))
+                                               panic("bad user/group number");
+                                       do
+                                               *num = *num * 10 + *argp++ - '0';
+                                       while (*argp >= '0' && *argp <= '9');
+                                       if (*num > 255)
+                                               panic("group/user number too large (%d > 255)", *num);
+                                       break;
+                               case 'n':
+                                       if (chgusr || chggrp)
+                                               panic("Can't specify -n with -g or -a");
+                                       chgusr++;
+                                       chggrp++;
+                                       newuser = findname(argp);
+                                       newuid = newuser & 0377;
+                                       newgid = (newuser >> 8) & 0377;
+                                       newname = argp;
+                                       all++;
+                                       while (*argp) ++argp;
+                                       break;
+                               default:
+                                       goto usage;
+                               }
+                       } while(*argp);
+               }
+               argc--;
+               argv++;
+       }
+       if (argc == 0)
+usage:
+       {
+               printf(usagestr, progname);
+               exit(1);
+       }
+       else
+       {
+               if (!chgusr && !chggrp)
+                       panic("no changes specified");
+               else if (all && (!chgusr || !chggrp))
+                       panic("all option requires both user and group to be specified");
+               while(argc)
+               {
+                       xargv = argv;
+                       if (all && !terse)
+                       {
+                               printf("last chance before scribbling uid %d and gid %d",
+                                       newuid, newgid);
+                               if (newname) printf(" (%s)",newname);
+                               printf(" all over \"%s\"\n", argv[0]);
+                               cani();
+                       }
+                       chtree(argv[0]);
+                       argv++;
+                       argc--;
+               }
+       }
+       exit(0);
+}
+
+int    old;
+int    new;
+
+owner(xgid, xuid)
+{
+       old = ((xgid & 0377) << 8) | (xuid & 0377);
+       if (all)
+               goto spankingnew;
+       else if (chgusr)
+               if (xuid != srcuid || xgid != srcgid)
+                       new = old;
+               else
+spankingnew:
+                       new = (((chggrp ? newgid : srcgid) & 0377) << 8) | (newuid & 0377);
+       else if (chggrp && xgid == srcgid)
+               new = ((newgid & 0377) << 8) | (xuid & 0377);
+       else
+               new = old;
+       return(new);
+}
+
+chtree(spth)
+char *spth;
+{
+       char nspth[120];
+       struct dbuff sdbuff;
+       struct stbuff source;
+       int sunit, i;
+
+       if (stat(spth, &source) < 0)
+               panic("\"%s\": cannot stat", spth);
+       else if (!isdir(source))
+               panic("\"%s\": not a directory", spth);
+       else if ((sunit = open(spth, 0)) < 0)
+               panic("\"%s\": cannot open directory", spth);
+       else
+       {
+               if (lev == 0)
+               {
+                       srcuid = source.uid;
+                       srcgid = source.gid;
+                       if (!srcuid && !srcgid && !chgusr)
+                       {
+                               printf("\"%s\" is owned by the root\n.", spth);
+                               printf("I don't think I should change all group 0's to group %d's there.\n", newgid);
+                               printf("Sorry.\n");
+                               exit(1);
+                       }
+                       if (chgusr && !chggrp && source.uid == 0)
+                               panic("owner of \"%s\" is uid 0 in his group !?!", spth);
+                       else if (!chgusr && chggrp && source.uid != 0)
+                               panic("owner of \"%s\" is not uid 0 of his group !?!", spth);
+               }
+               lev++;
+               while ((i = read(sunit, &sdbuff, 16) == 16))
+               {
+                       concat(nspth, spth, sdbuff.name);
+                       if (sdbuff.ino == 0)
+                               continue;
+                       else if (stat(nspth, &source) < 0)
+                               panic("\"%s\": cannot stat", nspth);
+                       else if (isdir(source))
+                               if (equal(sdbuff.name, ".."))
+                                       continue;               /* Whew ! */
+                               else if (!equal(sdbuff.name, "."))
+                                       chtree(nspth);
+                       if (owner(source.gid, source.uid) != old)
+                               if (chown(nspth, new) == -1)
+                                       panic("can't chown \"%s\" to %o !?!", nspth, new);
+               }
+               if (i == -1)
+                       panic("error reading \"%s\":", spth);
+               else if (i && i != 16)
+                       panic("panic: bad directory structure: \"%s\"", spth);
+       }
+       close(sunit);
+       if (!--lev)
+               if (chgusr && !chggrp || chggrp && !chgusr)
+                       if (chown(spth, owner(srcgid, srcuid)) == -1)
+                               panic("can't chown \"%s\" to %o !?!", spth, new);
+}
+
+
+char *concat(a, b, c)
+char *a, *b, *c;
+{
+       register char *ra, *rb;
+       register cnt;
+
+       cnt = 14;
+       rb = c;
+       while (*rb++)
+               if (!--cnt)
+                       break;
+       cnt = 14 - cnt;
+       rb = b;
+       while (*rb++)
+               cnt++;
+       if (cnt >= 100)
+               panic("path name too long: \"%s/%s\"", b, c);
+       ra = a;
+       rb = b;
+       while (*ra++ = *rb++)
+               continue;
+       *(ra-1) = '/';
+       rb = c;
+       cnt = 14;
+       while (*ra++ = *rb++)
+               if (!--cnt)
+               {
+                       *ra++ = 0;
+                       break;
+               }
+       return(a);
+}
+
+panic(a1, a2, a3, a4)
+{
+       printf("%s: ", progname);
+       printf(a1, a2, a3, a4);
+       putchar('\n');
+       exit(1);
+}
+
+equal(a, b)
+char *a, *b;
+{
+       register char *ra, *rb;
+
+       ra = a;
+       rb = b;
+       while (*ra == *rb++)
+               if (*ra)
+                       ra++;
+               else
+                       return(!*--rb);
+       return(0);
+}
+
+cani()
+{
+       register char c, ch;
+
+       printf("ok ? ");
+       ch = c = getchar();
+       while (ch != '\n' && ch)
+               ch = getchar();
+       if (c != 'y')
+               exit(1);
+}
+
+putchar(c)
+{
+       write(2, &c, 1);
+}
+
+findname(user)
+       char *user;
+{
+       int pbuf[259];
+       char *p,c,*pfile;
+       int u,v;
+       pfile = "/etc/passwd";
+       pbuf[0] = open(pfile, 0);
+       if(pbuf[0] < 0) {
+               write(2, "Cannot open /etc/passwd\n", 25);
+               exit(9);
+       }
+       goto l1;
+
+/*
+ * skip to beginning of next line
+ */
+
+skip:
+       while(c != '\n') {
+               if(c < 0)
+                       goto ill;
+               c = getc(pbuf);
+       }
+
+/*
+ * compare user names
+ */
+
+l1:
+       c = getc(pbuf);
+       if(c < 0) {
+               write(2, "User name not found in password file\n", 37);
+               exit(9);
+       }
+       p = user;
+       while(c != ':') {
+               if(*p++ != c)
+                       goto skip;
+               c = getc(pbuf);
+       }
+       if(*p)
+               goto skip;
+/*
+ * skip old password
+ */
+       do {
+               c = getc(pbuf);
+               if(c < 0)
+                       goto ill;
+       } while(c != ':');
+
+
+/*
+ * validate uid and gid
+ */
+
+       u = 0;
+       do {
+               c = getc(pbuf);
+               if(c >= '0' && c <= '9')
+                       u = u*10 + c-'0';
+               if(c < 0)
+                       goto ill;
+       } while(c != ':');
+       v = 0;
+       do {
+               c = getc(pbuf);
+               if(c >= '0' && c <= '9')
+                       v = v*10 + c-'0';
+               if(c < 0)
+                       goto ill;
+       } while(c != ':');
+       return ((v<<8) | u);
+ill:   write(2,"Password file illformed\n",24);
+       exit(9);
+}