#define MAXCOL 71 /* for CR if tty reaches this col */ /* load - execute cc on argument files - compiling those which need it. for each arg "file" - if file.c was modified since file.o was created, the arg passed is file.c, else file.o. Args preceded by - are left alone */ char svfile[] "/tmp/load.xxxxxxxxxx"; /* x's will be user name */ extern int fout; /* for putchar */ main (nargs, argary) int nargs; char *argary[]; { char ch, pwf[100]; char **a, *strptr; char *args[300]; int i, j, oc, col; int new0, new1, standout; /* standard output */ long int buf[9], /* to check dates between .c */ obuf[9]; /* and .o files */ getpw (getuid (), pwf); /* find entry in passwd file */ for (i = 12; pwf[i - 12] != ':'; i++) svfile[i] = pwf[i - 12]; /* copy up to colon */ svfile[i] = 0; /* terminate with a zero */ fout = standout = dup (1); if (nargs == 1) /* then read from /tmp file */ { new0 = dup (0); close (0); if (open (svfile, 0) < 0) { printf ("load: no args given\n"); flush (); exit (0); } i = j = 0; /* character and line counters */ args[0] = alloc (21); /* 20-char increments */ while ((ch = getchar ()) && (ch != '\n')) { col++; if (ch == ' ') /* end of argument */ { args[i][j] = '\0'; /* end str with null */ if (col >= MAXCOL - 30) { putchar ('\n'); col = 0; } printf ("%s ", args[i++]); if (i > sizeof args) { printf ("\nload: too many arguments.\n"); flush (); exit (1); } args[i] = alloc (21); args[i][j = 0] = 0; /* to test emptiness */ } else { args[i][j++] = ch; if (j % 20 == 0) /* get more space */ { args[i][j] = '\0'; strptr = alloc (j + 21); /* 20 char increment */ strcpy (args[i], strptr); free (args[i]); args[i] = strptr; } } } if (j != 0) { args[i][j] = 0; /* terminate the last one */ printf ("%s", args[i++]); } putchar ('\n'); nargs = i; close (0); /* reset standard input */ dup (new0); close (new0); } else { flush (); if ((fout = creat (svfile, 0644)) < 0) { /* make a trace file */ fout = standout; printf ("load: unable to create \"memory\" of this run.\n"); flush (); for (i = 0; i < nargs; i++)/* setup calling array */ args[i] = argary[i]; } else { for (i = 0; i < nargs; i++)/* make the trace */ printf ("%s ", args[i] = argary[i]); /* setup calling array */ putchar ('\n'); flush (); fout = standout; } } a = alloc (2 * (nargs + 1)); a[nargs] = 0; for (i = 1; i < nargs; i++) { if (*args[i] == '-') a[i] = args[i]; else { if (stat (a[i] = cat (args[i], ".c"), buf) != -1) { /* there's a .c file */ if ((stat (strptr = cat (args[i], ".o"), obuf) != -1) && (buf[8] < obuf[8])) a[i] = strptr; /* has .o file which is younger */ } else if (stat (strptr = cat (args[i], ".o"), buf) != -1) a[i] = strptr; /* will settle for .o file */ else if (stat (args[i], buf) != -1) a[i] = args[i];/* take named file if any */ else printf ("load: file \"%s\" not found.\n", args[i]); } } a[0] = "cc"; col = 0; for (i = 0; i < nargs; i++) /* tell user the real calling */ { /* arguments */ col =+ strlen (a[i]) + 1; if (col > MAXCOL) { putchar ('\n'); col = strlen (a[i]) + 1; } printf ("%s ", a[i]); } putchar ('\n'); flush (); unlink ("a.out"); /* if it is there */ if (!strcomp (args[0], "ex") || (fork () == 0)) { execvsrh (a); /* get cc from appropriate dir */ flush (); exit (-1); } /* If got here, then did a fork */ wait (&oc); /* wait for the compilation to be completed */ if (stat ("a.out", buf) != -1) /* then a.out exists */ { printf ("ex: executing a.out\n"); flush (); execl ("a.out", "a.out", 0); } exit (0); /* for some reason omitting */ /* this gives bus error */ } char *cat (a, b) /* assumes 2-char 2nd arg */ char *a, *b; { char *bb; register char *aa; aa = bb = alloc (3 + strlen (a)); /* 2 longer than orig string */ while (*aa++ = *a++); /* copy 1st source into new place */ aa--; while (*aa++ = *b++); /* concatenate 2nd to end */ return (bb); /* return address of result */ } strcomp (s, t) char *s, *t; { while (*s == *t++) if (!*s++) return (1); return (0); } strcpy (ss, tt) char *ss, *tt; { register char *s, *t; s = ss; t = tt; while (*t++ = *s++); } char *SRHLIST[] /* upper case!! */ { "", "%", "/bin/", "/usr/bin/", 0 }; char **srhlist SRHLIST; execvsrh (argv) char **argv; { extern errno; register char **r1, *r2, *r3; static char command[50]; for (r1 = srhlist; r2 = *r1++;) { r3 = command; flush (); if (*r2 == '%') { r2 = getpath (getluid () & 0377); flush (); while (*r3++ = *r2++); --r3; r2 = "/bin/"; } while (*r3++ = *r2++); --r3; r2 = argv[0]; while (*r3++ = *r2++); if ((execv (command, argv) == -1) && (errno != 2)) break; } printf ("Unable to run \"%s\" because: %s\n", argv[0], (errno == 7) ? "arg list too long" : "not found"); } /* * Inode structure as returned by * system call stat. */ struct inode { int i_dev; int i_number; int i_mode; char i_nlink; char i_uid; char i_gid; char i_size0; char *i_size1; int i_addr[8]; long i_atime; long i_mtime; }; /* advisable to use this define to generate owner as 16-bit num */ #define IOWNER(i_n_buf) (((i_n_buf).i_uid<<8)|(i_n_buf).i_gid&0377) /* modes */ #define IALLOC 0100000 #define IFMT 060000 #define IFDIR 040000 #define IFCHR 020000 #define IFBLK 060000 #define ILARG 010000 #define ISUID 04000 #define ISGID 02000 #define ISVTX 01000 #define IREAD 0400 #define IWRITE 0200 #define IEXEC 0100 struct { char d_minor, d_major; }; /* this subr returns owner of tty attached to file handle # 2 */ /* on harv/unix, this may not be the real uid, because */ /* we have the command "alias" which spawns a sub-shell with */ /* a new real uid. luid (login uid) is used by the harvard shell */ /* to find the "save.txt" file (via getpath(getluid())) for $a - $z */ /* shell macros, and elsewhere by certain accounting routines. */ getluid () { struct inode ibuf; if (fstat (2, &ibuf) < 0 && fstat (1, &ibuf) < 0) return (getuid () & 0377); if ((ibuf.i_mode & IFMT) != IFCHR) return (getuid () & 0377); return (ibuf.i_uid & 0377); } int last_uid; /* used to check if info already in u_buf */ char u_buf[120]; /* buffer used by get*.c */ int pich; /* global file handle used by get*.c */ #define NULSTR -1 /* guaranteed to be a null string */ getpath (uid) { char *path; register char *pp, *bp; register int n; if (getubuf (uid) <= 0) return (NULSTR); path = alloc (50); pp = path; bp = u_buf; for (n = 0; n < 5; n++) while (*bp++ != ':'); while ((*pp++ = *bp++) != ':'); *--pp = '\0'; return (path); } getubuf (uid) { if ((uid != last_uid) || (uid == 0)) if (getpw (uid, u_buf)) return (0); last_uid = uid; return (1); } /* */ /* Return the length of the given string. This length does not */ /* include the terminating null character. */ strlen (string) char *string; { register char *rstring; register int rlength; /* length of string */ rstring = string; for (rlength = 0; *rstring++ != 0; ++rlength); return (rlength); }