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: #include <errno.h>
  16: 
  17: #define DEAD    1   /* dead but haven't informed user yet */
  18: #define STOPPED 2   /* job stopped */
  19: #define RUNNING 3   /* just running */
  20: #define NEW 4   /* brand new, never been ... received no input */
  21: 
  22: /* If process is dead, flags says how. */
  23: #define EXITED  1
  24: #define KILLED  2
  25: 
  26: #define isdead(p)   (p == 0 || proc_state(p) == DEAD || p->p_fd == -1)
  27: #define makedead(p) (proc_state(p) = DEAD)
  28: 
  29: #define proc_buf(p) (p->p_buffer->b_name)
  30: #define proc_cmd(p) (p->p_name)
  31: #define proc_state(p)   (p->p_state)
  32: 
  33: private Process *procs = 0;
  34: 
  35: long    global_fd = 1;
  36: int NumProcs = 0;
  37: 
  38: #ifdef BRLUNIX
  39:     extern struct sg_brl sg1;
  40: #else
  41:     extern struct sgttyb sg1;
  42: #endif
  43: 
  44: extern struct tchars tc1;
  45: 
  46: #ifdef TIOCSLTC
  47:     extern struct ltchars ls1;
  48: #endif
  49: 
  50: char *
  51: pstate(p)
  52: Process *p;
  53: {
  54:     switch (proc_state(p)) {
  55:     case STOPPED:
  56:         return "Stopped";
  57: 
  58:     case RUNNING:
  59:         return "Running";
  60: 
  61:     case DEAD:
  62:         if (p->p_howdied == EXITED) {
  63:             if (p->p_reason == 0)
  64:                 return "Done";
  65:             return sprint("Exit %d", p->p_reason);
  66:         }
  67:         return sprint("Killed %d", p->p_reason);
  68: 
  69:     case NEW:
  70:         return "New";
  71: 
  72:     default:
  73:         return "Unknown state";
  74:     }
  75: }
  76: 
  77: static Process *
  78: proc_pid(pid)
  79: {
  80:     register Process    *p;
  81: 
  82:     for (p = procs; p != 0; p = p->p_next)
  83:         if (p->p_pid == pid)
  84:             break;
  85: 
  86:     return p;
  87: }
  88: 
  89: read_proc(fd)
  90: register int    fd;
  91: {
  92:     register Process    *p;
  93:     unsigned int    n;
  94:     char    ibuf[1024];
  95: 
  96:     for (p = procs; p != 0; p = p->p_next)
  97:         if (p->p_fd == fd)
  98:             break;
  99: 
 100:     if (p == 0) {
 101:         printf("\riproc: unknown fd %d", fd);
 102:         return;
 103:     }
 104: 
 105:     n = read(fd, ibuf, sizeof(ibuf) - 1);
 106:     if (n == -1 && errno == EIO) {
 107:         if (proc_state(p) == NEW)
 108:             return;
 109:         proc_close(p);
 110:         makedead(p);
 111:         return;
 112:     } else {
 113:         if (proc_state(p) != RUNNING) {
 114:             proc_state(p) = RUNNING;
 115:             UpdModLine = YES;
 116:         }
 117:     }
 118:     if (n <= 0) {
 119:         if (n == 0)
 120:             strcpy(ibuf, "[Process EOF]");
 121:         else
 122:             sprintf(ibuf, "\n[pty read error: %d]\n", errno);
 123:     } else
 124:         ibuf[n] = '\0';
 125:     proc_rec(p, ibuf);
 126: }
 127: 
 128: ProcKill()
 129: {
 130:     register Buffer *b;
 131:     Process *buf_to_proc();
 132:     char    *bname;
 133: 
 134:     bname = ask_buf(curbuf);
 135: 
 136:     if ((b = buf_exists(bname)) == 0)
 137:         complain("[No such buffer]");
 138:     if (b->b_process == 0)
 139:         complain("%s not tied to a process.", bname);
 140:     proc_kill(b->b_process, SIGKILL);
 141: }
 142: 
 143: ProcCont()
 144: {
 145:     Process *p;
 146: 
 147:     if ((p = curbuf->b_process) == 0)
 148:         complain("[No process]");
 149:     if (p->p_state != DEAD) {
 150:         proc_kill(p, SIGCONT);
 151:         p->p_state = RUNNING;
 152:     }
 153: }
 154: 
 155: ProcEof()
 156: {
 157:     send_p(tc1.t_eofc);
 158: }
 159: 
 160: ProcInt()
 161: {
 162:     send_p(tc1.t_intrc);
 163: }
 164: 
 165: ProcQuit()
 166: {
 167:     send_p(tc1.t_quitc);
 168: }
 169: 
 170: ProcStop()
 171: {
 172:     send_p(ls1.t_suspc);
 173: }
 174: 
 175: ProcDStop()
 176: {
 177:     send_p(ls1.t_dsuspc);
 178: }
 179: 
 180: send_p(c)
 181: char    c;
 182: {
 183:     Process *p;
 184:     char    buf[2];
 185: 
 186:     if ((p = curbuf->b_process) == 0)
 187:         complain("[No process]");
 188:     ToLast();
 189:     buf[0] = c;
 190:     buf[1] = '\0';
 191:     proc_rec(p, buf);
 192:     (void) write(p->p_fd, &c, 1);
 193: }
 194: 
 195: private
 196: proc_close(p)
 197: Process *p;
 198: {
 199:     sighold(SIGCHLD);   /* be mutually exclusive */
 200: 
 201:     if (p->p_fd >= 0) {
 202:         (void) close(p->p_fd);
 203:         global_fd &= ~(1L << p->p_fd);
 204:         NumProcs -= 1;
 205:         p->p_fd = -1;
 206:     }
 207: 
 208:     sigrelse(SIGCHLD);
 209: }
 210: 
 211: do_rtp(mp)
 212: register Mark   *mp;
 213: {
 214:     register Process    *p = curbuf->b_process;
 215:     Line    *line1 = curline,
 216:         *line2 = mp->m_line;
 217:     int char1 = curchar,
 218:         char2 = mp->m_char;
 219:     char    *gp;
 220:     int nbytes;
 221: 
 222:     if (isdead(p) || p->p_buffer != curbuf)
 223:         return;
 224: 
 225:     (void) fixorder(&line1, &char1, &line2, &char2);
 226:     while (line1 != line2->l_next) {
 227:         gp = ltobuf(line1, genbuf) + char1;
 228:         if (line1 == line2)
 229:             gp[char2] = '\0';
 230:         else
 231:             strcat(gp, "\n");
 232:         if (nbytes = strlen(gp))
 233:             (void) write(p->p_fd, gp, nbytes);
 234:         line1 = line1->l_next;
 235:         char1 = 0;
 236:     }
 237: }
 238: 
 239: /* VARARGS2 */
 240: 
 241: private
 242: proc_strt(bufname, clobber, va_alist)
 243: char    *bufname;
 244: va_dcl
 245: {
 246:     va_list ap;
 247:     char    *argv[32],
 248:         *cp;
 249:     Window *owind = curwind;
 250:     int pid;
 251:     Process *newp;
 252:     Buffer  *newbuf;
 253:     int i,
 254:         ptyfd,
 255:         ttyfd,
 256:         ldisc,
 257:         lmode;
 258:     register char   *s,
 259:             *t;
 260:     extern int  errno;
 261:     static char ttybuf[11],
 262:             ptybuf[11];
 263:     char    cmdbuf[128];
 264: #ifdef BRLUNIX
 265:     struct sg_brl sg;
 266: #else
 267:     struct sgttyb sg;
 268: #endif
 269: 
 270: #ifdef TIOCGWINSZ
 271:     struct winsize win;
 272: #else
 273: #  ifdef BTL_BLIT
 274: #  include <sys/jioctl.h>
 275:     struct jwinsize jwin;
 276: #  endif
 277: #endif
 278: 
 279:     isprocbuf(bufname); /* make sure BUFNAME is either nonexistant
 280: 				   or is of type B_PROCESS */
 281:     for (s = "pqrs"; *s; s++) {
 282:         for (t = "0123456789abcdef"; *t; t++) {
 283:             sprintf(ptybuf, "/dev/pty%c%c", *s, *t);
 284:             if ((ptyfd = open(ptybuf, 2)) >= 0) {
 285:                 strcpy(ttybuf, ptybuf);
 286:                 ttybuf[5] = 't';
 287:                 /* make sure both ends are available */
 288:                 if ((i = open(ttybuf, 2)) < 0)
 289:                     continue;
 290:                 (void) close(i);
 291:                 goto out;
 292:             }
 293:         }
 294:     }
 295: 
 296: out:    if (s == 0 && t == 0)
 297:         complain("[Out of ptys!]");
 298: 
 299: #ifdef TIOCGETD
 300:     (void) ioctl(0, TIOCGETD, (struct sgttyb *) &ldisc);
 301: #endif
 302: #ifdef TIOCLGET
 303:     (void) ioctl(0, TIOCLGET, (struct sgttyb *) &lmode);
 304: #endif
 305: #ifdef TIOCGWINSZ
 306:     (void) ioctl(0, TIOCGWINSZ, (struct sgttyb *) &win);
 307: #else
 308: #  ifdef BTL_BLIT
 309:     (void) ioctl(0, JWINSIZE, (struct sgttyb *) &jwin);
 310: #  endif /* BTL_BLIT */
 311: #endif
 312: 
 313:     sighold(SIGCHLD);
 314: #ifdef SIGWINCH
 315:     sighold(SIGWINCH);
 316: #endif
 317:     switch (pid = fork()) {
 318:     case -1:
 319:         (void) close(ptyfd);
 320:         message("[Fork failed!]");
 321:         goto fail;
 322: 
 323:     case 0:
 324:         sigrelse(SIGCHLD);
 325: #ifdef SIGWINCH
 326:         sigrelse(SIGWINCH);
 327: #endif
 328:         for (i = 0; i < 32; i++)
 329:             (void) close(i);
 330: 
 331: #ifdef TIOCNOTTY
 332:         if ((i = open("/dev/tty", 2)) >= 0) {
 333:             (void) ioctl(i, TIOCNOTTY, (struct sgttyb *) 0);
 334:             (void) close(i);
 335:         }
 336: #endif
 337:         if ((ttyfd = open(ttybuf, 2)) < 0)
 338:             exit(-1);
 339:         (void) dup2(ttyfd, 1);
 340:         (void) dup2(ttyfd, 2);
 341: 
 342: #ifdef TIOCSETD
 343:         (void) ioctl(0, TIOCSETD, (struct sgttyb *) &ldisc);
 344: #endif
 345: #ifdef TIOCLSET
 346:         (void) ioctl(0, TIOCLSET, (struct sgttyb *) &lmode);
 347: #endif
 348: #ifdef TIOCSETC
 349:         (void) ioctl(0, TIOCSETC, (struct sgttyb *) &tc1);
 350: #endif
 351: #ifdef TIOCSLTC
 352:         (void) ioctl(0, TIOCSLTC, (struct sgttyb *) &ls1);
 353: #endif
 354: 
 355: #ifdef TIOCGWINSZ
 356: #    ifdef SIGWINCH
 357:         (void) signal(SIGWINCH, SIG_IGN);
 358: #    endif
 359:         win.ws_row = curwind->w_height;
 360:         (void) ioctl(0, TIOCSWINSZ, (struct sgttyb *) &win);
 361: #else
 362: #  ifdef BTL_BLIT
 363:         jwin.bytesy = curwind->w_height;
 364:         (void) ioctl(0, JSWINSIZE, (struct sgttyb *) &jwin);
 365: #  endif
 366: #endif
 367: 
 368:         sg = sg1;
 369:         sg.sg_flags &= ~(ECHO | CRMOD);
 370:         (void) stty(0, &sg);
 371: 
 372:         i = getpid();
 373:         (void) ioctl(0, TIOCSPGRP, (struct sgttyb *) &i);
 374:         (void) setpgrp(0, i);
 375:         va_start(ap);
 376:         make_argv(argv, ap);
 377:         va_end(ap);
 378:         execv(argv[0], &argv[1]);
 379:         (void) write(1, "execve failed!\n", 15);
 380:         _exit(errno + 1);
 381:     }
 382: 
 383:     newp = (Process *) emalloc(sizeof *newp);
 384: 
 385:     newp->p_fd = ptyfd;
 386:     newp->p_pid = pid;
 387: 
 388:     newbuf = do_select((Window *) 0, bufname);
 389:     newbuf->b_type = B_PROCESS;
 390:     newp->p_buffer = newbuf;
 391:     newbuf->b_process = newp;   /* sorta circular, eh? */
 392:     pop_wind(bufname, clobber, B_PROCESS);
 393:     /* Pop_wind() after everything is set up; important!
 394: 	   Bindings won't work right unless newbuf->b_process is already
 395: 	   set up BEFORE NEWBUF is first SetBuf()'d. */
 396:     ToLast();
 397:     if (!bolp())
 398:         LineInsert(1);
 399: 
 400:     cmdbuf[0] = '\0';
 401:     va_start(ap);
 402:     while (cp = va_arg(ap, char *))
 403:         sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp++);
 404:     va_end(ap);
 405: 
 406:     newp->p_name = copystr(cmdbuf);
 407:     newp->p_state = NEW;
 408:     newp->p_reason = 0;
 409:     newp->p_mark = MakeMark(curline, curchar, M_FLOATER);
 410: 
 411:     newp->p_next = procs;
 412:     procs = newp;
 413:     NumProcs += 1;
 414:     global_fd |= 1L << newp->p_fd;
 415:     SetWind(owind);
 416: 
 417: fail:   sigrelse(SIGCHLD);
 418: #ifdef SIGWINCH
 419:     sigrelse(SIGWINCH);
 420: #endif
 421: }
 422: 
 423: pinit()
 424: {
 425:     (void) signal(SIGCHLD, proc_child);
 426: }

Defined functions

ProcCont defined in line 143; used 2 times
ProcDStop defined in line 175; used 2 times
ProcEof defined in line 155; used 2 times
ProcInt defined in line 160; used 2 times
ProcKill defined in line 128; used 2 times
ProcQuit defined in line 165; used 2 times
ProcStop defined in line 170; used 2 times
do_rtp defined in line 211; used 1 times
pinit defined in line 423; used 1 times
proc_close defined in line 195; used 2 times
proc_pid defined in line 77; never used
proc_strt defined in line 241; used 2 times
pstate defined in line 50; used 5 times
read_proc defined in line 89; used 1 times
send_p defined in line 180; used 5 times

Defined variables

NumProcs defined in line 36; used 2 times
global_fd defined in line 35; used 2 times

Defined macros

DEAD defined in line 17; used 4 times
EXITED defined in line 23; used 2 times
KILLED defined in line 24; used 1 times
NEW defined in line 20; used 2 times
RUNNING defined in line 19; used 3 times
STOPPED defined in line 18; used 1 times
isdead defined in line 26; used 9 times
makedead defined in line 27; used 1 times
proc_buf defined in line 29; used 2 times
proc_cmd defined in line 30; used 2 times
proc_state defined in line 31; used 6 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