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

Defined functions

ProcInt defined in line 146; never used
ProcKill defined in line 141; never used
ProcQuit defined in line 151; never used
do_rtp defined in line 171; never used
doread defined in line 300; used 2 times
pinit defined in line 288; never used
proc_close defined in line 156; used 1 times
proc_pid defined in line 65; used 1 times
proc_strt defined in line 199; never used
procs_read defined in line 77; used 1 times
pstate defined in line 38; never used
read_proc defined in line 104; used 1 times
  • in line 98

Defined variables

NumProcs defined in line 36; used 2 times
ProcInput defined in line 34; used 6 times
ProcOutput defined in line 35; used 3 times

Defined struct's

header defined in line 79; never used

Defined macros

DEAD defined in line 16; used 2 times
EXITED defined in line 22; used 1 times
  • in line 53
KILLED defined in line 23; never used
NEW defined in line 19; used 2 times
RUNNING defined in line 18; used 1 times
STOPPED defined in line 17; never used
isdead defined in line 25; used 1 times
makedead defined in line 26; used 1 times
proc_buf defined in line 28; never used
proc_cmd defined in line 29; never used
proc_state defined in line 30; used 4 times

Usage of this include

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