📄 process.c
字号:
sleep (1); immediate_quit = 0; continue; }#endif report_file_error ("writing to process", Fcons (proc, Qnil)); } buf += rv; len -= rv; } else { XPROCESS (proc)->raw_status_low = Qnil; XPROCESS (proc)->raw_status_high = Qnil; XPROCESS (proc)->status = Fcons (Qexit, Fcons (make_number (256), Qnil)); XSETINT (XPROCESS (proc)->tick, ++process_tick); deactivate_process (proc); error ("SIGPIPE raised on process %s; closed it", procname); }}DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region, 3, 3, 0, "Send current contents of region as input to PROCESS.\n\PROCESS may be a process name.\n\Called from program, takes three arguments, PROCESS, START and END.") (process, start, end) Lisp_Object process, start, end;{ Lisp_Object proc; int start1; proc = get_process (process); validate_region (&start, &end); if (XINT (start) < GPT && XINT (end) > GPT) move_gap (start); start1 = XINT (start); send_process (proc, &FETCH_CHAR (start1), XINT (end) - XINT (start)); return Qnil;}DEFUN ("process-send-string", Fprocess_send_string, Sprocess_send_string, 2, 2, 0, "Send PROCESS the contents of STRING as input.\n\PROCESS may be a process name.") (process, string) Lisp_Object process, string;{ Lisp_Object proc; CHECK_STRING (string, 1); proc = get_process (process); send_process (proc, XSTRING (string)->data, XSTRING (string)->size); return Qnil;}/* send a signal number SIGNO to PROCESS. CURRENT_GROUP means send to the process group that currently owns the terminal being used to communicate with PROCESS. This is used for various commands in shell mode. If NOMSG is zero, insert signal-announcements into process's buffers right away. */process_send_signal (process, signo, current_group, nomsg) Lisp_Object process; int signo; Lisp_Object current_group; int nomsg;{ Lisp_Object proc; register struct Lisp_Process *p; int gid; proc = get_process (process); p = XPROCESS (proc); if (!EQ (p->childp, Qt)) error ("Process %s is not a subprocess", XSTRING (p->name)->data); if (!XFASTINT (p->infd)) error ("Process %s is not active", XSTRING (p->name)->data); if (NULL (p->pty_flag)) current_group = Qnil;#ifdef TIOCGPGRP /* Not sure about this! (fnf) */ /* If we are using pgrps, get a pgrp number and make it negative. */ if (!NULL (current_group)) { ioctl (XFASTINT (p->infd), TIOCGPGRP, &gid); gid = - gid; } else gid = - XFASTINT (p->pid);#else /* not using pgrps */ /* Can't select pgrps on this system, so we know that the child itself heads the pgrp. */ gid = - XFASTINT (p->pid);#endif /* not using pgrps */ switch (signo) {#ifdef SIGCONT case SIGCONT: p->raw_status_low = Qnil; p->raw_status_high = Qnil; p->status = Qrun; XSETINT (p->tick, ++process_tick); if (!nomsg) status_notify (); break;#endif case SIGINT: case SIGQUIT: case SIGKILL: flush_pending_output (XFASTINT (p->infd)); break; } /* gid may be a pid, or minus a pgrp's number */#ifdef TIOCSIGSEND if (!NULL (current_group)) ioctl (XFASTINT (p->infd), TIOCSIGSEND, signo); else { gid = - XFASTINT (p->pid); kill (gid, signo); }#else /* no TIOCSIGSEND */#ifdef BSD /* On bsd, [man says] kill does not accept a negative number to kill a pgrp. Must do that differently. */ killpg (-gid, signo);#else /* Not BSD. */ kill (gid, signo);#endif /* Not BSD. */#endif /* no TIOCSIGSEND */}DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0, "Interrupt process PROCESS. May be process or name of one.\n\Nil or no arg means current buffer's process.\n\Second arg CURRENT-GROUP non-nil means send signal to\n\the current process-group of the process's controlling terminal\n\rather than to the process's own process group.\n\If the process is a shell, this means interrupt current subjob\n\rather than the shell.") (process, current_group) Lisp_Object process, current_group;{ process_send_signal (process, SIGINT, current_group, 0); return process;}DEFUN ("kill-process", Fkill_process, Skill_process, 0, 2, 0, "Kill process PROCESS. May be process or name of one.\n\See function interrupt-process for more details on usage.") (process, current_group) Lisp_Object process, current_group;{ process_send_signal (process, SIGKILL, current_group, 0); return process;}DEFUN ("quit-process", Fquit_process, Squit_process, 0, 2, 0, "Send QUIT signal to process PROCESS. May be process or name of one.\n\See function interrupt-process for more details on usage.") (process, current_group) Lisp_Object process, current_group;{ process_send_signal (process, SIGQUIT, current_group, 0); return process;}DEFUN ("stop-process", Fstop_process, Sstop_process, 0, 2, 0, "Stop process PROCESS. May be process or name of one.\n\See function interrupt-process for more details on usage.") (process, current_group) Lisp_Object process, current_group;{#ifndef SIGTSTP error ("no SIGTSTP support");#else process_send_signal (process, SIGTSTP, current_group, 0);#endif return process;}DEFUN ("continue-process", Fcontinue_process, Scontinue_process, 0, 2, 0, "Continue process PROCESS. May be process or name of one.\n\See function interrupt-process for more details on usage.") (process, current_group) Lisp_Object process, current_group;{#ifdef SIGCONT process_send_signal (process, SIGCONT, current_group, 0);#else error ("no SIGCONT support");#endif return process;}DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0, "Make PROCESS see end-of-file in its input.\n\Eof comes after any text already sent to it.\n\nil or no arg means current buffer's process.") (process) Lisp_Object process;{ Lisp_Object proc; proc = get_process (process); /* Sending a zero-length record is supposed to mean eof when TIOCREMOTE is turned on. */#ifdef DID_REMOTE { char buf[1]; write (XFASTINT (XPROCESS (proc)->outfd), buf, 0); }#else /* did not do TOICREMOTE */ send_process (proc, "\004", 1);#endif /* did not do TOICREMOTE */ return process;}/* Kill all processes associated with `buffer'. If `buffer' is nil, kill all processes */kill_buffer_processes (buffer) Lisp_Object buffer;{ Lisp_Object tail, proc; for (tail = Vprocess_alist; XGCTYPE (tail) == Lisp_Cons; tail = XCONS (tail)->cdr) { proc = XCONS (XCONS (tail)->car)->cdr; if (XGCTYPE (proc) == Lisp_Process && (NULL (buffer) || EQ (XPROCESS (proc)->buffer, buffer))) { if (NETCONN_P (proc)) deactivate_process (proc); else if (XFASTINT (XPROCESS (proc)->infd)) process_send_signal (proc, SIGHUP, Qnil, 1); } }}/* On receipt of a signal that a child status has changed, loop asking about children with changed statuses until the system says there are no more. All we do is change the status; we do not run sentinels or print notifications. That is saved for the next time keyboard input is done, in order to avoid timing errors. *//** WARNING: this can be called during garbage collection. Therefore, it must not be fooled by the presence of mark bits in Lisp objects. *//** USG WARNING: Although it is not obvious from the documentation in signal(2), on a USG system the SIGCLD handler MUST NOT call signal() before executing at least one wait(), otherwise the handler will be called again, resulting in an infinite loop. The relevant portion of the documentation reads "SIGCLD signals will be queued and the signal-catching function will be continually reentered until the queue is empty". Invoking signal() causes the kernel to reexamine the SIGCLD queue. Fred Fish, UniSoft Systems Inc. */sigchld_handler (signo) int signo;{ int old_errno = errno; Lisp_Object proc; register struct Lisp_Process *p;#ifdef BSD4_1 extern int synch_process_pid; extern int sigheld; sigheld |= sigbit (SIGCHLD);#endif while (1) { register int pid; WAITTYPE w; Lisp_Object tail;#ifdef WNOHANG#ifndef WUNTRACED#define WUNTRACED 0#endif /* no WUNTRACED */ /* Keep trying to get a status until we get a definitive result. */ do { errno = 0; pid = wait3 (&w, WNOHANG | WUNTRACED, 0); } while (pid <= 0 && errno == EINTR); if (pid <= 0) { /* A real failure. We have done all our job, so return. */ /* USG systems forget handlers when they are used; must reestablish each time */#ifdef USG signal (signo, sigchld_handler); /* WARNING - must come after wait3() */#endif#ifdef BSD4_1 sigheld &= ~sigbit (SIGCHLD); sigrelse (SIGCHLD);#endif errno = old_errno; return; }#else pid = wait (&w);#endif /* no WNOHANG */#ifdef BSD4_1 if (synch_process_pid == pid) synch_process_pid = 0; /* Zero it to show process has died. */#endif /* Find the process that signaled us, and record its status. */ p = 0; for (tail = Vprocess_alist; XSYMBOL (tail) != XSYMBOL (Qnil); tail = XCONS (tail)->cdr) { proc = XCONS (XCONS (tail)->car)->cdr; p = XPROCESS (proc); if (EQ (p->childp, Qt) && XFASTINT (p->pid) == pid) break; p = 0; } /* If we don't recognize the pid number, look for a process being created. */ if (p == 0) for (tail = Vprocess_alist; XSYMBOL (tail) != XSYMBOL (Qnil); tail = XCONS (tail)->cdr) { proc = XCONS (XCONS (tail)->car)->cdr; p = XPROCESS (proc); if (XINT (p->pid) == -1) break; p = 0; } /* Change the status of the process that was found. */ if (p != 0) { union { int i; WAITTYPE wt; } u; XSETINT (p->tick, ++process_tick); u.wt = w; XFASTINT (p->raw_status_low) = u.i & 0xffff; XFASTINT (p->raw_status_high) = u.i >> 16; /* If process has terminated, stop waiting for its output. */ if (WIFSIGNALED (w) || WIFEXITED (w)) if (p->infd) FD_CLR (p->infd, &input_wait_mask); } /* On some systems, we must return right away. If any more processes want to signal us, we will get another signal. Otherwise (on systems that have WNOHANG), loop around to use up all the processes that have something to tell us. */#if defined (USG) && ! (defined (HPUX) && defined (WNOHANG))#ifdef USG signal (signo, sigchld_handler);#endif errno = old_errno; return;#endif /* USG, but not HPUX with WNOHANG */ }}/* Report all recent events of a change in process status (either run the sentinel or output a message). This is done while Emacs is waiting for keyboard input. */status_notify (){ register Lisp_Object tail, proc, buffer; for (tail = Vprocess_alist; !NULL (tail); tail = Fcdr (tail)) { Lisp_Object symbol, msg; register struct Lisp_Process *p; proc = Fcdr (Fcar (tail)); p = XPROCESS (proc); if (XINT (p->tick) != XINT (p->update_tick)) { struct gcpro gcpro1; XSETINT (p->update_tick, XINT (p->tick)); /* If process is still active, read any output that remains. */ if (XFASTINT (p->infd)) while (read_process_output (proc, XFASTINT (p->infd)) > 0); buffer = p->buffer; /* Get the text to use for the message. */ if (!NULL (p->raw_status_low)) update_status (p); msg = status_message (p->status); GCPRO1 (msg); /* If process is terminated, deactivate it or delete it. */ symbol = p->status; if (XTYPE (p->status) == Lisp_Cons) symbol = XCONS (p->status)->car; if (EQ (symbol, Qsignal) || EQ (symbol, Qexit) || EQ (symbol, Qclosed)) { if (delete_exited_processes) remove_process (proc); else deactivate_process (proc); } UNGCPRO; /* Now output the message suitably. */ if (!NULL (p->sentinel)) exec_sentinel (proc, msg); /* Don't bother with a message in the buffer when a process becomes runnable. */ else if (!EQ (symbol, Qrun) && !NULL (buffer)) { Lisp_Object ro = XBUFFER (buffer)->read_only; Lisp_Object tem; struct buffer *old = current_buffer; int opoint; /* Avoid error if buffer is deleted (probably that's why the process is dead, too) */ if (NULL (XBUFFER (buffer)->name)) continue; Fset_buffer (buffer); opoint = point; /* Insert new output into buffer at the current end-of-output marker, thus preserving logical ordering of input and output. */ if (XMARKER (p->mark)->buffer) SET_PT (marker_position (p->mark)); else SET_PT (ZV); if (point <= opoint) opoint += XSTRING (msg)->size + XSTRING (p->name)->size + 10; tem = current_buffer->read_only; current_buffer->read_only = Qnil; GCPRO1 (msg); InsStr ("\nProcess "); Finsert (1, &p->name); InsStr (" "); Finsert (1, &msg); current_buffer->read_only = tem; Fset_marker (p->mark, make_number (point), p->buffer); UNGCPRO; SET_PT (opoint); set_buffer_internal (old); } } } /* end for */ update_mode_lines++; /* in case buffers use %s in mode-line-format */ redisplay_preserve_echo_area ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -