home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume10 / sxt-sh-jobs / part02 / proc.c next >
Encoding:
C/C++ Source or Header  |  1987-06-22  |  21.8 KB  |  1,102 lines

  1. /*
  2.  *         SH Shell.
  3.  *
  4.  *
  5.  *    Copyright (c) S. Brown, 1987
  6.  *
  7.  *
  8.  *    wait stuff, for processes to be waited for.
  9.  *
  10.  *    also, job-control.
  11.  */
  12.  
  13. #include "defs.h"
  14.  
  15. extern char *sysmsg[];        /* signal messages */
  16.  
  17. #ifdef JOB
  18.  
  19. /*
  20.  *    JOB-CONTROL
  21.  */
  22.  
  23.  
  24. #ifdef JOBSXT
  25. #undef input
  26. #include <sys/types.h>
  27. #include <sys/tty.h>
  28. #include <sys/sxt.h>
  29. #include <errno.h>
  30. #endif JOBSXT
  31.  
  32. #define PROCESS_DOT_C
  33. #include "job.h"
  34. #include <signal.h>
  35.  
  36. int currentjob = 0;        /* current job */
  37. int fgjobs = 0;            /* no. of foreground jobs */
  38. int bgjobs = 0;            /* no. of background jobs */
  39. int mainpgrp;            /* initial process group */
  40. int dfltjob;            /* default jobnumber for fg, bg, notify ... */
  41. int bdfltjob;            /* back-one default */
  42. int maxpri = 0;            /* max. priority */
  43. int extracnt=0;            /* number of children dead in queue */
  44.  
  45. #ifdef JOBSXT
  46. int sxtchan = -1;        /* sxt channel set */
  47. int savsxtchan = -1;        /* saved chan fd */
  48. struct sxtblock sxtblock;    /* block masks */
  49. int sxtcontrol = -1;        /* controlling sxt-tty */
  50. int sxtkludge = 1;        /* real tty virtual offset of controller */
  51. char blkmask;            /* virtual blocks */
  52. TTYNOD realtty;            /* state of physical tty */
  53.  
  54. #define BLKBIT(c,n) ((c)&(1<<SXT(n)))
  55. #define SIGBLOCK 21        /* fake signal-number for blockages */
  56. int sxt_fd = -1;
  57. #endif JOBSXT
  58.  
  59.  
  60.  
  61. struct jobnod *jobs[JOB_MAX];
  62. struct extrawait extras[EXTRAPROCS];
  63.  
  64. /*
  65.  *    empty all of jobs table
  66.  */
  67. postclr()
  68. {
  69.     register int i;
  70.  
  71.     for (i=1; i<JOB_MAX; i++)
  72.         postjclr(i);
  73.     bgjobs = fgjobs = 0;
  74. }
  75.  
  76.  
  77. /*
  78.  *    clear out an entry in jobs table
  79.  */
  80. postjclr(jobno)
  81. {
  82.     register int i;
  83.     if (jobs[i=jobno]){
  84.         free((char *)jobs[i]->jb_dir);
  85.         free((char *)jobs[i]->jb_cmd);
  86. #ifdef JOBSXT
  87.         if (jobs[i]->jb_sxtfg) close(jobs[i]->jb_sxtfg);
  88.         blkmask &= ~(1<<SXT(i));
  89. #endif 
  90.         free((char *)jobs[i]);
  91.         jobs[i] = (struct jobnod *)0;
  92.     }
  93.     if (i==dfltjob || i==bdfltjob) setdfj();
  94. }
  95.  
  96. /*
  97.  * set default job
  98.  */
  99. setdfj()
  100. {
  101.     register int i;
  102.  
  103.     maxpri = 0;
  104.     bdfltjob = dfltjob;
  105.     dfltjob = -1;
  106.     for (i=1; i<JOB_MAX; i++)
  107.         if (jobs[i] && jobs[i]->jb_pri > maxpri){
  108.             maxpri = jobs[i]->jb_pri;
  109.             bdfltjob = dfltjob;
  110.             dfltjob = i;
  111.         }
  112. }
  113.  
  114.  
  115. /*
  116.  *    place process in jobs table 
  117.  */
  118. post(procid)
  119. int    procid;
  120. {
  121.     register struct jobnod *jp;
  122.     register int i;
  123.  
  124.     jp = jobs[currentjob];
  125.     if (jp){
  126.         for (i=0; i<PPERJ; i++)
  127.             if (jp->jb_proc[i].proc_pid==0) break;
  128.         if (i>PPERJ-1 || (jp->jb_flags.singlebits.lifes&(1<<i)))
  129.             /*error("cannot post job")*/;    /* Never Happens */
  130.         jp->jb_proc[i].proc_pid = procid;
  131.         jp->jb_flags.singlebits.lifes |= (1<<i);
  132.     }
  133. }
  134.  
  135. /*
  136.  *    restart in background
  137.  */
  138. bg(jno)
  139. {
  140.     if (jobs[jno]){
  141. #ifdef JOBSXT
  142.         ioctl(sxt_fd,SXTIOCUBLK,SXT(jno));
  143.         sxtblock.input &= ~(1<<SXT(jno));
  144.         sxtblock.output &= ~(1<<SXT(jno));
  145.         blkmask &= ~(1<<SXT(jno));
  146. #endif JOBSXT
  147.         jobs[jno]->jb_flags.singlebits.back = jobs[jno]->jb_flags.singlebits.run = 1;
  148.         jobs[jno]->jb_pri = ++maxpri;        /* top priority */
  149.         bdfltjob = dfltjob;
  150.         if (jobs[jno]->jb_flags.singlebits.stop){
  151.             jobs[jno]->jb_flags.singlebits.stop = 0;
  152.             if (jobs[jno]->jb_cmd){
  153.                 prs(jobs[jno]->jb_cmd);
  154.                 prs(" &\n");
  155.             }
  156.         }
  157. #ifdef JOBSXT
  158.         if (sxtchan!=-1)
  159. #endif JOBSXT
  160.             iflags |= jobflg;
  161.         setjob(0);    /* so it'll stop if its reading from tty */
  162.         bgjobs++;
  163.     }
  164. }
  165.  
  166. /*
  167.  *    set the "notify" bit in a job 
  168.  */
  169. notify(jno)
  170. {
  171.     if (jobs[jno])
  172.         jobs[jno]->jb_flags.singlebits.notify = 1;
  173. }
  174.  
  175.  
  176.  
  177. /*
  178.  *    bring a job into foreground.
  179.  */
  180. fg(jno)
  181. {
  182.     if (jobs[jno] && jno>0){
  183.         jobs[jno]->jb_flags.singlebits.back = 0;
  184.         jobs[jno]->jb_flags.singlebits.run = 1;
  185.         jobs[jno]->jb_pri = ++maxpri;        /* top priority */
  186.         bdfltjob = dfltjob;
  187.         dfltjob = jno;
  188. #ifdef JOBSXT
  189.         if (sxtchan!=-1)
  190. #endif JOBSXT
  191.             iflags |= jobflg;            /* in case it was forgotten... */
  192.         if (jobs[jno]->jb_cmd){
  193.             prs(jobs[jno]->jb_cmd);
  194.             newline();
  195.         }
  196.         if (jobs[jno]->jb_flags.singlebits.stop)
  197.             jobs[jno]->jb_flags.singlebits.stop = 0;
  198. #ifdef JOBSXT
  199.         ioctl(sxt_fd, SXTIOCBLK, SXT(jno));
  200.         sxtblock.input &= ~(1<<SXT(jno));
  201.         sxtblock.output &= ~(1<<SXT(jno));
  202.         blkmask &= ~(1<<SXT(jno));
  203. #ifdef ERCC_SIGCONT
  204.         killpg(jobs[jno]->jb_pgrp,SIGCONT);
  205. #endif
  206.         setjob(jno);
  207. #endif SysV
  208.         await(-1,WAIT_FG);
  209.     }
  210. }
  211.  
  212. /*
  213.  *    wait for processes to terminate.
  214.  *    waitflags is an ORing of
  215.  *        WAIT_FG    - waiting for foreground jobs
  216.  *        WAIT_BG - waiting for background jobs
  217.  *        WAIT_NOPAUSE - fast wait, don't hang around
  218.  *        WAIT_JOB - waiting for a job-no, not a process-no.
  219.  */
  220. await(id,waitflags)
  221. {
  222.     register int i;
  223.     register int gotit=0;
  224. #ifdef JOBSXT
  225.     register int j;
  226.     struct sxtblock block;
  227.     register int oldex;
  228. #endif
  229.  
  230.     if ((waitflags&WAIT_JOB)==0 && id>0) post(id);
  231.     if (waitflags&WAIT_FG) fgjobs++;
  232.     flushb();
  233.     while (fgjobs>0 || ((waitflags&(WAIT_NOPAUSE|WAIT_BG)) && bgjobs>0)){
  234.         if ((trapnote&SIGSET) && fgjobs==0){
  235.             listjobs((char *)0);
  236.             prs("wait: interrupted\n");
  237.             break;
  238.         }
  239. #ifdef JOBSXT
  240.         if (extracnt>0){
  241.             gotit=announce();
  242.         } else if (sxtchan!=-1 && currentjob<SXTMAX
  243.                         && (waitflags&WAIT_BG)==0){
  244.             if (setsxt(currentjob) != SXT(currentjob))
  245.                 continue;
  246.             iflags |= sxtwaiting;
  247.             oldex = extracnt;
  248.             while (ioctl(sxt_fd,SXTIOCWF,0) == -1)
  249.             iflags &= ~sxtwaiting;
  250.             setsxt(currentjob);
  251.             if (jobs[currentjob]->jb_sxtfg!=(-1))
  252.                 ioctl(jobs[currentjob]->jb_sxtfg,TCSBRK,1);
  253.             ioctl(sxt_fd,SXTIOCSTAT,&block);
  254.             for (i=1; i<SXTMAX; i++){
  255.                 BOOL blkin = (BLKBIT(block.input,i)!=0);
  256.                 BOOL blkout = (BLKBIT(block.output,i)!=0);
  257.                 if (i!=currentjob){
  258.                     if (!blkin && !blkout) continue;
  259.                     if (BLKBIT(sxtblock.input,i) || BLKBIT(sxtblock.output,i) || BLKBIT(blkmask,i))
  260.                         continue;
  261.                 } else {
  262.                     if (extracnt!=oldex)
  263.                         continue;
  264.                 }
  265.                 blkmask |= (1<<SXT(i));
  266.                 jobs[i]->jb_flags.singlebits.stop = 1;
  267.                 jobs[i]->jb_flags.singlebits.run = 0;
  268.                 jobs[i]->jb_flags.singlebits.deaths = jobs[i]->jb_flags.singlebits.lifes;
  269.                 if (jobs[i]->jb_flags.singlebits.back)
  270.                     bgjobs--;
  271.                 else {
  272.                     fgjobs--;
  273.                     setsxt(0);
  274.                 }
  275.                 for (j=0; j<PPERJ; j++)
  276.                     if (jobs[i]->jb_proc[j].proc_pid)
  277.                         jobs[i]->jb_proc[j].proc_status = (SIGBLOCK<<8)|0177;
  278.                 donotify(i);
  279.             }
  280.             sxtblock.input = block.input;
  281.             sxtblock.output = block.output;
  282.         }
  283.         else 
  284. #endif JOBSXT
  285.         {    /* System-V or V7 without sxt's */
  286. #if defined(SIGCLD) || defined(SIGCHLD)
  287.             if (extracnt==0 && (waitflags&WAIT_NOPAUSE)==0)
  288.                 pause();
  289. #else
  290.             extrastack(0,0);
  291. #endif SIGCLD or SIGCHLD
  292.             if (extracnt>0) gotit=announce();    
  293.         }
  294.         if ( ((waitflags&WAIT_JOB) && gotit==id)
  295.                     || ((waitflags&WAIT_NOPAUSE) && gotit!=0 && extracnt<=0))
  296.             break;
  297.     }
  298.     if (fgjobs<0) fgjobs=0;
  299.     if (extracnt<0) extracnt=0;        /* ... */
  300.     for (i=1; i<JOB_MAX; i++)
  301.         if (jobs[i] && jobs[i]->jb_flags.singlebits.deaths==jobs[i]->jb_flags.singlebits.lifes){
  302.             jobs[i]->jb_flags.singlebits.deaths = 0;
  303.             printjob(i);
  304.             if (jobs[i]->jb_flags.singlebits.stop==0)
  305.                 postjclr(i);
  306.         }
  307.         setjob(0);         /* restore to control state */
  308. }
  309.  
  310. /*
  311.  *    trap routine for SIGCHLD/SIGCLD
  312.  */
  313. #if defined(SIGCHLD) || defined(SIGCLD)
  314. job_fault()
  315. {
  316.     extrastack(0,0);
  317. #ifdef JOBSXT
  318.     if ((flags&waiting)==0 && sxtchan!=-1 && (iflags&sxtwaiting))
  319.         setsxt(-1);
  320.     else if (flags&waiting) announce();
  321. #endif JOBSXT
  322. }
  323. #endif SIGCHLD or SIGCLD
  324.  
  325.  
  326.  
  327. /*
  328.  *    set current job to "job"
  329.  */
  330. setjob(jno)
  331. {
  332.     register struct jobnod *jp = jobs[jno<0? 0 : jno];
  333.  
  334.     if ((iflags&jobflg) && jp){
  335. #ifdef JOBSXT
  336.         setsxt(jno);
  337. #endif JOBSXT
  338.     }
  339.     currentjob = jno;
  340. }
  341.  
  342.  
  343. /*
  344.  *    set up job stuff in parent, assumimg I/O j-control has already
  345.  *    been set up in the child.
  346.  */
  347. setparjob(jno)
  348. {
  349.     register struct jobnod *jp = jobs[jno];
  350.  
  351.     if (jp && (iflags&jobflg)){
  352. #ifdef JOBSXT
  353.         sxtcontrol = jno;
  354. #endif JOBSXT
  355.     }
  356. }
  357.  
  358.  
  359. /*
  360.  *    set up j-control I/O in child
  361.  */
  362. setchildjob(jno,sxtflag)
  363. {
  364.     register struct jobnod *jp = jobs[jno];
  365.  
  366.     if (jp){
  367.         if (jp->jb_pgrp==0)
  368.             jp->jb_pgrp = getpid();
  369.     }
  370.     if (sxtflag && jno){
  371. #ifdef JOBSXT
  372.         if (sxtflag==1){
  373.             ioctl(sxt_fd,SXTIOCBLK,SXT(jno));
  374.             setsxt(jno);
  375.         } else  ioctl(sxt_fd,SXTIOCUBLK,SXT(jno));
  376. #endif JOBSXT
  377.     }
  378. }
  379.  
  380. /*
  381.  *    book a slot in the jobs-table
  382.  */
  383. bookjob()
  384. {
  385.     register int i;
  386.  
  387.     for (i=0; i<JOB_MAX; i++)
  388.         if (jobs[i]==0){
  389.             jobs[currentjob=i] = (struct jobnod *)alloc(sizeof(struct jobnod));
  390.             jobs[i]->jb_dir = jobs[i]->jb_cmd = (char *)0;
  391.             jobs[i]->jb_pgrp = 0;
  392. #ifdef JOBSXT
  393.             jobs[i]->jb_sxtfg = -1;
  394.             if ((flags&(ttyflg|forked))==(ttyflg)){
  395.                 if (sxtchan!=-1)
  396.                     iflags |= jobflg;
  397.             } else iflags &= ~jobflg;
  398. #endif JOBSXT
  399.             return;
  400.         }
  401.     /*printf("Jobs Table is Full!\n");*/    /* nobody should have THAT many jobs running! */
  402. }
  403.  
  404.  
  405.  
  406.  
  407. /*
  408.  *    create storage for a new job (already chosen by "bookjob")
  409.  */
  410. newjob(pid,jcmd,backing,chanid)
  411. struct argnod * jcmd;
  412. {
  413.     register struct jobnod *jp;
  414.     register int j;
  415.         register char * cmdbuffer;
  416.         register int cmdlength;
  417.         struct argnod * storcmd;
  418.  
  419.     /*        -- This should NEVER happen, so its commented out --
  420.     if (currentjob<0 || currentjob>=JOB_MAX || jobs[currentjob]==0){
  421.         prs("Job Control Error\n");
  422.         return(0);
  423.     }
  424.     */
  425.     jp = jobs[currentjob];
  426. #ifdef notdef
  427.     if ( (flags&(forked|ttyflg))!=ttyflg)
  428.         pid = 0;
  429. #endif notdef
  430. #ifdef JOBSXT
  431.     if (sxtchan!=-1)
  432.         jp->jb_sxtfg = chanid;        /* parent sxt channel access */
  433. #endif JOBSXT
  434.     jp->jb_pgrp = pid ? pid : jobs[0]->jb_pgrp;
  435.     jp->jb_pri = 0;
  436.     if (jcmd){
  437.         for (cmdlength=0, storcmd=jcmd; storcmd; storcmd=storcmd->argnxt)
  438.             cmdlength += length(storcmd->argval);
  439.         cmdbuffer = jp->jb_cmd = (char *)alloc(cmdlength+1);
  440.         *cmdbuffer = '\0';
  441.         for (storcmd=jcmd; storcmd; storcmd=storcmd->argnxt){
  442.             cmdbuffer = movstr(storcmd->argval,cmdbuffer);
  443.             cmdbuffer = movstr(" ",cmdbuffer);
  444.         }
  445.     } else jp->jb_cmd = make("(?)");
  446.     jp->jb_flags.totalbits = 0;
  447.     jp->jb_flags.singlebits.run = 1;
  448.     for (j=0; j<PPERJ; j++){
  449.         jp->jb_proc[j].proc_pid=0;
  450.         jp->jb_proc[j].proc_status=0;
  451.     }
  452.     if (!backing){
  453.         bdfltjob = dfltjob;
  454.         dfltjob = currentjob;
  455.         jp->jb_pri = ++maxpri;
  456.     }
  457.     if (pid && pid!=mainpgrp)
  458.         setparjob(currentjob);
  459.     return(currentjob);
  460. }
  461.             
  462.  
  463.  
  464. /*
  465.  *    the "jobs" command
  466.  */
  467. listjobs(llist)
  468. char *llist;
  469. {
  470.     register struct jobnod **jp;
  471.     register int j;
  472.  
  473. #ifdef JOBSXT
  474.     ioctl(sxt_fd,SXTIOCSTAT,&sxtblock);
  475. #endif
  476.  
  477.     for (jp = &jobs[1]; jp< &jobs[JOB_MAX]; jp++)
  478.         if (*jp){
  479.             prc('[');
  480.             prn(jp-jobs);
  481.             prs("] ");
  482.             if (llist){
  483.                 for (j=0; j<PPERJ; j++)
  484.                     if ((*jp)->jb_proc[j].proc_pid){
  485.                         prn((*jp)->jb_proc[j].proc_pid);
  486.                         prs((((*jp)->jb_flags.singlebits.lifes&(1<<j)))?" ":"Z ");
  487.                     }
  488.                 prc(' ');
  489.             } else prs("    ");
  490.             if (jp==&jobs[dfltjob]) prc('+');
  491.             else if (jp==&jobs[bdfltjob]) prc('-');
  492.             else prc(' ');
  493.             prc((*jp)->jb_flags.singlebits.notify ? '!' : ' ');
  494.             prc(' ');
  495. #ifdef JOBSXT
  496.             if (BLKBIT(sxtblock.input,jp-jobs) ||
  497.                        BLKBIT(sxtblock.output,jp-jobs))
  498.                 if ((*jp)->jb_flags.singlebits.stop==0){
  499.                     if ((*jp)->jb_flags.singlebits.back)
  500.                         bgjobs--;
  501.                     else fgjobs--;
  502.                     (*jp)->jb_flags.singlebits.stop=1;
  503.                 }
  504. #endif JOBSXT
  505.             if ((*jp)->jb_flags.singlebits.stop)
  506.                 prstop(jp-jobs, llist!=(char *)0);
  507.             else if ((*jp)->jb_flags.singlebits.run)
  508.                 prs("Running\t\t");
  509.             else prs("(?)\t\t");
  510.             prc('\t');
  511.             prs((*jp)->jb_cmd ? (*jp)->jb_cmd : "(?)");
  512.             newline();
  513.         }
  514. }
  515.  
  516.  
  517. /*
  518.  *    print stop-state
  519.  */
  520. prstop(jno,longlist)
  521. {
  522. #ifdef JOBSXT
  523.     register BOOL blkin, blkout;
  524.  
  525.     prs("Blocked");
  526.     blkin = BLKBIT(sxtblock.input,jno);
  527.     blkout = BLKBIT(sxtblock.output,jno);
  528.     if (blkin && blkout) prs(" (tty i/o)");
  529.     else if (blkin) prs(" (tty input)");
  530.     else if (blkout) prs(" (tty output)");
  531.     else  prs(longlist?"\t\t":"\t");
  532. #endif JOBSXT
  533. }
  534.  
  535.  
  536. /*
  537.  *    print info about jobs, and clean out if dead
  538.  */
  539. donotify(jobno)
  540. {
  541.     register int i;
  542.  
  543.     if ((i=jobno) > 0){
  544.         if (jobs[i] && (jobs[i]->jb_flags.singlebits.deaths)){
  545.             jobs[i]->jb_flags.singlebits.deaths=0;
  546.             if (jobs[i]->jb_flags.singlebits.stop){
  547.                 newline();
  548.                 printjob(i);
  549.             } else {
  550.                 printjob(i);
  551.                 postjclr(i);
  552.             }
  553.         }
  554.     }
  555. }
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562. /*
  563.  *    If any processes have terminated, do the works.
  564.  */
  565. announce()
  566. {
  567.     BOOL stoppage=FALSE;
  568.     register int i, j;
  569.     int w, status;
  570.  
  571.     if (extracnt>0){
  572.         extracnt--;
  573.         w = extras[extracnt].pid;
  574.         status = extras[extracnt].status;
  575.     } else {
  576.         /* This can NEVER happen! (ha ha) */
  577. #ifdef JOBSXT
  578.         /*printf("no wait/extra\n");*/
  579. #endif JOBSXT
  580.         w = 0;
  581.     }
  582.     if (w==0 || w==-1){
  583.         /* Can this happen? Does it matter if it does? No. */
  584.         /*printf("Process Failure:no wait\n");*/
  585.         return 0;
  586.     }
  587.     for (i=1; i<JOB_MAX; i++){
  588.         if (jobs[i]==0) continue;
  589.         for (j=0; j<PPERJ; j++)
  590.             if (jobs[i]->jb_proc[j].proc_pid == w){
  591.                 jobs[i]->jb_flags.singlebits.deaths |= (1<<j);
  592.                 jobs[i]->jb_flags.singlebits.stop = stoppage ? 1 : 0;
  593.                 jobs[i]->jb_proc[j].proc_status = status;
  594.                 if (jobs[i]->jb_flags.singlebits.deaths == jobs[i]->jb_flags.singlebits.lifes){
  595.                     if (jobs[i]->jb_flags.singlebits.run)
  596.                         if (jobs[i]->jb_flags.singlebits.back)
  597.                             bgjobs--;
  598.                         else    fgjobs--;
  599.                     jobs[i]->jb_flags.singlebits.run = 0;
  600.                     donotify(i);
  601.                 } else if (stoppage==0){
  602.                     jobs[i]->jb_flags.singlebits.lifes &= ~(01<<j);
  603.                     jobs[i]->jb_flags.singlebits.deaths &= ~(01<<j);
  604.                 }
  605.                 return(i);
  606.         }
  607.     }
  608.     /* it wasn't a known process -          */
  609.     /*    so forget about it.         */
  610.     /* printf("unknown process has died\n"); */
  611.     /* extras[extracnt].pid = w;         */
  612.     /* extras[extracnt].status = status;     */
  613.     /* extracnt++;                 */
  614.     return(0);
  615. }
  616.  
  617.  
  618. /*
  619.  *    stacking function for putting terminated jobs onto extras when
  620.  *    they die - 'cos they must be waited for immediately, but its
  621.  *    not safe to do an announce().
  622.  */
  623. extrastack(p,s)
  624. {
  625.     int w, status;
  626.  
  627.     if (p==0){
  628.         w = wait(&status);
  629.     } else {
  630.         w=p;
  631.         status=s;
  632.     }
  633.     if (w>0){
  634.         extras[extracnt].pid = w;
  635.         extras[extracnt].status = status;
  636.         extracnt++;
  637.     } /* else printf("stack: wait error\n"); */
  638. }
  639.  
  640.  
  641.  
  642. /*
  643.  *    initialize jobs table
  644.  *    (and set up sxt's under Sys-V)
  645.  */
  646. initjobs()
  647. {
  648.     if (jobs[0]) postjclr(0);
  649.     bookjob();
  650.     newjob(mainpgrp,(struct argnod *)0,0,0);    /* this had better be job[0] */
  651.     jobs[0]->jb_pgrp = mainpgrp;
  652. #ifdef JOBSXT
  653.     terminal(&realtty);
  654.     realtty.c_cc[VSWTCH] = 0377;
  655.     realtty.c_cflag &= ~LOBLK;
  656.     sxtinit();
  657. #endif
  658. }
  659.  
  660.  
  661.  
  662. /*
  663.  *    Something has happened to a job.
  664.  *    Print out info and clean up if necessary.
  665.  */
  666. printjob(jno)
  667. {
  668.     register struct jobnod *jp = jobs[jno];
  669.     register int j;
  670.     BOOL fgdone = FALSE;
  671.     int wx=0, rc=0;
  672.     int sig=0;
  673.     int status=0;
  674.     char * msg=0;
  675.  
  676.     if (jp){
  677.         for (j=0; j<PPERJ; j++){
  678.             int ww, ss, ww_hi;
  679.  
  680.             if (jp->jb_proc[j].proc_pid==0) continue;
  681.             ww = jp->jb_proc[j].proc_status;
  682.             ww_hi = (ww>>8)&LOBYTE;
  683.             ss = (ww&0177);
  684.             if (ss==0177){
  685.                 ss = ww_hi;
  686.             }
  687.             wx |= ww;
  688.             if (rc==0){
  689.                 if (ss) sig = ss;
  690.                 if (jp->jb_flags.singlebits.back)
  691.                     continue;    /* just wanted the signal */
  692.                 rc = ss ? ss|SIGFLG : ww_hi;
  693.                 status = ww;
  694.                 fgdone = TRUE;
  695.             }
  696.         }
  697.         if (jp->jb_flags.singlebits.stop==0 && jp->jb_flags.singlebits.back==0 && (sig==SIGINT || sig==SIGQUIT))
  698.             newline();
  699.         if (jp->jb_flags.singlebits.stop==0 
  700.                 && jp->jb_flags.singlebits.back==0){
  701.             TTYNOD tt;
  702. #ifdef JOBSXT
  703.             if (jp->jb_sxtfg!=(-1) && (flags&ttyflg) && sig!=SIGHUP){
  704.                 if (ioctl(jp->jb_sxtfg,TCGETA,&tt)==0){
  705.                     tt.c_cc[VSWTCH] = 0377; /* ^Z disabled */
  706.                     tt.c_cflag &= ~LOBLK;    /* no blocking */
  707.                     ioctl(0,TCSETA,&tt);
  708.                 }
  709.                 if (sig==SIGINT || sig==SIGQUIT){    /* Yeauch! */
  710.                     fault(sig);    /* simulate shell's tty pgrp */
  711.                     if (j==0 && jp->jb_proc[1].proc_pid)
  712.                         kill(jp->jb_proc[1].proc_pid,sig);
  713.                 }
  714.             }
  715. #endif JOBSXT
  716.         }
  717.  
  718.         if ( (msg=(sig==SIGBLOCK?"Blocked":sysmsg[sig]))
  719.                  || jp->jb_flags.singlebits.notify
  720.                  || (ntfynod.namval) ){
  721.             if (msg==0 && !fgdone) msg=nullstr;
  722.             if (msg && (flags&stdflg)){
  723. #if defined(JOBSXT) && defined(BLK_BOTTOM)
  724.                 if (jp->jb_flags.singlebits.stop)
  725.                     blk_bottom();
  726. #endif (JOBSXT && BLK_BOTTOM)
  727.                 if (jp->jb_flags.singlebits.back || jp->jb_flags.singlebits.stop){
  728.                     prc('[');
  729.                     prn(jno);
  730.                     prs("]\t");
  731.                 }
  732.                 if (jp->jb_cmd){
  733.                     register char *p = jp->jb_cmd;
  734.                     while (*p && *p!=' ')
  735.                         prc(*p++);
  736.                     prc('\t');
  737.                 }
  738.                 prs(*msg ? msg : "Done");
  739.                 if (status&0200) prs(coredump);
  740.                 newline();
  741.                 flushb();
  742.             }
  743.         }
  744.         if (fgdone)
  745.             if (wx && (flags&errflg)) exitsh(rc);
  746.             else {
  747.                 exitval=rc;
  748.                 exitset();
  749.             }
  750.     } /*else printf("trying to report unknown job\n");*/
  751. }
  752.  
  753.  
  754.  
  755.  
  756.  
  757.  
  758. /*
  759.  *    find a job-number from a describing "%..." string
  760.  */
  761. findjob(str)
  762. char *str;
  763. {
  764.     int number = -1;
  765.     register struct jobnod **jpp;
  766.     register char *p;
  767.     int found = 0;
  768.     int nlen;
  769.  
  770.     if (str==0 || *str=='\0'){
  771.         number=dfltjob;
  772.         if (number<1 || jobs[number]==0) error("No appropriate jobs");
  773.     } else {
  774.         if (*str=='%') str++;
  775.         if (*str=='%' || *str=='\0' || *str=='+')
  776.             number=dfltjob;
  777.         else if (*str=='-')
  778.             number=bdfltjob;
  779.         else if (digit(*str))
  780.             number=stoi(str);
  781.         else if (*str=='?'){
  782.             nlen = length(++str)-1;
  783.             for (jpp=jobs; jpp < &jobs[JOB_MAX]; jpp++)
  784.                 if (*jpp)
  785.                     for (p=(*jpp)->jb_cmd; *p; p++)
  786.                         if (cfn(str,p,nlen)==0){
  787.                             number = jpp-jobs;
  788.                             if (found++) failed(str,"ambiguous");
  789.                             break;
  790.                         }
  791.             if (!found) failed(str,"no such job");
  792.         } else {
  793.             nlen = length(str)-1;
  794.             for (jpp=jobs; jpp < &jobs[JOB_MAX]; jpp++)
  795.                 if (*jpp && cfn(str,(*jpp)->jb_cmd,nlen)==0){
  796.                     number = jpp-jobs;
  797.                     if (found++) failed(str,"ambiguous");
  798.                 }
  799.             if (!found) failed(str,"no such job");
  800.         }
  801.  
  802.     }
  803.     if (number<1 || number>=JOB_MAX || jobs[number]==0)
  804.         failed(str,"no such job");
  805.     return(number);
  806. }
  807.  
  808.  
  809.  
  810.  
  811. /*
  812.  * check for stopped jobs
  813.  */
  814. stpjobs()
  815. {
  816.       register int i;
  817.  
  818.       for(i=0; i<JOB_MAX; i++)
  819.               if (jobs[i] && jobs[i]->jb_flags.singlebits.stop)
  820.                       return(TRUE);
  821.       return(FALSE);
  822.  
  823. }
  824.  
  825.  
  826.  
  827. /*
  828.  * zap 'em
  829.  */
  830. zapjobs()
  831. {
  832.     register int i;
  833.  
  834.     for (i=1; i<JOB_MAX; i++)
  835.         if (jobs[i] && jobs[i]->jb_flags.singlebits.stop){
  836.             killpg(jobs[i]->jb_pgrp, SIGHUP);
  837.             jobs[i]->jb_flags.singlebits.stop = 0;
  838.             jobs[i]->jb_flags.singlebits.back = 1;             /* so that it gets reported properly */
  839.             jobs[i]->jb_proc[0].proc_status = SIGHUP;
  840.             printjob(i);
  841.         }
  842. }
  843.  
  844.  
  845.  
  846. #ifdef JOBSXT
  847.  
  848. #ifdef JOBSXT_HUP
  849. char Mstart[] = "echo \"\nsh was killed off, so I hung up the following processes:\n";
  850. char Mend[]   = "\n\" | mail -s sh_was_killed $LOGNAME";    /* good meta-usage */
  851.  
  852. /*
  853.  *    HUP has happened! Send mail and go away.
  854.  */
  855. hupmail()
  856. {
  857.     register int i;
  858.     char maillist[1024];
  859.     register char *mpoint;
  860.     int mcnt = 0;
  861.  
  862.     sxtchan = -1;
  863.     flags &= ~ttyflg;    /* just in case ... */
  864.     mpoint = movstr(Mstart, maillist);
  865.     for (i=1; i<JOB_MAX; i++)
  866.         if (jobs[i] && jobs[i]->jb_flags.singlebits.back==0){
  867.             killpg(jobs[i]->jb_pgrp,SIGHUP);
  868.             if (jobs[i]->jb_cmd){
  869.                 mpoint = movstr("\t", mpoint);
  870.                 mpoint = movstr(jobs[i]->jb_cmd,mpoint);
  871.                 mpoint = movstr("\n", mpoint);
  872.             } else mpoint = movstr("\t?\n", mpoint);
  873.             mcnt++;
  874.         }
  875.     movstr(Mend, mpoint);
  876.     if (mcnt)
  877.         execexp(maillist,(char * *)0);    /* bye! */
  878. }
  879. #endif JOBSXT_HUP
  880.  
  881. /*
  882.  *    set current job using sxt's
  883.  */
  884. setsxt(jno)
  885. {
  886.     if (sxtchan != -1 && jno<SXTMAX){
  887.         jno = SXT(jno);
  888.         sxtcontrol = -1;
  889.         do {
  890.             if (ioctl(sxt_fd,SXTIOCSWTCH,jno) == 0)
  891.                 sxtcontrol = jno;
  892.             /*else if (errno!=EINTR)
  893.                 printf("sxt switch (errno %d)\n", errno);*/
  894.         } while (sxtcontrol!=jno && errno==EINTR);
  895.         return(sxtcontrol);
  896.     } else return(-1);
  897. }
  898.  
  899. /*
  900.  *    block an sxt file
  901.  */
  902. sxtblk(jno)
  903. {
  904.     ioctl(sxt_fd, SXTIOCBLK, SXT(jno));
  905. }
  906.  
  907. #endif JOBSXT
  908.  
  909.  
  910. /*
  911.  *    send a signal to all processes in a tty group.
  912.  *    actually, it only sends to the first and last in the pipe-order,
  913.  *    'cos it only knows the pid's for these (jb_proc[0] ... jb_proc[PPERJ]).
  914.  *    This exists as a system-call under BSD.
  915.  *    Luckily it knows about negative pids.
  916.  */
  917. killpg(gid,sig)
  918. {
  919.     register struct jobnod **jp;
  920.     register int i=0;
  921.     int err = 0, proc;;
  922.  
  923.     for (jp=jobs; jp < &jobs[JOB_MAX]; jp++)
  924.         if (*jp && (*jp)->jb_pgrp==gid)
  925.             for (i=0; i<PPERJ; i++){
  926.                 proc = (*jp)->jb_proc[i].proc_pid;
  927.                 if (proc && kill(-proc,sig)==-1)
  928.                     err = errno;
  929.             }
  930.     /* Panic Stations! It didn't work, so get really desparate... */
  931.     if (err!=0)
  932.         if (kill(-gid,sig)==-1 && kill(gid,sig)==-1)
  933.             err = errno;
  934.         else err=0;
  935.     return(err);
  936. }
  937.  
  938. #if defined(JOBSXT) && defined(BLK_BOTTOM)
  939. /*
  940.  *    move cursor to bottom of screen - when job is blocked
  941.  *
  942.  *    if you have TERMCAP defined, it does it properly be sending
  943.  *    the "ll" string and clearing to end-of-line, otherwise it is
  944.  *    pretty dumb.
  945.  *    in fact, TERMCAP implies a lot of other stuff I havn't included
  946.  *    here, so tough.
  947.  *                simon@uk.ac.ed.its63b
  948.  */
  949. blk_bottom()
  950. {
  951. # ifdef TERMCAP
  952.     STRING it, p;
  953.  
  954.     if (p=tcapstr[TCAP_LL])
  955.         tputs(p,1,prc);
  956.     else if (it=tcapstr[TCAP_CM]){
  957.         p=tgoto(it,0,tcapflag[TCAP_ROW]);
  958.         tputs(p,1,prc);            /* move to bottom */
  959.     } else
  960. # endif TERMCAP
  961.     {
  962.         register int n = 24;    /* bound to have 24 lines */
  963.         while (n--)
  964.             newline();    /* chug chug chug ... */
  965.     }
  966. # ifdef TERMCAP
  967.     if (p=tcapstr[TCAP_CE])
  968.         tputs(p,1,prc);        /* clear to eoln */
  969. # endif TERMCAP
  970. }
  971. #endif (JOBSXT && BLK_BOTTOM)
  972.  
  973. #else !JOB
  974.  
  975.  
  976. /*
  977.  * for processes to be waited for
  978.  */
  979. #define MAXP 20
  980. static int    pwlist[MAXP];
  981. static int    pwc;
  982.  
  983. postclr()
  984. {
  985.     register int    *pw = pwlist;
  986.  
  987.     while (pw <= &pwlist[pwc])
  988.         *pw++ = 0;
  989.     pwc = 0;
  990. }
  991.  
  992. post(pcsid)
  993. int    pcsid;
  994. {
  995.     register int    *pw = pwlist;
  996.  
  997.     if (pcsid)
  998.     {
  999.         while (*pw)
  1000.             pw++;
  1001.         if (pwc >= MAXP - 1)
  1002.             pw--;
  1003.         else
  1004.             pwc++;
  1005.         *pw = pcsid;
  1006.     }
  1007. }
  1008.  
  1009. await(i, bckg)
  1010. int    i, bckg;
  1011. {
  1012.     int    rc = 0, wx = 0;
  1013.     int    w;
  1014.     int    ipwc = pwc;
  1015.  
  1016.     post(i);
  1017.     while (pwc)
  1018.     {
  1019.         register int    p;
  1020.         register int    sig;
  1021.         int        w_hi;
  1022.         int    found = 0;
  1023.  
  1024.         {
  1025.             register int    *pw = pwlist;
  1026.  
  1027.             p = wait(&w);
  1028.             if (wasintr)
  1029.             {
  1030.                 wasintr = 0;
  1031.                 if (bckg)
  1032.                 {
  1033.                     break;
  1034.                 }
  1035.             }
  1036.             while (pw <= &pwlist[ipwc])
  1037.             {
  1038.                 if (*pw == p)
  1039.                 {
  1040.                     *pw = 0;
  1041.                     pwc--;
  1042.                     found++;
  1043.                 }
  1044.                 else
  1045.                     pw++;
  1046.             }
  1047.         }
  1048.         if (p == -1)
  1049.         {
  1050.             if (bckg)
  1051.             {
  1052.                 register int *pw = pwlist;
  1053.  
  1054.                 while (pw <= &pwlist[ipwc] && i != *pw)
  1055.                     pw++;
  1056.                 if (i == *pw)
  1057.                 {
  1058.                     *pw = 0;
  1059.                     pwc--;
  1060.                 }
  1061.             }
  1062.             continue;
  1063.         }
  1064.         w_hi = (w >> 8) & LOBYTE;
  1065.         if (sig = w & 0177)
  1066.         {
  1067.             if (sig == 0177)    /* ptrace! return */
  1068.             {
  1069.                 prs("ptrace: ");
  1070.                 sig = w_hi;
  1071.             }
  1072.             if (sysmsg[sig])
  1073.             {
  1074.                 if (i != p || (flags & prompt) == 0)
  1075.                 {
  1076.                     prp();
  1077.                     prn(p);
  1078.                     blank();
  1079.                 }
  1080.                 prs(sysmsg[sig]);
  1081.                 if (w & 0200)
  1082.                     prs(coredump);
  1083.             }
  1084.             newline();
  1085.         }
  1086.         if (rc == 0 && found != 0)
  1087.             rc = (sig ? sig | SIGFLG : w_hi);
  1088.         wx |= w;
  1089.         if (p == i)
  1090.         {
  1091.             break;
  1092.         }
  1093.     }
  1094.     if (wx && flags & errflg)
  1095.         exitsh(rc);
  1096.     flags |= eflag;
  1097.     exitval = rc;
  1098.     exitset();
  1099. }
  1100.  
  1101. #endif JOB
  1102.