1: /*************************************************************************
   2:  * This program is copyright (C) 1985, 1986 by Jonathan Payne.  It is    *
   3:  * provided to you without charge for use only on a licensed Unix        *
   4:  * system.  You may copy JOVE provided that this notice is included with *
   5:  * the copy.  You may not sell copies of this program or versions        *
   6:  * modified for use on microcomputer systems, unless the copies are      *
   7:  * included with a Unix system distribution and the source is provided.  *
   8:  *************************************************************************/
   9: 
  10: #ifdef BSD4_2
  11: #   include <sys/wait.h>
  12: #else
  13: #   include <wait.h>
  14: #endif
  15: #include <signal.h>
  16: #include <sgtty.h>
  17: 
  18: typedef struct process  Process;
  19: 
  20: #define DEAD    1   /* Dead but haven't informed user yet */
  21: #define STOPPED 2   /* Job stopped */
  22: #define RUNNING 3   /* Just running */
  23: #define NEW 4   /* This process is brand new */
  24: 
  25: /* If process is dead, flags says how. */
  26: #define EXITED  1
  27: #define KILLED  2
  28: 
  29: #define isdead(p)   (p == 0 || proc_state(p) == DEAD || p->p_toproc == -1)
  30: 
  31: #define proc_buf(p) (p->p_buffer->b_name)
  32: #define proc_cmd(p) (p->p_name)
  33: #define proc_state(p)   (p->p_state)
  34: 
  35: struct process {
  36:     Process *p_next;
  37:     int p_toproc,   /* read p_fromproc and write p_toproc */
  38:         p_portpid,  /* Pid of child (the portsrv) */
  39:         p_pid;      /* Pid of real child i.e. not portsrv */
  40:     Buffer  *p_buffer;  /* Add output to end of this buffer */
  41:     char    *p_name;    /* ... */
  42:     char    p_state,    /* State */
  43:         p_howdied,  /* Killed? or Exited? */
  44:         p_reason,   /* If signaled, p_reason is the signal; else
  45: 				   it is the the exit code */
  46:         p_eof;      /* Received EOF, so can be free'd up */
  47:     Mark    *p_mark;    /* Where output left us. */
  48:     data_obj
  49:         *p_cmd;     /* Command to call when process dies */
  50: } *procs = 0,
  51:   *cur_proc = 0;
  52: 
  53: char    proc_prompt[80] = "% ";
  54: 
  55: int ProcInput,
  56:     ProcOutput,
  57:     NumProcs = 0;
  58: 
  59: static char *
  60: pstate(p)
  61: Process *p;
  62: {
  63:     switch (proc_state(p)) {
  64:     case NEW:
  65:         return "Pre-birth";
  66: 
  67:     case STOPPED:
  68:         return "Stopped";
  69: 
  70:     case RUNNING:
  71:         return "Running";
  72: 
  73:     case DEAD:
  74:         if (p->p_howdied == EXITED) {
  75:             if (p->p_reason == 0)
  76:                 return "Done";
  77:             return sprint("[Exit %d]", p->p_reason);
  78:         }
  79:         return sprint("[Killed %d]", p->p_reason);
  80: 
  81:     default:
  82:         return "Unknown state.";
  83:     }
  84: }
  85: 
  86: static Process *
  87: proc_pid(pid)
  88: {
  89:     register Process    *p;
  90: 
  91:     for (p = procs; p != 0; p = p->p_next)
  92:         if (p->p_portpid == pid)
  93:             break;
  94: 
  95:     return p;
  96: }
  97: 
  98: procs_read()
  99: {
 100:     struct header {
 101:         int pid;
 102:         int nbytes;
 103:     } header;
 104:     int n;
 105:     long    nbytes;
 106:     static int  here = 0;
 107: 
 108:     if (here)
 109:         return;
 110:     sighold(SIGCHLD);   /* Block any other children. */
 111:     here++;
 112:     for (;;) {
 113:         (void) ioctl(ProcInput, FIONREAD, (struct sgttyb *) &nbytes);
 114:         if (nbytes < sizeof header)
 115:             break;
 116:         n = read(ProcInput, (char *) &header, sizeof header);
 117:         if (n != sizeof header)
 118:             finish(1);
 119:         read_proc(header.pid, header.nbytes);
 120:     }
 121:     redisplay();
 122:     here = 0;
 123:     sigrelse(SIGCHLD);
 124: }
 125: 
 126: read_proc(pid, nbytes)
 127: int pid;
 128: register int    nbytes;
 129: {
 130:     register Process    *p;
 131:     int n;
 132:     char    ibuf[512];
 133: 
 134:     if ((p = proc_pid(pid)) == 0) {
 135:         printf("\riproc: unknown pid (%d)", pid);
 136:         return;
 137:     }
 138:     if (proc_state(p) == NEW) {
 139:         int rpid;
 140:         /* Pid of real child, not of portsrv. */
 141: 
 142:         doread(ProcInput, (char *) &rpid, nbytes);
 143:         nbytes -= sizeof rpid;
 144:         p->p_pid = rpid;
 145:         p->p_state = RUNNING;
 146:     }
 147: 
 148:     if (nbytes == EOF) {        /* Okay to clean up this process */
 149:         p->p_eof = 1;
 150:         NumProcs--; /* As far as getch() in main is concerned */
 151:         return;
 152:     }
 153: 
 154:     while (nbytes > 0) {
 155:         n = min((sizeof ibuf) - 1, nbytes);
 156:         doread(ProcInput, ibuf, n);
 157:         ibuf[n] = 0;    /* Null terminate for convenience */
 158:         nbytes -= n;
 159:         proc_rec(p, ibuf);
 160:     }
 161: }
 162: 
 163: ProcKill()
 164: {
 165:     proc_kill(cur_proc, SIGKILL);
 166: }
 167: 
 168: ProcInt()
 169: {
 170:     proc_kill(cur_proc, SIGINT);
 171: }
 172: 
 173: ProcQuit()
 174: {
 175:     proc_kill(cur_proc, SIGQUIT);
 176: }
 177: 
 178: static
 179: proc_close(p)
 180: Process *p;
 181: {
 182:     (void) close(p->p_toproc);
 183:     p->p_toproc = -1;   /* Writes will fail. */
 184: }
 185: 
 186: do_rtp(mp)
 187: register Mark   *mp;
 188: {
 189:     register Process    *p = cur_proc;
 190:     Line    *line1 = curline,
 191:         *line2 = mp->m_line;
 192:     int char1 = curchar,
 193:         char2 = mp->m_char;
 194:     char    *gp;
 195: 
 196:     if (isdead(p) || p->p_buffer != curbuf)
 197:         return;
 198: 
 199:     (void) fixorder(&line1, &char1, &line2, &char2);
 200:     while (line1 != line2->l_next) {
 201:         gp = ltobuf(line1, genbuf) + char1;
 202:         if (line1 == line2)
 203:             gp[char2] = '\0';
 204:         else
 205:             strcat(gp, "\n");
 206:         (void) write(p->p_toproc, gp, strlen(gp));
 207:         line1 = line1->l_next;
 208:         char1 = 0;
 209:     }
 210: }
 211: 
 212: /* VARARGS2 */
 213: 
 214: static
 215: proc_strt(bufname, procname, cmd)
 216: char    *bufname,
 217:     *procname,
 218:     *cmd;
 219: {
 220:     Window  *owind = curwind;
 221:     int toproc[2],
 222:         pid;
 223:     Process *newp;
 224:     Buffer  *bp;
 225:         char    *args[25],
 226:             **cp,
 227:             foo[10],
 228:         cmdbuf[128];
 229:         int i;
 230: 
 231:     bp = buf_exists(bufname);
 232:     if (bp != 0 && IsModified(bp) && bp->b_type != B_IPROCESS && bp->b_type != B_PROCESS)
 233:         complain("Command would over-write buffer %s.", procname, bufname);
 234:     pop_wind(bufname, 1, B_IPROCESS);
 235: 
 236:     dopipe(toproc);
 237: 
 238:     switch (pid = fork()) {
 239:     case -1:
 240:         pclose(toproc);
 241:         complain("[Fork failed.]");
 242: 
 243:     case 0:
 244:             args[0] = "portsrv";
 245:             args[1] = foo;
 246:         sprintf(foo, "%d", ProcInput);
 247:             for (i = 0, cp = &cmd; cp[i] != 0; i++)
 248:                 args[2 + i] = cp[i];
 249:             args[2 + i] = 0;
 250:         (void) dup2(toproc[0], 0);
 251:         (void) dup2(ProcOutput, 1);
 252:         (void) dup2(ProcOutput, 2);
 253:         pclose(toproc);
 254:         execv(PORTSRV, args);
 255:         printf("Execl failed.\n");
 256:         _exit(1);
 257:     }
 258: 
 259:     sighold(SIGCHLD);
 260:     cur_proc = newp = (Process *) malloc(sizeof *newp);
 261:     newp->p_next = procs;
 262:     newp->p_state = NEW;
 263:     newp->p_mark = MakeMark(curline, curchar, FLOATER);
 264:     newp->p_cmd = 0;
 265: 
 266:     cp = &cmd + 1;
 267:     cmdbuf[0] = '\0';
 268:     while (*cp != 0)
 269:         sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", *cp++);
 270:     newp->p_name = copystr(cmdbuf);
 271:     procs = newp;
 272:     newp->p_portpid = pid;
 273:     newp->p_pid = -1;
 274:     newp->p_buffer = curbuf;
 275:     newp->p_toproc = toproc[1];
 276:     newp->p_reason = 0;
 277:     newp->p_eof = 0;
 278:     NumProcs++;
 279:     (void) close(toproc[0]);
 280:     sigrelse(SIGCHLD);
 281:     SetWind(owind);
 282: }
 283: 
 284: pinit()
 285: {
 286:     int p[2];
 287: 
 288:     (void) signal(SIGCHLD, proc_child);
 289:     (void) pipe(p);
 290:     ProcInput = p[0];
 291:     ProcOutput = p[1];
 292:     (void) signal(INPUT_SIG, procs_read);
 293:     sighold(INPUT_SIG); /* Released during terminal read */
 294: }
 295: 
 296: doread(fd, buf, n)
 297: char    *buf;
 298: {
 299:     int nread;
 300: 
 301:     if ((nread = read(fd, buf, n)) != n)
 302:         complain("Cannot read %d (got %d) bytes.", n, nread);
 303: }

Defined functions

ProcInt defined in line 168; never used
ProcKill defined in line 163; never used
ProcQuit defined in line 173; never used
do_rtp defined in line 186; never used
doread defined in line 296; used 2 times
pinit defined in line 284; never used
proc_close defined in line 178; never used
proc_pid defined in line 86; used 1 times
proc_strt defined in line 214; never used
procs_read defined in line 98; used 1 times
pstate defined in line 59; never used
read_proc defined in line 126; used 1 times

Defined variables

NumProcs defined in line 57; used 2 times
ProcInput defined in line 55; used 6 times
ProcOutput defined in line 56; used 3 times
proc_prompt defined in line 53; never used
procs defined in line 50; used 3 times

Defined struct's

header defined in line 100; never used
process defined in line 35; used 1 times
  • in line 18

Defined typedef's

Process defined in line 18; used 9 times

Defined macros

DEAD defined in line 20; used 1 times
  • in line 29
EXITED defined in line 26; used 1 times
  • in line 74
KILLED defined in line 27; never used
NEW defined in line 23; used 2 times
RUNNING defined in line 22; used 1 times
STOPPED defined in line 21; never used
isdead defined in line 29; used 1 times
proc_buf defined in line 31; never used
proc_cmd defined in line 32; never used
proc_state defined in line 33; used 3 times

Usage of this include

Last modified: 1986-03-28
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: ?E00
Valid CSS Valid XHTML 1.0 Strict