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