|
|
1.1 ! root 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: #include "jove.h" ! 9: #include "re.h" ! 10: #include "ctype.h" ! 11: #include "disp.h" ! 12: #if defined(IPROCS) ! 13: # include "fp.h" ! 14: # include "iproc.h" ! 15: #endif ! 16: ! 17: #ifdef STDARGS ! 18: # include <stdargs.h> ! 19: #else ! 20: # include <varargs.h> ! 21: #endif ! 22: ! 23: #ifdef IPROCS ! 24: ! 25: private void ! 26: proc_rec proto ((Process *, char *)), ! 27: proc_close proto ((Process *)), ! 28: proc_kill proto((Process *, int)), ! 29: SendData proto ((int)); ! 30: ! 31: private int ! 32: proc_child proto((int)); ! 33: ! 34: #ifdef PIPEPROCS ! 35: # include "iproc-pipes.c" ! 36: #else ! 37: # include "iproc-ptys.c" ! 38: #endif ! 39: ! 40: char proc_prompt[128] = "% "; ! 41: ! 42: char * ! 43: pstate(p) ! 44: Process *p; ! 45: { ! 46: switch (proc_state(p)) { ! 47: case NEW: ! 48: return "New"; ! 49: ! 50: case STOPPED: ! 51: return "Stopped"; ! 52: ! 53: case RUNNING: ! 54: return "Running"; ! 55: ! 56: case DEAD: ! 57: if (p->p_howdied == EXITED) { ! 58: if (p->p_reason == 0) ! 59: return "Done"; ! 60: return sprint("Exit %d", p->p_reason); ! 61: } ! 62: return sprint("Killed %d", p->p_reason); ! 63: ! 64: default: ! 65: return "Unknown state"; ! 66: } ! 67: } ! 68: ! 69: void ! 70: KillProcs() ! 71: { ! 72: register Process *p; ! 73: register int killem = -1; /* -1 means undetermined */ ! 74: register char *yorn; ! 75: ! 76: for (p = procs; p != 0; p = p->p_next) ! 77: if (!isdead(p)) { ! 78: if (killem == -1) { ! 79: yorn = ask("y", "Should I kill your i-processes? "); ! 80: killem = (CharUpcase(*yorn) == 'Y'); ! 81: } ! 82: if (killem) ! 83: proc_kill(p, SIGKILL); ! 84: } ! 85: } ! 86: ! 87: void ! 88: pbuftiedp(b) ! 89: register Buffer *b; ! 90: { ! 91: register Process *p = b->b_process; ! 92: ! 93: if (!isdead(p)) ! 94: complain("Process %s, attached to %b, is %s.", ! 95: proc_cmd(p), b, pstate(p)); ! 96: } ! 97: ! 98: char dbx_parse_fmt[128] = "line \\([0-9]*\\) in \\{file,\\} *\"\\([^\"]*\\)\""; ! 99: ! 100: void ! 101: DBXpoutput() ! 102: { ! 103: if (curbuf->b_process == 0) ! 104: complain("[Must be in a process buffer to enable dbx mode]"); ! 105: curbuf->b_process->p_dbx_mode = !curbuf->b_process->p_dbx_mode; ! 106: UpdModLine = YES; ! 107: } ! 108: ! 109: private void ! 110: watch_input(m) ! 111: Mark *m; ! 112: { ! 113: Bufpos save; ! 114: char fname[FILESIZE], ! 115: lineno[FILESIZE]; ! 116: int lnum; ! 117: Window *savew = curwind; ! 118: Buffer *buf; ! 119: ! 120: DOTsave(&save); ! 121: ToMark(m); ! 122: if (dosearch(dbx_parse_fmt, FORWARD, YES) != NULL) { ! 123: get_FL_info(fname, lineno); ! 124: buf = do_find((Window *) 0, fname, YES); ! 125: pop_wind(buf->b_name, NO, -1); ! 126: lnum = atoi(lineno); ! 127: SetLine(next_line(buf->b_first, lnum - 1)); ! 128: SetWind(savew); ! 129: } ! 130: SetDot(&save); ! 131: } ! 132: ! 133: /* Process receive: receives the characters in buf, and appends them to ! 134: the buffer associated with p. */ ! 135: ! 136: private void ! 137: proc_rec(p, buf) ! 138: register Process *p; ! 139: char *buf; ! 140: { ! 141: Buffer *saveb = curbuf; ! 142: register Window *w; ! 143: register Mark *savepoint; ! 144: int sameplace = NO, ! 145: do_disp = NO; ! 146: ! 147: if (curwind->w_bufp == p->p_buffer) ! 148: w = curwind; ! 149: else ! 150: w = windbp(p->p_buffer); /* Is this window visible? */ ! 151: if (w != 0) ! 152: do_disp = (in_window(w, p->p_mark->m_line) != -1); ! 153: SetBuf(p->p_buffer); ! 154: savepoint = MakeMark(curline, curchar, M_FLOATER); ! 155: ToMark(p->p_mark); /* where output last stopped */ ! 156: if (savepoint->m_line == curline && savepoint->m_char == curchar) ! 157: sameplace = YES; ! 158: ins_str(buf, YES); ! 159: if (do_disp == YES && p->p_dbx_mode == YES) ! 160: watch_input(p->p_mark); ! 161: MarkSet(p->p_mark, curline, curchar); ! 162: if (!sameplace) ! 163: ToMark(savepoint); /* back to where we were */ ! 164: DelMark(savepoint); ! 165: /* redisplay now, instead of right after the ins_str, so that ! 166: we don't get a bouncing effect if point is not the same as ! 167: the process output position */ ! 168: if (do_disp) { ! 169: w->w_line = curline; ! 170: w->w_char = curchar; ! 171: redisplay(); ! 172: } ! 173: SetBuf(saveb); ! 174: } ! 175: ! 176: private void ! 177: proc_kill(p, sig) ! 178: register Process *p; ! 179: int sig; ! 180: { ! 181: if (isdead(p)) ! 182: return; ! 183: if (killpg(p->p_pid, sig) == -1) ! 184: s_mess("Cannot kill %s!", proc_buf(p)); ! 185: } ! 186: ! 187: /* Free process CHILD. Do all the necessary cleaning up (closing fd's, ! 188: etc.). */ ! 189: ! 190: private void ! 191: free_proc(child) ! 192: Process *child; ! 193: { ! 194: register Process *p, ! 195: *prev = 0; ! 196: ! 197: if (!isdead(child)) ! 198: return; ! 199: for (p = procs; p != child; prev = p, p = p->p_next) ! 200: ; ! 201: if (prev == 0) ! 202: procs = child->p_next; ! 203: else ! 204: prev->p_next = child->p_next; ! 205: proc_close(child); /* if not already closed */ ! 206: ! 207: /* It's possible that the buffer has been given another process ! 208: between the time CHILD dies and CHILD's death is noticed (via ! 209: list-processes). So we only set it the buffer's process to ! 210: 0 if CHILD is still the controlling process. */ ! 211: if (child->p_buffer->b_process == child) { ! 212: child->p_buffer->b_process = 0; ! 213: } ! 214: { ! 215: Buffer *old = curbuf; ! 216: ! 217: SetBuf(child->p_buffer); ! 218: DelMark(child->p_mark); ! 219: SetBuf(old); ! 220: } ! 221: free((char *) child->p_name); ! 222: free((char *) child); ! 223: } ! 224: ! 225: void ! 226: ProcList() ! 227: { ! 228: register Process *p, ! 229: *next; ! 230: char *fmt = "%-15s %-15s %-8s %s", ! 231: pidstr[16]; ! 232: ! 233: if (procs == 0) { ! 234: message("[No subprocesses]"); ! 235: return; ! 236: } ! 237: TOstart("Process list", TRUE); ! 238: ! 239: Typeout(fmt, "Buffer", "Status", "Pid ", "Command"); ! 240: Typeout(fmt, "------", "------", "--- ", "-------"); ! 241: for (p = procs; p != 0; p = next) { ! 242: next = p->p_next; ! 243: swritef(pidstr, "%d", p->p_pid); ! 244: Typeout(fmt, proc_buf(p), pstate(p), pidstr, p->p_name); ! 245: if (isdead(p)) { ! 246: free_proc(p); ! 247: UpdModLine = YES; ! 248: } ! 249: } ! 250: TOstop(); ! 251: } ! 252: ! 253: private void ! 254: do_rtp(mp) ! 255: register Mark *mp; ! 256: { ! 257: register Process *p = curbuf->b_process; ! 258: Line *line1 = curline, ! 259: *line2 = mp->m_line; ! 260: int char1 = curchar, ! 261: char2 = mp->m_char; ! 262: char *gp; ! 263: size_t nbytes; ! 264: ! 265: if (isdead(p) || p->p_buffer != curbuf) ! 266: return; ! 267: ! 268: (void) fixorder(&line1, &char1, &line2, &char2); ! 269: while (line1 != line2->l_next) { ! 270: gp = ltobuf(line1, genbuf) + char1; ! 271: if (line1 == line2) ! 272: gp[char2] = '\0'; ! 273: else ! 274: strcat(gp, "\n"); ! 275: if ((nbytes = strlen(gp)) != 0) ! 276: proc_write(p, gp, nbytes); ! 277: line1 = line1->l_next; ! 278: char1 = 0; ! 279: } ! 280: } ! 281: ! 282: void ! 283: ProcNewline() ! 284: { ! 285: #ifdef ABBREV ! 286: MaybeAbbrevExpand(); ! 287: #endif ! 288: SendData(YES); ! 289: } ! 290: ! 291: void ! 292: ProcSendData() ! 293: { ! 294: #ifdef ABBREV ! 295: MaybeAbbrevExpand(); ! 296: #endif ! 297: SendData(NO); ! 298: } ! 299: ! 300: private void ! 301: SendData(newlinep) ! 302: int newlinep; ! 303: { ! 304: register Process *p = curbuf->b_process; ! 305: register char *lp, ! 306: *gp; /* JF fix for better prompt handling */ ! 307: ! 308: if (isdead(p)) ! 309: return; ! 310: /* If the process mark was involved in a big deletion, because ! 311: the user hit ^W or something, then let's do some magic with ! 312: the process mark. Problem is that if the user yanks back the ! 313: text he deleted, the mark stays at the beginning of the region, ! 314: and so the next time SendData() is called the entire region ! 315: will be sent. That's not good. So, to deal with that we reset ! 316: the mark to the last line, after skipping over the prompt, etc. */ ! 317: if (p->p_mark->m_flags & M_BIG_DELETE) { ! 318: Bufpos bp; ! 319: ! 320: p->p_mark->m_flags &= ~M_BIG_DELETE; ! 321: ! 322: DOTsave(&bp); ! 323: ToLast(); ! 324: Bol(); ! 325: /* While we're looking at a prompt, and while we're ! 326: moving forward. This is for people who accidently ! 327: set their process-prompt to ">*" which will always ! 328: match! */ ! 329: while ((LookingAt(proc_prompt, linebuf, curchar)) && ! 330: (REeom > curchar)) ! 331: curchar = REeom; ! 332: MarkSet(p->p_mark, curline, curchar); ! 333: SetDot(&bp); ! 334: } ! 335: ! 336: if (lastp(curline)) { ! 337: Eol(); ! 338: if (newlinep) ! 339: LineInsert(1); ! 340: do_rtp(p->p_mark); ! 341: MarkSet(p->p_mark, curline, curchar); ! 342: } else { ! 343: /* Either we're looking at a prompt, or we're not, in ! 344: which case we want to strip off the beginning of the ! 345: line anything that looks like what the prompt at the ! 346: end of the file is. In other words, if "(dbx) stop in ! 347: ProcessNewline" is the line we're on, and the last ! 348: line in the buffer is "(dbx) ", then we strip off the ! 349: leading "(dbx) " from this line, because we know it's ! 350: part of the prompt. But this only happens if "(dbx) " ! 351: isn't one of the process prompts ... follow what I'm ! 352: saying? */ ! 353: Bol(); ! 354: if (LookingAt(proc_prompt, linebuf, curchar)) { ! 355: do ! 356: curchar = REeom; ! 357: while ((LookingAt(proc_prompt, linebuf, curchar)) && ! 358: (REeom > curchar)); ! 359: strcpy(genbuf, linebuf + curchar); ! 360: Eof(); ! 361: ins_str(genbuf, NO); ! 362: } else { ! 363: strcpy(genbuf, linebuf + curchar); ! 364: Eof(); ! 365: gp = genbuf; ! 366: lp = linebuf; ! 367: while (*lp == *gp && *lp != '\0') { ! 368: lp += 1; ! 369: gp += 1; ! 370: } ! 371: ins_str(gp, NO); ! 372: } ! 373: } ! 374: } ! 375: ! 376: void ! 377: ShellProc() ! 378: { ! 379: char *shbuf = "*shell*"; ! 380: register Buffer *b; ! 381: ! 382: b = buf_exists(shbuf); ! 383: if (b == 0 || isdead(b->b_process)) ! 384: proc_strt(shbuf, NO, Shell, "-i", (char *) 0); ! 385: pop_wind(shbuf, NO, -1); ! 386: } ! 387: ! 388: void ! 389: Iprocess() ! 390: { ! 391: register char *command; ! 392: char scratch[64], ! 393: *bnm; ! 394: int cnt = 1; ! 395: Buffer *bp; ! 396: ! 397: command = ask(ShcomBuf, ProcFmt); ! 398: null_ncpy(ShcomBuf, command, (sizeof ShcomBuf) - 1); ! 399: bnm = MakeName(command); ! 400: strcpy(scratch, bnm); ! 401: while ((bp = buf_exists(scratch)) != NIL && !isdead(bp->b_process)) ! 402: swritef(scratch, "%s.%d", bnm, cnt++); ! 403: proc_strt(scratch, YES, Shell, ShFlags, command, (char *) 0); ! 404: } ! 405: ! 406: private SIGRESULT ! 407: proc_child(junk) ! 408: int junk; /* needed for signal handler; not used */ ! 409: { ! 410: union wait w; ! 411: register int pid; ! 412: ! 413: for (;;) { ! 414: #ifndef WAIT3 ! 415: pid = wait2(&w.w_status, (WNOHANG | WUNTRACED)); ! 416: #else ! 417: pid = wait3(&w, (WNOHANG | WUNTRACED), (struct rusage *) 0); ! 418: #endif ! 419: if (pid <= 0) ! 420: break; ! 421: kill_off(pid, w); ! 422: } ! 423: SIGRETURN; ! 424: } ! 425: ! 426: void ! 427: kill_off(pid, w) ! 428: register int pid; ! 429: union wait w; ! 430: { ! 431: register Process *child; ! 432: ! 433: if ((child = proc_pid(pid)) == 0) ! 434: return; ! 435: ! 436: UpdModLine = YES; /* we're changing state ... */ ! 437: if (WIFSTOPPED(w)) ! 438: child->p_state = STOPPED; ! 439: else { ! 440: child->p_state = DEAD; ! 441: if (WIFEXITED(w)) ! 442: child->p_howdied = EXITED; ! 443: else if (WIFSIGNALED(w)) { ! 444: child->p_reason = w_termsignum(w); ! 445: child->p_howdied = KILLED; ! 446: } ! 447: { ! 448: Buffer *save = curbuf; ! 449: char mesg[128]; ! 450: ! 451: /* insert status message now */ ! 452: swritef(mesg, "[Process %s: %s]\n", ! 453: proc_cmd(child), ! 454: pstate(child)); ! 455: SetBuf(child->p_buffer); ! 456: ins_str(mesg, NO); ! 457: SetBuf(save); ! 458: redisplay(); ! 459: } ! 460: } ! 461: } ! 462: ! 463: #endif /* IPROCS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.