home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume1 / bourne / part6 < prev    next >
Internet Message Format  |  1986-11-30  |  63KB

  1. Date: Fri, 7 Jun 85 14:11:11 edt
  2. From: Arnold Robbins <gatech!arnold>
  3. Subject: Bourne shell history + tilde + job control + more (Part 6 of 9)
  4. Newsgroups: mod.sources
  5.  
  6. This is part 6 of 9.  It contains the second set of code diffs for the System V
  7. Release 2 Bourne shell.
  8.  
  9. BSD users who happen to also have source for System V Release 2 will probably
  10. want to use this version of the shell, since it has many bug fixes and
  11. improvements over the (much) earlier version that comes with Berkeley Unix.
  12.  
  13. Arnold Robbins
  14. arnold@gatech.{UUCP, CSNET}
  15. ----------- pretend your screen is really a paper towel ------------
  16. :::::::: name.c :::::::
  17. *** ../orig.u/name.c    Wed May 15 17:08:24 1985
  18. --- name.c    Tue May 21 19:02:42 1985
  19. ***************
  20. *** 15,21
  21.   struct namnod ps2nod =
  22.   {
  23.       (struct namnod *)NIL,
  24. !     &acctnod,
  25.       ps2name
  26.   };
  27.   struct namnod cdpnod = 
  28.  
  29. --- 15,21 -----
  30.   struct namnod ps2nod =
  31.   {
  32.       (struct namnod *)NIL,
  33. !     (struct namnod *)NIL,
  34.       ps2name
  35.   };
  36.   struct namnod cdpnod = 
  37. ***************
  38. *** 32,38
  39.   };
  40.   struct namnod ifsnod =
  41.   {
  42. !     &homenod,
  43.       &mailnod,
  44.       ifsname
  45.   };
  46.  
  47. --- 32,38 -----
  48.   };
  49.   struct namnod ifsnod =
  50.   {
  51. !     &histfnod,
  52.       &mailnod,
  53.       ifsname
  54.   };
  55. ***************
  56. *** 39,45
  57.   struct namnod ps1nod =
  58.   {
  59.       &pathnod,
  60. !     &ps2nod,
  61.       ps1name
  62.   };
  63.   struct namnod homenod =
  64.  
  65. --- 39,45 -----
  66.   struct namnod ps1nod =
  67.   {
  68.       &pathnod,
  69. !     &acctnod,
  70.       ps1name
  71.   };
  72.   struct namnod homenod =
  73. ***************
  74. *** 44,50
  75.   };
  76.   struct namnod homenod =
  77.   {
  78. -     &cdpnod,
  79.       (struct namnod *)NIL,
  80.       homename
  81.   };
  82.  
  83. --- 44,49 -----
  84.   };
  85.   struct namnod homenod =
  86.   {
  87.       (struct namnod *)NIL,
  88.       (struct namnod *)NIL,
  89.       homename
  90. ***************
  91. *** 46,51
  92.   {
  93.       &cdpnod,
  94.       (struct namnod *)NIL,
  95.       homename
  96.   };
  97.   struct namnod mailnod =
  98.  
  99. --- 45,51 -----
  100.   struct namnod homenod =
  101.   {
  102.       (struct namnod *)NIL,
  103. +     (struct namnod *)NIL,
  104.       homename
  105.   };
  106.   struct namnod mailnod =
  107. ***************
  108. *** 62,67
  109.   };
  110.   struct namnod acctnod =
  111.   {
  112.       (struct namnod *)NIL,
  113.       (struct namnod *)NIL,
  114.       acctname
  115.  
  116. --- 62,71 -----
  117.   };
  118.   struct namnod acctnod =
  119.   {
  120. +     &ps2nod,
  121. + #if pyr
  122. +     &univnod,
  123. + #else
  124.       (struct namnod *)NIL,
  125.   #endif
  126.       acctname
  127. ***************
  128. *** 63,69
  129.   struct namnod acctnod =
  130.   {
  131.       (struct namnod *)NIL,
  132. !     (struct namnod *)NIL,
  133.       acctname
  134.   };
  135.   struct namnod mailpnod =
  136.  
  137. --- 67,73 -----
  138.       &univnod,
  139.   #else
  140.       (struct namnod *)NIL,
  141. ! #endif
  142.       acctname
  143.   };
  144.   struct namnod mailpnod =
  145. ***************
  146. *** 72,77
  147.       (struct namnod *)NIL,
  148.       mailpname
  149.   };
  150.   
  151.   
  152.   struct namnod *namep = &mchknod;
  153.  
  154. --- 76,95 -----
  155.       (struct namnod *)NIL,
  156.       mailpname
  157.   };
  158. + struct namnod histfnod =
  159. + {
  160. +     &cdpnod,
  161. +     &homenod,
  162. +     histfilename
  163. + };
  164. + #if pyr
  165. + struct namnod univnod =
  166. + {
  167. +     (struct namnod *)NIL,
  168. +     (struct namnod *)NIL,
  169. +     univname
  170. + };
  171. + #endif
  172.   
  173.   
  174.   struct namnod *namep = &mchknod;
  175. ***************
  176. *** 86,91
  177.       int    low;
  178.       int    high;
  179.       int    mid;
  180.       register int cond;
  181.   
  182.       if (w == 0 || *w == 0)
  183.  
  184. --- 104,112 -----
  185.       int    low;
  186.       int    high;
  187.       int    mid;
  188. + #if gould
  189. +     int    cond;    /* DAG -- avoid optimizer bug */
  190. + #else
  191.       register int cond;
  192.   #endif
  193.   
  194. ***************
  195. *** 87,92
  196.       int    high;
  197.       int    mid;
  198.       register int cond;
  199.   
  200.       if (w == 0 || *w == 0)
  201.           return(0);
  202.  
  203. --- 108,114 -----
  204.       int    cond;    /* DAG -- avoid optimizer bug */
  205.   #else
  206.       register int cond;
  207. + #endif
  208.   
  209.       if (w == 0 || *w == 0)
  210.           return(0);
  211. ***************
  212. *** 228,233
  213.   readvar(names)
  214.   char    **names;
  215.   {
  216.       struct fileblk    fb;
  217.       register struct fileblk *f = &fb;
  218.       register char    c;
  219.  
  220. --- 250,256 -----
  221.   readvar(names)
  222.   char    **names;
  223.   {
  224. +     extern long lseek();    /* DAG -- bug fix (was missing) */
  225.       struct fileblk    fb;
  226.       register struct fileblk *f = &fb;
  227.       register char    c;
  228. ***************
  229. *** 238,244
  230.       push(f);
  231.       initf(dup(0));
  232.   
  233. !     if (lseek(0, 0L, 1) == -1)
  234.           f->fsiz = 1;
  235.   
  236.       /*
  237.  
  238. --- 261,267 -----
  239.       push(f);
  240.       initf(dup(0));
  241.   
  242. !     if (lseek(0, 0L, 1) == -1L)    /* DAG */
  243.           f->fsiz = 1;
  244.   
  245.       /*
  246. :::::::: name.h :::::::
  247. No differences encountered
  248. :::::::: print.c :::::::
  249. *** ../orig.u/print.c    Wed May 15 17:08:25 1985
  250. --- print.c    Mon May 20 15:32:21 1985
  251. ***************
  252. *** 7,12
  253.    */
  254.   
  255.   #include    "defs.h"
  256.   #include    <sys/param.h>
  257.   
  258.   #define        BUFLEN        256
  259.  
  260. --- 7,15 -----
  261.    */
  262.   
  263.   #include    "defs.h"
  264. + #if JOBS
  265. + #define        HZ    60
  266. + #else
  267.   #include    <sys/param.h>
  268.   #endif
  269.   
  270. ***************
  271. *** 8,13
  272.   
  273.   #include    "defs.h"
  274.   #include    <sys/param.h>
  275.   
  276.   #define        BUFLEN        256
  277.   
  278.  
  279. --- 11,17 -----
  280.   #define        HZ    60
  281.   #else
  282.   #include    <sys/param.h>
  283. + #endif
  284.   
  285.   #define        BUFLEN        256
  286.   
  287. ***************
  288. *** 66,73
  289.           prc_buff('h');
  290.       }
  291.   
  292. !     prn_buff(min);
  293. !     prc_buff('m');
  294.       prn_buff(sec);
  295.       prc_buff('s');
  296.   }
  297.  
  298. --- 70,80 -----
  299.           prc_buff('h');
  300.       }
  301.   
  302. !     if (min)    /* BRL... for consistency */
  303. !     {
  304. !         prn_buff(min);
  305. !         prc_buff('m');
  306. !     }
  307.       prn_buff(sec);
  308.       prc_buff('s');
  309.   }
  310. ***************
  311. *** 230,233
  312.       itos(n);
  313.   
  314.       prs_buff(numbuf);
  315.   }
  316.  
  317. --- 237,357 -----
  318.       itos(n);
  319.   
  320.       prs_buff(numbuf);
  321. + }
  322. + void
  323. + pr_prompt (str)
  324. + register char *str;
  325. + {
  326. +     for (; *str; str++)
  327. +     {
  328. +         if (*str != '%')
  329. +             prc_buff (*str);
  330. +         else if (*(str+1) == 'd')
  331. +         {
  332. +             /* current directory */
  333. +             str++;
  334. +             prs_buff (retcwd());
  335. +         }
  336. +         else if (*(str+1) == 'e')
  337. +         {
  338. +             /* event count */
  339. +             str++;
  340. +             if ((flags & nohistflg) == 0)
  341. +                 prn_buff (event_count);
  342. +         }
  343. +         else if (*(str+1) == 'h')
  344. +         {
  345. +             /* hostname */
  346. +             static char *cp = 0;
  347. +             static int didhost = FALSE;
  348. +             static int didgt = FALSE;
  349. + #ifdef JOBS
  350. +             static char buf[257];
  351. +             if (! didhost)
  352. +             {
  353. +                 gethostname (buf, sizeof buf);
  354. +                 didhost = TRUE;
  355. +                 cp = buf;
  356. +             }
  357. + #else
  358. + #include <sys/utsname.h>    /* has an extern declaration in it */
  359. +             static struct utsname name;
  360. +             if (! didhost)
  361. +             {
  362. +                 uname (& name);
  363. +                 /* avoid emulation bug */
  364. +                 name.sysname[sizeof(name.sysname)-1] = '\0';
  365. +                 didhost = TRUE;
  366. +                 cp = name.sysname;
  367. +             }
  368. + #endif
  369. + #ifdef GATECH
  370. +             /*
  371. +              * this is to get rid of the dumb gt- convention.
  372. +              * a gt w/out the - is also removed.
  373. +              */
  374. +             if (! didgt)
  375. +             {
  376. +                 didgt = TRUE;
  377. +                 if (cp[0] == 'g' && cp[1] == 't' && cp[2])
  378. +                 {
  379. +                     cp += 2;
  380. +                     if (cp[0] == '-' && cp[1])
  381. +                         cp++;
  382. +                 }
  383. +             }
  384. + #endif
  385. +             prs_buff (cp);
  386. +             str++;
  387. +         }
  388. +         else if (*(str+1) == 'l')
  389. +         {
  390. +             /* login name */
  391. +             static char *cp = 0;
  392. +             static int didname = FALSE;
  393. +             str++;
  394. +             if (! didname)
  395. +             {
  396. +                 cp = username ();
  397. +                 didname = TRUE;
  398. +             }
  399. +             if (cp)
  400. +                 prs_buff (cp);
  401. +         }
  402. +         else if (*(str+1) == 't')
  403. +         {
  404. +             /* current time, HH:MM */
  405. +             long l;
  406. +             char *cp, *ctime ();
  407. +             str++;
  408. +             time (& l);
  409. +             cp = ctime (& l);
  410. +             cp[16] = '\0';
  411. +             cp += 11;
  412. +             prs_buff (cp);
  413. +         }
  414. + #if pyr
  415. +         else if (*(str+1) == 'u')
  416. +         {
  417. +             /* current univeserse */
  418. +             str++;
  419. +             prs_buff (univ_name[cur_univ-1]);
  420. +         }
  421. + #endif
  422. +         else if (*(str+1) == '\0')    /* % was last char in string */
  423. +         {
  424. +             prc_buff (*str);
  425. +             continue;
  426. +         }
  427. +         else
  428. +             prc_buff (*(++str));
  429. +     }
  430. +     flushb();
  431.   }
  432. :::::::: profile.c :::::::
  433. No differences encountered
  434. :::::::: pwd.c :::::::
  435. *** ../orig.u/pwd.c    Wed May 15 17:08:27 1985
  436. --- pwd.c    Mon May 20 17:20:51 1985
  437. ***************
  438. *** 4,9
  439.    *
  440.    *    Bell Telephone Laboratories
  441.    *
  442.    */
  443.   
  444.   #include        "mac.h"
  445.  
  446. --- 4,14 -----
  447.    *
  448.    *    Bell Telephone Laboratories
  449.    *
  450. +  *    DAG -- Two ways of handling symbolic links in directory paths:
  451. +  *        Define SYMLINK if you want "cd .." to do just that.
  452. +  *        Otherwise, "cd .." takes you back the way you came.
  453. +  *    The first method was implemented by Ron Natalie and the
  454. +  *    second method was implemented by Douglas Gwyn, both of BRL.
  455.    */
  456.   
  457.   #include        "defs.h"    /* DAG -- was just "mac.h" */
  458. ***************
  459. *** 6,12
  460.    *
  461.    */
  462.   
  463. ! #include        "mac.h"
  464.   
  465.   #define    DOT        '.'
  466.   #define    NULL    0
  467.  
  468. --- 11,19 -----
  469.    *    second method was implemented by Douglas Gwyn, both of BRL.
  470.    */
  471.   
  472. ! #include        "defs.h"    /* DAG -- was just "mac.h" */
  473. ! #include    <sys/types.h>        /* DAG -- moved for SYMLINK */
  474. ! #include    <sys/stat.h>        /* DAG -- moved for SYMLINK */
  475.   
  476.   #if defined(SYMLINK) && !defined(S_IFLNK)
  477.   #define    S_IFLNK    0120000
  478. ***************
  479. *** 8,13
  480.   
  481.   #include        "mac.h"
  482.   
  483.   #define    DOT        '.'
  484.   #define    NULL    0
  485.   #define    SLASH    '/'
  486.  
  487. --- 15,24 -----
  488.   #include    <sys/types.h>        /* DAG -- moved for SYMLINK */
  489.   #include    <sys/stat.h>        /* DAG -- moved for SYMLINK */
  490.   
  491. + #if defined(SYMLINK) && !defined(S_IFLNK)
  492. + #define    S_IFLNK    0120000
  493. + #endif
  494.   #define    DOT        '.'
  495.   #define    NULL    0
  496.   #define    SLASH    '/'
  497. ***************
  498. *** 11,16
  499.   #define    DOT        '.'
  500.   #define    NULL    0
  501.   #define    SLASH    '/'
  502.   #define MAXPWD    256
  503.   
  504.   extern char    longpwd[];
  505.  
  506. --- 22,30 -----
  507.   #define    DOT        '.'
  508.   #define    NULL    0
  509.   #define    SLASH    '/'
  510. + #if defined(JOBS)
  511. + #define MAXPWD    (24*256)    /* who knows */
  512. + #else
  513.   #define MAXPWD    256
  514.   #endif
  515.   
  516. ***************
  517. *** 12,17
  518.   #define    NULL    0
  519.   #define    SLASH    '/'
  520.   #define MAXPWD    256
  521.   
  522.   extern char    longpwd[];
  523.   
  524.  
  525. --- 26,32 -----
  526.   #define MAXPWD    (24*256)    /* who knows */
  527.   #else
  528.   #define MAXPWD    256
  529. + #endif
  530.   
  531.   extern char    longpwd[];
  532.   
  533. ***************
  534. *** 17,22
  535.   
  536.   static char cwdname[MAXPWD];
  537.   static int     didpwd = FALSE;
  538.   
  539.   cwd(dir)
  540.       register char *dir;
  541.  
  542. --- 32,41 -----
  543.   
  544.   static char cwdname[MAXPWD];
  545.   static int     didpwd = FALSE;
  546. + #if SYMLINK
  547. + /* Stuff to handle chdirs around symbolic links */
  548. + static char    *symlink = 0;    /* Pointer to after last symlink in cwdname */
  549. + #endif
  550.   
  551.   cwd(dir)
  552.       register char *dir;
  553. ***************
  554. *** 21,26
  555.   cwd(dir)
  556.       register char *dir;
  557.   {
  558.       register char *pcwd;
  559.       register char *pdir;
  560.   
  561.  
  562. --- 40,48 -----
  563.   cwd(dir)
  564.       register char *dir;
  565.   {
  566. + #if SYMLINK
  567. +     struct stat statb;
  568. + #endif
  569.       register char *pcwd;
  570.       register char *pdir;
  571.   
  572. ***************
  573. *** 44,51
  574.           if (*pdir) 
  575.               pdir++;
  576.       }
  577. !     if(*(--pdir)==DOT && pdir>dir && *(--pdir)==SLASH)
  578. !         *pdir = NULL;
  579.       
  580.   
  581.       /* Remove extra /'s */
  582.  
  583. --- 66,73 -----
  584.           if (*pdir) 
  585.               pdir++;
  586.       }
  587. !     if(pdir>dir && *(--pdir)==DOT && pdir>dir && *(--pdir)==SLASH)    /* DAG -- bug fix (added first test) */
  588. !         *pdir = '\0';    /* DAG -- not NULL */
  589.       
  590.   
  591.       /* Remove extra /'s */
  592. ***************
  593. *** 65,70
  594.   
  595.           pcwd = cwdname;
  596.           didpwd = TRUE;
  597.       }
  598.       else
  599.       {
  600.  
  601. --- 87,95 -----
  602.   
  603.           pcwd = cwdname;
  604.           didpwd = TRUE;
  605. + #if SYMLINK
  606. +         symlink = 0;        /* Starting over, no links yet */
  607. + #endif
  608.       }
  609.       else
  610.       {
  611. ***************
  612. *** 71,76
  613.           /* Relative path */
  614.   
  615.           if (didpwd == FALSE) 
  616.               return;
  617.               
  618.           pcwd = cwdname + length(cwdname) - 1;
  619.  
  620. --- 96,104 -----
  621.           /* Relative path */
  622.   
  623.           if (didpwd == FALSE) 
  624. + #if !defined(SYMLINK) && defined(JOBS)
  625. +             pwd();        /* Get absolute pathname into cwdname[] */
  626. + #else
  627.               return;
  628.   #endif
  629.               
  630. ***************
  631. *** 72,77
  632.   
  633.           if (didpwd == FALSE) 
  634.               return;
  635.               
  636.           pcwd = cwdname + length(cwdname) - 1;
  637.           if(pcwd != cwdname+1)
  638.  
  639. --- 100,106 -----
  640.               pwd();        /* Get absolute pathname into cwdname[] */
  641.   #else
  642.               return;
  643. + #endif
  644.               
  645.           pcwd = cwdname + length(cwdname) - 1;
  646.           if(pcwd != cwdname+1)
  647. ***************
  648. *** 93,98
  649.                   ;
  650.               pcwd++;
  651.               dir += 2;
  652.               if(*dir==SLASH)
  653.               {
  654.                   dir++;
  655.  
  656. --- 122,135 -----
  657.                   ;
  658.               pcwd++;
  659.               dir += 2;
  660. + #if SYMLINK
  661. +             /* Just undid symlink, so pwd the hard way */
  662. +             if(pcwd < symlink)
  663. +             {
  664. +                 pwd();
  665. +                 return;
  666. +             }
  667. + #endif
  668.               if(*dir==SLASH)
  669.               {
  670.                   dir++;
  671. ***************
  672. *** 102,107
  673.           *pcwd++ = *dir++;
  674.           while((*dir) && (*dir != SLASH))
  675.               *pcwd++ = *dir++;
  676.           if (*dir) 
  677.               *pcwd++ = *dir++;
  678.       }
  679.  
  680. --- 139,161 -----
  681.           *pcwd++ = *dir++;
  682.           while((*dir) && (*dir != SLASH))
  683.               *pcwd++ = *dir++;
  684. + #if SYMLINK
  685. +         /* Check to see if this path component is a symbolic link */
  686. +         *pcwd = 0;
  687. +         if(lstat(cwdname, &statb) != 0)
  688. +         {
  689. +             prs(cwdname);    /* DAG */
  690. +             error(nolstat);    /* DAG -- made string sharable */
  691. +             pwd();
  692. +             return;
  693. +         }
  694. +         if((statb.st_mode & S_IFMT) == S_IFLNK)
  695. +             /* Set fence so that when we attempt to
  696. +              * "cd .." past it, we know that it is invalid
  697. +              * and have to do it the hard way
  698. +              */
  699. +             symlink = dir;
  700. + #endif
  701.           if (*dir) 
  702.               *pcwd++ = *dir++;
  703.       }
  704. ***************
  705. *** 105,111
  706.           if (*dir) 
  707.               *pcwd++ = *dir++;
  708.       }
  709. !     *pcwd = NULL;
  710.   
  711.       --pcwd;
  712.       if(pcwd>cwdname && *pcwd==SLASH)
  713.  
  714. --- 159,165 -----
  715.           if (*dir) 
  716.               *pcwd++ = *dir++;
  717.       }
  718. !     *pcwd = '\0';    /* DAG -- not NULL */
  719.   
  720.       --pcwd;
  721.       if(pcwd>cwdname && *pcwd==SLASH)
  722. ***************
  723. *** 112,118
  724.       {
  725.           /* Remove trailing / */
  726.   
  727. !         *pcwd = NULL;
  728.       }
  729.       return;
  730.   }
  731.  
  732. --- 166,172 -----
  733.       {
  734.           /* Remove trailing / */
  735.   
  736. !         *pcwd = '\0';    /* DAG -- not NULL */
  737.       }
  738.       return;
  739.   }
  740. ***************
  741. *** 168,174
  742.    *    Find the current directory the hard way.
  743.    */
  744.   
  745. ! #include    <sys/types.h>
  746.   #include    <sys/dir.h>
  747.   #include    <sys/stat.h>
  748.   
  749.  
  750. --- 222,230 -----
  751.    *    Find the current directory the hard way.
  752.    */
  753.   
  754. ! #if JOBS
  755. ! #include    <dir.h>
  756. ! #else
  757.   #include    <sys/dir.h>
  758.   #endif
  759.   
  760. ***************
  761. *** 170,176
  762.   
  763.   #include    <sys/types.h>
  764.   #include    <sys/dir.h>
  765. ! #include    <sys/stat.h>
  766.   
  767.   
  768.   static char dotdots[] =
  769.  
  770. --- 226,232 -----
  771.   #include    <dir.h>
  772.   #else
  773.   #include    <sys/dir.h>
  774. ! #endif
  775.   
  776.   
  777.   static char dotdots[] =
  778. ***************
  779. *** 176,181
  780.   static char dotdots[] =
  781.   "../../../../../../../../../../../../../../../../../../../../../../../..";
  782.   
  783.   extern struct direct    *getdir();
  784.   extern char        *movstrn();
  785.   
  786.  
  787. --- 232,240 -----
  788.   static char dotdots[] =
  789.   "../../../../../../../../../../../../../../../../../../../../../../../..";
  790.   
  791. + #if JOBS
  792. + #define    getdir(dirf)    readdir(dirf)
  793. + #else
  794.   extern struct direct    *getdir();
  795.   extern char        *movstrn();
  796.   #endif
  797. ***************
  798. *** 178,183
  799.   
  800.   extern struct direct    *getdir();
  801.   extern char        *movstrn();
  802.   
  803.   static
  804.   pwd()
  805.  
  806. --- 237,243 -----
  807.   #else
  808.   extern struct direct    *getdir();
  809.   extern char        *movstrn();
  810. + #endif
  811.   
  812.   static
  813.   pwd()
  814. ***************
  815. *** 185,190
  816.       struct stat        cdir;    /* current directory status */
  817.       struct stat        tdir;
  818.       struct stat        pdir;    /* parent directory status */
  819.       int                pdfd;    /* parent directory file descriptor */
  820.   
  821.       struct direct    *dir;
  822.  
  823. --- 245,253 -----
  824.       struct stat        cdir;    /* current directory status */
  825.       struct stat        tdir;
  826.       struct stat        pdir;    /* parent directory status */
  827. + #if JOBS
  828. +     DIR                *pdfd;    /* parent directory stream */
  829. + #else
  830.       int                pdfd;    /* parent directory file descriptor */
  831.   #endif
  832.   
  833. ***************
  834. *** 186,191
  835.       struct stat        tdir;
  836.       struct stat        pdir;    /* parent directory status */
  837.       int                pdfd;    /* parent directory file descriptor */
  838.   
  839.       struct direct    *dir;
  840.       char             *dot = dotdots + sizeof(dotdots) - 3;
  841.  
  842. --- 249,255 -----
  843.       DIR                *pdfd;    /* parent directory stream */
  844.   #else
  845.       int                pdfd;    /* parent directory file descriptor */
  846. + #endif
  847.   
  848.       struct direct    *dir;
  849.       char             *dot = dotdots + sizeof(dotdots) - 3;
  850. ***************
  851. *** 193,198
  852.       int                cwdindex = MAXPWD - 1;
  853.       int             i;
  854.       
  855.       cwdname[cwdindex] = 0;
  856.       dotdots[index] = 0;
  857.   
  858.  
  859. --- 257,265 -----
  860.       int                cwdindex = MAXPWD - 1;
  861.       int             i;
  862.       
  863. + #if SYMLINK
  864. +     symlink = 0;            /* Starting over, no links yet */
  865. + #endif
  866.       cwdname[cwdindex] = 0;
  867.       dotdots[index] = 0;
  868.   
  869. ***************
  870. *** 206,212
  871.       for(;;)
  872.       {
  873.           cdir = pdir;
  874.           if ((pdfd = open(dot, 0)) < 0)
  875.           {
  876.               error("pwd: cannot open ..");
  877.  
  878. --- 273,281 -----
  879.       for(;;)
  880.       {
  881.           cdir = pdir;
  882. ! #if JOBS
  883. !         if ((pdfd = opendir(dot)) == (DIR *)0)
  884. ! #else
  885.           if ((pdfd = open(dot, 0)) < 0)
  886.   #endif
  887.           {
  888. ***************
  889. *** 208,213
  890.           cdir = pdir;
  891.   
  892.           if ((pdfd = open(dot, 0)) < 0)
  893.           {
  894.               error("pwd: cannot open ..");
  895.           }
  896.  
  897. --- 277,283 -----
  898.           if ((pdfd = opendir(dot)) == (DIR *)0)
  899.   #else
  900.           if ((pdfd = open(dot, 0)) < 0)
  901. + #endif
  902.           {
  903.               error("pwd: cannot open ..");
  904.           }
  905. ***************
  906. *** 211,217
  907.           {
  908.               error("pwd: cannot open ..");
  909.           }
  910.           if(fstat(pdfd, &pdir) < 0)
  911.           {
  912.               close(pdfd);
  913.  
  914. --- 281,289 -----
  915.           {
  916.               error("pwd: cannot open ..");
  917.           }
  918. ! #if JOBS
  919. !         if(fstat(pdfd->dd_fd, &pdir) < 0)
  920. ! #else
  921.           if(fstat(pdfd, &pdir) < 0)
  922.   #endif
  923.           {
  924. ***************
  925. *** 213,218
  926.           }
  927.   
  928.           if(fstat(pdfd, &pdir) < 0)
  929.           {
  930.               close(pdfd);
  931.               error("pwd: cannot stat ..");
  932.  
  933. --- 285,291 -----
  934.           if(fstat(pdfd->dd_fd, &pdir) < 0)
  935.   #else
  936.           if(fstat(pdfd, &pdir) < 0)
  937. + #endif
  938.           {
  939.   #if JOBS
  940.               closedir(pdfd);
  941. ***************
  942. *** 214,219
  943.   
  944.           if(fstat(pdfd, &pdir) < 0)
  945.           {
  946.               close(pdfd);
  947.               error("pwd: cannot stat ..");
  948.           }
  949.  
  950. --- 287,295 -----
  951.           if(fstat(pdfd, &pdir) < 0)
  952.   #endif
  953.           {
  954. + #if JOBS
  955. +             closedir(pdfd);
  956. + #else
  957.               close(pdfd);
  958.   #endif
  959.               error("pwd: cannot stat ..");
  960. ***************
  961. *** 215,220
  962.           if(fstat(pdfd, &pdir) < 0)
  963.           {
  964.               close(pdfd);
  965.               error("pwd: cannot stat ..");
  966.           }
  967.   
  968.  
  969. --- 291,297 -----
  970.               closedir(pdfd);
  971.   #else
  972.               close(pdfd);
  973. + #endif
  974.               error("pwd: cannot stat ..");
  975.           }
  976.   
  977. ***************
  978. *** 223,228
  979.               if(cdir.st_ino == pdir.st_ino)
  980.               {
  981.                   didpwd = TRUE;
  982.                   close(pdfd);
  983.                   if (cwdindex == (MAXPWD - 1))
  984.                       cwdname[--cwdindex] = SLASH;
  985.  
  986. --- 300,308 -----
  987.               if(cdir.st_ino == pdir.st_ino)
  988.               {
  989.                   didpwd = TRUE;
  990. + #if JOBS
  991. +                 closedir(pdfd);
  992. + #else
  993.                   close(pdfd);
  994.   #endif
  995.                   if (cwdindex == (MAXPWD - 1))
  996. ***************
  997. *** 224,229
  998.               {
  999.                   didpwd = TRUE;
  1000.                   close(pdfd);
  1001.                   if (cwdindex == (MAXPWD - 1))
  1002.                       cwdname[--cwdindex] = SLASH;
  1003.   
  1004.  
  1005. --- 304,310 -----
  1006.                   closedir(pdfd);
  1007.   #else
  1008.                   close(pdfd);
  1009. + #endif
  1010.                   if (cwdindex == (MAXPWD - 1))
  1011.                       cwdname[--cwdindex] = SLASH;
  1012.   
  1013. ***************
  1014. *** 235,240
  1015.               {
  1016.                   if ((dir = getdir(pdfd)) == 0)
  1017.                   {
  1018.                       close(pdfd);
  1019.                       reset_dir();
  1020.                       error("pwd: read error in ..");
  1021.  
  1022. --- 316,324 -----
  1023.               {
  1024.                   if ((dir = getdir(pdfd)) == 0)
  1025.                   {
  1026. + #if JOBS
  1027. +                     closedir(pdfd);
  1028. + #else
  1029.                       close(pdfd);
  1030.                       reset_dir();
  1031.   #endif
  1032. ***************
  1033. *** 237,242
  1034.                   {
  1035.                       close(pdfd);
  1036.                       reset_dir();
  1037.                       error("pwd: read error in ..");
  1038.                   }
  1039.               }
  1040.  
  1041. --- 321,327 -----
  1042.   #else
  1043.                       close(pdfd);
  1044.                       reset_dir();
  1045. + #endif
  1046.                       error("pwd: read error in ..");
  1047.                   }
  1048.               }
  1049. ***************
  1050. *** 244,250
  1051.           }
  1052.           else
  1053.           {
  1054. !             char name[512];
  1055.               
  1056.               movstr(dot, name);
  1057.               i = length(name) - 1;
  1058.  
  1059. --- 329,335 -----
  1060.           }
  1061.           else
  1062.           {
  1063. !             char name[256+MAXPWD];    /* DAG -- (was 512) */
  1064.               
  1065.               movstr(dot, name);
  1066.               i = length(name) - 1;
  1067. ***************
  1068. *** 251,256
  1069.   
  1070.               name[i++] = '/';
  1071.   
  1072.               do
  1073.               {
  1074.                   if ((dir = getdir(pdfd)) == 0)
  1075.  
  1076. --- 336,342 -----
  1077.   
  1078.               name[i++] = '/';
  1079.   
  1080. +             tdir.st_dev = pdir.st_dev;    /* DAG -- (safety) */
  1081.               do
  1082.               {
  1083.                   if ((dir = getdir(pdfd)) == 0)
  1084. ***************
  1085. *** 255,260
  1086.               {
  1087.                   if ((dir = getdir(pdfd)) == 0)
  1088.                   {
  1089.                       close(pdfd);
  1090.                       reset_dir();
  1091.                       error("pwd: read error in ..");
  1092.  
  1093. --- 341,349 -----
  1094.               {
  1095.                   if ((dir = getdir(pdfd)) == 0)
  1096.                   {
  1097. + #if JOBS
  1098. +                     closedir(pdfd);
  1099. + #else
  1100.                       close(pdfd);
  1101.                       reset_dir();
  1102.   #endif
  1103. ***************
  1104. *** 257,262
  1105.                   {
  1106.                       close(pdfd);
  1107.                       reset_dir();
  1108.                       error("pwd: read error in ..");
  1109.                   }
  1110.                   *(movstrn(dir->d_name, &name[i], DIRSIZ)) = 0;
  1111.  
  1112. --- 346,352 -----
  1113.   #else
  1114.                       close(pdfd);
  1115.                       reset_dir();
  1116. + #endif
  1117.                       error("pwd: read error in ..");
  1118.                   }
  1119.   #if JOBS
  1120. ***************
  1121. *** 259,264
  1122.                       reset_dir();
  1123.                       error("pwd: read error in ..");
  1124.                   }
  1125.                   *(movstrn(dir->d_name, &name[i], DIRSIZ)) = 0;
  1126.                   stat(name, &tdir);
  1127.               }        
  1128.  
  1129. --- 349,357 -----
  1130.   #endif
  1131.                       error("pwd: read error in ..");
  1132.                   }
  1133. + #if JOBS
  1134. +                 movstr(dir->d_name, &name[i]);
  1135. + #else
  1136.                   *(movstrn(dir->d_name, &name[i], DIRSIZ)) = 0;
  1137.   #endif
  1138.                   stat(name, &tdir);
  1139. ***************
  1140. *** 260,265
  1141.                       error("pwd: read error in ..");
  1142.                   }
  1143.                   *(movstrn(dir->d_name, &name[i], DIRSIZ)) = 0;
  1144.                   stat(name, &tdir);
  1145.               }        
  1146.               while(tdir.st_ino != cdir.st_ino || tdir.st_dev != cdir.st_dev);
  1147.  
  1148. --- 353,359 -----
  1149.                   movstr(dir->d_name, &name[i]);
  1150.   #else
  1151.                   *(movstrn(dir->d_name, &name[i], DIRSIZ)) = 0;
  1152. + #endif
  1153.                   stat(name, &tdir);
  1154.               }        
  1155.               while(tdir.st_ino != cdir.st_ino || tdir.st_dev != cdir.st_dev);
  1156. ***************
  1157. *** 264,269
  1158.               }        
  1159.               while(tdir.st_ino != cdir.st_ino || tdir.st_dev != cdir.st_dev);
  1160.           }
  1161.           close(pdfd);
  1162.           reset_dir();
  1163.   
  1164.  
  1165. --- 358,366 -----
  1166.               }        
  1167.               while(tdir.st_ino != cdir.st_ino || tdir.st_dev != cdir.st_dev);
  1168.           }
  1169. + #if JOBS
  1170. +         closedir(pdfd);
  1171. + #else
  1172.           close(pdfd);
  1173.           reset_dir();
  1174.   #endif
  1175. ***************
  1176. *** 266,271
  1177.           }
  1178.           close(pdfd);
  1179.           reset_dir();
  1180.   
  1181.           for (i = 0; i < DIRSIZ; i++)
  1182.               if (dir->d_name[i] == 0)
  1183.  
  1184. --- 363,369 -----
  1185.   #else
  1186.           close(pdfd);
  1187.           reset_dir();
  1188. + #endif
  1189.   
  1190.   #if JOBS
  1191.           i = dir->d_namlen;
  1192. ***************
  1193. *** 267,272
  1194.           close(pdfd);
  1195.           reset_dir();
  1196.   
  1197.           for (i = 0; i < DIRSIZ; i++)
  1198.               if (dir->d_name[i] == 0)
  1199.                   break;
  1200.  
  1201. --- 365,373 -----
  1202.           reset_dir();
  1203.   #endif
  1204.   
  1205. + #if JOBS
  1206. +         i = dir->d_namlen;
  1207. + #else
  1208.           for (i = 0; i < DIRSIZ; i++)
  1209.               if (dir->d_name[i] == 0)
  1210.                   break;
  1211. ***************
  1212. *** 270,275
  1213.           for (i = 0; i < DIRSIZ; i++)
  1214.               if (dir->d_name[i] == 0)
  1215.                   break;
  1216.   
  1217.           if (i > cwdindex - 1)
  1218.                   error(longpwd);
  1219.  
  1220. --- 371,377 -----
  1221.           for (i = 0; i < DIRSIZ; i++)
  1222.               if (dir->d_name[i] == 0)
  1223.                   break;
  1224. + #endif
  1225.   
  1226.           if (i > cwdindex - 1)
  1227.                   error(longpwd);
  1228. ***************
  1229. *** 284,287
  1230.           if (dot<dotdots) 
  1231.               error(longpwd);
  1232.       }
  1233.   }
  1234.  
  1235. --- 386,419 -----
  1236.           if (dot<dotdots) 
  1237.               error(longpwd);
  1238.       }
  1239. + }
  1240. + #if !defined(SYMLINK) && defined(JOBS)
  1241. + /* The following chdir() interface is used to outwit symbolic links. */
  1242. + int
  1243. + cwdir( dir )                /* attempt a full-pathname chdir */
  1244. +     char        *dir;        /* name to feed to chdir() */
  1245. +     {
  1246. +     char        savname[MAXPWD];    /* saved cwdname[] */
  1247. +     register int    retval;        /* chdir() return value */
  1248. +     (void)movstr( cwdname, savname );    /* save current name */
  1249. +     cwd( dir );            /* adjust cwdname[] */
  1250. +     if ( (retval = chdir( cwdname )) < 0 )
  1251. +         (void)movstr( savname, cwdname );    /* restore name */
  1252. +     return retval;
  1253. +     }
  1254. + #endif
  1255. + char *
  1256. + retcwd()
  1257. + {
  1258. +     if (didpwd == FALSE)
  1259. +         pwd ();
  1260. +     
  1261. +     return (cwdname);
  1262.   }
  1263. :::::::: service.c :::::::
  1264. *** ../orig.u/service.c    Wed May 15 17:08:28 1985
  1265. --- service.c    Wed May 29 15:54:16 1985
  1266. ***************
  1267. *** 8,13
  1268.   
  1269.   #include    "defs.h"
  1270.   #include    <errno.h>
  1271.   
  1272.   #define ARGMK    01
  1273.   
  1274.  
  1275. --- 8,17 -----
  1276.   
  1277.   #include    "defs.h"
  1278.   #include    <errno.h>
  1279. + #if JOBS
  1280. + extern int    errno;
  1281. + #include    "/usr/include/sys/wait.h"
  1282. + #endif
  1283.   
  1284.   #define ARGMK    01
  1285.   
  1286. ***************
  1287. *** 24,29
  1288.       struct ionod    *iop;
  1289.       int        save;
  1290.   {
  1291.       register char    *ion;
  1292.       register int    iof, fd;
  1293.       int        ioufd;
  1294.  
  1295. --- 28,34 -----
  1296.       struct ionod    *iop;
  1297.       int        save;
  1298.   {
  1299. +     extern long    lseek();    /* DAG -- bug fix (was missing) */
  1300.       register char    *ion;
  1301.       register int    iof, fd;
  1302.       int        ioufd;
  1303. ***************
  1304. *** 70,75
  1305.                   else
  1306.                       fd = dup(fd);
  1307.               }
  1308.               else if ((iof & IOPUT) == 0)
  1309.                   fd = chkopen(ion);
  1310.               else if (flags & rshflg)
  1311.  
  1312. --- 75,85 -----
  1313.                   else
  1314.                       fd = dup(fd);
  1315.               }
  1316. +             else if (iof & IORDW)
  1317. +             {
  1318. +                 if ((fd = open(ion, 2)) < 0)
  1319. +                     failed(ion, badopen);
  1320. +             }
  1321.               else if ((iof & IOPUT) == 0)
  1322.                   fd = chkopen(ion);
  1323.               else if (flags & rshflg)
  1324. ***************
  1325. *** 145,150
  1326.        */
  1327.       register char    *scanp = path;
  1328.       register char    *argp = locstak();
  1329.   
  1330.       while (*scanp && *scanp != COLON)
  1331.           *argp++ = *scanp++;
  1332.  
  1333. --- 155,162 -----
  1334.        */
  1335.       register char    *scanp = path;
  1336.       register char    *argp = locstak();
  1337. +     char    *save = argp;
  1338. +     char    *cp;
  1339.   
  1340.       while (*scanp && *scanp != COLON)
  1341.           *argp++ = *scanp++;
  1342. ***************
  1343. *** 148,153
  1344.   
  1345.       while (*scanp && *scanp != COLON)
  1346.           *argp++ = *scanp++;
  1347.       if (scanp != path)
  1348.           *argp++ = '/';
  1349.       if (*scanp == COLON)
  1350.  
  1351. --- 160,172 -----
  1352.   
  1353.       while (*scanp && *scanp != COLON)
  1354.           *argp++ = *scanp++;
  1355. +     *argp = '\0';
  1356. +     /* try a tilde expansion */
  1357. +     if (*save == SQUIGGLE && (cp = homedir (save + 1)) != nullstr)
  1358. +     {
  1359. +         movstr (cp, save);
  1360. +         argp = save + length (save) - 1;
  1361. +     }
  1362.       if (scanp != path)
  1363.           *argp++ = '/';
  1364.       if (*scanp == COLON)
  1365. ***************
  1366. *** 232,237
  1367.           if (input)
  1368.               close(input);
  1369.           input = chkopen(p);
  1370.       
  1371.   #ifdef ACCT
  1372.           preacct(p);    /* reset accounting */
  1373.  
  1374. --- 251,271 -----
  1375.           if (input)
  1376.               close(input);
  1377.           input = chkopen(p);
  1378. + #if JOBS
  1379. +         /* don't try to interpret directories etc. */
  1380. +         {
  1381. + #include    <sys/types.h>
  1382. + #include    <sys/stat.h>
  1383. +             struct stat    sbuf;
  1384. +             if (fstat(input, &sbuf) == 0
  1385. +                 && (sbuf.st_mode&S_IFMT) != S_IFREG)
  1386. +             {
  1387. +                 close (input);
  1388. +                 goto def;    /* badexec unless other found */
  1389. +             }
  1390. +         }
  1391. + #endif
  1392.       
  1393.   #ifdef ACCT
  1394.           preacct(p);    /* reset accounting */
  1395. ***************
  1396. *** 254,259
  1397.           failed(p, txtbsy);
  1398.   
  1399.       default:
  1400.           xecmsg = badexec;
  1401.       case ENOENT:
  1402.           return(prefix);
  1403.  
  1404. --- 288,296 -----
  1405.           failed(p, txtbsy);
  1406.   
  1407.       default:
  1408. + #if JOBS
  1409. +     def:
  1410. + #endif
  1411.           xecmsg = badexec;
  1412.       case ENOENT:
  1413.           return(prefix);
  1414. ***************
  1415. *** 268,273
  1416.   static int    pwlist[MAXP];
  1417.   static int    pwc;
  1418.   
  1419.   postclr()
  1420.   {
  1421.       register int    *pw = pwlist;
  1422.  
  1423. --- 305,355 -----
  1424.   static int    pwlist[MAXP];
  1425.   static int    pwc;
  1426.   
  1427. + #if JOBS
  1428. + static int    *wf_pwlist;
  1429. + static int    wf_pwc;
  1430. + void
  1431. + set_wfence()
  1432. + {
  1433. +     wf_pwlist = &pwlist[pwc];
  1434. +     wf_pwc = 0;
  1435. + }
  1436. + BOOL
  1437. + unpost(pcsid)
  1438. +     int    pcsid;
  1439. + {
  1440. +     register int    *pw = pwlist;
  1441. +     if (pcsid)
  1442. +     {
  1443. +         while (pw <= &pwlist[pwc])
  1444. +         {
  1445. +             if (pcsid == *pw)
  1446. +             {
  1447. +                 if (pw >= wf_pwlist)
  1448. +                     wf_pwc--;
  1449. +                 else
  1450. +                     wf_pwlist--;
  1451. +                 while (pw <= &pwlist[pwc])
  1452. +                 {
  1453. +                     *pw = pw[1];
  1454. +                     pw++;
  1455. +                 }
  1456. +                 pw[pwc] = 0;
  1457. +                 pwc--;
  1458. +                 return TRUE;
  1459. +             }
  1460. +             pw++;
  1461. +         }
  1462. +         return FALSE;
  1463. +     }
  1464. +     else
  1465. +         return TRUE;
  1466. + }
  1467. + #endif
  1468.   postclr()
  1469.   {
  1470.       register int    *pw = pwlist;
  1471. ***************
  1472. *** 273,278
  1473.       register int    *pw = pwlist;
  1474.   
  1475.       while (pw <= &pwlist[pwc])
  1476.           *pw++ = 0;
  1477.       pwc = 0;
  1478.   }
  1479.  
  1480. --- 355,364 -----
  1481.       register int    *pw = pwlist;
  1482.   
  1483.       while (pw <= &pwlist[pwc])
  1484. +     {
  1485. + #if JOBS
  1486. +         j_child_clear(*pw);
  1487. + #endif
  1488.           *pw++ = 0;
  1489.       }
  1490.       pwc = 0;
  1491. ***************
  1492. *** 274,279
  1493.   
  1494.       while (pw <= &pwlist[pwc])
  1495.           *pw++ = 0;
  1496.       pwc = 0;
  1497.   }
  1498.   
  1499.  
  1500. --- 360,366 -----
  1501.           j_child_clear(*pw);
  1502.   #endif
  1503.           *pw++ = 0;
  1504. +     }
  1505.       pwc = 0;
  1506.   }
  1507.   
  1508. ***************
  1509. *** 285,291
  1510.       if (pcsid)
  1511.       {
  1512.           while (*pw)
  1513. !             pw++;
  1514.           if (pwc >= MAXP - 1)
  1515.               pw--;
  1516.           else
  1517.  
  1518. --- 372,383 -----
  1519.       if (pcsid)
  1520.       {
  1521.           while (*pw)
  1522. ! #if JOBS
  1523. !             if (pcsid == *pw)
  1524. !                 return;
  1525. !             else
  1526. ! #endif
  1527. !                 pw++;
  1528.           if (pwc >= MAXP - 1)
  1529.               pw--;
  1530.           else
  1531. ***************
  1532. *** 289,294
  1533.           if (pwc >= MAXP - 1)
  1534.               pw--;
  1535.           else
  1536.               pwc++;
  1537.           *pw = pcsid;
  1538.       }
  1539.  
  1540. --- 381,387 -----
  1541.           if (pwc >= MAXP - 1)
  1542.               pw--;
  1543.           else
  1544. +         {
  1545.               pwc++;
  1546.   #if JOBS
  1547.               wf_pwc++;
  1548. ***************
  1549. *** 290,295
  1550.               pw--;
  1551.           else
  1552.               pwc++;
  1553.           *pw = pcsid;
  1554.       }
  1555.   }
  1556.  
  1557. --- 383,392 -----
  1558.           else
  1559.           {
  1560.               pwc++;
  1561. + #if JOBS
  1562. +             wf_pwc++;
  1563. + #endif
  1564. +         }
  1565.           *pw = pcsid;
  1566.       }
  1567.   }
  1568. ***************
  1569. *** 297,302
  1570.   await(i, bckg)
  1571.   int    i, bckg;
  1572.   {
  1573.       int    rc = 0, wx = 0;
  1574.       int    w;
  1575.       int    ipwc = pwc;
  1576.  
  1577. --- 394,404 -----
  1578.   await(i, bckg)
  1579.   int    i, bckg;
  1580.   {
  1581. + #if JOBS
  1582. + #include    "/usr/include/sys/time.h"
  1583. + #include    "/usr/include/sys/resource.h"
  1584. +     struct rusage    ru;
  1585. + #endif
  1586.       int    rc = 0, wx = 0;
  1587.       int    w;
  1588.       int    ipwc = pwc;
  1589. ***************
  1590. *** 300,305
  1591.       int    rc = 0, wx = 0;
  1592.       int    w;
  1593.       int    ipwc = pwc;
  1594.   
  1595.       post(i);
  1596.       while (pwc)
  1597.  
  1598. --- 402,409 -----
  1599.       int    rc = 0, wx = 0;
  1600.       int    w;
  1601.       int    ipwc = pwc;
  1602. + #if JOBS
  1603. +     BOOL    update_only = i == -2;
  1604.   
  1605.       if (update_only)
  1606.           i = -1;
  1607. ***************
  1608. *** 301,307
  1609.       int    w;
  1610.       int    ipwc = pwc;
  1611.   
  1612. !     post(i);
  1613.       while (pwc)
  1614.       {
  1615.           register int    p;
  1616.  
  1617. --- 405,418 -----
  1618.   #if JOBS
  1619.       BOOL    update_only = i == -2;
  1620.   
  1621. !     if (update_only)
  1622. !         i = -1;
  1623. !     if ((flags&jobflg) == 0 || i != -1)
  1624. ! #endif
  1625. !         post(i);
  1626. ! #if JOBS
  1627. !     while (pwc || (flags&jobflg))
  1628. ! #else
  1629.       while (pwc)
  1630.   #endif
  1631.       {
  1632. ***************
  1633. *** 303,308
  1634.   
  1635.       post(i);
  1636.       while (pwc)
  1637.       {
  1638.           register int    p;
  1639.           register int    sig;
  1640.  
  1641. --- 414,420 -----
  1642.       while (pwc || (flags&jobflg))
  1643.   #else
  1644.       while (pwc)
  1645. + #endif
  1646.       {
  1647.           register int    p;
  1648.           register int    sig;
  1649. ***************
  1650. *** 310,315
  1651.           int    found = 0;
  1652.   
  1653.           {
  1654.               register int    *pw = pwlist;
  1655.   
  1656.               p = wait(&w);
  1657.  
  1658. --- 422,428 -----
  1659.           int    found = 0;
  1660.   
  1661.           {
  1662. + #ifndef JOBS
  1663.               register int    *pw = pwlist;
  1664.   #endif
  1665.   
  1666. ***************
  1667. *** 311,316
  1668.   
  1669.           {
  1670.               register int    *pw = pwlist;
  1671.   
  1672.               p = wait(&w);
  1673.               if (wasintr)
  1674.  
  1675. --- 424,430 -----
  1676.           {
  1677.   #ifndef JOBS
  1678.               register int    *pw = pwlist;
  1679. + #endif
  1680.   
  1681.   #if JOBS
  1682.               if (i == 0 && (flags&jobflg) && wf_pwc == 0)
  1683. ***************
  1684. *** 312,317
  1685.           {
  1686.               register int    *pw = pwlist;
  1687.   
  1688.               p = wait(&w);
  1689.               if (wasintr)
  1690.               {
  1691.  
  1692. --- 426,447 -----
  1693.               register int    *pw = pwlist;
  1694.   #endif
  1695.   
  1696. + #if JOBS
  1697. +             if (i == 0 && (flags&jobflg) && wf_pwc == 0)
  1698. +                 break;
  1699. +             if ((pwc == 0 && (flags&jobflg)) || update_only)
  1700. +             {
  1701. +                 if ((p = wait3(&w, WUNTRACED|WNOHANG, &ru)) == 0)
  1702. +                 {
  1703. +                     unpost (i);
  1704. +                     break;
  1705. +                 }
  1706. +                 if (pwc == 0 && p == -1)
  1707. +                     break;
  1708. +             }
  1709. +             else
  1710. +                 p = wait3(&w, WUNTRACED, &ru);
  1711. + #else
  1712.               p = wait(&w);
  1713.   #endif
  1714.               if (wasintr)
  1715. ***************
  1716. *** 313,318
  1717.               register int    *pw = pwlist;
  1718.   
  1719.               p = wait(&w);
  1720.               if (wasintr)
  1721.               {
  1722.                   wasintr = 0;
  1723.  
  1724. --- 443,449 -----
  1725.                   p = wait3(&w, WUNTRACED, &ru);
  1726.   #else
  1727.               p = wait(&w);
  1728. + #endif
  1729.               if (wasintr)
  1730.               {
  1731.                   wasintr = 0;
  1732. ***************
  1733. *** 321,326
  1734.                       break;
  1735.                   }
  1736.               }
  1737.               while (pw <= &pwlist[ipwc])
  1738.               {
  1739.                   if (*pw == p)
  1740.  
  1741. --- 452,462 -----
  1742.                       break;
  1743.                   }
  1744.               }
  1745. + #if JOBS
  1746. +             if (unpost(p))
  1747. +                 found++;
  1748. + #else
  1749.               while (pw <= &pwlist[ipwc])
  1750.               {
  1751.                   if (*pw == p)
  1752. ***************
  1753. *** 332,337
  1754.                   else
  1755.                       pw++;
  1756.               }
  1757.           }
  1758.           if (p == -1)
  1759.           {
  1760.  
  1761. --- 468,474 -----
  1762.                   else
  1763.                       pw++;
  1764.               }
  1765. + #endif
  1766.           }
  1767.           if (p == -1)
  1768.           {
  1769. ***************
  1770. *** 337,342
  1771.           {
  1772.               if (bckg)
  1773.               {
  1774.                   register int *pw = pwlist;
  1775.   
  1776.                   while (pw <= &pwlist[ipwc] && i != *pw)
  1777.  
  1778. --- 474,483 -----
  1779.           {
  1780.               if (bckg)
  1781.               {
  1782. + #if JOBS
  1783. +                 j_child_clear(i);
  1784. +                 unpost(i);
  1785. + #else
  1786.                   register int *pw = pwlist;
  1787.   
  1788.                   while (pw <= &pwlist[ipwc] && i != *pw)
  1789. ***************
  1790. *** 346,351
  1791.                       *pw = 0;
  1792.                       pwc--;
  1793.                   }
  1794.               }
  1795.               continue;
  1796.           }
  1797.  
  1798. --- 487,493 -----
  1799.                       *pw = 0;
  1800.                       pwc--;
  1801.                   }
  1802. + #endif
  1803.               }
  1804.               continue;
  1805.           }
  1806. ***************
  1807. *** 354,360
  1808.           {
  1809.               if (sig == 0177)    /* ptrace! return */
  1810.               {
  1811. -                 prs("ptrace: ");
  1812.                   sig = w_hi;
  1813.               }
  1814.               if (sysmsg[sig])
  1815.  
  1816. --- 496,501 -----
  1817.           {
  1818.               if (sig == 0177)    /* ptrace! return */
  1819.               {
  1820.                   sig = w_hi;
  1821.   #if JOBS
  1822.                   if ((flags&jobflg) &&
  1823. ***************
  1824. *** 356,361
  1825.               {
  1826.                   prs("ptrace: ");
  1827.                   sig = w_hi;
  1828.               }
  1829.               if (sysmsg[sig])
  1830.               {
  1831.  
  1832. --- 497,512 -----
  1833.               if (sig == 0177)    /* ptrace! return */
  1834.               {
  1835.                   sig = w_hi;
  1836. + #if JOBS
  1837. +                 if ((flags&jobflg) &&
  1838. +                     (sig == SIGSTOP || sig == SIGTSTP ||
  1839. +                      sig == SIGTTOU || sig == SIGTTIN))
  1840. +                 {
  1841. +                     j_child_stop(p, sig);
  1842. +                     goto j_bypass;
  1843. +                 }
  1844. + #endif
  1845. +                 prs("ptrace: ");
  1846.               }
  1847.               if (sysmsg[sig])
  1848.               {
  1849. ***************
  1850. *** 371,376
  1851.               }
  1852.               newline();
  1853.           }
  1854.           if (rc == 0 && found != 0)
  1855.               rc = (sig ? sig | SIGFLG : w_hi);
  1856.           wx |= w;
  1857.  
  1858. --- 522,558 -----
  1859.               }
  1860.               newline();
  1861.           }
  1862. + #if JOBS
  1863. +         if (flags&infoflg)
  1864. +         {
  1865. +             register int    k;
  1866. +             long        l;
  1867. +             prc('[');
  1868. +             l = ru.ru_utime.tv_sec * 1000000L + ru.ru_utime.tv_usec
  1869. +               + ru.ru_stime.tv_sec * 1000000L + ru.ru_stime.tv_usec;
  1870. +             prn((int)(l / 1000000));    /* integral seconds */
  1871. +             k = (int)(l % 1000000L) / 1000;    /* thousandths */
  1872. +             prc('.');
  1873. +             if (k < 100)
  1874. +                 prc('0');
  1875. +             if (k < 10)
  1876. +                 prc('0');
  1877. +             prn(k);
  1878. +             blank();
  1879. +             prn((int)ru.ru_inblock);
  1880. +             blank();
  1881. +             prn((int)ru.ru_oublock);
  1882. +             blank();
  1883. +             prn((int)ru.ru_minflt);
  1884. +             blank();
  1885. +             prn((int)ru.ru_majflt);
  1886. +             prc(']');
  1887. +             newline();
  1888. +         }
  1889. +         j_child_die(p);
  1890. +     j_bypass:
  1891. + #endif
  1892.           if (rc == 0 && found != 0)
  1893.               rc = (sig ? sig | SIGFLG : w_hi);
  1894.           wx |= w;
  1895. :::::::: setbrk.c :::::::
  1896. No differences encountered
  1897. :::::::: sh.mk :::::::
  1898. *** ../orig.u/sh.mk    Wed May 15 17:08:30 1985
  1899. --- sh.mk    Wed May 29 16:28:26 1985
  1900. ***************
  1901. *** 5,11
  1902.   ROOT=
  1903.   INS = /etc/install -n $(ROOT)/bin
  1904.   INSDIR =
  1905. ! CFLAGS = -O -DNICE -DACCT -DNICEVAL=4
  1906.   LDFLAGS = -n -s
  1907.   
  1908.   OFILES = setbrk.o blok.o stak.o cmd.o fault.o main.o word.o string.o\
  1909.  
  1910. --- 5,11 -----
  1911.   ROOT=
  1912.   INS = /etc/install -n $(ROOT)/bin
  1913.   INSDIR =
  1914. ! CFLAGS = -O -DNICE -DNICEVAL=4 -DJOBS
  1915.   LDFLAGS = -n -s
  1916.   
  1917.   OFILES = setbrk.o blok.o stak.o cmd.o fault.o main.o word.o string.o\
  1918. ***************
  1919. *** 10,15
  1920.   
  1921.   OFILES = setbrk.o blok.o stak.o cmd.o fault.o main.o word.o string.o\
  1922.   name.o args.o xec.o service.o error.o io.o print.o macro.o expand.o\
  1923.   ctype.o msg.o test.o defs.o echo.o hash.o hashserv.o pwd.o func.o
  1924.   
  1925.   all: sh
  1926.  
  1927. --- 10,17 -----
  1928.   
  1929.   OFILES = setbrk.o blok.o stak.o cmd.o fault.o main.o word.o string.o\
  1930.   name.o args.o xec.o service.o error.o io.o print.o macro.o expand.o\
  1931. + history.o homedir.o \
  1932. + jobs.o signal.o ulimit.o \
  1933.   ctype.o msg.o test.o defs.o echo.o hash.o hashserv.o pwd.o func.o
  1934.   
  1935.   all: sh
  1936. ***************
  1937. *** 20,34
  1938.   $(OFILES):    defs.h $(FRC)
  1939.   
  1940.   ctype.o:    ctype.h
  1941. !         if [ "${_ID_}" ];\
  1942. !         then \
  1943. !             $(CC) $(CFLAGS) -c ctype.c; \
  1944. !         elif [ "${_SH_}" ]; \
  1945. !         then \
  1946. !             CC=$(CC) AS=$(AS) $(_SH_) ./:fix ctype; \
  1947. !         else \
  1948. !             CC=$(CC) AS=$(AS) sh ./:fix ctype; \
  1949. !         fi
  1950.   
  1951.   xec.o:        xec.c
  1952.       set +e; if u370;\
  1953.  
  1954. --- 22,32 -----
  1955.   $(OFILES):    defs.h $(FRC)
  1956.   
  1957.   ctype.o:    ctype.h
  1958. !         $(CC) $(CFLAGS) -S ctype.c
  1959. !         sed '/^[     ]*\.data/s/data/text/' < ctype.s > x.s
  1960. !         mv x.s ctype.s
  1961. !         $(AS) ctype.s -o ctype.o
  1962. !         rm ctype.s
  1963.   
  1964.   xec.o:        xec.c
  1965.       set +e; if u370;\
  1966. ***************
  1967. *** 55,69
  1968.   
  1969.   
  1970.   msg.o:        msg.c $(FRC)
  1971. !         if [ "${_ID_}" ];\
  1972. !         then \
  1973. !             $(CC) $(CFLAGS) -c msg.c; \
  1974. !         elif [ "${_SH_}" ]; \
  1975. !         then \
  1976. !             CC=$(CC) AS=$(AS) $(_SH_) ./:fix msg; \
  1977. !         else \
  1978. !             CC=$(CC) AS=$(AS) sh ./:fix msg; \
  1979. !         fi
  1980.   
  1981.   test:
  1982.         rtest $(TESTDIR)/sh
  1983.  
  1984. --- 53,63 -----
  1985.   
  1986.   
  1987.   msg.o:        msg.c $(FRC)
  1988. !         $(CC) $(CFLAGS) -S msg.c
  1989. !         sed '/^[     ]*\.data/s/data/text/' < msg.s > x.s
  1990. !         mv x.s msg.s
  1991. !         $(AS) msg.s -o msg.o
  1992. !         rm msg.s
  1993.   
  1994.   test:
  1995.         rtest $(TESTDIR)/sh
  1996. :::::::: stak.c :::::::
  1997. No differences encountered
  1998. :::::::: stak.h :::::::
  1999. No differences encountered
  2000. :::::::: string.c :::::::
  2001. No differences encountered
  2002. :::::::: sym.h :::::::
  2003. *** ../orig.u/sym.h    Wed May 15 17:08:32 1985
  2004. --- sym.h    Sun May 19 16:37:20 1985
  2005. ***************
  2006. *** 45,47
  2007.   #define ESCAPE    '\\'
  2008.   #define BRACE    '{'
  2009.   #define COMCHAR '#'
  2010.  
  2011. --- 45,48 -----
  2012.   #define ESCAPE    '\\'
  2013.   #define BRACE    '{'
  2014.   #define COMCHAR '#'
  2015. + #define PERCENT '%'    /* DAG -- useful addition */
  2016. :::::::: test.c :::::::
  2017. *** ../orig.u/test.c    Wed May 15 17:08:33 1985
  2018. --- test.c    Mon May 20 15:57:01 1985
  2019. ***************
  2020. *** 126,131
  2021.           if (eq(a, "-k"))
  2022.               return(ftype(nxtarg(0), S_ISVTX));
  2023.           if (eq(a, "-p"))
  2024.               return(filtyp(nxtarg(0),S_IFIFO));
  2025.              if (eq(a, "-s"))
  2026.               return(fsizep(nxtarg(0)));
  2027.  
  2028. --- 126,134 -----
  2029.           if (eq(a, "-k"))
  2030.               return(ftype(nxtarg(0), S_ISVTX));
  2031.           if (eq(a, "-p"))
  2032. + #if JOBS && !defined(pyr)
  2033. + #define    S_IFIFO        S_IFSOCK    /* fifo - map to socket on 4.2BSD */
  2034. + #endif
  2035.               return(filtyp(nxtarg(0),S_IFIFO));
  2036.              if (eq(a, "-s"))
  2037.               return(fsizep(nxtarg(0)));
  2038. :::::::: timeout.h :::::::
  2039. No differences encountered
  2040. :::::::: word.c :::::::
  2041. *** ../orig.u/word.c    Wed May 15 17:08:34 1985
  2042. --- word.c    Thu Jun  6 14:37:41 1985
  2043. ***************
  2044. *** 19,24
  2045.       struct argnod    *arg = (struct argnod *)locstak();
  2046.       register char    *argp = arg->argval;
  2047.       int        alpha = 1;
  2048.   
  2049.       wdnum = 0;
  2050.       wdset = 0;
  2051.  
  2052. --- 19,25 -----
  2053.       struct argnod    *arg = (struct argnod *)locstak();
  2054.       register char    *argp = arg->argval;
  2055.       int        alpha = 1;
  2056. +     char        *save;
  2057.   
  2058.       wdnum = 0;
  2059.       wdset = 0;
  2060. ***************
  2061. *** 23,28
  2062.       wdnum = 0;
  2063.       wdset = 0;
  2064.   
  2065.       while (1)
  2066.       {
  2067.           while (c = nextc(0), space(c))        /* skipc() */
  2068.  
  2069. --- 24,30 -----
  2070.       wdnum = 0;
  2071.       wdset = 0;
  2072.   
  2073. +     catcheof = TRUE;
  2074.       while (1)
  2075.       {
  2076.           while (c = nextc(0), space(c))        /* skipc() */
  2077. ***************
  2078. *** 38,43
  2079.               break;    /* out of comment - white space loop */
  2080.           }
  2081.       }
  2082.       if (!eofmeta(c))
  2083.       {
  2084.           do
  2085.  
  2086. --- 40,46 -----
  2087.               break;    /* out of comment - white space loop */
  2088.           }
  2089.       }
  2090. +     save = argp;    /* save start of word */
  2091.       if (!eofmeta(c))
  2092.       {
  2093.           do
  2094. ***************
  2095. *** 69,74
  2096.                               chkpr();
  2097.                       }
  2098.                   }
  2099.               }
  2100.           } while ((c = nextc(0), !eofmeta(c)));
  2101.           argp = endstak(argp);
  2102.  
  2103. --- 72,93 -----
  2104.                               chkpr();
  2105.                       }
  2106.                   }
  2107. +                 else if (c == SQUIGGLE &&
  2108. +                         validtilde (save, argp))
  2109. +                 {
  2110. +                     char *name, *home;
  2111. +                     name = argp;
  2112. +                     while ((c = nextc(0)) != '/' &&
  2113. +                             !eofmeta(c))
  2114. +                         *name++ = c;
  2115. +                     peekc = c;
  2116. +                     *name = '\0';
  2117. +                     home = homedir (argp);
  2118. +                     if(*home)
  2119. +                         movstr (home, --argp);
  2120. +                     argp += length (argp) - 1;
  2121. +                 }
  2122.               }
  2123.           } while ((c = nextc(0), !eofmeta(c)));
  2124.           argp = endstak(argp);
  2125. ***************
  2126. *** 117,122
  2127.               wdval = EOFSYM;
  2128.           if (iopend && eolchar(c))
  2129.           {
  2130.               copy(iopend);
  2131.               iopend = 0;
  2132.           }
  2133.  
  2134. --- 136,144 -----
  2135.               wdval = EOFSYM;
  2136.           if (iopend && eolchar(c))
  2137.           {
  2138. +             int histon = (flags&nohistflg) == 0;
  2139. +             flags |= nohistflg;    /* no history for here docs */
  2140.               copy(iopend);
  2141.               if (histon)        /* turn history back on */
  2142.                   flags &= ~nohistflg;
  2143. ***************
  2144. *** 118,123
  2145.           if (iopend && eolchar(c))
  2146.           {
  2147.               copy(iopend);
  2148.               iopend = 0;
  2149.           }
  2150.       }
  2151.  
  2152. --- 140,147 -----
  2153.   
  2154.               flags |= nohistflg;    /* no history for here docs */
  2155.               copy(iopend);
  2156. +             if (histon)        /* turn history back on */
  2157. +                 flags &= ~nohistflg;
  2158.               iopend = 0;
  2159.           }
  2160.       }
  2161. ***************
  2162. *** 121,126
  2163.               iopend = 0;
  2164.           }
  2165.       }
  2166.       reserv = FALSE;
  2167.       return(wdval);
  2168.   }
  2169.  
  2170. --- 145,151 -----
  2171.               iopend = 0;
  2172.           }
  2173.       }
  2174. +     catcheof = FALSE;
  2175.       reserv = FALSE;
  2176.       return(wdval);
  2177.   }
  2178. ***************
  2179. *** 157,162
  2180.   
  2181.   readc()
  2182.   {
  2183.       register char    c;
  2184.       register int    len;
  2185.       register struct fileblk *f;
  2186.  
  2187. --- 182,188 -----
  2188.   
  2189.   readc()
  2190.   {
  2191. +     static int    eofcount = 0;    /* to break endless catcheof loop */
  2192.       register char    c;
  2193.       register int    len;
  2194.       register struct fileblk *f;
  2195. ***************
  2196. *** 200,209
  2197.       }
  2198.       else if ((len = readb()) <= 0)
  2199.       {
  2200. !         close(f->fdes);
  2201. !         f->fdes = -1;
  2202. !         c = EOF;
  2203. !         f->feof++;
  2204.       }
  2205.       else
  2206.       {
  2207.  
  2208. --- 226,260 -----
  2209.       }
  2210.       else if ((len = readb()) <= 0)
  2211.       {
  2212. !         if (catcheof
  2213. ! #if JOBS
  2214. !          && (flags&(ttyflg|prompt|dotflg)) == (ttyflg|prompt)
  2215. !          && ((flags&noeotflg) || j_finish(FALSE))
  2216. ! #else
  2217. !          && (flags&(ttyflg|prompt|noeotflg|dotflg)) == (ttyflg|prompt|noeotflg)
  2218. ! #endif
  2219. !          && ++eofcount < 10)    /* in case terminal is disconnected */
  2220. !         {
  2221. ! #if JOBS
  2222. !             if ((flags&(ttyflg|prompt|noeotflg))
  2223. !              == (ttyflg|prompt|noeotflg))
  2224. ! #endif
  2225. !                 prs ("use \"exit\"\n");
  2226. ! #if JOBS
  2227. !             /* else "there are stopped jobs" was printed */
  2228. ! #endif
  2229. !             c = NL;
  2230. !         }
  2231. !         else
  2232. !         {
  2233. !             close(f->fdes);
  2234. !             f->fdes = -1;
  2235. !             c = EOF;
  2236. !             f->feof++;
  2237. ! #if JOBS
  2238. !             j_finish(TRUE);
  2239. ! #endif
  2240. !         }
  2241.       }
  2242.       else
  2243.       {
  2244. ***************
  2245. *** 207,213
  2246.       }
  2247.       else
  2248.       {
  2249. !         f->fend = (f->fnxt = f->fbuf) + len;
  2250.           goto retry;
  2251.       }
  2252.       return(c);
  2253.  
  2254. --- 258,265 -----
  2255.       }
  2256.       else
  2257.       {
  2258. !         f->fend = f->fnxt + len;
  2259. !         eofcount = 0;
  2260.           goto retry;
  2261.       }
  2262.       return(c);
  2263. ***************
  2264. *** 214,220
  2265.   }
  2266.   
  2267.   static
  2268. ! readb()
  2269.   {
  2270.       register struct fileblk *f = standin;
  2271.       register int    len;
  2272.  
  2273. --- 266,272 -----
  2274.   }
  2275.   
  2276.   static
  2277. ! readblock ()    /* ADR -- changed the name */
  2278.   {
  2279.       register struct fileblk *f = standin;
  2280.       register int    len;
  2281. ***************
  2282. *** 234,237
  2283.           }
  2284.       } while ((len = read(f->fdes, f->fbuf, f->fsiz)) < 0 && trapnote);
  2285.       return(len);
  2286.   }
  2287.  
  2288. --- 286,486 -----
  2289.           }
  2290.       } while ((len = read(f->fdes, f->fbuf, f->fsiz)) < 0 && trapnote);
  2291.       return(len);
  2292. + }
  2293. + /* readb --- read a block from the outside world, and history process it */
  2294. + /*
  2295. +  * In BSD systems, using the literal next capability of the tty driver, it
  2296. +  * is actually possible to put a newline in the middle of the input line,
  2297. +  * and then hit return, so that the shell sees two lines of input.
  2298. +  *
  2299. +  * As a design decision, if there is a \n in the middle of what we've read
  2300. +  * from a terminal, treat the commands as two separately typed commands. I.e.
  2301. +  *
  2302. +  *    echo hi ^J echo there
  2303. +  *
  2304. +  * is the same as
  2305. +  *
  2306. +  *    echo hi
  2307. +  *    echo there
  2308. +  *
  2309. +  * The major reason for doing it this way is that the history mechanism knows
  2310. +  * that a \n is the end of a line.
  2311. +  *
  2312. +  * Finally, on USG systems, we just leave this code alone, since it won't
  2313. +  * get executed anyway.
  2314. +  */
  2315. + /*
  2316. +  * In word.c, the readc() function keeps a pointer to what standin pointed to
  2317. +  * when readc first gets called.  Therefore, where standin points to can not 
  2318. +  * not change across calls to readb().  To get around this, we change the
  2319. +  * contents of the structure pointed to by standin, saving and restoring
  2320. +  * it as necessary.
  2321. +  */
  2322. + #define LARGEBUF    (HISTSIZE / 2)    /* size of expanded history */
  2323. + static
  2324. + readb()
  2325. + {
  2326. +     int ilen, i, j;
  2327. +     char ibuf[BUFSIZ];    /* input into scratch area, pass to history */
  2328. +     static char expansion[LARGEBUF];
  2329. +     static int moreinbuf = FALSE;
  2330. +     static int saved_ilen = 0;
  2331. +     static int start_here = 0;
  2332. +     static struct fileblk *f = 0;
  2333. +     auto int gotoutofbuf = 0;
  2334. +     if (expanded)    /* just did a history substitution */
  2335. +         expanded = 0;
  2336. +     if ((flags & nohistflg) || (flags & prompt) == 0 || ! isatty (input)
  2337. +             || standin->fstak != 0)
  2338. +     {
  2339. +         ilen = readblock ();
  2340. +         if (ilen > 0)
  2341. +             standin->fnxt = standin->fbuf;
  2342. +         return (ilen);
  2343. +         /* not doing history expansion at all */
  2344. +     }
  2345. +     if (f == 0)
  2346. +         f = standin;
  2347. +     ilen = 0;
  2348. +     /*
  2349. +      * First, if there was more stuff in the last buffer, go and get it.
  2350. +      * If not get some more from the outside world.
  2351. +      *
  2352. +      * Then, make sure we've read up to a newline.
  2353. +      * This is basically in case someone has done something bizarre
  2354. +      * like 'stty raw', and input is coming in one character at a time.
  2355. +      *
  2356. +      * We use a heuristic.  If amount read is just 1, keep reading till
  2357. +      * we get a newline.  Else, read in a complete line from the terminal.
  2358. +      * Once we're in raw mode, can't reset it until a newline is typed.
  2359. +      *
  2360. +      * If not reading one character at a time, then do the stuff for
  2361. +      * embedded newlines.
  2362. +      */
  2363. +     if (moreinbuf)
  2364. +     {
  2365. +         for (i = 0, j = start_here; f->fbuf[j] != NL && j < saved_ilen; i++, j++)
  2366. +             ibuf[i] = f->fbuf[j];
  2367. + #ifdef notdef
  2368. +         if (f->fbuf[j] != NL)
  2369. +         {
  2370. +             prs ("internal i/o error C in readb\n");
  2371. +             return (0);
  2372. +         }
  2373. + #endif
  2374. +         if (f->fbuf[j] == NL)
  2375. +             ibuf[i++] = NL;
  2376. +         ibuf[i] = '\0';
  2377. +         ilen = i;
  2378. +         /* embedded newline */
  2379. +         moreinbuf = (++j < saved_ilen - 1);
  2380. +         if (moreinbuf)
  2381. +             start_here = j;    /* where to start next time */
  2382. +         gotoutofbuf = 1;
  2383. +     }
  2384. +     else    /* wasn't an embedded \n last time */
  2385. +     {
  2386. +         ilen = readblock ();
  2387. +     
  2388. +         if (ilen <= 0)    /* EOF or error */
  2389. +             return (ilen);
  2390. +         if (ilen == 1)    /* either in raw mode, or an empty line */
  2391. +         {
  2392. +             i = 0;
  2393. +             ibuf[i++] = f->fbuf[0];
  2394. +             if (f->fbuf[0] == NL)
  2395. +             {
  2396. +                 ibuf[i] = '\0';
  2397. +                 goto dohist;
  2398. +             }
  2399. +             while ((ilen = readblock()) > 0)
  2400. +             {
  2401. +                 if (ilen != 1)
  2402. +                 {
  2403. +                     prs ("internal i/o error A in readb\n");
  2404. +                     return (0);
  2405. +                 }
  2406. +                 ibuf[i++] = f->fbuf[0];
  2407. +                 if (f->fbuf[0] == NL)
  2408. +                 {
  2409. +                     ibuf[i] = '\0';
  2410. +                     break;    /* while */
  2411. +                 }
  2412. +             }
  2413. +             ilen = i;
  2414. +             gotoutofbuf = TRUE;
  2415. +             /* force code below to use collected string */
  2416. +         }
  2417. +         else
  2418. +         {
  2419. +             /* reading bunches of characters at once */
  2420. +             for (i = 0; f->fbuf[i] != NL && i < ilen; i++)
  2421. +                 ibuf[i] = f->fbuf[i];
  2422. + #ifdef notdef
  2423. +             if (f->fbuf[i] != NL)
  2424. +             {
  2425. +                 prs ("internal i/o error B in readb\n");
  2426. +                 return (0);
  2427. +             }
  2428. + #endif
  2429. +             ibuf[i++] = NL;
  2430. +             ibuf[i] = '\0';
  2431. +             /* ilen was set by readblock() */
  2432. +             /* embedded newline */
  2433. +             moreinbuf = (i < ilen - 1);
  2434. +             if (moreinbuf)
  2435. +             {
  2436. +                 saved_ilen = ilen;
  2437. +                 start_here = i;
  2438. +                 /* where to start next time */
  2439. +                 gotoutofbuf = 1;
  2440. +             }
  2441. +         }
  2442. +     }
  2443. + dohist:
  2444. +     /* quick heuristic */
  2445. +     if (! gotoutofbuf && ilen == 1 && f->fbuf[0] == NL)
  2446. +     {
  2447. +         f->fnxt = f->fbuf;
  2448. +         return (ilen);
  2449. +     }
  2450. +     if (histsub (ibuf, expansion, sizeof expansion))
  2451. +     {
  2452. +         int olen = length (expansion) - 1;
  2453. +         if (! expanded && ! gotoutofbuf)
  2454. +         {
  2455. +             standin->fnxt = standin->fbuf;
  2456. +             return (ilen);
  2457. +         }
  2458. +         /* else
  2459. +             expanded == TRUE or from buffer */
  2460. +         standin->fnxt = expansion;
  2461. +         return (olen);
  2462. +     }
  2463. +     else
  2464. +     {
  2465. +         /* hist expansion failed, return an empty line */
  2466. +         standin->fnxt = standin->fbuf;
  2467. +         standin->fbuf[0] = NL;
  2468. +         return (1);
  2469. +     }
  2470.   }
  2471. :::::::: xec.c :::::::
  2472. *** ../orig.u/xec.c    Wed May 15 17:08:37 1985
  2473. --- xec.c    Wed Jun  5 11:11:18 1985
  2474. ***************
  2475. *** 27,32
  2476.        */
  2477.       register struct trenod    *t;
  2478.       char        *sav = savstak();
  2479.   
  2480.       sigchk();
  2481.       if (!errorflg)
  2482.  
  2483. --- 27,42 -----
  2484.        */
  2485.       register struct trenod    *t;
  2486.       char        *sav = savstak();
  2487. + #if pyr
  2488. +     auto int change_univ = FALSE;
  2489. +     auto int new_univ = 0;
  2490. +     /*
  2491. +      * univesrses run from 1 to NUMUNIV: We start out at 0
  2492. +      * and increment new_univ in the switch for internal
  2493. +      * commands, below.  new_univ must *not* be assigned to, directly
  2494. +      * or via side effects, any place else.
  2495. +      */
  2496. + #endif
  2497.   
  2498.       sigchk();
  2499.       if (!errorflg)
  2500. ***************
  2501. *** 109,114
  2502.                       if (flags & execpr)
  2503.                           execprint(com);
  2504.   
  2505.                       if (comtype == NOTFOUND)
  2506.                       {
  2507.                           pos = hashdata(cmdhash);
  2508.  
  2509. --- 119,130 -----
  2510.                       if (flags & execpr)
  2511.                           execprint(com);
  2512.   
  2513. +                     /*
  2514. +                      * fix a bug which caused the shell
  2515. +                      * to do not do a second command if
  2516. +                      * the first was not found. (bug fix
  2517. +                      * from USENET)
  2518. +                      */
  2519.                       if (comtype == NOTFOUND)
  2520.                       {
  2521.                           char *errstr;
  2522. ***************
  2523. *** 111,116
  2524.   
  2525.                       if (comtype == NOTFOUND)
  2526.                       {
  2527.                           pos = hashdata(cmdhash);
  2528.                           if (pos == 1)
  2529.                               failed(*com, notfound);
  2530.  
  2531. --- 127,134 -----
  2532.                        */
  2533.                       if (comtype == NOTFOUND)
  2534.                       {
  2535. +                         char *errstr;
  2536.                           pos = hashdata(cmdhash);
  2537.                           if (pos == 1)
  2538.                               errstr = notfound;
  2539. ***************
  2540. *** 113,119
  2541.                       {
  2542.                           pos = hashdata(cmdhash);
  2543.                           if (pos == 1)
  2544. !                             failed(*com, notfound);
  2545.                           else if (pos == 2)
  2546.                               failed(*com, badexec);
  2547.                           else
  2548.  
  2549. --- 131,137 -----
  2550.   
  2551.                           pos = hashdata(cmdhash);
  2552.                           if (pos == 1)
  2553. !                             errstr = notfound;
  2554.                           else if (pos == 2)
  2555.                               errstr = badexec;
  2556.                           else
  2557. ***************
  2558. *** 115,121
  2559.                           if (pos == 1)
  2560.                               failed(*com, notfound);
  2561.                           else if (pos == 2)
  2562. !                             failed(*com, badexec);
  2563.                           else
  2564.                               failed(*com, badperm);
  2565.                           break;
  2566.  
  2567. --- 133,139 -----
  2568.                           if (pos == 1)
  2569.                               errstr = notfound;
  2570.                           else if (pos == 2)
  2571. !                             errstr = badexec;
  2572.                           else
  2573.                               errstr = badperm;
  2574.                           prp();
  2575. ***************
  2576. *** 117,123
  2577.                           else if (pos == 2)
  2578.                               failed(*com, badexec);
  2579.                           else
  2580. !                             failed(*com, badperm);
  2581.                           break;
  2582.                       }
  2583.   
  2584.  
  2585. --- 135,147 -----
  2586.                           else if (pos == 2)
  2587.                               errstr = badexec;
  2588.                           else
  2589. !                             errstr = badperm;
  2590. !                         prp();
  2591. !                         prs_cntl(*com);
  2592. !                         prs (colon);
  2593. !                         prs (errstr);
  2594. !                         newline();
  2595. !                         exitval = 1;
  2596.                           break;
  2597.                       }
  2598.   
  2599. ***************
  2600. *** 148,153
  2601.                                   if ((f = pathopen(getpath(a1), a1)) < 0)    
  2602.                                       failed(a1, notfound);    
  2603.                                   else    
  2604.                                       execexp(0, f);    
  2605.                               }    
  2606.                               break;    
  2607.  
  2608. --- 172,181 -----
  2609.                                   if ((f = pathopen(getpath(a1), a1)) < 0)    
  2610.                                       failed(a1, notfound);    
  2611.                                   else    
  2612. +                                 {
  2613. +                                     int    savedot = flags&dotflg;
  2614. +                                     flags |= dotflg;
  2615.                                       execexp(0, f);    
  2616.                                       flags &= ~dotflg;
  2617.                                       flags |= savedot;
  2618. ***************
  2619. *** 149,154
  2620.                                       failed(a1, notfound);    
  2621.                                   else    
  2622.                                       execexp(0, f);    
  2623.                               }    
  2624.                               break;    
  2625.                   
  2626.  
  2627. --- 177,185 -----
  2628.   
  2629.                                       flags |= dotflg;
  2630.                                       execexp(0, f);    
  2631. +                                     flags &= ~dotflg;
  2632. +                                     flags |= savedot;
  2633. +                                 }
  2634.                               }    
  2635.                               break;    
  2636.                   
  2637. ***************
  2638. *** 163,169
  2639.                                   prc_buff(NL);    
  2640.                               }    
  2641.                               break;    
  2642. !                 
  2643.                           case SYSEXIT:    
  2644.                               flags |= forked;    /* force exit */    
  2645.                               exitsh(a1 ? stoi(a1) : retval);
  2646.  
  2647. --- 194,200 -----
  2648.                                   prc_buff(NL);    
  2649.                               }    
  2650.                               break;    
  2651.                           case SYSEXIT:    
  2652.   #if JOBS
  2653.                               if (j_finish(FALSE))
  2654. ***************
  2655. *** 165,170
  2656.                               break;    
  2657.                   
  2658.                           case SYSEXIT:    
  2659.                               flags |= forked;    /* force exit */    
  2660.                               exitsh(a1 ? stoi(a1) : retval);
  2661.                   
  2662.  
  2663. --- 196,207 -----
  2664.                               break;    
  2665.   
  2666.                           case SYSEXIT:    
  2667. + #if JOBS
  2668. +                             if (j_finish(FALSE))
  2669. +                                 break;
  2670. + #endif
  2671. +                             histsave (histfnod.namval);
  2672. +                             /* save before setting flag */
  2673.                               flags |= forked;    /* force exit */    
  2674.   
  2675.                               exitsh(a1 ? stoi(a1) : retval);
  2676. ***************
  2677. *** 166,171
  2678.                   
  2679.                           case SYSEXIT:    
  2680.                               flags |= forked;    /* force exit */    
  2681.                               exitsh(a1 ? stoi(a1) : retval);
  2682.                   
  2683.                           case SYSNULL:    
  2684.  
  2685. --- 203,209 -----
  2686.                               histsave (histfnod.namval);
  2687.                               /* save before setting flag */
  2688.                               flags |= forked;    /* force exit */    
  2689.                               exitsh(a1 ? stoi(a1) : retval);
  2690.                   
  2691.                           case SYSNULL:    
  2692. ***************
  2693. *** 248,256
  2694.                               }    
  2695.           
  2696.   #ifdef RES    /* Research includes login as part of the shell */    
  2697. !         
  2698. !                         case SYSLOGIN:    
  2699. !                             oldsigs();    
  2700.                               execa(com, -1);
  2701.                               done();    
  2702.   #else    
  2703.  
  2704. --- 286,296 -----
  2705.                               }    
  2706.           
  2707.   #ifdef RES    /* Research includes login as part of the shell */    
  2708. !                         case SYSLOGIN:
  2709. !                             histsave (histfnod.namval);
  2710. !                             flags |= forked;    /* DAG -- bug fix (force bad exec to terminate shell) */
  2711. !                             oldsigs();
  2712.                               execa(com, -1);
  2713.                               done();
  2714.   #else
  2715. ***************
  2716. *** 252,260
  2717.                           case SYSLOGIN:    
  2718.                               oldsigs();    
  2719.                               execa(com, -1);
  2720. !                             done();    
  2721. ! #else    
  2722. !             
  2723.                           case SYSNEWGRP:    
  2724.                               if (flags & rshflg)    
  2725.                                   failed(com[0], restricted);    
  2726.  
  2727. --- 292,299 -----
  2728.                               flags |= forked;    /* DAG -- bug fix (force bad exec to terminate shell) */
  2729.                               oldsigs();
  2730.                               execa(com, -1);
  2731. !                             done();
  2732. ! #else
  2733.                           case SYSNEWGRP:    
  2734.                               if (flags & rshflg)    
  2735.                                   failed(com[0], restricted);    
  2736. ***************
  2737. *** 260,265
  2738.                                   failed(com[0], restricted);    
  2739.                               else    
  2740.                               {    
  2741.                                   flags |= forked;    /* force bad exec to terminate shell */    
  2742.                                   oldsigs();    
  2743.                                   execa(com, -1);
  2744.  
  2745. --- 299,305 -----
  2746.                                   failed(com[0], restricted);    
  2747.                               else    
  2748.                               {    
  2749. +                                 histsave (histfnod.namval);
  2750.                                   flags |= forked;    /* force bad exec to terminate shell */    
  2751.                                   oldsigs();    
  2752.                                   execa(com, -1);
  2753. ***************
  2754. *** 266,272
  2755.                                   done();    
  2756.                               }    
  2757.           
  2758. ! #endif    
  2759.           
  2760.                           case SYSCD:    
  2761.                               if (flags & rshflg)    
  2762.  
  2763. --- 306,312 -----
  2764.                                   done();    
  2765.                               }    
  2766.           
  2767. ! #endif
  2768.           
  2769.                           case SYSCD:    
  2770.                               if (flags & rshflg)    
  2771. ***************
  2772. *** 273,278
  2773.                                   failed(com[0], restricted);    
  2774.                               else if ((a1 && *a1) || (a1 == 0 && (a1 = homenod.namval)))    
  2775.                               {    
  2776.                                   char *cdpath;    
  2777.                                   char *dir;    
  2778.                                   int f;    
  2779.  
  2780. --- 313,319 -----
  2781.                                   failed(com[0], restricted);    
  2782.                               else if ((a1 && *a1) || (a1 == 0 && (a1 = homenod.namval)))    
  2783.                               {    
  2784. +                                 register char *safe;    /* DAG -- added (see note, below) */
  2785.                                   char *cdpath;    
  2786.                                   char *dir;    
  2787.                                   int f;    
  2788. ***************
  2789. *** 279,286
  2790.           
  2791.                                   if ((cdpath = cdpnod.namval) == 0 ||    
  2792.                                        *a1 == '/' ||    
  2793. !                                      cf(a1, ".") == 0 ||    
  2794. !                                      cf(a1, "..") == 0 ||    
  2795.                                        (*a1 == '.' && (*(a1+1) == '/' || *(a1+1) == '.' && *(a1+2) == '/')))    
  2796.                                       cdpath = nullstr;    
  2797.           
  2798.  
  2799. --- 320,327 -----
  2800.           
  2801.                                   if ((cdpath = cdpnod.namval) == 0 ||    
  2802.                                        *a1 == '/' ||    
  2803. !                                      cf(a1, ".") == 0 ||
  2804. !                                      cf(a1, "..") == 0 ||
  2805.                                        (*a1 == '.' && (*(a1+1) == '/' || *(a1+1) == '.' && *(a1+2) == '/')))    
  2806.                                       cdpath = nullstr;    
  2807.           
  2808. ***************
  2809. *** 284,289
  2810.                                        (*a1 == '.' && (*(a1+1) == '/' || *(a1+1) == '.' && *(a1+2) == '/')))    
  2811.                                       cdpath = nullstr;    
  2812.           
  2813.                                   do    
  2814.                                   {    
  2815.                                       dir = cdpath;    
  2816.  
  2817. --- 325,337 -----
  2818.                                        (*a1 == '.' && (*(a1+1) == '/' || *(a1+1) == '.' && *(a1+2) == '/')))    
  2819.                                       cdpath = nullstr;    
  2820.           
  2821. + /* DAG -- catpath() leaves the trial directory above the top of the "stack".
  2822. +     This is too dangerous; systems using directory access routines may
  2823. +     alloc() storage and clobber the string.  Therefore I have changed the
  2824. +     code to alloc() a safe place to put the trial strings.  Most of the
  2825. +     changes involved replacing "curstak()" with "safe".
  2826. + */                                safe = alloc((unsigned)(length(cdpath) + length(a1)));    /* DAG -- added */
  2827.                                   do    
  2828.                                   {    
  2829.                                       dir = cdpath;    
  2830. ***************
  2831. *** 288,293
  2832.                                   {    
  2833.                                       dir = cdpath;    
  2834.                                       cdpath = catpath(cdpath,a1);    
  2835.                                   }    
  2836.                                   while ((f = (chdir(curstak()) < 0)) && cdpath);
  2837.           
  2838.  
  2839. --- 336,342 -----
  2840.                                   {    
  2841.                                       dir = cdpath;    
  2842.                                       cdpath = catpath(cdpath,a1);    
  2843. +                                     (void)movstr(curstak(),safe);    /* DAG -- added (see note, above) */
  2844.                                   }    
  2845.   #if !defined(SYMLINK) && defined(JOBS)
  2846.                                   while ((f = (cwdir(safe) < 0)) && cdpath);    /* DAG */
  2847. ***************
  2848. *** 289,295
  2849.                                       dir = cdpath;    
  2850.                                       cdpath = catpath(cdpath,a1);    
  2851.                                   }    
  2852. !                                 while ((f = (chdir(curstak()) < 0)) && cdpath);
  2853.           
  2854.                                   if (f)    
  2855.                                       failed(a1, baddir);    
  2856.  
  2857. --- 338,348 -----
  2858.                                       cdpath = catpath(cdpath,a1);    
  2859.                                       (void)movstr(curstak(),safe);    /* DAG -- added (see note, above) */
  2860.                                   }    
  2861. ! #if !defined(SYMLINK) && defined(JOBS)
  2862. !                                 while ((f = (cwdir(safe) < 0)) && cdpath);    /* DAG */
  2863. ! #else
  2864. !                                 while ((f = (chdir(safe) < 0)) && cdpath);    /* DAG */
  2865. ! #endif
  2866.           
  2867.                                   if (f)    
  2868.                                   {
  2869. ***************
  2870. *** 292,297
  2871.                                   while ((f = (chdir(curstak()) < 0)) && cdpath);
  2872.           
  2873.                                   if (f)    
  2874.                                       failed(a1, baddir);    
  2875.                                   else 
  2876.                                   {
  2877.  
  2878. --- 345,352 -----
  2879.   #endif
  2880.           
  2881.                                   if (f)    
  2882. +                                 {
  2883. +                                     free(safe);    /* DAG -- added (see note, above) */
  2884.                                       failed(a1, baddir);    
  2885.                                   }
  2886.                                   else 
  2887. ***************
  2888. *** 293,298
  2889.           
  2890.                                   if (f)    
  2891.                                       failed(a1, baddir);    
  2892.                                   else 
  2893.                                   {
  2894.                                       cwd(curstak());
  2895.  
  2896. --- 348,354 -----
  2897.                                   {
  2898.                                       free(safe);    /* DAG -- added (see note, above) */
  2899.                                       failed(a1, baddir);    
  2900. +                                 }
  2901.                                   else 
  2902.                                   {
  2903.   #if defined(SYMLINK) || !defined(JOBS)
  2904. ***************
  2905. *** 295,301
  2906.                                       failed(a1, baddir);    
  2907.                                   else 
  2908.                                   {
  2909. !                                     cwd(curstak());
  2910.                                       if (cf(nullstr, dir) &&    
  2911.                                           *dir != ':' &&    
  2912.                                            any('/', curstak()) &&    
  2913.  
  2914. --- 351,359 -----
  2915.                                   }
  2916.                                   else 
  2917.                                   {
  2918. ! #if defined(SYMLINK) || !defined(JOBS)
  2919. !                                     cwd(safe);    /* DAG */
  2920. ! #endif
  2921.                                       if (cf(nullstr, dir) &&    
  2922.                                           *dir != ':' &&    
  2923.                                            any('/', safe) &&    /* DAG */
  2924. ***************
  2925. *** 298,304
  2926.                                       cwd(curstak());
  2927.                                       if (cf(nullstr, dir) &&    
  2928.                                           *dir != ':' &&    
  2929. !                                          any('/', curstak()) &&    
  2930.                                            flags & prompt)    
  2931.                                       {    
  2932.                                           prs_buff(curstak());    
  2933.  
  2934. --- 356,362 -----
  2935.   #endif
  2936.                                       if (cf(nullstr, dir) &&    
  2937.                                           *dir != ':' &&    
  2938. !                                          any('/', safe) &&    /* DAG */
  2939.                                            flags & prompt)    
  2940.                                           cwdprint();    /* DAG -- improvement */
  2941.                                       free(safe);    /* DAG -- added (see note, above) */
  2942. ***************
  2943. *** 300,309
  2944.                                           *dir != ':' &&    
  2945.                                            any('/', curstak()) &&    
  2946.                                            flags & prompt)    
  2947. !                                     {    
  2948. !                                         prs_buff(curstak());    
  2949. !                                         prc_buff(NL);    
  2950. !                                     }
  2951.                                   }
  2952.                                   zapcd();
  2953.                               }    
  2954.  
  2955. --- 358,365 -----
  2956.                                           *dir != ':' &&    
  2957.                                            any('/', safe) &&    /* DAG */
  2958.                                            flags & prompt)    
  2959. !                                         cwdprint();    /* DAG -- improvement */
  2960. !                                     free(safe);    /* DAG -- added (see note, above) */
  2961.                                   }
  2962.                                   zapcd();
  2963.                               }    
  2964. ***************
  2965. *** 452,458
  2966.                                   if (command == 1 || command == 4)    
  2967.                                   {    
  2968.                                       prl(i);    
  2969. !                                     prc_buff('\n');    
  2970.                                   }    
  2971.                                   break;    
  2972.                               }                
  2973.  
  2974. --- 508,514 -----
  2975.                                   if (command == 1 || command == 4)    
  2976.                                   {    
  2977.                                       prl(i);    
  2978. !                                     prc_buff(NL);    
  2979.                                   }    
  2980.                                   break;    
  2981.                               }                
  2982. ***************
  2983. *** 478,486
  2984.                                   prc_buff(NL);    
  2985.                               }    
  2986.                               break;    
  2987. !         
  2988. ! #endif    
  2989. !         
  2990.                           case SYSTST:
  2991.                               exitval = test(argn, com);
  2992.                               break;
  2993.  
  2994. --- 534,540 -----
  2995.                                   prc_buff(NL);    
  2996.                               }    
  2997.                               break;    
  2998.                           case SYSTST:
  2999.                               exitval = test(argn, com);
  3000.                               break;
  3001. ***************
  3002. *** 484,489
  3003.                           case SYSTST:
  3004.                               exitval = test(argn, com);
  3005.                               break;
  3006.   
  3007.                           case SYSECHO:
  3008.                               exitval = echo(argn, com);
  3009.  
  3010. --- 538,544 -----
  3011.                           case SYSTST:
  3012.                               exitval = test(argn, com);
  3013.                               break;
  3014. + #endif    /* RES (DAG -- bug fix: SYSTST not in RES) */
  3015.   
  3016.                           case SYSECHO:
  3017.                               exitval = echo(argn, com);
  3018. ***************
  3019. *** 548,553
  3020.                               }
  3021.                               break;
  3022.   
  3023.                           default:    
  3024.                               prs_buff("unknown builtin\n");
  3025.                           }    
  3026.  
  3027. --- 603,675 -----
  3028.                               }
  3029.                               break;
  3030.   
  3031. + #if JOBS
  3032. +                         case SYSJOBS:
  3033. +                             j_print();
  3034. +                             break;
  3035. +                         case SYSFG:
  3036. +                             j_resume(a1, FALSE);
  3037. +                             break;
  3038. +                         case SYSBG:
  3039. +                             j_resume(a1, TRUE);
  3040. +                             break;
  3041. +                         case SYSSUSPEND:
  3042. +                             exitval = 1;
  3043. +                             if (getppid() == 1)
  3044. +                                 prs ("cannot suspend a login shell\n");    /* yet ... */
  3045. +                             else
  3046. +                             {
  3047. +                                 exitval = 0;
  3048. +                                 kill (getpid(), SIGSTOP);
  3049. +                             }
  3050. +                             break;
  3051. + #endif
  3052. + #if pyr
  3053. +                         /*
  3054. +                          * UCB is Universe 2
  3055. +                          * ATT is Universe 1
  3056. +                          * new_univ == 0
  3057. +                          */
  3058. +                         case SYSUCB:
  3059. +                             new_univ++;
  3060. +                             /* fall thru */
  3061. +                         case SYSATT:
  3062. +                             new_univ++;
  3063. +                             if (argn > 1)
  3064. +                             {
  3065. +                                 change_univ = TRUE;
  3066. +                                 com++;
  3067. +                                 goto doit;
  3068. +                             }
  3069. +                             else
  3070. +                             {
  3071. +                                 setuniverse (cur_univ = new_univ);
  3072. +                                 univnod.namflg &= ~N_RDONLY;
  3073. +                                 assign (& univnod, univ_name[cur_univ - 1]);
  3074. +                                 attrib ((& univnod), N_RDONLY);
  3075. +                                 break;
  3076. +                             }
  3077. +                         
  3078. +                         case SYSUNIVERSE:
  3079. +                             if (eq(com[1], "-l"))
  3080. +                                 prs_buff (univ_longname[cur_univ - 1]);
  3081. +                             else
  3082. +                                 prs_buff (univ_name[cur_univ - 1]);
  3083. +                             prc_buff (NL);
  3084. +                             break;
  3085. + #endif
  3086. +                         case SYSHISTORY:
  3087. +                             exitval = history (argn, com);
  3088. +                             break;
  3089.                           default:    
  3090.                               prs_buff("unknown builtin\n");
  3091.                           }    
  3092. ***************
  3093. *** 586,591
  3094.               }
  3095.   
  3096.           case TFORK:
  3097.               exitval = 0;
  3098.               if (execflg && (treeflgs & (FAMP | FPOU)) == 0)
  3099.                   parent = 0;
  3100.  
  3101. --- 708,716 -----
  3102.               }
  3103.   
  3104.           case TFORK:
  3105. + #if pyr
  3106. +         doit:
  3107. + #endif
  3108.               exitval = 0;
  3109.               if (execflg && (treeflgs & (FAMP | FPOU)) == 0)
  3110.                   parent = 0;
  3111. ***************
  3112. *** 625,630
  3113.                       alarm(forkcnt);
  3114.                       pause(); 
  3115.                   }
  3116.               }
  3117.               if (parent)
  3118.               {
  3119.  
  3120. --- 750,759 -----
  3121.                       alarm(forkcnt);
  3122.                       pause(); 
  3123.                   }
  3124. + #if JOBS
  3125. +                 if (parent == 0)
  3126. +                     j_top_level = FALSE;
  3127. + #endif
  3128.               }
  3129.               if (parent)
  3130.               {
  3131. ***************
  3132. *** 633,638
  3133.                    * it may or may not wait for the child
  3134.                    */
  3135.                   if (treeflgs & FPRS && flags & ttyflg)
  3136.                   {
  3137.                       prn(parent);
  3138.                       newline();
  3139.  
  3140. --- 762,770 -----
  3141.                    * it may or may not wait for the child
  3142.                    */
  3143.                   if (treeflgs & FPRS && flags & ttyflg)
  3144. + #if JOBS
  3145. +                 if ((flags&jobflg) == 0)
  3146. + #endif
  3147.                   {
  3148.                       prn(parent);
  3149.                       newline();
  3150. ***************
  3151. *** 639,644
  3152.                   }
  3153.                   if (treeflgs & FPCL)
  3154.                       closepipe(pf1);
  3155.                   if ((treeflgs & (FAMP | FPOU)) == 0)
  3156.                       await(parent, 0);
  3157.                   else if ((treeflgs & FAMP) == 0)
  3158.  
  3159. --- 771,779 -----
  3160.                   }
  3161.                   if (treeflgs & FPCL)
  3162.                       closepipe(pf1);
  3163. + #if JOBS
  3164. +                 j_child_post(parent, treeflgs&FAMP, treeflgs&FPIN, t);
  3165. + #endif
  3166.                   if ((treeflgs & (FAMP | FPOU)) == 0)
  3167.                   {
  3168.                       await(parent, 0);
  3169. ***************
  3170. *** 640,645
  3171.                   if (treeflgs & FPCL)
  3172.                       closepipe(pf1);
  3173.                   if ((treeflgs & (FAMP | FPOU)) == 0)
  3174.                       await(parent, 0);
  3175.                   else if ((treeflgs & FAMP) == 0)
  3176.                       post(parent);
  3177.  
  3178. --- 775,781 -----
  3179.                   j_child_post(parent, treeflgs&FAMP, treeflgs&FPIN, t);
  3180.   #endif
  3181.                   if ((treeflgs & (FAMP | FPOU)) == 0)
  3182. +                 {
  3183.                       await(parent, 0);
  3184.   #if JOBS
  3185.                       j_reset_pg();
  3186. ***************
  3187. *** 641,646
  3188.                       closepipe(pf1);
  3189.                   if ((treeflgs & (FAMP | FPOU)) == 0)
  3190.                       await(parent, 0);
  3191.                   else if ((treeflgs & FAMP) == 0)
  3192.                       post(parent);
  3193.                   else
  3194.  
  3195. --- 777,786 -----
  3196.                   if ((treeflgs & (FAMP | FPOU)) == 0)
  3197.                   {
  3198.                       await(parent, 0);
  3199. + #if JOBS
  3200. +                     j_reset_pg();
  3201. + #endif
  3202. +                 }
  3203.                   else if ((treeflgs & FAMP) == 0)
  3204.                       post(parent);
  3205.                   else
  3206. ***************
  3207. *** 650,655
  3208.               }
  3209.               else    /* this is the forked branch (child) of execute */
  3210.               {
  3211.                   flags |= forked;
  3212.                   fiotemp  = 0;
  3213.   
  3214.  
  3215. --- 790,805 -----
  3216.               }
  3217.               else    /* this is the forked branch (child) of execute */
  3218.               {
  3219. + #if pyr
  3220. +                 if (change_univ)
  3221. +                 {
  3222. +                     setuniverse (new_univ);
  3223. +                     univnod.namflg &= ~N_RDONLY;
  3224. +                     assign (& univnod, univ_name[cur_univ - 1]);
  3225. +                     attrib ((& univnod), N_RDONLY);
  3226. +                 }
  3227. + #endif
  3228.                   flags |= forked;
  3229.                   fiotemp  = 0;
  3230.   
  3231. ***************
  3232. *** 674,679
  3233.                    */
  3234.                   oldsigs();
  3235.                   if (treeflgs & FINT)
  3236.                   {
  3237.                       signal(SIGINT, 1);
  3238.                       signal(SIGQUIT, 1);
  3239.  
  3240. --- 824,832 -----
  3241.                    */
  3242.                   oldsigs();
  3243.                   if (treeflgs & FINT)
  3244. + #if JOBS
  3245. +                 if ((flags&jobflg) == 0)
  3246. + #endif
  3247.                   {
  3248.                       signal(SIGINT, SIG_IGN);    /* DAG */
  3249.                       signal(SIGQUIT, SIG_IGN);    /* DAG */
  3250. ***************
  3251. *** 675,682
  3252.                   oldsigs();
  3253.                   if (treeflgs & FINT)
  3254.                   {
  3255. !                     signal(SIGINT, 1);
  3256. !                     signal(SIGQUIT, 1);
  3257.   
  3258.   #ifdef NICE
  3259.                       nice(NICEVAL);
  3260.  
  3261. --- 828,835 -----
  3262.                   if ((flags&jobflg) == 0)
  3263.   #endif
  3264.                   {
  3265. !                     signal(SIGINT, SIG_IGN);    /* DAG */
  3266. !                     signal(SIGQUIT, SIG_IGN);    /* DAG */
  3267.   
  3268.   #ifdef NICE
  3269.                       nice(NICEVAL);
  3270. ***************
  3271. *** 700,705
  3272.                    * default std input for &
  3273.                    */
  3274.                   if (treeflgs & FINT && ioset == 0)
  3275.                       rename(chkopen(devnull), 0);
  3276.                   /*
  3277.                    * io redirection
  3278.  
  3279. --- 853,861 -----
  3280.                    * default std input for &
  3281.                    */
  3282.                   if (treeflgs & FINT && ioset == 0)
  3283. + #if JOBS
  3284. +                 if ((flags&jobflg) == 0)
  3285. + #endif
  3286.                       rename(chkopen(devnull), 0);
  3287.                   /*
  3288.                    * io redirection
  3289.  
  3290.