From sources-request@genrad.UUCP Tue Jun 11 11:47:17 1985 Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site seismo.UUCP Posting-Version: version B 2.10.2 9/3/84; site genrad.UUCP Path: seismo!harvard!talcott!panda!grkermi!genrad!sources-request From: sources-request@genrad.UUCP Newsgroups: mod.sources Subject: Bourne shell history + tilde + job control + more (Part 6 of 9) Message-ID: <884@genrad.UUCP> Date: 11 Jun 85 15:47:17 GMT Date-Received: 12 Jun 85 00:44:21 GMT Sender: john@genrad.UUCP Lines: 3347 Approved: john@genrad.UUCP From: Arnold Robbins This is part 6 of 9. It contains the second set of code diffs for the System V Release 2 Bourne shell. BSD users who happen to also have source for System V Release 2 will probably want to use this version of the shell, since it has many bug fixes and improvements over the (much) earlier version that comes with Berkeley Unix. Arnold Robbins arnold@gatech.{UUCP, CSNET} ----------- pretend your screen is really a paper towel ------------ :::::::: name.c ::::::: *** ../orig.u/name.c Wed May 15 17:08:24 1985 --- name.c Tue May 21 19:02:42 1985 *************** *** 15,21 struct namnod ps2nod = { (struct namnod *)NIL, ! &acctnod, ps2name }; struct namnod cdpnod = --- 15,21 ----- struct namnod ps2nod = { (struct namnod *)NIL, ! (struct namnod *)NIL, ps2name }; struct namnod cdpnod = *************** *** 32,38 }; struct namnod ifsnod = { ! &homenod, &mailnod, ifsname }; --- 32,38 ----- }; struct namnod ifsnod = { ! &histfnod, &mailnod, ifsname }; *************** *** 39,45 struct namnod ps1nod = { &pathnod, ! &ps2nod, ps1name }; struct namnod homenod = --- 39,45 ----- struct namnod ps1nod = { &pathnod, ! &acctnod, ps1name }; struct namnod homenod = *************** *** 44,50 }; struct namnod homenod = { - &cdpnod, (struct namnod *)NIL, homename }; --- 44,49 ----- }; struct namnod homenod = { (struct namnod *)NIL, (struct namnod *)NIL, homename *************** *** 46,51 { &cdpnod, (struct namnod *)NIL, homename }; struct namnod mailnod = --- 45,51 ----- struct namnod homenod = { (struct namnod *)NIL, + (struct namnod *)NIL, homename }; struct namnod mailnod = *************** *** 62,67 }; struct namnod acctnod = { (struct namnod *)NIL, (struct namnod *)NIL, acctname --- 62,71 ----- }; struct namnod acctnod = { + &ps2nod, + #if pyr + &univnod, + #else (struct namnod *)NIL, #endif acctname *************** *** 63,69 struct namnod acctnod = { (struct namnod *)NIL, ! (struct namnod *)NIL, acctname }; struct namnod mailpnod = --- 67,73 ----- &univnod, #else (struct namnod *)NIL, ! #endif acctname }; struct namnod mailpnod = *************** *** 72,77 (struct namnod *)NIL, mailpname }; struct namnod *namep = &mchknod; --- 76,95 ----- (struct namnod *)NIL, mailpname }; + struct namnod histfnod = + { + &cdpnod, + &homenod, + histfilename + }; + #if pyr + struct namnod univnod = + { + (struct namnod *)NIL, + (struct namnod *)NIL, + univname + }; + #endif struct namnod *namep = &mchknod; *************** *** 86,91 int low; int high; int mid; register int cond; if (w == 0 || *w == 0) --- 104,112 ----- int low; int high; int mid; + #if gould + int cond; /* DAG -- avoid optimizer bug */ + #else register int cond; #endif *************** *** 87,92 int high; int mid; register int cond; if (w == 0 || *w == 0) return(0); --- 108,114 ----- int cond; /* DAG -- avoid optimizer bug */ #else register int cond; + #endif if (w == 0 || *w == 0) return(0); *************** *** 228,233 readvar(names) char **names; { struct fileblk fb; register struct fileblk *f = &fb; register char c; --- 250,256 ----- readvar(names) char **names; { + extern long lseek(); /* DAG -- bug fix (was missing) */ struct fileblk fb; register struct fileblk *f = &fb; register char c; *************** *** 238,244 push(f); initf(dup(0)); ! if (lseek(0, 0L, 1) == -1) f->fsiz = 1; /* --- 261,267 ----- push(f); initf(dup(0)); ! if (lseek(0, 0L, 1) == -1L) /* DAG */ f->fsiz = 1; /* :::::::: name.h ::::::: No differences encountered :::::::: print.c ::::::: *** ../orig.u/print.c Wed May 15 17:08:25 1985 --- print.c Mon May 20 15:32:21 1985 *************** *** 7,12 */ #include "defs.h" #include #define BUFLEN 256 --- 7,15 ----- */ #include "defs.h" + #if JOBS + #define HZ 60 + #else #include #endif *************** *** 8,13 #include "defs.h" #include #define BUFLEN 256 --- 11,17 ----- #define HZ 60 #else #include + #endif #define BUFLEN 256 *************** *** 66,73 prc_buff('h'); } ! prn_buff(min); ! prc_buff('m'); prn_buff(sec); prc_buff('s'); } --- 70,80 ----- prc_buff('h'); } ! if (min) /* BRL... for consistency */ ! { ! prn_buff(min); ! prc_buff('m'); ! } prn_buff(sec); prc_buff('s'); } *************** *** 230,233 itos(n); prs_buff(numbuf); } --- 237,357 ----- itos(n); prs_buff(numbuf); + } + + void + pr_prompt (str) + register char *str; + { + for (; *str; str++) + { + if (*str != '%') + prc_buff (*str); + else if (*(str+1) == 'd') + { + /* current directory */ + str++; + prs_buff (retcwd()); + } + else if (*(str+1) == 'e') + { + /* event count */ + str++; + if ((flags & nohistflg) == 0) + prn_buff (event_count); + } + else if (*(str+1) == 'h') + { + /* hostname */ + static char *cp = 0; + static int didhost = FALSE; + static int didgt = FALSE; + #ifdef JOBS + static char buf[257]; + + if (! didhost) + { + gethostname (buf, sizeof buf); + didhost = TRUE; + cp = buf; + } + #else + #include /* has an extern declaration in it */ + static struct utsname name; + + if (! didhost) + { + uname (& name); + /* avoid emulation bug */ + name.sysname[sizeof(name.sysname)-1] = '\0'; + didhost = TRUE; + cp = name.sysname; + } + #endif + + #ifdef GATECH + /* + * this is to get rid of the dumb gt- convention. + * a gt w/out the - is also removed. + */ + if (! didgt) + { + didgt = TRUE; + if (cp[0] == 'g' && cp[1] == 't' && cp[2]) + { + cp += 2; + if (cp[0] == '-' && cp[1]) + cp++; + } + } + #endif + prs_buff (cp); + str++; + } + else if (*(str+1) == 'l') + { + /* login name */ + static char *cp = 0; + static int didname = FALSE; + + str++; + if (! didname) + { + cp = username (); + didname = TRUE; + } + + if (cp) + prs_buff (cp); + } + else if (*(str+1) == 't') + { + /* current time, HH:MM */ + long l; + char *cp, *ctime (); + + str++; + time (& l); + cp = ctime (& l); + cp[16] = '\0'; + cp += 11; + prs_buff (cp); + } + #if pyr + else if (*(str+1) == 'u') + { + /* current univeserse */ + str++; + prs_buff (univ_name[cur_univ-1]); + } + #endif + else if (*(str+1) == '\0') /* % was last char in string */ + { + prc_buff (*str); + continue; + } + else + prc_buff (*(++str)); + } + flushb(); } :::::::: profile.c ::::::: No differences encountered :::::::: pwd.c ::::::: *** ../orig.u/pwd.c Wed May 15 17:08:27 1985 --- pwd.c Mon May 20 17:20:51 1985 *************** *** 4,9 * * Bell Telephone Laboratories * */ #include "mac.h" --- 4,14 ----- * * Bell Telephone Laboratories * + * DAG -- Two ways of handling symbolic links in directory paths: + * Define SYMLINK if you want "cd .." to do just that. + * Otherwise, "cd .." takes you back the way you came. + * The first method was implemented by Ron Natalie and the + * second method was implemented by Douglas Gwyn, both of BRL. */ #include "defs.h" /* DAG -- was just "mac.h" */ *************** *** 6,12 * */ ! #include "mac.h" #define DOT '.' #define NULL 0 --- 11,19 ----- * second method was implemented by Douglas Gwyn, both of BRL. */ ! #include "defs.h" /* DAG -- was just "mac.h" */ ! #include /* DAG -- moved for SYMLINK */ ! #include /* DAG -- moved for SYMLINK */ #if defined(SYMLINK) && !defined(S_IFLNK) #define S_IFLNK 0120000 *************** *** 8,13 #include "mac.h" #define DOT '.' #define NULL 0 #define SLASH '/' --- 15,24 ----- #include /* DAG -- moved for SYMLINK */ #include /* DAG -- moved for SYMLINK */ + #if defined(SYMLINK) && !defined(S_IFLNK) + #define S_IFLNK 0120000 + #endif + #define DOT '.' #define NULL 0 #define SLASH '/' *************** *** 11,16 #define DOT '.' #define NULL 0 #define SLASH '/' #define MAXPWD 256 extern char longpwd[]; --- 22,30 ----- #define DOT '.' #define NULL 0 #define SLASH '/' + #if defined(JOBS) + #define MAXPWD (24*256) /* who knows */ + #else #define MAXPWD 256 #endif *************** *** 12,17 #define NULL 0 #define SLASH '/' #define MAXPWD 256 extern char longpwd[]; --- 26,32 ----- #define MAXPWD (24*256) /* who knows */ #else #define MAXPWD 256 + #endif extern char longpwd[]; *************** *** 17,22 static char cwdname[MAXPWD]; static int didpwd = FALSE; cwd(dir) register char *dir; --- 32,41 ----- static char cwdname[MAXPWD]; static int didpwd = FALSE; + #if SYMLINK + /* Stuff to handle chdirs around symbolic links */ + static char *symlink = 0; /* Pointer to after last symlink in cwdname */ + #endif cwd(dir) register char *dir; *************** *** 21,26 cwd(dir) register char *dir; { register char *pcwd; register char *pdir; --- 40,48 ----- cwd(dir) register char *dir; { + #if SYMLINK + struct stat statb; + #endif register char *pcwd; register char *pdir; *************** *** 44,51 if (*pdir) pdir++; } ! if(*(--pdir)==DOT && pdir>dir && *(--pdir)==SLASH) ! *pdir = NULL; /* Remove extra /'s */ --- 66,73 ----- if (*pdir) pdir++; } ! if(pdir>dir && *(--pdir)==DOT && pdir>dir && *(--pdir)==SLASH) /* DAG -- bug fix (added first test) */ ! *pdir = '\0'; /* DAG -- not NULL */ /* Remove extra /'s */ *************** *** 65,70 pcwd = cwdname; didpwd = TRUE; } else { --- 87,95 ----- pcwd = cwdname; didpwd = TRUE; + #if SYMLINK + symlink = 0; /* Starting over, no links yet */ + #endif } else { *************** *** 71,76 /* Relative path */ if (didpwd == FALSE) return; pcwd = cwdname + length(cwdname) - 1; --- 96,104 ----- /* Relative path */ if (didpwd == FALSE) + #if !defined(SYMLINK) && defined(JOBS) + pwd(); /* Get absolute pathname into cwdname[] */ + #else return; #endif *************** *** 72,77 if (didpwd == FALSE) return; pcwd = cwdname + length(cwdname) - 1; if(pcwd != cwdname+1) --- 100,106 ----- pwd(); /* Get absolute pathname into cwdname[] */ #else return; + #endif pcwd = cwdname + length(cwdname) - 1; if(pcwd != cwdname+1) *************** *** 93,98 ; pcwd++; dir += 2; if(*dir==SLASH) { dir++; --- 122,135 ----- ; pcwd++; dir += 2; + #if SYMLINK + /* Just undid symlink, so pwd the hard way */ + if(pcwd < symlink) + { + pwd(); + return; + } + #endif if(*dir==SLASH) { dir++; *************** *** 102,107 *pcwd++ = *dir++; while((*dir) && (*dir != SLASH)) *pcwd++ = *dir++; if (*dir) *pcwd++ = *dir++; } --- 139,161 ----- *pcwd++ = *dir++; while((*dir) && (*dir != SLASH)) *pcwd++ = *dir++; + #if SYMLINK + /* Check to see if this path component is a symbolic link */ + *pcwd = 0; + if(lstat(cwdname, &statb) != 0) + { + prs(cwdname); /* DAG */ + error(nolstat); /* DAG -- made string sharable */ + pwd(); + return; + } + if((statb.st_mode & S_IFMT) == S_IFLNK) + /* Set fence so that when we attempt to + * "cd .." past it, we know that it is invalid + * and have to do it the hard way + */ + symlink = dir; + #endif if (*dir) *pcwd++ = *dir++; } *************** *** 105,111 if (*dir) *pcwd++ = *dir++; } ! *pcwd = NULL; --pcwd; if(pcwd>cwdname && *pcwd==SLASH) --- 159,165 ----- if (*dir) *pcwd++ = *dir++; } ! *pcwd = '\0'; /* DAG -- not NULL */ --pcwd; if(pcwd>cwdname && *pcwd==SLASH) *************** *** 112,118 { /* Remove trailing / */ ! *pcwd = NULL; } return; } --- 166,172 ----- { /* Remove trailing / */ ! *pcwd = '\0'; /* DAG -- not NULL */ } return; } *************** *** 168,174 * Find the current directory the hard way. */ ! #include #include #include --- 222,230 ----- * Find the current directory the hard way. */ ! #if JOBS ! #include ! #else #include #endif *************** *** 170,176 #include #include ! #include static char dotdots[] = --- 226,232 ----- #include #else #include ! #endif static char dotdots[] = *************** *** 176,181 static char dotdots[] = "../../../../../../../../../../../../../../../../../../../../../../../.."; extern struct direct *getdir(); extern char *movstrn(); --- 232,240 ----- static char dotdots[] = "../../../../../../../../../../../../../../../../../../../../../../../.."; + #if JOBS + #define getdir(dirf) readdir(dirf) + #else extern struct direct *getdir(); extern char *movstrn(); #endif *************** *** 178,183 extern struct direct *[etdir(); extern char *movstrn(); static pwd() --- 237,243 ----- #else extern struct direct *getdir(); extern char *movstrn(); + #endif static pwd() *************** *** 185,190 struct stat cdir; /* current directory status */ struct stat tdir; struct stat pdir; /* parent directory status */ int pdfd; /* parent directory file descriptor */ struct direct *dir; --- 245,253 ----- struct stat cdir; /* current directory status */ struct stat tdir; struct stat pdir; /* parent directory status */ + #if JOBS + DIR *pdfd; /* parent directory stream */ + #else int pdfd; /* parent directory file descriptor */ #endif *************** *** 186,191 struct stat tdir; struct stat pdir; /* parent directory status */ int pdfd; /* parent directory file descriptor */ struct direct *dir; char *dot = dotdots + sizeof(dotdots) - 3; --- 249,255 ----- DIR *pdfd; /* parent directory stream */ #else int pdfd; /* parent directory file descriptor */ + #endif struct direct *dir; char *dot = dotdots + sizeof(dotdots) - 3; *************** *** 193,198 int cwdindex = MAXPWD - 1; int i; cwdname[cwdindex] = 0; dotdots[index] = 0; --- 257,265 ----- int cwdindex = MAXPWD - 1; int i; + #if SYMLINK + symlink = 0; /* Starting over, no links yet */ + #endif cwdname[cwdindex] = 0; dotdots[index] = 0; *************** *** 206,212 for(;;) { cdir = pdir; ! if ((pdfd = open(dot, 0)) < 0) { error("pwd: cannot open .."); --- 273,281 ----- for(;;) { cdir = pdir; ! #if JOBS ! if ((pdfd = opendir(dot)) == (DIR *)0) ! #else if ((pdfd = open(dot, 0)) < 0) #endif { *************** *** 208,213 cdir = pdir; if ((pdfd = open(dot, 0)) < 0) { error("pwd: cannot open .."); } --- 277,283 ----- if ((pdfd = opendir(dot)) == (DIR *)0) #else if ((pdfd = open(dot, 0)) < 0) + #endif { error("pwd: cannot open .."); } *************** *** 211,217 { error("pwd: cannot open .."); } ! if(fstat(pdfd, &pdir) < 0) { close(pdfd); --- 281,289 ----- { error("pwd: cannot open .."); } ! #if JOBS ! if(fstat(pdfd->dd_fd, &pdir) < 0) ! #else if(fstat(pdfd, &pdir) < 0) #endif { *************** *** 213,218 } if(fstat(pdfd, &pdir) < 0) { close(pdfd); error("pwd: cannot stat .."); --- 285,291 ----- if(fstat(pdfd->dd_fd, &pdir) < 0) #else if(fstat(pdfd, &pdir) < 0) + #endif { #if JOBS closedir(pdfd); *************** *** 214,219 if(fstat(pdfd, &pdir) < 0) { close(pdfd); error("pwd: cannot stat .."); } --- 287,295 ----- if(fstat(pdfd, &pdir) < 0) #endif { + #if JOBS + closedir(pdfd); + #else close(pdfd); #endif error("pwd: cannot stat .."); *************** *** 215,220 if(fstat(pdfd, &pdir) < 0) { close(pdfd); error("pwd: cannot stat .."); } --- 291,297 ----- closedir(pdfd); #else close(pdfd); + #endif error("pwd: cannot stat .."); } *************** *** 223,228 if(cdir.st_ino == pdir.st_ino) { didpwd = TRUE; close(pdfd); if (cwdindex == (MAXPWD - 1)) cwdname[--cwdindex] = SLASH; --- 300,308 ----- if(cdir.st_ino == pdir.st_ino) { didpwd = TRUE; + #if JOBS + closedir(pdfd); + #else close(pdfd); #endif if (cwdindex == (MAXPWD - 1)) *************** *** 224,229 { didpwd = TRUE; close(pdfd); if (cwdindex == (MAXPWD - 1)) cwdname[--cwdindex] = SLASH; --- 304,310 ----- closedir(pdfd); #else close(pdfd); + #endif if (cwdindex == (MAXPWD - 1)) cwdname[--cwdindex] = SLASH; *************** *** 235,240 { if ((dir = getdir(pdfd)) == 0) { close(pdfd); reset_dir(); error("pwd: read error in .."); --- 316,324 ----- { if ((dir = getdir(pdfd)) == 0) { + #if JOBS + closedir(pdfd); + #else close(pdfd); reset_dir(); #endif *************** *** 237,242 { close(pdfd); reset_dir(); error("pwd: read error in .."); } } --- 321,327 ----- #else close(pdfd); reset_dir(); + #endif error("pwd: read error in .."); } } *************** *** 244,250 } else { ! char name[512]; movstr(dot, name); i = length(name) - 1; --- 329,335 ----- } else { ! char name[256+MAXPWD]; /* DAG -- (was 512) */ movstr(dot, name); i = length(name) - 1; *************** *** 251,256 name[i++] = '/'; do { if ((dir = getdir(pdfd)) == 0) --- 336,342 ----- name[i++] = '/'; + tdir.st_dev = pdir.st_dev; /* DAG -- (safety) */ do { if ((dir = getdir(pdfd)) == 0) *************** *** 255,260 { if ((dir = getdir(pdfd)) == 0) { close(pdfd); reset_dir(); error("pwd: read error in .."); --- 341,349 ----- { if ((dir = getdir(pdfd)) == 0) { + #if JOBS + closedir(pdfd); + #else close(pdfd); reset_dir(); #endif *************** *** 257,262 { close(pdfd); reset_dir(); error("pwd: read error in .."); } *(movstrn(dir->d_name, &name[i], DIRSIZ)) = 0; --- 346,352 ----- #else close(pdfd); reset_dir(); + #endif error("pwd: read error in .."); } #if JOBS *************** *** 259,264 reset_dir(); error("pwd: read error in .."); } *(movstrn(dir->d_name, &name[i], DIRSIZ)) = 0; stat(name, &tdir); } --- 349,357 ----- #endif error("pwd: read error in .."); } + #if JOBS + movstr(dir->d_name, &name[i]); + #else *(movstrn(dir->d_name, &name[i], DIRSIZ)) = 0; #endif stat(name, &tdir); *************** *** 260,265 error("pwd: read error in .."); } *(movstrn(dir->d_name, &name[i], DIRSIZ)) = 0; stat(name, &tdir); } while(tdir.st_ino != cdir.st_ino || tdir.st_dev != cdir.st_dev); --- 353,359 ----- movstr(dir->d_name, &name[i]); #else *(movstrn(dir->d_name, &name[i], DIRSIZ)) = 0; + #endif stat(name, &tdir); } while(tdir.st_ino != cdir.st_ino || tdir.st_dev != cdir.st_dev); *************** *** 264,269 } while(tdir.st_ino != cdir.st_ino || tdir.st_dev != cdir.st_dev); } close(pdfd); reset_dir(); --- 358,366 ----- } while(tdir.st_ino != cdir.st_ino || tdir.st_dev != cdir.st_dev); } + #if JOBS + closedir(pdfd); + #else close(pdfd); reset_dir(); #endif *************** *** 266,271 } close(pdfd); reset_dir(); for (i = 0; i < DIRSIZ; i++) if (dir->d_name[i] == 0) --- 363,369 ----- #else close(pdfd); reset_dir(); + #endif #if JOBS i = dir->d_namlen; *************** *** 267,272 close(pdfd); reset_dir(); for (i = 0; i < DIRSIZ; i++) if (dir->d_name[i] == 0) break; --- 365,373 ----- reset_dir(); #endif + #if JOBS + i = dir->d_namlen; + #else for (i = 0; i < DIRSIZ; i++) if (dir->d_name[i] == 0) break; *************** *** 270,275 for (i = 0; i < DIRSIZ; i++) if (dir->d_name[i] == 0) break; if (i > cwdindex - 1) error(longpwd); --- 371,377 ----- for (i = 0; i < DIRSIZ; i++) if (dir->d_name[i] == 0) break; + #endif if (i > cwdindex - 1) error(longpwd); *************** *** 284,287 if (dot #define ARGMK 01 --- 8,17 ----- #include "defs.h" #include + #if JOBS + extern int errno; + #include "/usr/include/sys/wait.h" + #endif #define ARGMK 01 *************** *** 24,29 struct ionod *iop; int save; { register char *ion; register int iof, fd; int ioufd; --- 28,34 ----- struct ionod *iop; int save; { + extern long lseek(); /* DAG -- bug fix (was missing) */ register char *ion; register int iof, fd; int ioufd; *************** *** 70,75 else fd = dup(fd); } else if ((iof & IOPUT) == 0) fd = chkopen(ion); else if (flags & rshflg) --- 75,85 ----- else fd = dup(fd); } + else if (iof & IORDW) + { + if ((fd = open(ion, 2)) < 0) + failed(ion, badopen); + } else if ((iof & IOPUT) == 0) fd = chkopen(ion); else if (flags & rshflg) *************** *** 145,150 */ register char *scanp = path; register char *argp = locstak(); while (*scanp && *scanp != COLON) *argp++ = *scanp++; --- 155,162 ----- */ register char *scanp = path; register char *argp = locstak(); + char *save = argp; + char *cp; while (*scanp && *scanp != COLON) *argp++ = *scanp++; *************** *** 148,153 while (*scanp && *scanp != COLON) *argp++ = *scanp++; if (scanp != path) *argp++ = '/'; if (*scanp == COLON) --- 160,172 ----- while (*scanp && *scanp != COLON) *argp++ = *scanp++; + *argp = '\0'; + /* try a tilde expansion */ + if (*save == SQUIGGLE && (cp = homedir (save + 1)) != nullstr) + { + movstr (cp, save); + argp = save + length (save) - 1; + } if (scanp != path) *argp++ = '/'; if (*scanp == COLON) *************** *** 232,237 if (input) close(input); input = chkopen(p); #ifdef ACCT preacct(p); /* reset accounting */ --- 251,271 ----- if (input) close(input); input = chkopen(p); + #if JOBS + /* don't try to interpret directories etc. */ + { + #include + #include + struct stat sbuf; + + if (fstat(input, &sbuf) == 0 + && (sbuf.st_mode&S_IFMT) != S_IFREG) + { + close (input); + goto def; /* badexec unless other found */ + } + } + #endif #ifdef ACCT preacct(p); /* reset accounting */ *************** *** 254,259 failed(p, txtbsy); default: xecmsg = badexec; case ENOENT: return(prefix); --- 288,296 ----- failed(p, txtbsy); default: + #if JOBS + def: + #endif xecmsg = badexec; case ENOENT: return(prefix); *************** *** 268,273 static int pwlist[MAXP]; static int pwc; postclr() { register int *pw = pwlist; --- 305,355 ----- static int pwlist[MAXP]; static int pwc; + #if JOBS + static int *wf_pwlist; + static int wf_pwc; + + void + set_wfence() + { + wf_pwlist = &pwlist[pwc]; + wf_pwc = 0; + } + + BOOL + unpost(pcsid) + int pcsid; + { + register int *pw = pwlist; + + if (pcsid) + { + while (pw <= &pwlist[pwc]) + { + if (pcsid == *pw) + { + if (pw >= wf_pwlist) + wf_pwc--; + else + wf_pwlist--; + while (pw <= &pwlist[pwc]) + { + *pw = pw[1]; + pw++; + } + pw[pwc] = 0; + pwc--; + return TRUE; + } + pw++; + } + return FALSE; + } + else + return TRUE; + } + #endif + postclr() { register int *pw = pwlist; *************** *** 273,278 register int *pw = pwlist; while (pw <= &pwlist[pwc]) *pw++ = 0; pwc = 0; } --- 355,364 ----- register int *pw = pwlist; while (pw <= &pwlist[pwc]) + { + #if JOBS + j_child_clear(*pw); + #endif *pw++ = 0; } pwc = 0; *************** *** 274,279 while (pw <= &pwlist[pwc]) *pw++ = 0; pwc = 0; } --- 360,366 ----- j_child_clear(*pw); #endif *pw++ = 0; + } pwc = 0; } *************** *** 285,291 if (pcsid) { while (*pw) ! pw++; if (pwc >= MAXP - 1) pw--; else --- 372,383 ----- if (pcsid) { while (*pw) ! #if JOBS ! if (pcsid == *pw) ! return; ! else ! #endif ! pw++; if (pwc >= MAXP - 1) pw--; else *************** *** 289,294 if (pwc >= MAXP - 1) pw--; else pwc++; *pw = pcsid; } --- 381,387 ----- if (pwc >= MAXP - 1) pw--; else + { pwc++; #if JOBS wf_pwc++; *************** *** 290,295 pw--; else pwc++; *pw = pcsid; } } --- 383,392 ----- else { pwc++; + #if JOBS + wf_pwc++; + #endif + } *pw = pcsid; } } *************** *** 297,302 await(i, bckg) int i, bckg; { int rc = 0, wx = 0; int w; int ipwc = pwc; --- 394,404 ----- await(i, bckg) int i, bckg; { + #if JOBS + #include "/usr/include/sys/time.h" + #include "/usr/include/sys/resource.h" + struct rusage ru; + #endif int rc = 0, wx = 0; int w; int ipwc = pwc; *************** *** 300,305 int rc = 0, wx = 0; int w; int ipwc = pwc; post(i); while (pwc) --- 402,409 ----- int rc = 0, wx = 0; int w; int ipwc = pwc; + #if JOBS + BOOL update_only = i == -2; if (update_only) i = -1; *************** *** 301,307 int w; int ipwc = pwc; ! post(i); while (pwc) { register int p; --- 405,418 ----- #if JOBS BOOL update_only = i == -2; ! if (update_only) ! i = -1; ! if ((flags&jobflg) == 0 || i != -1) ! #endif ! post(i); ! #if JOBS ! while (pwc || (flags&jobflg)) ! #else while (pwc) #endif { *************** *** 303,308 post(i); while (pwc) { register int p; register int sig; --- 414,420 ----- while (pwc || (flags&jobflg)) #else while (pwc) + #endif { register int p; register int sig; *************** *** 310,315 int found = 0; { register int *pw = pwlist; p = wait(&w); --- 422,428 ----- int found = 0; { + #ifndef JOBS register int *pw = pwlist; #endif *************** *** 311,316 { register int *pw = pwlist; p = wait(&w); if (wasintr) --- 424,430 ----- { #ifndef JOBS register int *pw = pwlist; + #endif #if JOBS if (i == 0 && (flags&jobflg) && wf_pwc == 0) *************** *** 312,317 { register int *pw = pwlist; p = wait(&w); if (wasintr) { --- 426,447 ----- register int *pw = pwlist; #endif + #if JOBS + if (i == 0 && (flags&jobflg) && wf_pwc == 0) + break; + if ((pwc == 0 && (flags&jobflg)) || update_only) + { + if ((p = wait3(&w, WUNTRACED|WNOHANG, &ru)) == 0) + { + unpost (i); + break; + } + if (pwc == 0 && p == -1) + break; + } + else + p = wait3(&w, WUNTRACED, &ru); + #else p = wait(&w); #endif if (wasintr) *************** *** 313,318 register int *pw = pwlist; p = wait(&w); if (wasintr) { wasintr = 0; --- 443,449 ----- p = wait3(&w, WUNTRACED, &ru); #else p = wait(&w); + #endif if (wasintr) { wasintr = 0; *************** *** 321,326 break; } } while (pw <= &pwlist[ipwc]) { if (*pw == p) --- 452,462 ----- break; } } + + #if JOBS + if (unpost(p)) + found++; + #else while (pw <= &pwlist[ipwc]) { if (*pw == p) *************** *** 332,337 else pw++; } } if (p == -1) { --- 468,474 ----- else pw++; } + #endif } if (p == -1) { *************** *** 337,342 { if (bckg) { register int *pw = pwlist; while (pw <= &pwlist[ipwc] && i != *pw) --- 474,483 ----- { if (bckg) { + #if JOBS + j_child_clear(i); + unpost(i); + #else register int *pw = pwlist; while (pw <= &pwlist[ipwc] && i != *pw) *************** *** 346,351 *pw = 0; pwc--; } } continue; } --- 487,493 ----- *pw = 0; pwc--; } + #endif } continue; } *************** *** 354,360 { if (sig == 0177) /* ptrace! return */ { - prs("ptrace: "); sig = w_hi; } if (sysmsg[sig]) --- 496,501 ----- { if (sig == 0177) /* ptrace! return */ { sig = w_hi; #if JOBS if ((flags&jobflg) && *************** *** 356,361 { prs("ptrace: "); sig = w_hi; } if (sysmsg[sig]) { --- 497,512 ----- if (sig == 0177) /* ptrace! return */ { sig = w_hi; + #if JOBS + if ((flags&jobflg) && + (sig == SIGSTOP || sig == SIGTSTP || + sig == SIGTTOU || sig == SIGTTIN)) + { + j_child_stop(p, sig); + goto j_bypass; + } + #endif + prs("ptrace: "); } if (sysmsg[sig]) { *************** *** 371,376 } newline(); } if (rc == 0 && found != 0) rc = (sig ? sig | SIGFLG : w_hi); wx |= w; --- 522,558 ----- } newline(); } + #if JOBS + if (flags&infoflg) + { + register int k; + long l; + + prc('['); + l = ru.ru_utime.tv_sec * 1000000L + ru.ru_utime.tv_usec + + ru.ru_stime.tv_sec * 1000000L + ru.ru_stime.tv_usec; + prn((int)(l / 1000000)); /* integral seconds */ + k = (int)(l % 1000000L) / 1000; /* thousandths */ + prc('.'); + if (k < 100) + prc('0'); + if (k < 10) + prc('0'); + prn(k); + blank(); + prn((int)ru.ru_inblock); + blank(); + prn((int)ru.ru_oublock); + blank(); + prn((int)ru.ru_minflt); + blank(); + prn((int)ru.ru_majflt); + prc(']'); + newline(); + } + j_child_die(p); + j_bypass: + #endif if (rc == 0 && found != 0) rc = (sig ? sig | SIGFLG : w_hi); wx |= w; :::::::: setbrk.c ::::::: No differences encountered :::::::: sh.mk ::::::: *** ../orig.u/sh.mk Wed May 15 17:08:30 1985 --- sh.mk Wed May 29 16:28:26 1985 *************** *** 5,11 ROOT= INS = /etc/install -n $(ROOT)/bin INSDIR = ! CFLAGS = -O -DNICE -DACCT -DNICEVAL=4 LDFLAGS = -n -s OFILES = setbrk.o blok.o stak.o cmd.o fault.o main.o word.o string.o\ --- 5,11 ----- ROOT= INS = /etc/install -n $(ROOT)/bin INSDIR = ! CFLAGS = -O -DNICE -DNICEVAL=4 -DJOBS LDFLAGS = -n -s OFILES = setbrk.o blok.o stak.o cmd.o fault.o main.o word.o string.o\ *************** *** 10,15 OFILES = setbrk.o blok.o stak.o cmd.o fault.o main.o word.o string.o\ name.o args.o xec.o service.o error.o io.o print.o macro.o expand.o\ ctype.o msg.o test.o defs.o echo.o hash.o hashserv.o pwd.o func.o all: sh --- 10,17 ----- OFILES = setbrk.o blok.o stak.o cmd.o fault.o main.o word.o string.o\ name.o args.o xec.o service.o error.o io.o print.o macro.o expand.o\ + history.o homedir.o \ + jobs.o signal.o ulimit.o \ ctype.o msg.o test.o defs.o echo.o hash.o hashserv.o pwd.o func.o all: sh *************** *** 20,34 $(OFILES): defs.h $(FRC) ctype.o: ctype.h ! if [ "${_ID_}" ];\ ! then \ ! $(CC) $(CFLAGS) -c ctype.c; \ ! elif [ "${_SH_}" ]; \ ! then \ ! CC=$(CC) AS=$(AS) $(_SH_) ./:fix ctype; \ ! else \ ! CC=$(CC) AS=$(AS) sh ./:fix ctype; \ ! fi xec.o: xec.c set +e; if u370;\ --- 22,32 ----- $(OFILES): defs.h $(FRC) ctype.o: ctype.h ! $(CC) $(CFLAGS) -S ctype.c ! sed '/^[ ]*\.data/s/data/text/' < ctype.s > x.s ! mv x.s ctype.s ! $(AS) ctype.s -o ctype.o ! rm ctype.s xec.o: xec.c set +e; if u370;\ *************** *** 55,69 msg.o: msg.c $(FRC) ! if [ "${_ID_}" ];\ ! then \ ! $(CC) $(CFLAGS) -c msg.c; \ ! elif [ "${_SH_}" ]; \ ! then \ ! CC=$(CC) AS=$(AS) $(_SH_) ./:fix msg; \ ! else \ ! CC=$(CC) AS=$(AS) sh ./:fix msg; \ ! fi test: rtest $(TESTDIR)/sh --- 53,63 ----- msg.o: msg.c $(FRC) ! $(CC) $(CFLAGS) -S msg.c ! sed '/^[ ]*\.data/s/data/text/' < msg.s > x.s ! mv x.s msg.s ! $(AS) msg.s -o msg.o ! rm msg.s test: rtest $(TESTDIR)/sh :::::::: stak.c ::::::: No differences encountered :::::::: stak.h ::::::: No differences encountered :::::::: string.c ::::::: No differences encountered :::::::: sym.h ::::::: *** ../orig.u/sym.h Wed May 15 17:08:32 1985 --- sym.h Sun May 19 16:37:20 1985 *************** *** 45,47 #define ESCAPE '\\' #define BRACE '{' #define COMCHAR '#' --- 45,48 ----- #define ESCAPE '\\' #define BRACE '{' #define COMCHAR '#' + #define PERCENT '%' /* DAG -- useful addition */ :::::::: test.c ::::::: *** ../orig.u/test.c Wed May 15 17:08:33 1985 --- test.c Mon May 20 15:57:01 1985 *************** *** 126,131 if (eq(a, "-k")) return(ftype(nxtarg(0), S_ISVTX)); if (eq(a, "-p")) return(filtyp(nxtarg(0),S_IFIFO)); if (eq(a, "-s")) return(fsizep(nxtarg(0))); --- 126,134 ----- if (eq(a, "-k")) return(ftype(nxtarg(0), S_ISVTX)); if (eq(a, "-p")) + #if JOBS && !defined(pyr) + #define S_IFIFO S_IFSOCK /* fifo - map to socket on 4.2BSD */ + #endif return(filtyp(nxtarg(0),S_IFIFO)); if (eq(a, "-s")) return(fsizep(nxtarg(0))); :::::::: timeout.h ::::::: No differences encountered :::::::: word.c ::::::: *** ../orig.u/word.c Wed May 15 17:08:34 1985 --- word.c Thu Jun 6 14:37:41 1985 *************** *** 19,24 struct argnod *arg = (struct argnod *)locstak(); register char *argp = arg->argval; int alpha = 1; wdnum = 0; wdset = 0; --- 19,25 ----- struct argnod *arg = (struct argnod *)locstak(); register char *argp = arg->argval; int alpha = 1; + char *save; wdnum = 0; wdset = 0; *************** *** 23,28 wdnum = 0; wdset = 0; while (1) { while (c = nextc(0), space(c)) /* skipc() */ --- 24,30 ----- wdnum = 0; wdset = 0; + catcheof = TRUE; while (1) { while (c = nextc(0), space(c)) /* skipc() */ *************** *** 38,43 break; /* out of comment - white space loop */ } } if (!eofmeta(c)) { do --- 40,46 ----- break; /* out of comment - white space loop */ } } + save = argp; /* save start of word */ if (!eofmeta(c)) { do *************** *** 69,74 chkpr(); } } } } while ((c = nextc(0), !eofmeta(c))); argp = endstak(argp); --- 72,93 ----- chkpr(); } } + else if (c == SQUIGGLE && + validtilde (save, argp)) + { + char *name, *home; + + name = argp; + while ((c = nextc(0)) != '/' && + !eofmeta(c)) + *name++ = c; + peekc = c; + *name = '\0'; + home = homedir (argp); + if(*home) + movstr (home, --argp); + argp += length (argp) - 1; + } } } while ((c = nextc(0), !eofmeta(c))); argp = endstak(argp); *************** *** 117,122 wdval = EOFSYM; if (iopend && eolchar(c)) { copy(iopend); iopend = 0; } --- 136,144 ----- wdval = EOFSYM; if (iopend && eolchar(c)) { + int histon = (flags&nohistflg) == 0; + + flags |= nohistflg; /* no history for here docs */ copy(iopend); if (histon) /* turn history back on */ flags &= ~nohistflg; *************** *** 118,123 if (iopend && eolchar(c)) { copy(iopend); iopend = 0; } } --- 140,147 ----- flags |= nohistflg; /* no history for here docs */ copy(iopend); + if (histon) /* turn history back on */ + flags &= ~nohistflg; iopend = 0; } } *************** *** 121,126 iopend = 0; } } reserv = FALSE; return(wdval); } --- 145,151 ----- iopend = 0; } } + catcheof = FALSE; reserv = FALSE; return(wdval); } *************** *** 157,162 readc() { register char c; register int len; register struct fileblk *f; --- 182,188 ----- readc() { + static int eofcount = 0; /* to break endless catcheof loop */ register char c; register int len; register struct fileblk *f; *************** *** 200,209 } else if ((len = readb()) <= 0) { ! close(f->fdes); ! f->fdes = -1; ! c = EOF; ! f->feof++; } else { --- 226,260 ----- } else if ((len = readb()) <= 0) { ! if (catcheof ! #if JOBS ! && (flags&(ttyflg|prompt|dotflg)) == (ttyflg|prompt) ! && ((flags&noeotflg) || j_finish(FALSE)) ! #else ! && (flags&(ttyflg|prompt|noeotflg|dotflg)) == (ttyflg|prompt|noeotflg) ! #endif ! && ++eofcount < 10) /* in case terminal is disconnected */ ! { ! #if JOBS ! if ((flags&(ttyflg|prompt|noeotflg)) ! == (ttyflg|prompt|noeotflg)) ! #endif ! prs ("use \"exit\"\n"); ! #if JOBS ! /* else "there are stopped jobs" was printed */ ! #endif ! c = NL; ! } ! else ! { ! close(f->fdes); ! f->fdes = -1; ! c = EOF; ! f->feof++; ! #if JOBS ! j_finish(TRUE); ! #endif ! } } else { *************** *** 207,213 } else { ! f->fend = (f->fnxt = f->fbuf) + len; goto retry; } return(c); --- 258,265 ----- } else { ! f->fend = f->fnxt + len; ! eofcount = 0; goto retry; } return(c); *************** *** 214,220 } static ! readb() { register struct fileblk *f = standin; register int len; --- 266,272 ----- } static ! readblock () /* ADR -- changed the name */ { register struct fileblk *f = standin; register int len; *************** *** 234,237 } } while ((len = read(f->fdes, f->fbuf, f->fsiz)) < 0 && trapnote); return(len); } --- 286,486 ----- } } while ((len = read(f->fdes, f->fbuf, f->fsiz)) < 0 && trapnote); return(len); + } + + /* readb --- read a block from the outside world, and history process it */ + + /* + * In BSD systems, using the literal next capability of the tty driver, it + * is actually possible to put a newline in the middle of the input line, + * and then hit return, so that the shell sees two lines of input. + * + * As a design decision, if there is a \n in the middle of what we've read + * from a terminal, treat the commands as two separately typed commands. I.e. + * + * echo hi ^J echo there + * + * is the same as + * + * echo hi + * echo there + * + * The major reason for doing it this way is that the history mechanism knows + * that a \n is the end of a line. + * + * Finally, on USG systems, we just leave this code alone, since it won't + * get executed anyway. + */ + + /* + * In word.c, the readc() function keeps a pointer to what standin pointed to + * when readc first gets called. Therefore, where standin points to can not + * not change across calls to readb(). To get around this, we change the + * contents of the structure pointed to by standin, saving and restoring + * it as necessary. + */ + + #define LARGEBUF (HISTSIZE / 2) /* size of expanded history */ + + static + readb() + { + int ilen, i, j; + char ibuf[BUFSIZ]; /* input into scratch area, pass to history */ + static char expansion[LARGEBUF]; + static int moreinbuf = FALSE; + static int saved_ilen = 0; + static int start_here = 0; + static struct fileblk *f = 0; + auto int gotoutofbuf = 0; + + if (expanded) /* just did a history substitution */ + expanded = 0; + + if ((flags & nohistflg) || (flags & prompt) == 0 || ! isatty (input) + || standin->fstak != 0) + { + ilen = readblock (); + if (ilen > 0) + standin->fnxt = standin->fbuf; + return (ilen); + /* not doing history expansion at all */ + } + + if (f == 0) + f = standin; + + ilen = 0; + + /* + * First, if there was more stuff in the last buffer, go and get it. + * If not get some more from the outside world. + * + * Then, make sure we've read up to a newline. + * This is basically in case someone has done something bizarre + * like 'stty raw', and input is coming in one character at a time. + * + * We use a heuristic. If amount read is just 1, keep reading till + * we get a newline. Else, read in a complete line from the terminal. + * Once we're in raw mode, can't reset it until a newline is typed. + * + * If not reading one character at a time, then do the stuff for + * embedded newlines. + */ + + if (moreinbuf) + { + for (i = 0, j = start_here; f->fbuf[j] != NL && j < saved_ilen; i++, j++) + ibuf[i] = f->fbuf[j]; + + #ifdef notdef + if (f->fbuf[j] != NL) + { + prs ("internal i/o error C in readb\n"); + return (0); + } + #endif + + if (f->fbuf[j] == NL) + ibuf[i++] = NL; + ibuf[i] = '\0'; + ilen = i; + /* embedded newline */ + moreinbuf = (++j < saved_ilen - 1); + if (moreinbuf) + start_here = j; /* where to start next time */ + gotoutofbuf = 1; + } + else /* wasn't an embedded \n last time */ + { + ilen = readblock (); + + if (ilen <= 0) /* EOF or error */ + return (ilen); + + if (ilen == 1) /* either in raw mode, or an empty line */ + { + i = 0; + ibuf[i++] = f->fbuf[0]; + if (f->fbuf[0] == NL) + { + ibuf[i] = '\0'; + goto dohist; + } + + while ((ilen = readblock()) > 0) + { + if (ilen != 1) + { + prs ("internal i/o error A in readb\n"); + return (0); + } + ibuf[i++] = f->fbuf[0]; + if (f->fbuf[0] == NL) + { + ibuf[i] = '\0'; + break; /* while */ + } + } + ilen = i; + gotoutofbuf = TRUE; + /* force code below to use collected string */ + } + else + { + /* reading bunches of characters at once */ + for (i = 0; f->fbuf[i] != NL && i < ilen; i++) + ibuf[i] = f->fbuf[i]; + + #ifdef notdef + if (f->fbuf[i] != NL) + { + prs ("internal i/o error B in readb\n"); + return (0); + } + #endif + + ibuf[i++] = NL; + ibuf[i] = '\0'; + /* ilen was set by readblock() */ + /* embedded newline */ + moreinbuf = (i < ilen - 1); + if (moreinbuf) + { + saved_ilen = ilen; + start_here = i; + /* where to start next time */ + gotoutofbuf = 1; + } + } + } + + dohist: + /* quick heuristic */ + if (! gotoutofbuf && ilen == 1 && f->fbuf[0] == NL) + { + f->fnxt = f->fbuf; + return (ilen); + } + + if (histsub (ibuf, expansion, sizeof expansion)) + { + int olen = length (expansion) - 1; + if (! expanded && ! gotoutofbuf) + { + standin->fnxt = standin->fbuf; + return (ilen); + } + /* else + expanded == TRUE or from buffer */ + standin->fnxt = expansion; + return (olen); + } + else + { + /* hist expansion failed, return an empty line */ + standin->fnxt = standin->fbuf; + standin->fbuf[0] = NL; + return (1); + } } :::::::: xec.c ::::::: *** ../orig.u/xec.c Wed May 15 17:08:37 1985 --- xec.c Wed Jun 5 11:11:18 1985 *************** *** 27,32 */ register struct trenod *t; char *sav = savstak(); sigchk(); if (!errorflg) --- 27,42 ----- */ register struct trenod *t; char *sav = savstak(); + #if pyr + auto int change_univ = FALSE; + auto int new_univ = 0; + /* + * univesrses run from 1 to NUMUNIV: We start out at 0 + * and increment new_univ in the switch for internal + * commands, below. new_univ must *not* be assigned to, directly + * or via side effects, any place else. + */ + #endif sigchk(); if (!errorflg) *************** *** 109,114 if (flags & execpr) execprint(com); if (comtype == NOTFOUND) { pos = hashdata(cmdhash); --- 119,130 ----- if (flags & execpr) execprint(com); + /* + * fix a bug which caused the shell + * to do not do a second command if + * the first was not found. (bug fix + * from USENET) + */ if (comtype == NOTFOUND) { char *errstr; *************** *** 111,116 if (comtype == NOTFOUND) { pos = hashdata(cmdhash); if (pos == 1) failed(*com, notfound); --- 127,134 ----- */ if (comtype == NOTFOUND) { + char *errstr; + pos = hashdata(cmdhash); if (pos == 1) errstr = notfound; *************** *** 113,119 { pos = hashdata(cmdhash); if (pos == 1) ! failed(*com, notfound); else if (pos == 2) failed(*com, badexec); else --- 131,137 ----- pos = hashdata(cmdhash); if (pos == 1) ! errstr = notfound; else if (pos == 2) errstr = badexec; else *************** *** 115,121 if (pos == 1) failed(*com, notfound); else if (pos == 2) ! failed(*com, badexec); else failed(*com, badperm); break; --- 133,139 ----- if (pos == 1) errstr = notfound; else if (pos == 2) ! errstr = badexec; else errstr = badperm; prp(); *************** *** 117,123 else if (pos == 2) failed(*com, badexec); else ! failed(*com, badperm); break; } --- 135,147 ----- else if (pos == 2) errstr = badexec; else ! errstr = badperm; ! prp(); ! prs_cntl(*com); ! prs (colon); ! prs (errstr); ! newline(); ! exitval = 1; break; } *************** *** 148,153 if ((f = pathopen(getpath(a1), a1)) < 0) failed(a1, notfound); else execexp(0, f); } break; --- 172,181 ----- if ((f = pathopen(getpath(a1), a1)) < 0) failed(a1, notfound); else + { + int savedot = flags&dotflg; + + flags |= dotflg; execexp(0, f); flags &= ~dotflg; flags |= savedot; *************** *** 149,154 failed(a1, notfound); else execexp(0, f); } break; --- 177,185 ----- flags |= dotflg; execexp(0, f); + flags &= ~dotflg; + flags |= savedot; + } } break; *************** *** 163,169 prc_buff(NL); } break; ! case SYSEXIT: flags |= forked; /* force exit */ exitsh(a1 ? stoi(a1) : retval); --- 194,200 ----- prc_buff(NL); } break; ! case SYSEXIT: #if JOBS if (j_finish(FALSE)) *************** *** 165,170 break; case SYSEXIT: flags |= forked; /* force exit */ exitsh(a1 ? stoi(a1) : retval); --- 196,207 ----- break; case SYSEXIT: + #if JOBS + if (j_finish(FALSE)) + break; + #endif + histsave (histfnod.namval); + /* save before setting flag */ flags |= forked; /* force exit */ exitsh(a1 ? stoi(a1) : retval); *************** *** 166,171 case SYSEXIT: flags |= forked; /* force exit */ exitsh(a1 ? stoi(a1) : retval); case SYSNULL: --- 203,209 ----- histsave (histfnod.namval); /* save before setting flag */ flags |= forked; /* force exit */ + exitsh(a1 ? stoi(a1) : retval); case SYSNULL: *************** *** 248,256 } #ifdef RES /* Research includes login as part of the shell */ ! ! case SYSLOGIN: ! oldsigs(); execa(com, -1); done(); #else --- 286,296 ----- } #ifdef RES /* Research includes login as part of the shell */ ! ! case SYSLOGIN: ! histsave (histfnod.namval); ! flags |= forked; /* DAG -- bug fix (force bad exec to terminate shell) */ ! oldsigs(); execa(com, -1); done(); #else *************** *** 252,260 case SYSLOGIN: oldsigs(); execa(com, -1); ! done(); ! #else ! case SYSNEWGRP: if (flags & rshflg) failed(com[0], restricted); --- 292,299 ----- flags |= forked; /* DAG -- bug fix (force bad exec to terminate shell) */ oldsigs(); execa(com, -1); ! done(); ! #else case SYSNEWGRP: if (flags & rshflg) failed(com[0], restricted); *************** *** 260,265 failed(com[0], restricted); else { flags |= forked; /* force bad exec to terminate shell */ oldsigs(); execa(com, -1); --- 299,305 ----- failed(com[0], restricted); else { + histsave (histfnod.namval); flags |= forked; /* force bad exec to terminate shell */ oldsigs(); execa(com, -1); *************** *** 266,272 done(); } ! #endif case SYSCD: if (flags & rshflg) --- 306,312 ----- done(); } ! #endif case SYSCD: if (flags & rshflg) *************** *** 273,278 failed(com[0], restricted); else if ((a1 && *a1) || (a1 == 0 && (a1 = homenod.namval))) { char *cdpath; char *dir; int f; --- 313,319 ----- failed(com[0], restricted); else if ((a1 && *a1) || (a1 == 0 && (a1 = homenod.namval))) { + register char *safe; /* DAG -- added (see note, below) */ char *cdpath; char *dir; int f; *************** *** 279,286 if ((cdpath = cdpnod.namval) == 0 || *a1 == '/' || ! cf(a1, ".") == 0 || ! cf(a1, "..") == 0 || (*a1 == '.' && (*(a1+1) == '/' || *(a1+1) == '.' && *(a1+2) == '/'))) cdpath = nullstr; --- 320,327 ----- if ((cdpath = cdpnod.namval) == 0 || *a1 == '/' || ! cf(a1, ".") == 0 || ! cf(a1, "..") == 0 || (*a1 == '.' && (*(a1+1) == '/' || *(a1+1) == '.' && *(a1+2) == '/'))) cdpath = nullstr; *************** *** 284,289 (*a1 == '.' && (*(a1+1) == '/' || *(a1+1) == '.' && *(a1+2) == '/'))) cdpath = nullstr; do { dir = cdpath; --- 325,337 ----- (*a1 == '.' && (*(a1+1) == '/' || *(a1+1) == '.' && *(a1+2) == '/'))) cdpath = nullstr; + /* DAG -- catpath() leaves the trial directory above the top of the "stack". + This is too dangerous; systems using directory access routines may + alloc() storage and clobber the string. Therefore I have changed the + code to alloc() a safe place to put the trial strings. Most of the + changes involved replacing "curstak()" with "safe". + */ safe = alloc((unsigned)(length(cdpath) + length(a1))); /* DAG -- added */ + do { dir = cdpath; *************** *** 288,293 { dir = cdpath; cdpath = catpath(cdpath,a1); } while ((f = (chdir(curstak()) < 0)) && cdpath); --- 336,342 ----- { dir = cdpath; cdpath = catpath(cdpath,a1); + (void)movstr(curstak(),safe); /* DAG -- added (see note, above) */ } #if !defined(SYMLINK) && defined(JOBS) while ((f = (cwdir(safe) < 0)) && cdpath); /* DAG */ *************** *** 289,295 dir = cdpath; cdpath = catpath(cdpath,a1); } ! while ((f = (chdir(curstak()) < 0)) && cdpath); if (f) failed(a1, baddir); --- 338,348 ----- cdpath = catpath(cdpath,a1); (void)movstr(curstak(),safe); /* DAG -- added (see note, above) */ } ! #if !defined(SYMLINK) && defined(JOBS) ! while ((f = (cwdir(safe) < 0)) && cdpath); /* DAG */ ! #else ! while ((f = (chdir(safe) < 0)) && cdpath); /* DAG */ ! #endif if (f) { *************** *** 292,297 while ((f = (chdir(curstak()) < 0)) && cdpath); if (f) failed(a1, baddir); else { --- 345,352 ----- #endif if (f) + { + free(safe); /* DAG -- added (see note, above) */ failed(a1, baddir); } else *************** *** 293,298 if (f) failed(a1, baddir); else { cwd(curstak()); --- 348,354 ----- { free(safe); /* DAG -- added (see note, above) */ failed(a1, baddir); + } else { #if defined(SYMLINK) || !defined(JOBS) *************** *** 295,301 failed(a1, baddir); else { ! cwd(curstak()); if (cf(nullstr, dir) && *dir != ':' && any('/', curstak()) && --- 351,359 ----- } else { ! #if defined(SYMLINK) || !defined(JOBS) ! cwd(safe); /* DAG */ ! #endif if (cf(nullstr, dir) && *dir != ':' && any('/', safe) && /* DAG */ *************** *** 298,304 cwd(curstak()); if (cf(nullstr, dir) && *dir != ':' && ! any('/', curstak()) && flags & prompt) { prs_buff(curstak()); --- 356,362 ----- #endif if (cf(nullstr, dir) && *dir != ':' && ! any('/', safe) && /* DAG */ flags & prompt) cwdprint(); /* DAG -- improvement */ free(safe); /* DAG -- added (see note, above) */ *************** *** 300,309 *dir != ':' && any('/', curstak()) && flags & prompt) ! { ! prs_buff(curstak()); ! prc_buff(NL); ! } } zapcd(); } --- 358,365 ----- *dir != ':' && any('/', safe) && /* DAG */ flags & prompt) ! cwdprint(); /* DAG -- improvement */ ! free(safe); /* DAG -- added (see note, above) */ } zapcd(); } *************** *** 452,458 if (command == 1 || command == 4) { prl(i); ! prc_buff('\n'); } break; } --- 508,514 ----- if (command == 1 || command == 4) { prl(i); ! prc_buff(NL); } break; } *************** *** 478,486 prc_buff(NL); } break; ! ! #endif ! case SYSTST: exitval = test(argn, com); break; --- 534,540 ----- prc_buff(NL); } break; ! case SYSTST: exitval = test(argn, com); break; *************** *** 484,489 case SYSTST: exitval = test(argn, com); break; case SYSECHO: exitval = echo(argn, com); --- 538,544 ----- case SYSTST: exitval = test(argn, com); break; + #endif /* RES (DAG -- bug fix: SYSTST not in RES) */ case SYSECHO: exitval = echo(argn, com); *************** *** 548,553 } break; default: prs_buff("unknown builtin\n"); } --- 603,675 ----- } break; + #if JOBS + case SYSJOBS: + + j_print(); + break; + + case SYSFG: + + j_resume(a1, FALSE); + break; + + case SYSBG: + + j_resume(a1, TRUE); + break; + + case SYSSUSPEND: + exitval = 1; + if (getppid() == 1) + prs ("cannot suspend a login shell\n"); /* yet ... */ + else + { + exitval = 0; + kill (getpid(), SIGSTOP); + } + break; + #endif + + #if pyr + /* + * UCB is Universe 2 + * ATT is Universe 1 + * new_univ == 0 + */ + case SYSUCB: + new_univ++; + /* fall thru */ + case SYSATT: + new_univ++; + if (argn > 1) + { + change_univ = TRUE; + com++; + goto doit; + } + else + { + setuniverse (cur_univ = new_univ); + univnod.namflg &= ~N_RDONLY; + assign (& univnod, univ_name[cur_univ - 1]); + attrib ((& univnod), N_RDONLY); + break; + } + + case SYSUNIVERSE: + if (eq(com[1], "-l")) + prs_buff (univ_longname[cur_univ - 1]); + else + prs_buff (univ_name[cur_univ - 1]); + prc_buff (NL); + break; + #endif + + case SYSHISTORY: + exitval = history (argn, com); + break; + default: prs_buff("unknown builtin\n"); } *************** *** 586,591 } case TFORK: exitval = 0; if (execflg && (treeflgs & (FAMP | FPOU)) == 0) parent = 0; --- 708,716 ----- } case TFORK: + #if pyr + doit: + #endif exitval = 0; if (execflg && (treeflgs & (FAMP | FPOU)) == 0) parent = 0; *************** *** 625,630 alarm(forkcnt); pause(); } } if (parent) { --- 750,759 ----- alarm(forkcnt); pause(); } + #if JOBS + if (parent == 0) + j_top_level = FALSE; + #endif } if (parent) { *************** *** 633,638 * it may or may not wait for the child */ if (treeflgs & FPRS && flags & ttyflg) { prn(parent); newline(); --- 762,770 ----- * it may or may not wait for the child */ if (treeflgs & FPRS && flags & ttyflg) + #if JOBS + if ((flags&jobflg) == 0) + #endif { prn(parent); newline(); *************** *** 639,644 } if (treeflgs & FPCL) closepipe(pf1); if ((treeflgs & (FAMP | FPOU)) == 0) await(parent, 0); else if ((treeflgs & FAMP) == 0) --- 771,779 ----- } if (treeflgs & FPCL) closepipe(pf1); + #if JOBS + j_child_post(parent, treeflgs&FAMP, treeflgs&FPIN, t); + #endif if ((treeflgs & (FAMP | FPOU)) == 0) { await(parent, 0); *************** *** 640,645 if (treeflgs & FPCL) closepipe(pf1); if ((treeflgs & (FAMP | FPOU)) == 0) await(parent, 0); else if ((treeflgs & FAMP) == 0) post(parent); --- 775,781 ----- j_child_post(parent, treeflgs&FAMP, treeflgs&FPIN, t); #endif if ((treeflgs & (FAMP | FPOU)) == 0) + { await(parent, 0); #if JOBS j_reset_pg(); *************** *** 641,646 closepipe(pf1); if ((treeflgs & (FAMP | FPOU)) == 0) await(parent, 0); else if ((treeflgs & FAMP) == 0) post(parent); else --- 777,786 ----- if ((treeflgs & (FAMP | FPOU)) == 0) { await(parent, 0); + #if JOBS + j_reset_pg(); + #endif + } else if ((treeflgs & FAMP) == 0) post(parent); else *************** *** 650,655 } else /* this is the forked branch (child) of execute */ { flags |= forked; fiotemp = 0; --- 790,805 ----- } else /* this is the forked branch (child) of execute */ { + #if pyr + if (change_univ) + { + setuniverse (new_univ); + univnod.namflg &= ~N_RDONLY; + assign (& univnod, univ_name[cur_univ - 1]); + attrib ((& univnod), N_RDONLY); + } + #endif + flags |= forked; fiotemp = 0; *************** *** 674,679 */ oldsigs(); if (treeflgs & FINT) { signal(SIGINT, 1); signal(SIGQUIT, 1); --- 824,832 ----- */ oldsigs(); if (treeflgs & FINT) + #if JOBS + if ((flags&jobflg) == 0) + #endif { signal(SIGINT, SIG_IGN); /* DAG */ signal(SIGQUIT, SIG_IGN); /* DAG */ *************** *** 675,682 oldsigs(); if (treeflgs & FINT) { ! signal(SIGINT, 1); ! signal(SIGQUIT, 1); #ifdef NICE nice(NICEVAL); --- 828,835 ----- if ((flags&jobflg) == 0) #endif { ! signal(SIGINT, SIG_IGN); /* DAG */ ! signal(SIGQUIT, SIG_IGN); /* DAG */ #ifdef NICE nice(NICEVAL); *************** *** 700,705 * default std input for & */ if (treeflgs & FINT && ioset == 0) rename(chkopen(devnull), 0); /* * io redirection --- 853,861 ----- * default std input for & */ if (treeflgs & FINT && ioset == 0) + #if JOBS + if ((flags&jobflg) == 0) + #endif rename(chkopen(devnull), 0); /* * io redirection