Research V7 development
authorKen Thompson <ken@research.uucp>
Wed, 10 Jan 1979 20:02:03 +0000 (15:02 -0500)
committerKen Thompson <ken@research.uucp>
Wed, 10 Jan 1979 20:02:03 +0000 (15:02 -0500)
Work on file usr/src/cmd/makekey.c
Work on file usr/src/cmd/mkfs.c
Work on file usr/src/cmd/mount.c
Work on file usr/src/cmd/mknod.c
Work on file usr/src/cmd/mv.c
Work on file usr/src/cmd/ncheck.c
Work on file usr/src/cmd/newgrp.c
Work on file usr/src/cmd/nice.c

Co-Authored-By: Dennis Ritchie <dmr@research.uucp>
Synthesized-from: v7

usr/src/cmd/makekey.c [new file with mode: 0644]
usr/src/cmd/mkfs.c [new file with mode: 0644]
usr/src/cmd/mknod.c [new file with mode: 0644]
usr/src/cmd/mount.c [new file with mode: 0644]
usr/src/cmd/mv.c [new file with mode: 0644]
usr/src/cmd/ncheck.c [new file with mode: 0644]
usr/src/cmd/newgrp.c [new file with mode: 0644]
usr/src/cmd/nice.c [new file with mode: 0644]

diff --git a/usr/src/cmd/makekey.c b/usr/src/cmd/makekey.c
new file mode 100644 (file)
index 0000000..1640e51
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * You send it 10 bytes.
+ * It sends you 13 bytes.
+ * The transformation is expensive to perform
+ * (a significant part of a second).
+ */
+
+char   *crypt();
+
+main()
+{
+       char key[8];
+       char salt[2];
+       
+       read(0, key, 8);
+       read(0, salt, 2);
+       write(1, crypt(key, salt), 13);
+       return(0);
+}
diff --git a/usr/src/cmd/mkfs.c b/usr/src/cmd/mkfs.c
new file mode 100644 (file)
index 0000000..cf66b7b
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ * Make a file system prototype.
+ * usage: mkfs filsys proto/size [ m n ]
+ */
+#define        NIPB    (BSIZE/sizeof(struct dinode))
+#define        NINDIR  (BSIZE/sizeof(daddr_t))
+#define        NDIRECT (BSIZE/sizeof(struct direct))
+#define        LADDR   10
+#define        MAXFN   500
+#define        itoo(x) (int)((x+15)&07)
+#ifndef STANDALONE
+#include <stdio.h>
+#include <a.out.h>
+#endif
+#include <sys/param.h>
+#include <sys/ino.h>
+#include <sys/inode.h>
+#include <sys/filsys.h>
+#include <sys/fblk.h>
+#include <sys/dir.h>
+time_t utime;
+#ifndef STANDALONE
+FILE   *fin;
+#else
+int    fin;
+#endif
+int    fsi;
+int    fso;
+char   *charp;
+char   buf[BSIZE];
+union {
+       struct fblk fb;
+       char pad1[BSIZE];
+} fbuf;
+#ifndef STANDALONE
+struct exec head;
+#endif
+char   string[50];
+union {
+       struct filsys fs;
+       char pad2[BSIZE];
+} filsys;
+char   *fsys;
+char   *proto;
+int    f_n     = MAXFN;
+int    f_m     = 3;
+int    error;
+ino_t  ino;
+long   getnum();
+daddr_t        alloc();
+
+main(argc, argv)
+char *argv[];
+{
+       int f, c;
+       long n;
+
+#ifndef STANDALONE
+       time(&utime);
+       if(argc < 3) {
+               printf("usage: mkfs filsys proto/size [ m n ]\n");
+               exit(1);
+       }
+       fsys = argv[1];
+       proto = argv[2];
+#else
+       {
+               static char protos[60];
+
+               printf("file sys size: ");
+               gets(protos);
+               proto = protos;
+       }
+#endif
+#ifdef STANDALONE
+       {
+               char fsbuf[100];
+
+               do {
+                       printf("file system: ");
+                       gets(fsbuf);
+                       fso = open(fsbuf, 1);
+                       fsi = open(fsbuf, 0);
+               } while (fso < 0 || fsi < 0);
+       }
+       fin = NULL;
+       argc = 0;
+#else
+       fso = creat(fsys, 0666);
+       if(fso < 0) {
+               printf("%s: cannot create\n", fsys);
+               exit(1);
+       }
+       fsi = open(fsys, 0);
+       if(fsi < 0) {
+               printf("%s: cannot open\n", fsys);
+               exit(1);
+       }
+       fin = fopen(proto, "r");
+#endif
+       if(fin == NULL) {
+               n = 0;
+               for(f=0; c=proto[f]; f++) {
+                       if(c<'0' || c>'9') {
+                               printf("%s: cannot open\n", proto);
+                               exit(1);
+                       }
+                       n = n*10 + (c-'0');
+               }
+               filsys.s_fsize = n;
+               n = n/25;
+               if(n <= 0)
+                       n = 1;
+               if(n > 65500/NIPB)
+                       n = 65500/NIPB;
+               filsys.s_isize = n + 2;
+               printf("isize = %D\n", n*NIPB);
+               charp = "d--777 0 0 $ ";
+               goto f3;
+       }
+
+#ifndef STANDALONE
+       /*
+        * get name of boot load program
+        * and read onto block 0
+        */
+
+       getstr();
+       f = open(string, 0);
+       if(f < 0) {
+               printf("%s: cannot  open init\n", string);
+               goto f2;
+       }
+       read(f, (char *)&head, sizeof head);
+       if(head.a_magic != A_MAGIC1) {
+               printf("%s: bad format\n", string);
+               goto f1;
+       }
+       c = head.a_text + head.a_data;
+       if(c > BSIZE) {
+               printf("%s: too big\n", string);
+               goto f1;
+       }
+       read(f, buf, c);
+       wtfs((long)0, buf);
+
+f1:
+       close(f);
+
+       /*
+        * get total disk size
+        * and inode block size
+        */
+
+f2:
+       filsys.s_fsize = getnum();
+       n = getnum();
+       n /= NIPB;
+       filsys.s_isize = n + 3;
+
+#endif
+f3:
+       if(argc >= 5) {
+               f_m = atoi(argv[3]);
+               f_n = atoi(argv[4]);
+               if(f_n <= 0 || f_n >= MAXFN)
+                       f_n = MAXFN;
+               if(f_m <= 0 || f_m > f_n)
+                       f_m = 3;
+       }
+       filsys.s_m = f_m;
+       filsys.s_n = f_n;
+       printf("m/n = %d %d\n", f_m, f_n);
+       if(filsys.s_isize >= filsys.s_fsize) {
+               printf("%ld/%ld: bad ratio\n", filsys.s_fsize, filsys.s_isize-2);
+               exit(1);
+       }
+       filsys.s_tfree = 0;
+       filsys.s_tinode = 0;
+       for(c=0; c<BSIZE; c++)
+               buf[c] = 0;
+       for(n=2; n!=filsys.s_isize; n++) {
+               wtfs(n, buf);
+               filsys.s_tinode += NIPB;
+       }
+       ino = 0;
+
+       bflist();
+
+       cfile((struct inode *)0);
+
+       filsys.s_time = utime;
+       wtfs((long)1, (char *)&filsys);
+       exit(error);
+}
+
+cfile(par)
+struct inode *par;
+{
+       struct inode in;
+       int dbc, ibc;
+       char db[BSIZE];
+       daddr_t ib[NINDIR];
+       int i, f, c;
+
+       /*
+        * get mode, uid and gid
+        */
+
+       getstr();
+       in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
+       in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0);
+       in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0);
+       for(i=3; i<6; i++) {
+               c = string[i];
+               if(c<'0' || c>'7') {
+                       printf("%c/%s: bad octal mode digit\n", c, string);
+                       error = 1;
+                       c = 0;
+               }
+               in.i_mode |= (c-'0')<<(15-3*i);
+       }
+       in.i_uid = getnum();
+       in.i_gid = getnum();
+
+       /*
+        * general initialization prior to
+        * switching on format
+        */
+
+       ino++;
+       in.i_number = ino;
+       for(i=0; i<BSIZE; i++)
+               db[i] = 0;
+       for(i=0; i<NINDIR; i++)
+               ib[i] = (daddr_t)0;
+       in.i_nlink = 1;
+       in.i_size = 0;
+       for(i=0; i<NADDR; i++)
+               in.i_un.i_addr[i] = (daddr_t)0;
+       if(par == (struct inode *)0) {
+               par = &in;
+               in.i_nlink--;
+       }
+       dbc = 0;
+       ibc = 0;
+       switch(in.i_mode&IFMT) {
+
+       case IFREG:
+               /*
+                * regular file
+                * contents is a file name
+                */
+
+               getstr();
+               f = open(string, 0);
+               if(f < 0) {
+                       printf("%s: cannot open\n", string);
+                       error = 1;
+                       break;
+               }
+               while((i=read(f, db, BSIZE)) > 0) {
+                       in.i_size += i;
+                       newblk(&dbc, db, &ibc, ib);
+               }
+               close(f);
+               break;
+
+       case IFBLK:
+       case IFCHR:
+               /*
+                * special file
+                * content is maj/min types
+                */
+
+               i = getnum() & 0377;
+               f = getnum() & 0377;
+               in.i_un.i_addr[0] = (i<<8) | f;
+               break;
+
+       case IFDIR:
+               /*
+                * directory
+                * put in extra links
+                * call recursively until
+                * name of "$" found
+                */
+
+               par->i_nlink++;
+               in.i_nlink++;
+               entry(in.i_number, ".", &dbc, db, &ibc, ib);
+               entry(par->i_number, "..", &dbc, db, &ibc, ib);
+               in.i_size = 2*sizeof(struct direct);
+               for(;;) {
+                       getstr();
+                       if(string[0]=='$' && string[1]=='\0')
+                               break;
+                       entry(ino+1, string, &dbc, db, &ibc, ib);
+                       in.i_size += sizeof(struct direct);
+                       cfile(&in);
+               }
+               break;
+       }
+       if(dbc != 0)
+               newblk(&dbc, db, &ibc, ib);
+       iput(&in, &ibc, ib);
+}
+
+gmode(c, s, m0, m1, m2, m3)
+char c, *s;
+{
+       int i;
+
+       for(i=0; s[i]; i++)
+               if(c == s[i])
+                       return((&m0)[i]);
+       printf("%c/%s: bad mode\n", c, string);
+       error = 1;
+       return(0);
+}
+
+long
+getnum()
+{
+       int i, c;
+       long n;
+
+       getstr();
+       n = 0;
+       i = 0;
+       for(i=0; c=string[i]; i++) {
+               if(c<'0' || c>'9') {
+                       printf("%s: bad number\n", string);
+                       error = 1;
+                       return((long)0);
+               }
+               n = n*10 + (c-'0');
+       }
+       return(n);
+}
+
+getstr()
+{
+       int i, c;
+
+loop:
+       switch(c=getch()) {
+
+       case ' ':
+       case '\t':
+       case '\n':
+               goto loop;
+
+       case '\0':
+               printf("EOF\n");
+               exit(1);
+
+       case ':':
+               while(getch() != '\n');
+               goto loop;
+
+       }
+       i = 0;
+
+       do {
+               string[i++] = c;
+               c = getch();
+       } while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0');
+       string[i] = '\0';
+}
+
+rdfs(bno, bf)
+daddr_t bno;
+char *bf;
+{
+       int n;
+
+       lseek(fsi, bno*BSIZE, 0);
+       n = read(fsi, bf, BSIZE);
+       if(n != BSIZE) {
+               printf("read error: %ld\n", bno);
+               exit(1);
+       }
+}
+
+wtfs(bno, bf)
+daddr_t bno;
+char *bf;
+{
+       int n;
+
+       lseek(fso, bno*BSIZE, 0);
+       n = write(fso, bf, BSIZE);
+       if(n != BSIZE) {
+               printf("write error: %D\n", bno);
+               exit(1);
+       }
+}
+
+daddr_t
+alloc()
+{
+       int i;
+       daddr_t bno;
+
+       filsys.s_tfree--;
+       bno = filsys.s_free[--filsys.s_nfree];
+       if(bno == 0) {
+               printf("out of free space\n");
+               exit(1);
+       }
+       if(filsys.s_nfree <= 0) {
+               rdfs(bno, (char *)&fbuf);
+               filsys.s_nfree = fbuf.df_nfree;
+               for(i=0; i<NICFREE; i++)
+                       filsys.s_free[i] = fbuf.df_free[i];
+       }
+       return(bno);
+}
+
+bfree(bno)
+daddr_t bno;
+{
+       int i;
+
+       filsys.s_tfree++;
+       if(filsys.s_nfree >= NICFREE) {
+               fbuf.df_nfree = filsys.s_nfree;
+               for(i=0; i<NICFREE; i++)
+                       fbuf.df_free[i] = filsys.s_free[i];
+               wtfs(bno, (char *)&fbuf);
+               filsys.s_nfree = 0;
+       }
+       filsys.s_free[filsys.s_nfree++] = bno;
+}
+
+entry(inum, str, adbc, db, aibc, ib)
+ino_t inum;
+char *str;
+int *adbc, *aibc;
+char *db;
+daddr_t *ib;
+{
+       struct direct *dp;
+       int i;
+
+       dp = (struct direct *)db;
+       dp += *adbc;
+       (*adbc)++;
+       dp->d_ino = inum;
+       for(i=0; i<DIRSIZ; i++)
+               dp->d_name[i] = 0;
+       for(i=0; i<DIRSIZ; i++)
+               if((dp->d_name[i] = str[i]) == 0)
+                       break;
+       if(*adbc >= NDIRECT)
+               newblk(adbc, db, aibc, ib);
+}
+
+newblk(adbc, db, aibc, ib)
+int *adbc, *aibc;
+char *db;
+daddr_t *ib;
+{
+       int i;
+       daddr_t bno;
+
+       bno = alloc();
+       wtfs(bno, db);
+       for(i=0; i<BSIZE; i++)
+               db[i] = 0;
+       *adbc = 0;
+       ib[*aibc] = bno;
+       (*aibc)++;
+       if(*aibc >= NINDIR) {
+               printf("indirect block full\n");
+               error = 1;
+               *aibc = 0;
+       }
+}
+
+getch()
+{
+
+#ifndef STANDALONE
+       if(charp)
+#endif
+               return(*charp++);
+#ifndef STANDALONE
+       return(getc(fin));
+#endif
+}
+
+bflist()
+{
+       struct inode in;
+       daddr_t ib[NINDIR];
+       int ibc;
+       char flg[MAXFN];
+       int adr[MAXFN];
+       int i, j;
+       daddr_t f, d;
+
+       for(i=0; i<f_n; i++)
+               flg[i] = 0;
+       i = 0;
+       for(j=0; j<f_n; j++) {
+               while(flg[i])
+                       i = (i+1)%f_n;
+               adr[j] = i+1;
+               flg[i]++;
+               i = (i+f_m)%f_n;
+       }
+
+       ino++;
+       in.i_number = ino;
+       in.i_mode = IFREG;
+       in.i_uid = 0;
+       in.i_gid = 0;
+       in.i_nlink = 0;
+       in.i_size = 0;
+       for(i=0; i<NADDR; i++)
+               in.i_un.i_addr[i] = (daddr_t)0;
+
+       for(i=0; i<NINDIR; i++)
+               ib[i] = (daddr_t)0;
+       ibc = 0;
+       bfree((daddr_t)0);
+       d = filsys.s_fsize-1;
+       while(d%f_n)
+               d++;
+       for(; d > 0; d -= f_n)
+       for(i=0; i<f_n; i++) {
+               f = d - adr[i];
+               if(f < filsys.s_fsize && f >= filsys.s_isize)
+                       if(badblk(f)) {
+                               if(ibc >= NINDIR) {
+                                       printf("too many bad blocks\n");
+                                       error = 1;
+                                       ibc = 0;
+                               }
+                               ib[ibc] = f;
+                               ibc++;
+                       } else
+                               bfree(f);
+       }
+       iput(&in, &ibc, ib);
+}
+
+iput(ip, aibc, ib)
+struct inode *ip;
+int *aibc;
+daddr_t *ib;
+{
+       struct dinode *dp;
+       daddr_t d;
+       int i;
+
+       filsys.s_tinode--;
+       d = itod(ip->i_number);
+       if(d >= filsys.s_isize) {
+               if(error == 0)
+                       printf("ilist too small\n");
+               error = 1;
+               return;
+       }
+       rdfs(d, buf);
+       dp = (struct dinode *)buf;
+       dp += itoo(ip->i_number);
+
+       dp->di_mode = ip->i_mode;
+       dp->di_nlink = ip->i_nlink;
+       dp->di_uid = ip->i_uid;
+       dp->di_gid = ip->i_gid;
+       dp->di_size = ip->i_size;
+       dp->di_atime = utime;
+       dp->di_mtime = utime;
+       dp->di_ctime = utime;
+
+       switch(ip->i_mode&IFMT) {
+
+       case IFDIR:
+       case IFREG:
+               for(i=0; i<*aibc; i++) {
+                       if(i >= LADDR)
+                               break;
+                       ip->i_un.i_addr[i] = ib[i];
+               }
+               if(*aibc >= LADDR) {
+                       ip->i_un.i_addr[LADDR] = alloc();
+                       for(i=0; i<NINDIR-LADDR; i++) {
+                               ib[i] = ib[i+LADDR];
+                               ib[i+LADDR] = (daddr_t)0;
+                       }
+                       wtfs(ip->i_un.i_addr[LADDR], (char *)ib);
+               }
+
+       case IFBLK:
+       case IFCHR:
+               ltol3(dp->di_addr, ip->i_un.i_addr, NADDR);
+               break;
+
+       default:
+               printf("bad mode %o\n", ip->i_mode);
+               exit(1);
+       }
+       wtfs(d, buf);
+}
+
+badblk(bno)
+daddr_t bno;
+{
+
+       return(0);
+}
diff --git a/usr/src/cmd/mknod.c b/usr/src/cmd/mknod.c
new file mode 100644 (file)
index 0000000..4fccc28
--- /dev/null
@@ -0,0 +1,42 @@
+main(argc, argv)
+int argc;
+char **argv;
+{
+       int m, a, b;
+
+       if(argc != 5) {
+               printf("arg count\n");
+               goto usage;
+       }
+       if(*argv[2] == 'b')
+               m = 060666; else
+       if(*argv[2] == 'c')
+               m = 020666; else
+               goto usage;
+       a = number(argv[3]);
+       if(a < 0)
+               goto usage;
+       b = number(argv[4]);
+       if(b < 0)
+               goto usage;
+       if(mknod(argv[1], m, (a<<8)|b) < 0)
+               perror("mknod");
+       exit(0);
+
+usage:
+       printf("usage: mknod name b/c major minor\n");
+}
+
+number(s)
+char *s;
+{
+       int n, c;
+
+       n = 0;
+       while(c = *s++) {
+               if(c<'0' || c>'9')
+                       return(-1);
+               n = n*10 + c-'0';
+       }
+       return(n);
+}
diff --git a/usr/src/cmd/mount.c b/usr/src/cmd/mount.c
new file mode 100644 (file)
index 0000000..6ec1d00
--- /dev/null
@@ -0,0 +1,65 @@
+#include <stdio.h>
+
+#define        NMOUNT  16
+#define        NAMSIZ  32
+
+struct mtab {
+       char    file[NAMSIZ];
+       char    spec[NAMSIZ];
+} mtab[NMOUNT];
+
+main(argc, argv)
+char **argv;
+{
+       register int ro;
+       register struct mtab *mp;
+       register char *np;
+       int mf;
+
+       mf = open("/etc/mtab", 0);
+       read(mf, (char *)mtab, NMOUNT*2*NAMSIZ);
+       if (argc==1) {
+               for (mp = mtab; mp < &mtab[NMOUNT]; mp++)
+                       if (mp->file[0])
+                               printf("%s on %s\n", mp->spec, mp->file);
+               exit(0);
+       }
+       if(argc < 3) {
+               fprintf(stderr,"arg count\n");
+               exit(1);
+       }
+       ro = 0;
+       if(argc > 3)
+               ro++;
+       if(mount(argv[1], argv[2], ro) < 0) {
+               perror("mount");
+               exit(1);
+       }
+       np = argv[1];
+       while(*np++)
+               ;
+       np--;
+       while(*--np == '/')
+               *np = '\0';
+       while(np > argv[1] && *--np != '/')
+               ;
+       if(*np == '/')
+               np++;
+       argv[1] = np;
+       for (mp = mtab; mp < &mtab[NMOUNT]; mp++) {
+               if (mp->file[0] == 0) {
+                       for (np = mp->spec; np < &mp->spec[NAMSIZ-1];)
+                               if ((*np++ = *argv[1]++) == 0)
+                                       argv[1]--;
+                       for (np = mp->file; np < &mp->file[NAMSIZ-1];)
+                               if ((*np++ = *argv[2]++) == 0)
+                                       argv[2]--;
+                       mp = &mtab[NMOUNT];
+                       while ((--mp)->file[0] == 0);
+                       mf = creat("/etc/mtab", 0644);
+                       write(mf, (char *)mtab, (mp-mtab+1)*2*NAMSIZ);
+                       exit(0);
+               }
+       }
+       exit(0);
+}
diff --git a/usr/src/cmd/mv.c b/usr/src/cmd/mv.c
new file mode 100644 (file)
index 0000000..0e2b701
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * mv file1 file2
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <signal.h>
+
+#define        DOT     "."
+#define        DOTDOT  ".."
+#define        DELIM   '/'
+#define SDELIM "/"
+#define        MAXN    100
+#define MODEBITS 07777
+#define ROOTINO 2
+
+char   *pname();
+char   *sprintf();
+char   *dname();
+struct stat s1, s2;
+
+main(argc, argv)
+register char *argv[];
+{
+       register i, r;
+
+       if (argc < 3)
+               goto usage;
+       if (stat(argv[1], &s1) < 0) {
+               fprintf(stderr, "mv: cannot access %s\n", argv[1]);
+               return(1);
+       }
+       if ((s1.st_mode & S_IFMT) == S_IFDIR) {
+               if (argc != 3)
+                       goto usage;
+               return mvdir(argv[1], argv[2]);
+       }
+       setuid(getuid());
+       if (argc > 3)
+               if (stat(argv[argc-1], &s2) < 0 || (s2.st_mode & S_IFMT) != S_IFDIR)
+                       goto usage;
+       r = 0;
+       for (i=1; i<argc-1; i++)
+               r |= move(argv[i], argv[argc-1]);
+       return(r);
+usage:
+       fprintf(stderr, "usage: mv f1 f2; or mv d1 d2; or mv f1 ... fn d1\n");
+       return(1);
+}
+
+move(source, target)
+char *source, *target;
+{
+       register c, i;
+       int     status;
+       char    buf[MAXN];
+
+       if (stat(source, &s1) < 0) {
+               fprintf(stderr, "mv: cannot access %s\n", source);
+               return(1);
+       }
+       if ((s1.st_mode & S_IFMT) == S_IFDIR) {
+               fprintf(stderr, "mv: directory rename only\n");
+               return(1);
+       }
+       if (stat(target, &s2) >= 0) {
+               if ((s2.st_mode & S_IFMT) == S_IFDIR) {
+                       sprintf(buf, "%s/%s", target, dname(source));
+                       target = buf;
+               }
+               if (stat(target, &s2) >= 0) {
+                       if ((s2.st_mode & S_IFMT) == S_IFDIR) {
+                               fprintf(stderr, "mv: %s is a directory\n", target);
+                               return(1);
+                       }
+                       if (s1.st_dev==s2.st_dev && s1.st_ino==s2.st_ino) {
+                               fprintf(stderr, "mv: %s and %s are identical\n",
+                                               source, target);
+                               return(1);
+                       }
+                       if (access(target, 2) < 0 && isatty(fileno(stdin))) {
+                               fprintf(stderr, "mv: %s: %o mode ", target,
+                                       s2.st_mode & MODEBITS);
+                               i = c = getchar();
+                               while (c != '\n' && c != EOF)
+                                       c = getchar();
+                               if (i != 'y')
+                                       return(1);
+                       }
+                       if (unlink(target) < 0) {
+                               fprintf(stderr, "mv: cannot unlink %s\n", target);
+                               return(1);
+                       }
+               }
+       }
+       if (link(source, target) < 0) {
+               i = fork();
+               if (i == -1) {
+                       fprintf(stderr, "mv: try again\n");
+                       return(1);
+               }
+               if (i == 0) {
+                       execl("/bin/cp", "cp", source, target, 0);
+                       fprintf(stderr, "mv: cannot exec cp\n");
+                       exit(1);
+               }
+               while ((c = wait(&status)) != i && c != -1)
+                       ;
+               if (status != 0)
+                       return(1);
+               utime(target, &s1.st_atime);
+       }
+       if (unlink(source) < 0) {
+               fprintf(stderr, "mv: cannot unlink %s\n", source);
+               return(1);
+       }
+       return(0);
+}
+
+mvdir(source, target)
+char *source, *target;
+{
+       register char *p;
+       register i;
+       char buf[MAXN];
+
+       if (stat(target, &s2) >= 0) {
+               if ((s2.st_mode&S_IFMT) != S_IFDIR) {
+                       fprintf(stderr, "mv: %s exists\n", target);
+                       return(1);
+               }
+               if (strlen(target) > MAXN-DIRSIZ-2) {
+                       fprintf(stderr, "mv :target name too long\n");
+                       return(1);
+               }
+               strcpy(buf, target);
+               target = buf;
+               strcat(buf, SDELIM);
+               strcat(buf, dname(source));
+               if (stat(target, &s2) >= 0) {
+                       fprintf(stderr, "mv: %s exists\n", buf);
+                       return(1);
+               }
+       }
+       if (strcmp(source, target) == 0) {
+               fprintf(stderr, "mv: ?? source == target, source exists and target doesnt\n");
+               return(1);
+       }
+       p = dname(source);
+       if (!strcmp(p, DOT) || !strcmp(p, DOTDOT) || !strcmp(p, "") || p[strlen(p)-1]=='/') {
+               fprintf(stderr, "mv: cannot rename %s\n", p);
+               return(1);
+       }
+       if (stat(pname(source), &s1) < 0 || stat(pname(target), &s2) < 0) {
+               fprintf(stderr, "mv: cannot locate parent\n");
+               return(1);
+       }
+       if (access(pname(target), 2) < 0) {
+               fprintf(stderr, "mv: no write access to %s\n", pname(target));
+               return(1);
+       }
+       if (access(pname(source), 2) < 0) {
+               fprintf(stderr, "mv: no write access to %s\n", pname(source));
+               return(1);
+       }
+       if (access(source, 2) < 0) {
+               fprintf(stderr, "mv: no write access to %s\n", source);
+               return(1);
+       }
+       if (s1.st_dev != s2.st_dev) {
+               fprintf(stderr, "mv: cannot move directories across devices\n");
+               return(1);
+       }
+       if (s1.st_ino != s2.st_ino) {
+               char dst[MAXN+5];
+
+               if (chkdot(source) || chkdot(target)) {
+                       fprintf(stderr, "mv: Sorry, path names including %s aren't allowed\n", DOTDOT);
+                       return(1);
+               }
+               stat(source, &s1);
+               if (check(pname(target), s1.st_ino))
+                       return(1);
+               for (i = 1; i <= NSIG; i++)
+                       signal(i, SIG_IGN);
+               if (link(source, target) < 0) {
+                       fprintf(stderr, "mv: cannot link %s to %s\n", target, source);
+                       return(1);
+               }
+               if (unlink(source) < 0) {
+                       fprintf(stderr, "mv: %s: cannot unlink\n", source);
+                       unlink(target);
+                       return(1);
+               }
+               strcat(dst, target);
+               strcat(dst, "/");
+               strcat(dst, DOTDOT);
+               if (unlink(dst) < 0) {
+                       fprintf(stderr, "mv: %s: cannot unlink\n", dst);
+                       if (link(target, source) >= 0)
+                               unlink(target);
+                       return(1);
+               }
+               if (link(pname(target), dst) < 0) {
+                       fprintf(stderr, "mv: cannot link %s to %s\n",
+                               dst, pname(target));
+                       if (link(pname(source), dst) >= 0)
+                               if (link(target, source) >= 0)
+                                       unlink(target);
+                       return(1);
+               }
+               return(0);
+       }
+       if (link(source, target) < 0) {
+               fprintf(stderr, "mv: cannot link %s and %s\n",
+                       source, target);
+               return(1);
+       }
+       if (unlink(source) < 0) {
+               fprintf(stderr, "mv: ?? cannot unlink %s\n", source);
+               return(1);
+       }
+       return(0);
+}
+
+char *
+pname(name)
+register char *name;
+{
+       register c;
+       register char *p, *q;
+       static  char buf[MAXN];
+
+       p = q = buf;
+       while (c = *p++ = *name++)
+               if (c == DELIM)
+                       q = p-1;
+       if (q == buf && *q == DELIM)
+               q++;
+       *q = 0;
+       return buf[0]? buf : DOT;
+}
+
+char *
+dname(name)
+register char *name;
+{
+       register char *p;
+
+       p = name;
+       while (*p)
+               if (*p++ == DELIM && *p)
+                       name = p;
+       return name;
+}
+
+check(spth, dinode)
+char *spth;
+ino_t dinode;
+{
+       char nspth[MAXN];
+       struct stat sbuf;
+
+       sbuf.st_ino = 0;
+
+       strcpy(nspth, spth);
+       while (sbuf.st_ino != ROOTINO) {
+               if (stat(nspth, &sbuf) < 0) {
+                       fprintf(stderr, "mv: cannot access %s\n", nspth);
+                       return(1);
+               }
+               if (sbuf.st_ino == dinode) {
+                       fprintf(stderr, "mv: cannot move a directory into itself\n");
+                       return(1);
+               }
+               if (strlen(nspth) > MAXN-2-sizeof(DOTDOT)) {
+                       fprintf(stderr, "mv: name too long\n");
+                       return(1);
+               }
+               strcat(nspth, SDELIM);
+               strcat(nspth, DOTDOT);
+       }
+       return(0);
+}
+
+chkdot(s)
+register char *s;
+{
+       do {
+               if (strcmp(dname(s), DOTDOT) == 0)
+                       return(1);
+               s = pname(s);
+       } while (strcmp(s, DOT) != 0 && strcmp(s, SDELIM) != 0);
+       return(0);
+}
diff --git a/usr/src/cmd/ncheck.c b/usr/src/cmd/ncheck.c
new file mode 100644 (file)
index 0000000..3bbe4a2
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * ncheck -- obtain file names from reading filesystem
+ */
+
+#define        NI      16
+#define        NB      100
+#define        HSIZE   2503
+#define        NDIR    (BSIZE/sizeof(struct direct))
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/inode.h>
+#include <sys/ino.h>
+#include <sys/dir.h>
+#include <sys/filsys.h>
+#include <sys/fblk.h>
+
+struct filsys  sblock;
+struct dinode  itab[INOPB*NI];
+daddr_t        iaddr[NADDR];
+ino_t  ilist[NB];
+struct htab
+{
+       ino_t   h_ino;
+       ino_t   h_pino;
+       char    h_name[DIRSIZ];
+} htab[HSIZE];
+
+int    aflg;
+int    sflg;
+int    fi;
+ino_t  ino;
+int    nhent;
+int    nxfile;
+
+int    nerror;
+daddr_t        bmap();
+long   atol();
+struct htab *lookup();
+
+main(argc, argv)
+char *argv[];
+{
+       register i;
+       long n;
+
+       while (--argc) {
+               argv++;
+               if (**argv=='-')
+               switch ((*argv)[1]) {
+
+               case 'a':
+                       aflg++;
+                       continue;
+
+               case 'i':
+                       for(i=0; i<NB; i++) {
+                               n = atol(argv[1]);
+                               if(n == 0)
+                                       break;
+                               ilist[i] = n;
+                               nxfile = i;
+                               argv++;
+                               argc--;
+                       }
+                       continue;
+
+               case 's':
+                       sflg++;
+                       continue;
+
+               default:
+                       fprintf(stderr, "ncheck: bad flag %c\n", (*argv)[1]);
+                       nerror++;
+               }
+               check(*argv);
+       }
+       return(nerror);
+}
+
+check(file)
+char *file;
+{
+       register i, j;
+       ino_t mino;
+
+       fi = open(file, 0);
+       if(fi < 0) {
+               fprintf(stderr, "ncheck: cannot open %s\n", file);
+               nerror++;
+               return;
+       }
+       nhent = 0;
+       printf("%s:\n", file);
+       sync();
+       bread((daddr_t)1, (char *)&sblock, sizeof(sblock));
+       mino = (sblock.s_isize-2) * INOPB;
+       ino = 0;
+       for(i=2;; i+=NI) {
+               if(ino >= mino)
+                       break;
+               bread((daddr_t)i, (char *)itab, sizeof(itab));
+               for(j=0; j<INOPB*NI; j++) {
+                       if(ino >= mino)
+                               break;
+                       ino++;
+                       pass1(&itab[j]);
+               }
+       }
+       ilist[nxfile+1] = 0;
+       ino = 0;
+       for(i=2;; i+=NI) {
+               if(ino >= mino)
+                       break;
+               bread((daddr_t)i, (char *)itab, sizeof(itab));
+               for(j=0; j<INOPB*NI; j++) {
+                       if(ino >= mino)
+                               break;
+                       ino++;
+                       pass2(&itab[j]);
+               }
+       }
+       ino = 0;
+       for(i=2;; i+=NI) {
+               if(ino >= mino)
+                       break;
+               bread((daddr_t)i, (char *)itab, sizeof(itab));
+               for(j=0; j<INOPB*NI; j++) {
+                       if(ino >= mino)
+                               break;
+                       ino++;
+                       pass3(&itab[j]);
+               }
+       }
+}
+
+pass1(ip)
+register struct dinode *ip;
+{
+       if((ip->di_mode & IFMT) != IFDIR) {
+               if (sflg==0 || nxfile>=NB)
+                       return;
+               if ((ip->di_mode&IFMT)==IFBLK || (ip->di_mode&IFMT)==IFCHR
+                 || ip->di_mode&(ISUID|ISGID))
+                       ilist[nxfile++] = ino;
+                       return;
+       }
+       lookup(ino, 1);
+}
+
+pass2(ip)
+register struct dinode *ip;
+{
+       struct direct dbuf[NDIR];
+       long doff;
+       struct direct *dp;
+       register i, j;
+       int k;
+       struct htab *hp;
+       daddr_t d;
+       ino_t kno;
+
+       if((ip->di_mode&IFMT) != IFDIR)
+               return;
+       l3tol(iaddr, ip->di_addr, NADDR);
+       doff = 0;
+       for(i=0;; i++) {
+               if(doff >= ip->di_size)
+                       break;
+               d = bmap(i);
+               if(d == 0)
+                       break;
+               bread(d, (char *)dbuf, sizeof(dbuf));
+               for(j=0; j<NDIR; j++) {
+                       if(doff >= ip->di_size)
+                               break;
+                       doff += sizeof(struct direct);
+                       dp = dbuf+j;
+                       kno = dp->d_ino;
+                       if(kno == 0)
+                               continue;
+                       hp = lookup(kno, 0);
+                       if(hp == 0)
+                               continue;
+                       if(dotname(dp))
+                               continue;
+                       hp->h_pino = ino;
+                       for(k=0; k<DIRSIZ; k++)
+                               hp->h_name[k] = dp->d_name[k];
+               }
+       }
+}
+
+pass3(ip)
+register struct dinode *ip;
+{
+       struct direct dbuf[NDIR];
+       long doff;
+       struct direct *dp;
+       register i, j;
+       int k;
+       daddr_t d;
+       ino_t kno;
+
+       if((ip->di_mode&IFMT) != IFDIR)
+               return;
+       l3tol(iaddr, ip->di_addr, NADDR);
+       doff = 0;
+       for(i=0;; i++) {
+               if(doff >= ip->di_size)
+                       break;
+               d = bmap(i);
+               if(d == 0)
+                       break;
+               bread(d, (char *)dbuf, sizeof(dbuf));
+               for(j=0; j<NDIR; j++) {
+                       if(doff >= ip->di_size)
+                               break;
+                       doff += sizeof(struct direct);
+                       dp = dbuf+j;
+                       kno = dp->d_ino;
+                       if(kno == 0)
+                               continue;
+                       if(aflg==0 && dotname(dp))
+                               continue;
+                       if(ilist[0] == 0)
+                               goto pr;
+                       for(k=0; ilist[k] != 0; k++)
+                               if(ilist[k] == kno)
+                                       goto pr;
+                       continue;
+               pr:
+                       printf("%u      ", kno);
+                       pname(ino, 0);
+                       printf("/%.14s", dp->d_name);
+                       if (lookup(kno, 0))
+                               printf("/.");
+                       printf("\n");
+               }
+       }
+}
+
+dotname(dp)
+register struct direct *dp;
+{
+
+       if (dp->d_name[0]=='.')
+               if (dp->d_name[1]==0 || (dp->d_name[1]=='.' && dp->d_name[2]==0))
+                       return(1);
+       return(0);
+}
+
+pname(i, lev)
+ino_t i;
+{
+       register struct htab *hp;
+
+       if (i==ROOTINO)
+               return;
+       if ((hp = lookup(i, 0)) == 0) {
+               printf("???");
+               return;
+       }
+       if (lev > 10) {
+               printf("...");
+               return;
+       }
+       pname(hp->h_pino, ++lev);
+       printf("/%.14s", hp->h_name);
+}
+
+struct htab *
+lookup(i, ef)
+ino_t i;
+{
+       register struct htab *hp;
+
+       for (hp = &htab[i%HSIZE]; hp->h_ino;) {
+               if (hp->h_ino==i)
+                       return(hp);
+               if (++hp >= &htab[HSIZE])
+                       hp = htab;
+       }
+       if (ef==0)
+               return(0);
+       if (++nhent >= HSIZE) {
+               fprintf(stderr, "ncheck: out of core-- increase HSIZE\n");
+               exit(1);
+       }
+       hp->h_ino = i;
+       return(hp);
+}
+
+bread(bno, buf, cnt)
+daddr_t bno;
+char *buf;
+{
+       register i;
+
+       lseek(fi, bno*BSIZE, 0);
+       if (read(fi, buf, cnt) != cnt) {
+               fprintf(stderr, "ncheck: read error %d\n", bno);
+               for(i=0; i<BSIZE; i++)
+                       buf[i] = 0;
+       }
+}
+
+daddr_t
+bmap(i)
+{
+       daddr_t ibuf[NINDIR];
+
+       if(i < NADDR-3)
+               return(iaddr[i]);
+       i -= NADDR-3;
+       if(i > NINDIR) {
+               fprintf(stderr, "ncheck: %u - huge directory\n", ino);
+               return((daddr_t)0);
+       }
+       bread(iaddr[NADDR-3], (char *)ibuf, sizeof(ibuf));
+       return(ibuf[i]);
+}
diff --git a/usr/src/cmd/newgrp.c b/usr/src/cmd/newgrp.c
new file mode 100644 (file)
index 0000000..af49a5e
--- /dev/null
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <grp.h>
+#include <pwd.h>
+
+struct group   *getgrnam(), *grp;
+struct passwd  *getpwuid(), *pwd;
+char   *getpass(), *crypt();
+
+main(argc,argv)
+int    argc;
+char   **argv;
+{
+       register i;
+       if(argc != 2) {
+               printf("usage: newgrp groupname\n");
+               done();
+       }
+       if((grp=getgrnam(argv[1])) == NULL) {
+               printf("%s: no such group\n", argv[1]);
+               done();
+       }
+       if((pwd=getpwuid(getuid())) == NULL) {
+               printf("You do not exist!\n");
+               done();
+       }
+       for(i=0;grp->gr_mem[i];i++) 
+               if(strcmp(grp->gr_mem[i], pwd->pw_name) == 0)
+                       break;
+       if(grp->gr_mem[i] == 0 && strcmp(grp->gr_name,"other")) {
+               printf("Sorry\n");
+               done();
+       }
+
+       if(grp->gr_passwd[0] != '\0' && pwd->pw_passwd[0] == '\0') {
+               if(strcmp(grp->gr_passwd, crypt(getpass("Password:"),grp->gr_passwd)) != 0) {
+                       printf("Sorry\n");
+                       done();
+               }
+       }
+       if(setgid(grp->gr_gid) < 0)
+               perror("setgid");
+       done();
+}
+
+done()
+{
+       register i;
+
+       setuid(getuid());
+       for (i=3; i<15; i++)
+               close(i);
+       execl("/bin/sh", "sh", 0);
+       printf("No shell!\n");
+       exit(0);
+}
diff --git a/usr/src/cmd/nice.c b/usr/src/cmd/nice.c
new file mode 100644 (file)
index 0000000..ed22a93
--- /dev/null
@@ -0,0 +1,26 @@
+/* nice */
+
+#include <stdio.h>
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       int nicarg = 10;
+       extern errno;
+       extern char *sys_errlist[];
+
+       if(argc > 1 && argv[1][0] == '-') {
+               nicarg = atoi(&argv[1][1]);
+               argc--;
+               argv++;
+       }
+       if(argc < 2) {
+               fputs("usage: nice [ -n ] command\n", stderr);
+               exit(1);
+       }
+       nice(nicarg);
+       execvp(argv[1], &argv[1]);
+       fprintf(stderr, "%s: %s\n", sys_errlist[errno], argv[1]);
+       exit(1);
+}