home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume1 / bourne / part1 / jobs.c < prev    next >
C/C++ Source or Header  |  1986-11-30  |  12KB  |  659 lines

  1. /*
  2.  *  JOBS.C -- job control for Bourne shell
  3.  *
  4.  *  created by Ron Natalie, BRL
  5.  *  slight changes by Doug Gwyn
  6.  *  some more slight changes by Arnold Robbins (mainly for the BSD /bin/sh)
  7.  */
  8.  
  9. #include "defs.h"
  10. #include "sym.h"
  11.  
  12. #ifndef TAB    /* very original, early /bin/sh */
  13. #include <signal.h>
  14. #define comptr(x)    ((COMPTR) x)
  15. #define lstptr(x)    ((LSTPTR) x)
  16. #define forkptr(x)    ((FORKPTR) x)
  17. #define parptr(x)    ((PARPTR) x)
  18. #define forptr(x)    ((FORPTR) x)
  19. #define whptr(x)    ((WHPTR) x)
  20. #define ifptr(x)    ((IFPTR) x)
  21. #define swptr(x)    ((SWPTR) x)
  22. #endif
  23.  
  24. #if BSD || (JOBS && ! BRL)    /* native /bin/sh */
  25. #include <sys/ioctl.h>
  26. #else    /* /usr/5bin/sh */
  27. #include    <sys/_ioctl.h>
  28. #define    ioctl    _ioctl
  29. #define    killpg    _killpg
  30. #define    setpgrp    _setpgrp
  31. #define    TIOCSETD    _IOW( 't', 1, int )
  32. #define    TIOCSPGRP    _IOW( 't', 118, int )
  33. #define    NTTYDISC    2
  34. #endif
  35.  
  36. #define    NJCH    30
  37. #define    JCOMSIZE 50
  38. static struct    j_child  {
  39.     int    j_pgid;
  40.     int    j_status;
  41.     int    j_info;
  42.     char    j_com[JCOMSIZE];
  43.     int    j_jobnum;
  44. } j_children[NJCH];
  45.  
  46. static int    j_number = 1;
  47. static int    j_current = 0;
  48.  
  49. #define    JEMPTY    0
  50. #define    JALIVE    1
  51. #define    JSTOP    2
  52. #define    JBG    3
  53.  
  54. BOOL        j_top_level = TRUE;
  55. int        j_default_pg = 0;
  56. int        j_original_pg = 0;
  57. static int    j_last_pgrp = 0;
  58. static int    j_do(), j_getnumber(), j_stuff();
  59. static void    j_backoff(), j_print_ent(), j_really_reset_pg(), j_setcommand();
  60.     
  61. j_child_post(p, bg, pin, t)
  62.     int        p;
  63.     int        bg;
  64.     register int    pin;
  65.     struct trenod    ***t;
  66. {
  67.     register struct j_child *j = j_children;
  68.  
  69.     if((flags & jobflg) == 0)
  70.         return;
  71.     if(!j_top_level)
  72.         return;
  73.  
  74.     if(!pin)  {
  75.         setpgrp(p, p);
  76.         j_last_pgrp = p;
  77.         if(!bg)  {
  78.             ioctl(1, TIOCSPGRP, &p);
  79.             setpgrp(0, p);
  80.         }
  81.     }
  82.     else
  83.         setpgrp(p, j_last_pgrp);
  84.  
  85.     for(j=j_children; j < &j_children[NJCH]; j++)  {
  86.         if(pin && j->j_pgid == j_last_pgrp)  {
  87.             j_setcommand(j, t);
  88.             return;
  89.         }
  90.  
  91.         if(!pin &&j->j_status == JEMPTY)  {
  92.             j->j_com[0] = 0;
  93.             j->j_status = bg ? JBG : JALIVE;
  94.             j->j_pgid = p;
  95.             j_setcommand(j, t);
  96.             if(bg)  {
  97.                 post(p);
  98.                 j->j_jobnum = j_getnumber();
  99.                 j_print_ent(j);
  100.             }
  101.             else
  102.                 j->j_jobnum = 0;
  103.             return;
  104.         }
  105.     }
  106.     prn(p);
  107.     prs(cjpostr);            /* DAG -- made strings sharable */
  108. }
  109.  
  110. j_child_clear(p)
  111.     register int    p;
  112. {
  113.     register struct j_child *j = j_children;
  114.  
  115.     if(p == 0 || p == -1)
  116.         return;
  117.  
  118.     for(; j < &j_children[NJCH]; j++)
  119.         if(j->j_status == JALIVE && j->j_pgid == p)  {
  120.             j->j_status = JEMPTY;
  121.             if(j->j_jobnum && j->j_jobnum == j_current)
  122.                 j_backoff();
  123.             break;
  124.         }
  125. }
  126.  
  127. j_child_stop(p, sig)
  128.     register int    p;
  129.     int        sig;
  130. {
  131.     register struct j_child *j = j_children; 
  132.  
  133.     for(; j < &j_children[NJCH]; j++)
  134.         if((j->j_status == JALIVE || j->j_status == JBG) && j->j_pgid == p)  {
  135.             j->j_status = JSTOP;
  136.             j->j_info = sig;
  137.             if(j->j_jobnum == 0)
  138.                 j->j_jobnum = j_getnumber();
  139.             j_current = j->j_jobnum;
  140.             prc(NL);
  141.             j_print_ent(j);
  142.             fault(SIGSTOP);
  143.             break;
  144.         }
  145. }
  146.  
  147. j_child_die(p)
  148.     register int    p;
  149. {
  150.     register struct j_child *j = j_children; 
  151.  
  152.     if(p == 0 || p == -1)
  153.         return;
  154.  
  155.     for(; j < &j_children[NJCH]; j++)
  156.         if( j->j_status != JEMPTY && j->j_pgid == p)  {
  157.             j->j_status = JEMPTY;
  158.             if(j->j_jobnum && j->j_jobnum == j_current)
  159.                 j_backoff();
  160.             break;
  161.         }
  162. }
  163.  
  164. j_print()
  165. {
  166.     register struct j_child *j = j_children; 
  167.  
  168.     if((flags & jobflg) == 0)  {
  169.         prs(jcoffstr);        /* DAG */
  170.         return;
  171.     }
  172.  
  173.     await(-2, 1);
  174.     for(; j < &j_children[NJCH]; j++)
  175.         j_print_ent(j);
  176. }
  177.  
  178. static void
  179. j_print_ent(j)
  180.     register struct j_child *j;
  181. {
  182.     if(j->j_status == JEMPTY)
  183.         return;
  184.  
  185.     if(j->j_jobnum == 0) {
  186.         prs(jpanstr);        /* DAG */
  187.         prn(j->j_pgid);
  188.         prc(NL);
  189.     }
  190.     prc('[');
  191.     prn(j->j_jobnum);
  192.     prs(rsqbrk);            /* DAG */
  193.     if(j_current == j->j_jobnum)
  194.         prs(execpmsg);        /* DAG */
  195.     else
  196.         prs(spspstr);        /* DAG */
  197.     prn(j->j_pgid);
  198.     prc(' ');
  199.  
  200.     switch(j->j_status)  {
  201.     case JALIVE:
  202.         prs(fgdstr);        /* DAG */
  203.         break;
  204.     case JSTOP:
  205.         prs(stpdstr);        /* DAG */
  206.         switch(j->j_info)  {
  207.         case SIGTSTP:
  208.             prs(lotspstr);    /* DAG */
  209.             break;
  210.         case SIGSTOP:
  211.             prs(psgpstr);    /* DAG */
  212.             break;
  213.         case SIGTTIN:
  214.             prs(ptinstr);    /* DAG */
  215.             break;
  216.         case SIGTTOU:
  217.             prs(ptoustr);    /* DAG */
  218.             break;
  219.         }
  220.         break;
  221.     case JBG:
  222.         prs(bgdstr);        /* DAG */
  223.         break;
  224.     }
  225.     prc(' ');
  226.     prs(j->j_com);
  227.     prc(NL);
  228. }
  229.  
  230. j_resume(cp, bg)
  231.     char    *cp;
  232.     BOOL    bg;
  233. {
  234.     register struct j_child *j = j_children; 
  235.     int    p;
  236.     
  237.     if((flags & jobflg) == 0)  {
  238.         prs(jcoffstr);        /* DAG */
  239.         return;
  240.     }
  241.  
  242.     if(cp)  {
  243.         p = atoi(cp);
  244.         if(p == 0)  {
  245.             prs(jinvstr);    /* DAG */
  246.             return;
  247.         }
  248.     }
  249.     else
  250.         p = 0;
  251.         
  252.     await(-2, 1);
  253.     if(p == 0 && j_current == 0)  {
  254.         prs(ncjstr);        /* DAG */
  255.         return;
  256.     }
  257.  
  258.     for(; j < &j_children[NJCH]; j++)
  259.         if(j->j_status != JEMPTY)
  260.             if(
  261.                (p != 0 && j->j_pgid == p) ||
  262.                (p == 0 && j->j_jobnum == j_current)
  263.             )  {
  264.                 p = j->j_pgid;
  265.                 if(!bg)  {
  266.                     ioctl(1, TIOCSPGRP, &p);
  267.                     setpgrp(0, p);
  268.                 }
  269.                 j->j_status = bg ? JBG : JALIVE;
  270.                 j_print_ent(j);
  271.                 if(killpg(p, SIGCONT) == -1)  {
  272.                     j->j_status = JEMPTY;
  273.                     break;
  274.                 }
  275.                 if(bg)
  276.                     post(p);
  277.                 else
  278.                     await(p, 0);
  279.                 j_reset_pg();
  280.                 return;
  281.             }
  282.     prn(p);
  283.     prs(nstpstr);            /* DAG */
  284. }
  285.  
  286. char    *
  287. j_macro()
  288. {
  289.     static char    digbuf[40];
  290.     register char    *c;
  291.     register int    i;
  292.     register struct j_child *j = j_children; 
  293.  
  294.     c = digbuf;
  295.     *c++ = '%';
  296.  
  297.     for(;;) {
  298.         *c = readc();
  299.         if( c==(digbuf+1) && *c == '%')  {
  300.             i = j_current;
  301.             break;
  302.         }
  303.         if(!digchar(*c))  {
  304.             peekc = *c | MARK;
  305.             *c = 0;
  306.             i = stoi(digbuf+1);
  307.             break;
  308.         }
  309.         c++;
  310.     }
  311.  
  312.     if(i != 0)
  313.         for(; j < &j_children[NJCH]; j++)
  314.             if(j->j_status != JEMPTY && j->j_jobnum == i)  {
  315.                 itos(j->j_pgid);
  316.                 movstr(numbuf, digbuf);    /* DAG */
  317.                 break;
  318.             }
  319.  
  320.     return digbuf;
  321. }
  322.  
  323. j_reset_pg()
  324. {
  325.     if((flags & jobflg) == 0)
  326.         return;
  327.     if(j_top_level)  {
  328.         ioctl(0, TIOCSPGRP, &j_default_pg);
  329.         setpgrp(0, j_default_pg);
  330.     }
  331. }
  332.  
  333. static void
  334. j_really_reset_pg()
  335. {
  336.     ioctl(0, TIOCSPGRP, &j_original_pg);
  337.     setpgrp(0, j_original_pg);
  338. }
  339.  
  340.  
  341. #include "ctype.h"
  342. extern BOOL trapflg[];
  343.  
  344. j_init()
  345. {
  346.     static int    ldisc = NTTYDISC;    /* BSD ioctl brain damage */
  347.  
  348.     if(flags & jobflg)
  349.         return;
  350.     j_reset_pg();
  351.     trapflg[SIGTTIN] = SIGMOD | 1;
  352.     trapflg[SIGTTOU] = SIGMOD | 1;
  353.     trapflg[SIGTSTP] = SIGMOD | 1;
  354.     trapflg[SIGSTOP] = SIGMOD | 1;
  355.     ignsig(SIGTSTP);
  356.     ignsig(SIGSTOP);    /*  Just to make sure  */
  357.     (void)ioctl( 0, TIOCSETD, &ldisc );    /* DAG -- require "new tty" handler */
  358. /*    flags |= jobflg;    */
  359. }
  360.  
  361. BOOL
  362. j_finish(force)
  363.     BOOL    force;
  364. {
  365.     register struct j_child *j = j_children; 
  366.  
  367.     if((flags & jobflg) == 0)
  368.         return FALSE;
  369.  
  370.     await(-2, 1);
  371.     for(; j < &j_children[NJCH]; j++)
  372.         if(j->j_status == JSTOP )
  373.             if(force)  {
  374.                 killpg(j->j_pgid, SIGHUP);
  375.                 killpg(j->j_pgid, SIGCONT);
  376.             }
  377.             else  {
  378.                 prs(tasjstr);    /* DAG */
  379.                 return TRUE;
  380.             }
  381.     if(force)  {
  382.         await(-2, 1);        
  383.         return FALSE;
  384.     }
  385.     trapflg[SIGTTIN] = SIGMOD;
  386.     trapflg[SIGTTOU] = SIGMOD;
  387.     trapflg[SIGTSTP] = SIGMOD;
  388.     trapflg[SIGSTOP] = SIGMOD;
  389.     flags &= ~jobflg;
  390.     j_really_reset_pg();
  391.     return FALSE;
  392. }
  393.  
  394.  
  395. static int    j_numbers = 0;
  396.  
  397. static int
  398. j_getnumber()
  399. {
  400.     register struct j_child *j = j_children; 
  401.     
  402.     for(; j < &j_children[NJCH]; j++)
  403.         if(j->j_status != JEMPTY && j->j_jobnum)
  404.             return j_numbers++;
  405.     j_numbers = 2;
  406.     return 1;
  407. }
  408.  
  409. static void
  410. j_backoff()
  411. {
  412.     register struct j_child *j = j_children; 
  413.     
  414.     j_current = 0;
  415.     for(; j < &j_children[NJCH]; j++)
  416.         if(j->j_status != JEMPTY && j->j_jobnum)
  417.             if(j->j_jobnum > j_current)
  418.                 j_current = j->j_jobnum;
  419. }
  420.  
  421. static    int    jcleft;
  422. static  char    *jcp;
  423.  
  424. static void
  425. j_setcommand(j, t)
  426.     register struct j_child    *j;
  427.     struct trenod        *t;
  428. {
  429.     jcleft = strlen(j->j_com);
  430.     jcp = j->j_com + jcleft;
  431.     jcleft = JCOMSIZE - 1  - jcleft;
  432.  
  433.     if(j->j_com[0] == '\0' || !j_stuff(pipestr))    /* DAG */
  434.         j_do(t);
  435. }
  436.  
  437. static int
  438. j_do_chain(a)
  439.     register struct argnod *a;
  440. {
  441.     while(a)  {
  442.         if(j_stuff(a->argval))
  443.             return 1;
  444.         a = a->argnxt;
  445.         if(a)
  446.             j_stuff(spcstr);    /* DAG */
  447.     }
  448.     return 0;
  449. }
  450.  
  451. #define IOGET 0
  452. static int
  453. j_do_redir(t)
  454.     register struct ionod    *t;
  455. {
  456.     register int    iof;    /* DAG -- added for speed */
  457.     register int    i;
  458.  
  459.     while(t)  {
  460.         if(t->ioname)  {
  461.             if(j_stuff(spcstr))    /* DAG */
  462.                 return 1;
  463.             iof = t->iofile;
  464.             i = iof & IOUFD;
  465.             if(
  466.                 ((iof&IOPUT) && (i != 1)) ||
  467.                 (((iof&IOPUT)==0) && (i!= 0))
  468.             )  {
  469.                 itos(i);
  470.                 if(j_stuff(numbuf))
  471.                     return 1;
  472.             }
  473.             switch(iof & (IODOC|IOPUT|IOMOV|IOAPP|IORDW))  {
  474.             case IOGET:
  475.                 if(j_stuff(rdinstr))    /* DAG */
  476.                     return 1;
  477.                 break;
  478.             case IOPUT:
  479.                 if(j_stuff(readmsg))    /* DAG */
  480.                     return 1;
  481.                 break;
  482.             case IOAPP|IOPUT:
  483.                 if(j_stuff(appdstr))    /* DAG */
  484.                     return 1;
  485.                 break;
  486.             case IODOC:
  487.                 if(j_stuff(inlnstr))    /* DAG */
  488.                     return 1;
  489.                 break;
  490.             case IOMOV|IOPUT:
  491.                 if(j_stuff(toastr))    /* DAG */
  492.                     return 1;
  493.                 break; 
  494.             case IOMOV|IOGET:
  495.                 if(j_stuff(fromastr))    /* DAG */
  496.                     return 1;
  497.                 break;
  498.             case IORDW:
  499.                 if(j_stuff(rdwstr))    /* ADR */
  500.                     return 1;
  501.                 break;
  502.             }
  503.             if(j_stuff(t->ioname))
  504.                 return 1;
  505.         }
  506.         t = t->ionxt;
  507.     }
  508.     return 0;
  509. }
  510.                 
  511.                 
  512. static int
  513. j_do(t)    
  514.     register struct trenod *t;
  515. {
  516.     int    type;
  517.  
  518.     if (t == (struct trenod *)0)    /* DAG -- added safety check */
  519.         return 0;
  520.  
  521.     type = t->tretyp & COMMSK;
  522.     switch(type)  {
  523. #ifdef TFND    /* ADR --- don't put this stuff in the plain BSD /bin/sh */
  524.     case    TFND:    /* added by DAG for System V Release 2 shell */
  525.         return j_stuff(fndptr(t)->fndnam)
  526.             || j_stuff(sfnstr)    /* DAG */
  527.             || j_do(fndptr(t)->fndval)
  528.             || j_stuff(efnstr);    /* DAG */
  529. #endif
  530.  
  531.     case    TCOM:
  532.         if(comptr(t)->comset)  {
  533.             if(j_do_chain(comptr(t)->comset)
  534.             || j_stuff(spcstr))
  535.                 return 1;            
  536.         }
  537.         return j_do_chain(comptr(t)->comarg)
  538.             || j_do_redir(comptr(t)->comio);
  539.  
  540.     case    TLST:
  541.     case    TAND:
  542.     case    TORF:
  543.     case    TFIL:    /* DAG -- merged */
  544.         if(j_do(lstptr(t)->lstlef))
  545.             return 1;
  546.         switch(type)  {
  547.         case TLST:
  548.             if(j_stuff(semspstr))    /* DAG */
  549.                 return 1;
  550.             break;
  551.         case TAND:
  552.             if(j_stuff(andstr))    /* DAG */
  553.                 return 1;
  554.             break;
  555.         case TORF:
  556.             if(j_stuff(orstr))    /* DAG */
  557.                 return 1;
  558.             break;
  559.         case TFIL:
  560.             if(j_stuff(pipestr))    /* DAG */
  561.                 return 1;
  562.             break;
  563.         }
  564.         return j_do(lstptr(t)->lstrit);
  565.  
  566.     case    TFORK:
  567.         return j_do(forkptr(t)->forktre)
  568.             || j_do_redir(forkptr(t)->forkio)
  569.             || (forkptr(t)->forktyp & FAMP) && j_stuff(amperstr);    /* DAG */
  570.  
  571.     case    TPAR:
  572.         return j_stuff(lpnstr)    /* DAG */
  573.             || j_do(parptr(t)->partre)
  574.             || j_stuff(rpnstr);    /* DAG */
  575.  
  576.     case    TFOR:
  577.     case    TWH:
  578.     case    TUN:
  579.     {
  580.         struct trenod *c;
  581.  
  582.         switch(type)  {
  583.         case TFOR:
  584.             if(j_stuff(forstr)    /* DAG */
  585.             || j_stuff(forptr(t)->fornam))
  586.                 return 1;
  587.             if(forptr(t)->forlst)  {
  588.                 if(j_stuff(insstr)    /* DAG */
  589.                 || j_do_chain(forptr(t)->forlst->comarg))
  590.                     return 1;
  591.             }
  592.             c = forptr(t)->fortre;
  593.             break;
  594.  
  595.         case TWH:
  596.             if(j_stuff(whilestr)    /* DAG */
  597.             || j_do(whptr(t)->whtre))
  598.                 return 1;
  599.             c = whptr(t)->dotre;
  600.             break;
  601.  
  602.         case TUN:
  603.             if(j_stuff(untilstr)    /* DAG */
  604.             || j_do(whptr(t)->whtre))
  605.                 return 1;
  606.             c = whptr(t)->dotre;
  607.             break;
  608.         }
  609.         return j_stuff(sdostr)    /* DAG */
  610.             || j_do(c)
  611.             || j_stuff(sdonstr);    /* DAG */
  612.     }
  613.     case    TIF:
  614.         if(j_stuff(ifstr)    /* DAG */
  615.         || j_do(ifptr(t)->iftre)
  616.         || j_stuff(sthnstr)    /* DAG */
  617.         || j_do(ifptr(t)->thtre))
  618.             return 1;
  619.         if(ifptr(t)->eltre)  {
  620.             if(j_stuff(selsstr)    /* DAG */
  621.             || j_do(ifptr(t)->eltre))
  622.                 return 1;
  623.         }
  624.         return j_stuff(sfistr);    /* DAG -- bug fix (was "; done") */
  625.  
  626.     case    TSW:
  627.         return j_stuff(casestr)    /* DAG */
  628.             || j_stuff(swptr(t)->swarg)
  629.             || j_stuff(iesacstr);    /* DAG */
  630.  
  631.     default:
  632. /*        printf("sh bug: j_do--unknown type %d\n", type);    */
  633.         return 0;
  634.     }
  635. }
  636.  
  637. static int
  638. j_stuff(f)
  639.     char    *f;
  640. {
  641.     register int    i;
  642.     register int    runover;
  643.  
  644.     i = strlen(f);
  645.     runover = i > jcleft;
  646.     if(runover)
  647.         i = jcleft;
  648.     strncpy(jcp, f, i);
  649.     jcleft -= i;
  650.     jcp += i;
  651.     *jcp = 0;
  652.     if(runover)  {
  653.         jcp[-1] = '.';
  654.         jcp[-2] = '.';
  655.         jcp[-3] = '.';
  656.     }
  657.     return runover;
  658. }
  659.