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_fd == -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_fd,       /* File descriptor of ptyp? opened r/w */
  38:         p_pid;      /* pid of child (the shell) */
  39:     Buffer  *p_buffer;  /* Add output to end of this buffer */
  40:     char    *p_name;    /* ... */
  41:     char    p_state,    /* State */
  42:         p_howdied,  /* Killed? or Exited? */
  43:         p_reason,   /* If signaled, p_reason is the signal; else
  44: 				   it is the the exit code */
  45:         p_eof;      /* Received EOF, so can be free'd up */
  46:     Mark    *p_mark;    /* Where output left us. */
  47:     data_obj
  48:         *p_cmd;     /* Command to call when process dies */
  49: } *procs = 0,
  50:   *cur_proc = 0;
  51: 
  52: char    proc_prompt[80] = "% ";
  53: 
  54: int global_fd = 1,
  55:     NumProcs = 0;
  56: 
  57: #ifdef BRLUNIX
  58:     extern struct sg_brl sg1;
  59: #else
  60:     extern struct sgttyb sg1;
  61: #endif
  62: 
  63: extern struct tchars tc1;
  64: 
  65: #ifdef TIOCSLTC
  66:     extern struct ltchars ls1;
  67: #endif
  68: 
  69: static char *
  70: pstate(p)
  71: Process *p;
  72: {
  73:     switch (proc_state(p)) {
  74:     case STOPPED:
  75:         return "Stopped";
  76: 
  77:     case RUNNING:
  78:         return "Running";
  79: 
  80:     case DEAD:
  81:         if (p->p_howdied == EXITED) {
  82:             if (p->p_reason == 0)
  83:                 return "Done";
  84:             return sprint("exit(%d)", p->p_reason);
  85:         }
  86:         return sprint("Killed(%d)", p->p_reason);
  87: 
  88:     default:
  89:         return "Unknown state.";
  90:     }
  91: }
  92: 
  93: static Process *
  94: proc_pid(pid)
  95: {
  96:     register Process    *p;
  97: 
  98:     for (p = procs; p != 0; p = p->p_next)
  99:         if (p->p_pid == pid)
 100:             break;
 101: 
 102:     return p;
 103: }
 104: 
 105: read_proc(fd)
 106: register int    fd;
 107: {
 108:     register Process    *p;
 109:     unsigned int    n;
 110:     char    ibuf[1024];
 111: 
 112:     for (p = procs; p != 0; p = p->p_next)
 113:         if (p->p_fd == fd)
 114:             break;
 115: 
 116:     if (p == 0) {
 117:         printf("\riproc: unknown fd %d", fd);
 118:         return;
 119:     }
 120: 
 121:     n = read(fd, ibuf, sizeof(ibuf) - 1);
 122: 
 123:     if (n == 0) {
 124:         proc_close(p);
 125:         NumProcs--;
 126:         return;
 127:     }
 128: 
 129:     ibuf[n] = '\0';
 130:     proc_rec(p, ibuf);
 131:     redisplay();
 132: }
 133: 
 134: ProcKill()
 135: {
 136:     register Buffer *b;
 137:     register Process    *p;
 138:     Process *buf_to_proc();
 139:     char    *bname;
 140: 
 141:     bname = ask_buf(cur_proc ? cur_proc->p_buffer : (Buffer *) 0);
 142: 
 143:     if ((b = buf_exists(bname)) == 0)
 144:         complain("[No such buffer]");
 145:     if ((p = buf_to_proc(b)) == 0)
 146:         complain("%s not tied to a process.", bname);
 147:     proc_kill(p, SIGKILL);
 148: }
 149: 
 150: Process *
 151: buf_to_proc(b)
 152: register Buffer *b;
 153: {
 154:     register Process *p;
 155: 
 156:     for (p = procs; p != 0; p = p->p_next)
 157:         if (p->p_buffer == b)
 158:             return p;
 159:     return 0;
 160: }
 161: 
 162: ProcCont()
 163: {
 164:     if (cur_proc == 0)
 165:         complain("[No processes]");
 166:     if (cur_proc->p_state != DEAD) {
 167:         proc_kill(cur_proc, SIGCONT);
 168:         cur_proc->p_state = RUNNING;
 169:     }
 170: }
 171: 
 172: ProcEof()
 173: {
 174:     send_p(tc1.t_eofc);
 175: }
 176: 
 177: ProcInt()
 178: {
 179:     send_p(tc1.t_intrc);
 180: }
 181: 
 182: ProcQuit()
 183: {
 184:     send_p(tc1.t_quitc);
 185: }
 186: 
 187: #ifdef TIOCSLTC
 188: 
 189: ProcStop()
 190: {
 191:     send_p(ls1.t_suspc);
 192: }
 193: 
 194: ProcDStop()
 195: {
 196:     send_p(ls1.t_dsuspc);
 197: }
 198: 
 199: #endif
 200: 
 201: send_p(c)
 202: char    c;
 203: {
 204:     if (cur_proc == 0)
 205:         complain("[No processes]");
 206:     if (cur_proc->p_buffer == curbuf)
 207:         ToLast();
 208:     (void) write(cur_proc->p_fd, &c, 1);
 209: }
 210: 
 211: static
 212: proc_close(p)
 213: Process *p;
 214: {
 215:     (void) close(p->p_fd);
 216:     global_fd &= ~(1 << p->p_fd);
 217:     p->p_eof++;
 218: }
 219: 
 220: do_rtp(mp)
 221: register Mark   *mp;
 222: {
 223:     register Process    *p = cur_proc;
 224:     Line    *line1 = curline,
 225:         *line2 = mp->m_line;
 226:     int char1 = curchar,
 227:         char2 = mp->m_char;
 228:     char    *gp;
 229: 
 230:     if (isdead(p) || p->p_buffer != curbuf)
 231:         return;
 232: 
 233:     (void) fixorder(&line1, &char1, &line2, &char2);
 234:     while (line1 != line2->l_next) {
 235:         gp = ltobuf(line1, genbuf) + char1;
 236:         if (line1 == line2)
 237:             gp[char2] = '\0';
 238:         else
 239:             strcat(gp, "\n");
 240:         (void) write(p->p_fd, gp, strlen(gp));
 241:         line1 = line1->l_next;
 242:         char1 = 0;
 243:     }
 244: }
 245: 
 246: /* VARARGS2 */
 247: 
 248: static
 249: proc_strt(bufname, procname, cmd)
 250: char    *bufname,
 251:     *procname,
 252:     *cmd;
 253: {
 254:     Window *owind   = curwind;
 255:     int pid;
 256:     Process *newp;
 257:     Buffer  *bp;
 258:     char    **cp;
 259:     int i,
 260:         f,
 261:         ttyfd;
 262:     long    ldisc,
 263:         lmode;
 264:     register char   *s,
 265:             *t;
 266:     extern int  errno;
 267:     extern char     **environ;
 268:     static char ttybuf[11],
 269:             ptybuf[11];
 270:     char    cmdbuf[128];
 271: #ifdef BRLUNIX
 272:     struct sg_brl sg;
 273: #else
 274:     struct sgttyb sg;
 275: #endif
 276: 
 277: #ifdef TIOCGWINSZ
 278:     struct winsize win;
 279: #else
 280: #  ifdef BTL_BLIT
 281: #  include <sys/jioctl.h>
 282:     struct jwinsize jwin;
 283: #  endif
 284: #endif
 285: 
 286:     bp = buf_exists(bufname);
 287:     if (bp != 0 && IsModified(bp) && bp->b_type != B_IPROCESS && bp->b_type != B_PROCESS)
 288:         complain("Command would over-write buffer %s.", procname, bufname);
 289:     pop_wind(bufname, 1, B_IPROCESS);
 290: 
 291:     for (s = "pqrs"; *s; s++) {
 292:         for (t = "0123456789abcdef"; *t; t++) {
 293:             sprintf(ptybuf, "/dev/pty%c%c", *s, *t);
 294:             if ((ttyfd = open(ptybuf, 2)) >= 0)
 295:                 goto out;
 296:         }
 297:     }
 298: 
 299: out:    if (s == 0 && t == 0)
 300:         complain("[Out of ptys!]");
 301: 
 302:     strcpy(ttybuf, ptybuf);
 303:     ttybuf[5] = 't';
 304: 
 305: #ifdef TIOCGETD
 306:     (void) ioctl(0, TIOCGETD, (struct sgttyb *) &ldisc);
 307: #endif
 308: #ifdef TIOCLGET
 309:     (void) ioctl(0, TIOCLGET, (struct sgttyb *) &lmode);
 310: #endif
 311: #ifdef TIOCGWINSZ
 312:     (void) ioctl(0, TIOCGWINSZ, (struct sgttyb *) &win);
 313: #else
 314: #  ifdef BTL_BLIT
 315:     (void) ioctl(0, JWINSIZE, (struct sgttyb *) &jwin);
 316: #  endif BTL_BLIT
 317: #endif
 318: 
 319:     switch (pid = fork()) {
 320:     case -1:
 321:         (void) close(ttyfd);
 322:         complain("[Fork failed!]");
 323: 
 324:     case 0:
 325:         cp = &cmd;
 326: 
 327:         for (i = 0; i < 32; i++)
 328:             (void) close(i);
 329: 
 330: #ifdef TIOCNOTTY
 331:         if ((i = open("/dev/tty", 2)) >= 0) {
 332:             (void) ioctl(i, TIOCNOTTY, (struct sgttyb *) 0);
 333:             (void) close(i);
 334:         }
 335: #endif
 336:         i = open(ttybuf, 2);
 337:         for (f = 0; f <= 2; f++)
 338:             (void) dup2(i, f);
 339: 
 340: #ifdef TIOCSETD
 341:         (void) ioctl(0, TIOCSETD, (struct sgttyb *) &ldisc);
 342: #endif
 343: #ifdef TIOCLSET
 344:         (void) ioctl(0, TIOCLSET, (struct sgttyb *) &lmode);
 345: #endif
 346: #ifdef TIOCSETC
 347:         (void) ioctl(0, TIOCSETC, (struct sgttyb *) &tc1);
 348: #endif
 349: #ifdef TIOCSLTC
 350:         (void) ioctl(0, TIOCSLTC, (struct sgttyb *) &ls1);
 351: #endif
 352: 
 353: #ifdef TIOCGWINSZ
 354: #    ifdef SIGWINCH
 355:         (void) signal(SIGWINCH, SIG_IGN);
 356: #    endif
 357:         win.ws_row = curwind->w_height;
 358:         (void) ioctl(0, TIOCSWINSZ, (struct sgttyb *) &win);
 359: #else
 360: #  ifdef BTL_BLIT
 361:         jwin.bytesy = curwind->w_height;
 362:         (void) ioctl(0, JSWINSIZE, (struct sgttyb *) &jwin);
 363: #  endif
 364: #endif
 365: 
 366:         sg = sg1;
 367:         sg.sg_flags &= ~(ECHO | CRMOD);
 368:         (void) stty(0, &sg);
 369: 
 370:         i = getpid();
 371:         (void) ioctl(0, TIOCSPGRP, (struct sgttyb *) &i);
 372:         (void) setpgrp(0, i);
 373:         execve(cp[0], &cp[1], environ);
 374:         (void) write(1, "execve failed!\n", 15);
 375:         _exit(errno + 1);
 376:     }
 377: 
 378:     sighold(SIGCHLD);
 379: #ifdef SIGWINCH
 380:     sighold(SIGWINCH);
 381: #endif
 382:     cur_proc = newp = (Process *) emalloc(sizeof *newp);
 383: 
 384:     newp->p_fd = ttyfd;
 385:     newp->p_pid = pid;
 386:     newp->p_eof = 0;
 387:     newp->p_buffer = curbuf;
 388: 
 389:     cp = &cmd + 1;
 390:     cmdbuf[0] = '\0';
 391:     while (*cp != 0)
 392:         (void) sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", *cp++);
 393: 
 394:     newp->p_name = copystr(cmdbuf);
 395:     newp->p_state = RUNNING;
 396:     newp->p_reason = 0;
 397:     newp->p_mark = MakeMark(curline, curchar, FLOATER);
 398: 
 399:     newp->p_next = procs;
 400:     procs = newp;
 401:     NumProcs++;
 402:     global_fd |= 1 << newp->p_fd;
 403:     sigrelse(SIGCHLD);
 404:     SetWind(owind);
 405: }
 406: 
 407: pinit()
 408: {
 409:     (void) signal(SIGCHLD, proc_child);
 410: }

Defined functions

ProcCont defined in line 162; used 2 times
ProcDStop defined in line 194; used 2 times
ProcEof defined in line 172; used 2 times
ProcInt defined in line 177; used 2 times
ProcKill defined in line 134; used 2 times
ProcQuit defined in line 182; used 2 times
ProcStop defined in line 189; used 2 times
buf_to_proc defined in line 150; used 2 times
do_rtp defined in line 220; used 1 times
pinit defined in line 407; used 1 times
proc_close defined in line 211; used 1 times
proc_pid defined in line 93; never used
proc_strt defined in line 248; never used
pstate defined in line 69; never used
read_proc defined in line 105; used 1 times
send_p defined in line 201; used 5 times

Defined variables

global_fd defined in line 54; used 2 times
proc_prompt defined in line 52; used 3 times
procs defined in line 49; used 13 times

Defined struct's

process defined in line 35; used 1 times
  • in line 18

Defined typedef's

Process defined in line 18; used 23 times

Defined macros

DEAD defined in line 20; used 4 times
EXITED defined in line 26; used 2 times
KILLED defined in line 27; used 1 times
NEW defined in line 23; never used
RUNNING defined in line 22; used 2 times
STOPPED defined in line 21; used 1 times
isdead defined in line 29; used 3 times
proc_buf defined in line 31; used 5 times
proc_cmd defined in line 32; used 1 times
proc_state defined in line 33; used 2 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