Annotation of GNUtools/emacs/src/process.c, revision 1.1

1.1     ! root        1: /* Asynchronous subprocess control for GNU Emacs.
        !             2:    Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU Emacs.
        !             5: 
        !             6: GNU Emacs is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 1, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GNU Emacs is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU Emacs; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: 
        !            21: /* This must precede sys/signal.h on certain machines.  */
        !            22: #include <sys/types.h>
        !            23: #include <signal.h>
        !            24: 
        !            25: #include "config.h"
        !            26: 
        !            27: #ifdef VMS
        !            28: /* Prevent the file from being totally empty.  */
        !            29: static dummy () {}
        !            30: #endif
        !            31: 
        !            32: #ifdef subprocesses
        !            33: /* The entire file is within this conditional */
        !            34: 
        !            35: #include <stdio.h>
        !            36: #include <errno.h>
        !            37: #include <setjmp.h>
        !            38: #include <sys/file.h>
        !            39: #include <sys/stat.h>
        !            40: 
        !            41: #ifdef HAVE_SOCKETS    /* TCP connection support, if kernel can do it */
        !            42: #include <sys/socket.h>
        !            43: #include <netdb.h>
        !            44: #include <netinet/in.h>
        !            45: #endif /* HAVE_SOCKETS */
        !            46: 
        !            47: #if defined(BSD) || defined(STRIDE)
        !            48: #include <sys/ioctl.h>
        !            49: #if !defined (O_NDELAY) && defined (HAVE_PTYS)
        !            50: #include <fcntl.h>
        !            51: #endif /* HAVE_PTYS and no O_NDELAY */
        !            52: #endif /* BSD or STRIDE */
        !            53: #ifdef USG
        !            54: #ifndef NO_TERMIO
        !            55: #include <termio.h>
        !            56: #endif
        !            57: #include <fcntl.h>
        !            58: #endif /* USG */
        !            59: 
        !            60: #ifdef NEED_BSDTTY
        !            61: #include <sys/bsdtty.h>
        !            62: #endif
        !            63: 
        !            64: #ifdef NEED_TERMIOS
        !            65: #include <sys/termios.h>
        !            66: #endif
        !            67: 
        !            68: #ifdef TRITON88                        /* To make emacs send C-c correctly in shell */
        !            69: #define TIOCGPGRP FIOGETOWN
        !            70: #endif
        !            71: 
        !            72: #ifdef HPUX
        !            73: #undef TIOCGPGRP
        !            74: #endif
        !            75: 
        !            76: /* Include time.h or sys/time.h or both.  */
        !            77: #include "gettime.h"
        !            78: 
        !            79: #if defined (HPUX) && defined (HAVE_PTYS)
        !            80: #include <sys/ptyio.h>
        !            81: #endif
        !            82:   
        !            83: #ifdef AIX
        !            84: #include <sys/pty.h>
        !            85: #include <unistd.h>
        !            86: #endif /* AIX */
        !            87: 
        !            88: #ifdef SYSV_PTYS
        !            89: #include <sys/tty.h>
        !            90: #include <sys/pty.h>
        !            91: #endif
        !            92: 
        !            93: #ifdef XENIX
        !            94: #undef TIOCGETC  /* Avoid confusing some conditionals that test this.  */
        !            95: #endif
        !            96: 
        !            97: #ifdef BROKEN_TIOCGETC
        !            98: #undef TIOCGETC
        !            99: #endif
        !           100: 
        !           101: #ifdef BROKEN_O_NONBLOCK
        !           102: #undef O_NONBLOCK
        !           103: #endif
        !           104: 
        !           105: #undef NULL
        !           106: #include "lisp.h"
        !           107: #include "window.h"
        !           108: #include "buffer.h"
        !           109: #include "process.h"
        !           110: #include "termhooks.h"
        !           111: #include "termopts.h"
        !           112: #include "commands.h"
        !           113: #include "dispextern.h"
        !           114: 
        !           115: Lisp_Object Qrun, Qstop, Qsignal, Qopen, Qclosed;
        !           116: extern Lisp_Object Qexit;
        !           117: 
        !           118: /* a process object is a network connection when its childp field is neither
        !           119:    Qt nor Qnil but is instead a string (name of foreign host we
        !           120:    are connected to + name of port we are connected to) */
        !           121: 
        !           122: #ifdef HAVE_SOCKETS
        !           123: #define NETCONN_P(p) (XGCTYPE (XPROCESS (p)->childp) == Lisp_String)
        !           124: #else
        !           125: #define NETCONN_P(p) 0
        !           126: #endif /* HAVE_SOCKETS */
        !           127: 
        !           128: /* Define SIGCHLD as an alias for SIGCLD.  There are many conditionals
        !           129:    testing SIGCHLD.  */
        !           130: 
        !           131: #if !defined (SIGCHLD) && defined (SIGCLD)
        !           132: #define SIGCHLD SIGCLD
        !           133: #endif /* SIGCLD */
        !           134: 
        !           135: #include "emacssignal.h"
        !           136: 
        !           137: /* Define the structure that the wait system call stores.
        !           138:    On many systems, there is a structure defined for this.
        !           139:    But on vanilla-ish USG systems there is not.  */
        !           140: 
        !           141: #ifndef WAITTYPE
        !           142: #if !defined (BSD) && !defined (UNIPLUS) && !defined (STRIDE) && !(defined (HPUX) && !defined (NOMULTIPLEJOBS)) && !defined (HAVE_WAIT_HEADER)
        !           143: #define WAITTYPE int
        !           144: #define WIFSTOPPED(w) ((w&0377) == 0177)
        !           145: #define WIFSIGNALED(w) ((w&0377) != 0177 && (w&~0377) == 0)
        !           146: #define WIFEXITED(w) ((w&0377) == 0)
        !           147: #define WRETCODE(w) (w >> 8)
        !           148: #define WSTOPSIG(w) (w >> 8)
        !           149: #define WTERMSIG(w) (w & 0377)
        !           150: #ifndef WCOREDUMP
        !           151: #define WCOREDUMP(w) ((w&0200) != 0)
        !           152: #endif
        !           153: #else
        !           154: #ifdef BSD4_1
        !           155: #include <wait.h>
        !           156: #else
        !           157: #include <sys/wait.h>
        !           158: #endif /* not BSD 4.1 */
        !           159: 
        !           160: #define WAITTYPE union wait
        !           161: #define WRETCODE(w) w.w_retcode
        !           162: #define WCOREDUMP(w) w.w_coredump
        !           163: 
        !           164: #ifdef HPUX
        !           165: /* HPUX version 7 has broken definitions of these.  */
        !           166: #undef WTERMSIG
        !           167: #undef WSTOPSIG
        !           168: #undef WIFSTOPPED
        !           169: #undef WIFSIGNALED
        !           170: #undef WIFEXITED
        !           171: #endif
        !           172: 
        !           173: #ifndef WTERMSIG
        !           174: #define WTERMSIG(w) w.w_termsig
        !           175: #endif
        !           176: #ifndef WSTOPSIG
        !           177: #define WSTOPSIG(w) w.w_stopsig
        !           178: #endif
        !           179: #ifndef WIFSTOPPED
        !           180: #define WIFSTOPPED(w) (WTERMSIG (w) == 0177)
        !           181: #endif
        !           182: #ifndef WIFSIGNALED
        !           183: #define WIFSIGNALED(w) (WTERMSIG (w) != 0177 && (WSTOPSIG (w)) == 0)
        !           184: #endif
        !           185: #ifndef WIFEXITED
        !           186: #define WIFEXITED(w) (WTERMSIG (w) == 0)
        !           187: #endif
        !           188: #endif /* BSD or UNIPLUS or STRIDE */
        !           189: #endif /* no WAITTYPE */
        !           190: 
        !           191: extern errno;
        !           192: extern sys_nerr;
        !           193: extern char *sys_errlist[];
        !           194: 
        !           195: #ifndef BSD4_1
        !           196: extern char *sys_siglist[];
        !           197: #else
        !           198: char *sys_siglist[] =
        !           199:   {
        !           200:     "bum signal!!",
        !           201:     "hangup",
        !           202:     "interrupt",
        !           203:     "quit",
        !           204:     "illegal instruction",
        !           205:     "trace trap",
        !           206:     "iot instruction",
        !           207:     "emt instruction",
        !           208:     "floating point exception",
        !           209:     "kill",
        !           210:     "bus error",
        !           211:     "segmentation violation",
        !           212:     "bad argument to system call",
        !           213:     "write on a pipe with no one to read it",
        !           214:     "alarm clock",
        !           215:     "software termination signal from kill",
        !           216:     "status signal",
        !           217:     "sendable stop signal not from tty",
        !           218:     "stop signal from tty",
        !           219:     "continue a stopped process",
        !           220:     "child status has changed",
        !           221:     "background read attempted from control tty",
        !           222:     "background write attempted from control tty",
        !           223:     "input record available at control tty",
        !           224:     "exceeded CPU time limit",
        !           225:     "exceeded file size limit"
        !           226:     };
        !           227: #endif
        !           228: 
        !           229: #ifdef vipc
        !           230: 
        !           231: #include "vipc.h"
        !           232: extern int comm_server;
        !           233: extern int net_listen_address;
        !           234: #endif /* vipc */
        !           235: 
        !           236: /* Communicate exit status of synch process to callproc.c.  */
        !           237: extern int synch_process_retcode;
        !           238: extern char *synch_process_death;
        !           239: 
        !           240: /* t means use pty, nil means use a pipe,
        !           241:    maybe other values to come.  */
        !           242: Lisp_Object Vprocess_connection_type;
        !           243: 
        !           244: #ifdef SKTPAIR
        !           245: #ifndef HAVE_SOCKETS
        !           246: #include <sys/socket.h>
        !           247: #endif
        !           248: #endif /* SKTPAIR */
        !           249: 
        !           250: /* Number of events of change of status of a process.  */
        !           251: int process_tick;
        !           252: 
        !           253: /* Number of events for which the user or sentinel has been notified.  */
        !           254: int update_tick;
        !           255: 
        !           256: int delete_exited_processes;
        !           257: 
        !           258: #ifdef FD_SET
        !           259: /* We could get this from param.h, but better not to depend on finding that.
        !           260:    And better not to risk that it might define other symbols used in this
        !           261:    file.  */
        !           262: #define MAXDESC 64
        !           263: #define SELECT_TYPE fd_set
        !           264: #else /* no FD_SET */
        !           265: #define MAXDESC 32
        !           266: #define SELECT_TYPE int
        !           267: 
        !           268: /* Define the macros to access a single-int bitmap of descriptors.  */
        !           269: #define FD_SET(n, p) (*(p) |= (1 << (n)))
        !           270: #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
        !           271: #define FD_ISSET(n, p) (*(p) & (1 << (n)))
        !           272: #define FD_ZERO(p) (*(p) = 0)
        !           273: #endif /* no FD_SET */
        !           274: 
        !           275: /* Mask of bits indicating the descriptors that we wait for input on */
        !           276: 
        !           277: SELECT_TYPE input_wait_mask;
        !           278: 
        !           279: /* Indexed by descriptor, gives the process (if any) for that descriptor */
        !           280: Lisp_Object chan_process[MAXDESC];
        !           281: 
        !           282: /* Alist of elements (NAME . PROCESS) */
        !           283: Lisp_Object Vprocess_alist;
        !           284: 
        !           285: Lisp_Object Qprocessp;
        !           286: 
        !           287: Lisp_Object get_process ();
        !           288: 
        !           289: /* Buffered-ahead input char from process, indexed by channel.
        !           290:    -1 means empty (no char is buffered).
        !           291:    Used on sys V where the only way to tell if there is any
        !           292:    output from the process is to read at least one char.
        !           293:    Always -1 on systems that support FIONREAD.  */
        !           294: 
        !           295: int proc_buffered_char[MAXDESC];
        !           296: 
        !           297: /* These variables hold the filter about to be run, and its args,
        !           298:    between read_process_output and run_filter.
        !           299:    Also used in exec_sentinel for sentinels.  */
        !           300: Lisp_Object this_filter;
        !           301: Lisp_Object filter_process, filter_string;
        !           302: 
        !           303: /* Compute the Lisp form of the process status, p->status,
        !           304:    from the numeric status that was returned by `wait'.  */
        !           305: 
        !           306: update_status (p)
        !           307:      struct Lisp_Process *p;
        !           308: {
        !           309:   union { int i; WAITTYPE wt; } u;
        !           310:   u.i = XFASTINT (p->raw_status_low) + (XFASTINT (p->raw_status_high) << 16);
        !           311:   p->status = status_convert (u.wt);
        !           312:   p->raw_status_low = Qnil;
        !           313:   p->raw_status_high = Qnil;
        !           314: }
        !           315: 
        !           316: /* Convert a process status word in Unix format
        !           317:    to the list that we use internally.  */
        !           318: 
        !           319: Lisp_Object
        !           320: status_convert (w)
        !           321:      WAITTYPE w;
        !           322: {
        !           323:   if (WIFSTOPPED (w))
        !           324:     return Fcons (Qstop, Fcons (make_number (WSTOPSIG (w)), Qnil));
        !           325:   else if (WIFEXITED (w))
        !           326:     return Fcons (Qexit, Fcons (make_number (WRETCODE (w)),
        !           327:                                WCOREDUMP (w) ? Qt : Qnil));
        !           328:   else if (WIFSIGNALED (w))
        !           329:     return Fcons (Qsignal, Fcons (make_number (WTERMSIG (w)),
        !           330:                                  WCOREDUMP (w) ? Qt : Qnil));
        !           331:   else
        !           332:     return Qrun;
        !           333: }
        !           334: 
        !           335: /* Given a status-list, extract the three pieces of information
        !           336:    and store them individually through the three pointers.  */
        !           337: 
        !           338: void
        !           339: decode_status (l, symbol, code, coredump)
        !           340:      Lisp_Object l;
        !           341:      Lisp_Object *symbol;
        !           342:      int *code;
        !           343:      int *coredump;
        !           344: {
        !           345:   Lisp_Object tem;
        !           346: 
        !           347:   if (XTYPE (l) == Lisp_Symbol)
        !           348:     {
        !           349:       *symbol = l;
        !           350:       *code = 0;
        !           351:       *coredump = 0;
        !           352:     }
        !           353:   else
        !           354:     {
        !           355:       *symbol = XCONS (l)->car;
        !           356:       tem = XCONS (l)->cdr;
        !           357:       *code = XFASTINT (XCONS (tem)->car);
        !           358:       tem = XFASTINT (XCONS (tem)->cdr);
        !           359:       *coredump = !NULL (tem);
        !           360:     }
        !           361: }
        !           362: 
        !           363: /* Return a string describing a process status list.  */
        !           364: 
        !           365: Lisp_Object 
        !           366: status_message (status)
        !           367:      Lisp_Object status;
        !           368: {
        !           369:   Lisp_Object symbol;
        !           370:   int code, coredump;
        !           371:   Lisp_Object string, string2;
        !           372: 
        !           373:   decode_status (status, &symbol, &code, &coredump);
        !           374: 
        !           375:   if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
        !           376:     {
        !           377:       string = build_string (code < NSIG ? sys_siglist[code] : "unknown");
        !           378:       string2 = build_string (coredump ? " (core dumped)\n" : "\n");
        !           379:       XSTRING (string)->data[0] = DOWNCASE (XSTRING (string)->data[0]);
        !           380:       return concat2 (string, string2);
        !           381:     }
        !           382:   else if (EQ (symbol, Qexit))
        !           383:     {
        !           384:       if (code == 0)
        !           385:        return build_string ("finished\n");
        !           386:       string = Fint_to_string (make_number (code));
        !           387:       string2 = build_string (coredump ? " (core dumped)\n" : "\n");
        !           388:       return concat2 (build_string ("exited abnormally with code "),
        !           389:                      concat2 (string, string2));
        !           390:     }
        !           391:   else
        !           392:     return Fcopy_sequence (Fsymbol_name (symbol));
        !           393: }
        !           394: 
        !           395: #ifdef HAVE_PTYS
        !           396: 
        !           397: /* Open an available pty, returning a file descriptor.
        !           398:    Return -1 on failure.
        !           399:    The file name of the terminal corresponding to the pty
        !           400:    is left in the variable pty_name.  */
        !           401: 
        !           402: char pty_name[24];
        !           403: 
        !           404: int
        !           405: allocate_pty ()
        !           406: {
        !           407:   struct stat stb;
        !           408:   register c, i;
        !           409:   int fd;
        !           410: 
        !           411:   /* Some systems name their pseudoterminals so that there are gaps in
        !           412:      the usual sequence - for example, on HP9000/S700 systems, there
        !           413:      are no pseudoterminals with names ending in 'f'.  So we wait for
        !           414:      three failures in a row before deciding that we've reached the
        !           415:      end of the ptys.  */
        !           416:   int failed_count = 0;
        !           417: 
        !           418: #ifdef PTY_ITERATION
        !           419:   PTY_ITERATION
        !           420: #else
        !           421:   for (c = FIRST_PTY_LETTER; c <= 'z'; c++)
        !           422:     for (i = 0; i < 16; i++)
        !           423: #endif
        !           424:       {
        !           425: #ifdef PTY_NAME_SPRINTF
        !           426:        PTY_NAME_SPRINTF
        !           427: #else
        !           428: #ifdef HPUX
        !           429:        sprintf (pty_name, "/dev/ptym/pty%c%x", c, i);
        !           430: #else
        !           431: #ifdef RTU
        !           432:        sprintf (pty_name, "/dev/pty%x", i);
        !           433: #else
        !           434:        sprintf (pty_name, "/dev/pty%c%x", c, i);
        !           435: #endif /* not RTU */
        !           436: #endif /* not HPUX */
        !           437: #endif /* no PTY_NAME_SPRINTF */
        !           438: 
        !           439: #ifdef PTY_OPEN
        !           440:        PTY_OPEN;
        !           441: #else /* no PTY_OPEN */
        !           442: #ifndef IRIS
        !           443:        if (stat (pty_name, &stb) < 0)
        !           444:          {
        !           445:            failed_count++;
        !           446:            if (failed_count >= 3)
        !           447:              return -1;
        !           448:          }
        !           449:        else
        !           450:          failed_count = 0;
        !           451: #ifdef O_NONBLOCK
        !           452:        fd = open (pty_name, O_RDWR | O_NONBLOCK, 0);
        !           453: #else
        !           454:        fd = open (pty_name, O_RDWR | O_NDELAY, 0);
        !           455: #endif
        !           456: #else /* Unusual IRIS code */
        !           457:        fd = open ("/dev/ptc", O_RDWR | O_NDELAY, 0);
        !           458:        if (fd < 0)
        !           459:          return -1;
        !           460:        if (fstat (fd, &stb) < 0)
        !           461:          return -1;
        !           462: #endif /* IRIS */
        !           463: #endif /* no PTY_OPEN */
        !           464: 
        !           465:        if (fd >= 0)
        !           466:          {
        !           467:            /* check to make certain that both sides are available
        !           468:               this avoids a nasty yet stupid bug in rlogins */
        !           469: #ifdef PTY_TTY_NAME_SPRINTF
        !           470:            PTY_TTY_NAME_SPRINTF
        !           471: #else
        !           472:            /* In version 19, make these special cases use the macro above.  */
        !           473: #ifdef HPUX
        !           474:             sprintf (pty_name, "/dev/pty/tty%c%x", c, i);
        !           475: #else
        !           476: #ifdef RTU
        !           477:             sprintf (pty_name, "/dev/ttyp%x", i);
        !           478: #else
        !           479: #ifdef IRIS
        !           480:            sprintf (pty_name, "/dev/ttyq%d", minor (stb.st_rdev));
        !           481: #else
        !           482:             sprintf (pty_name, "/dev/tty%c%x", c, i);
        !           483: #endif /* not IRIS */
        !           484: #endif /* not RTU */
        !           485: #endif /* not HPUX */
        !           486: #endif /* no PTY_TTY_NAME_SPRINTF */
        !           487: #ifndef UNIPLUS
        !           488:            if (access (pty_name, 6) != 0)
        !           489:              {
        !           490:                close (fd);
        !           491: #ifndef IRIS
        !           492:                continue;
        !           493: #else
        !           494:                return -1;
        !           495: #endif /* IRIS */
        !           496:              }
        !           497: #endif /* not UNIPLUS */
        !           498:            setup_pty (fd);
        !           499:            return fd;
        !           500:          }
        !           501:       }
        !           502:   return -1;
        !           503: }
        !           504: #endif /* HAVE_PTYS */
        !           505: 
        !           506: Lisp_Object
        !           507: make_process (name)
        !           508:      Lisp_Object name;
        !           509: {
        !           510:   register Lisp_Object val, tem, name1;
        !           511:   register struct Lisp_Process *p;
        !           512:   char suffix[10];
        !           513:   register int i;
        !           514: 
        !           515:   /* size of process structure includes the vector header,
        !           516:      so deduct for that.  But struct Lisp_Vector includes the first
        !           517:      element, thus deducts too much, so add it back.  */
        !           518:   val = Fmake_vector (make_number ((sizeof (struct Lisp_Process)
        !           519:                                    - sizeof (struct Lisp_Vector)
        !           520:                                    + sizeof (Lisp_Object))
        !           521:                                   / sizeof (Lisp_Object)),
        !           522:                      Qnil);
        !           523:   XSETTYPE (val, Lisp_Process);
        !           524: 
        !           525:   p = XPROCESS (val);
        !           526:   XFASTINT (p->infd) = 0;
        !           527:   XFASTINT (p->outfd) = 0;
        !           528:   XFASTINT (p->pid) = 0;
        !           529:   XFASTINT (p->tick) = 0;
        !           530:   XFASTINT (p->update_tick) = 0;
        !           531:   p->raw_status_low = Qnil;
        !           532:   p->raw_status_high = Qnil;
        !           533:   p->status = Qrun;
        !           534:   p->mark = Fmake_marker ();
        !           535: 
        !           536:   /* If name is already in use, modify it until it is unused.  */
        !           537: 
        !           538:   name1 = name;
        !           539:   for (i = 1; ; i++)
        !           540:     {
        !           541:       tem = Fget_process (name1);
        !           542:       if (NULL (tem)) break;
        !           543:       sprintf (suffix, "<%d>", i);
        !           544:       name1 = concat2 (name, build_string (suffix));
        !           545:     }
        !           546:   name = name1;
        !           547:   p->name = name;
        !           548:   Vprocess_alist = Fcons (Fcons (name, val), Vprocess_alist);
        !           549:   return val;
        !           550: }
        !           551: 
        !           552: remove_process (proc)
        !           553:      register Lisp_Object proc;
        !           554: {
        !           555:   register Lisp_Object pair;
        !           556: 
        !           557:   pair = Frassq (proc, Vprocess_alist);
        !           558:   Vprocess_alist = Fdelq (pair, Vprocess_alist);
        !           559:   Fset_marker (XPROCESS (proc)->mark, Qnil, Qnil);
        !           560: 
        !           561:   deactivate_process (proc);
        !           562: }
        !           563: 
        !           564: DEFUN ("processp", Fprocessp, Sprocessp, 1, 1, 0,
        !           565:   "Return t if OBJECT is a process.")
        !           566:   (obj)
        !           567:      Lisp_Object obj;
        !           568: {
        !           569:   return XTYPE (obj) == Lisp_Process ? Qt : Qnil;
        !           570: }
        !           571: 
        !           572: DEFUN ("get-process", Fget_process, Sget_process, 1, 1, 0,
        !           573:   "Return the process named NAME, or nil if there is none.")
        !           574:   (name)
        !           575:      register Lisp_Object name;
        !           576: {
        !           577:   if (XTYPE (name) == Lisp_Process)
        !           578:     return name;
        !           579:   CHECK_STRING (name, 0);
        !           580:   return Fcdr (Fassoc (name, Vprocess_alist));
        !           581: }
        !           582: 
        !           583: DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
        !           584:   "Return the (or, a) process associated with BUFFER.\n\
        !           585: BUFFER may be a buffer or the name of one.")
        !           586:   (name)
        !           587:      register Lisp_Object name;
        !           588: {
        !           589:   register Lisp_Object buf, tail, proc;
        !           590: 
        !           591:   if (NULL (name)) return Qnil;
        !           592:   buf = Fget_buffer (name);
        !           593:   if (NULL (buf)) return Qnil;
        !           594: 
        !           595:   for (tail = Vprocess_alist; !NULL (tail); tail = Fcdr (tail))
        !           596:     {
        !           597:       proc = Fcdr (Fcar (tail));
        !           598:       if (XTYPE (proc) == Lisp_Process && EQ (XPROCESS (proc)->buffer, buf))
        !           599:        return proc;
        !           600:     }
        !           601:   return Qnil;
        !           602: }
        !           603: 
        !           604: /* This is how commands for the user decode process arguments */
        !           605: 
        !           606: Lisp_Object
        !           607: get_process (name)
        !           608:      register Lisp_Object name;
        !           609: {
        !           610:   register Lisp_Object proc;
        !           611:   if (NULL (name))
        !           612:     proc = Fget_buffer_process (Fcurrent_buffer ());
        !           613:   else
        !           614:     {
        !           615:       proc = Fget_process (name);
        !           616:       if (NULL (proc))
        !           617:        proc = Fget_buffer_process (Fget_buffer (name));
        !           618:     }
        !           619: 
        !           620:   if (!NULL (proc))
        !           621:     return proc;
        !           622: 
        !           623:   if (NULL (name))
        !           624:     error ("Current buffer has no process");
        !           625:   else
        !           626:     error ("Process %s does not exist", XSTRING (name)->data);
        !           627:   /* NOTREACHED */
        !           628: }
        !           629: 
        !           630: DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
        !           631:   "Delete PROCESS: kill it and forget about it immediately.\n\
        !           632: PROCESS may be a process or the name of one, or a buffer name.")
        !           633:   (proc)
        !           634:      register Lisp_Object proc;
        !           635: {
        !           636:   proc = get_process (proc);
        !           637:   XPROCESS (proc)->raw_status_low = Qnil;
        !           638:   XPROCESS (proc)->raw_status_high = Qnil;
        !           639:   if (NETCONN_P (proc))
        !           640:     {
        !           641:       XPROCESS (proc)->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
        !           642:       XSETINT (XPROCESS (proc)->tick, ++process_tick);
        !           643:     }
        !           644:   else if (XFASTINT (XPROCESS (proc)->infd))
        !           645:     {
        !           646:       Fkill_process (proc, Qnil);
        !           647:       /* Do this now, since remove_process will make sigchld_handler do nothing.  */
        !           648:       XPROCESS (proc)->status
        !           649:        = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
        !           650:       XSETINT (XPROCESS (proc)->tick, ++process_tick);
        !           651:       status_notify ();
        !           652:     }
        !           653:   remove_process (proc);
        !           654:   return Qnil;
        !           655: }
        !           656: 
        !           657: DEFUN ("process-status", Fprocess_status, Sprocess_status, 1, 1, 0,
        !           658:   "Return the status of PROCESS: a symbol, one of these:\n\
        !           659: run  -- for a process that is running.\n\
        !           660: stop -- for a process stopped but continuable.\n\
        !           661: exit -- for a process that has exited.\n\
        !           662: signal -- for a process that has got a fatal signal.\n\
        !           663: open -- for a network stream connection that is open.\n\
        !           664: closed -- for a network stream connection that is closed.\n\
        !           665: nil -- if arg is a process name and no such process exists.")
        !           666: /* command -- for a command channel opened to Emacs by another process.\n\
        !           667:    external -- for an i/o channel opened to Emacs by another process.\n\  */
        !           668:   (proc)
        !           669:      register Lisp_Object proc;
        !           670: {
        !           671:   register struct Lisp_Process *p;
        !           672:   register Lisp_Object status;
        !           673:   proc = Fget_process (proc);
        !           674:   if (NULL (proc))
        !           675:     return proc;
        !           676:   p = XPROCESS (proc);
        !           677:   if (!NULL (p->raw_status_low))
        !           678:     update_status (p);
        !           679:   status = p->status;
        !           680:   if (XTYPE (status) == Lisp_Cons)
        !           681:     status = XCONS (status)->car;
        !           682:   if (NETCONN_P (proc))
        !           683:     {
        !           684:       if (EQ (status, Qrun))
        !           685:        status = Qopen;
        !           686:       else if (EQ (status, Qexit))
        !           687:        status = Qclosed;
        !           688:     }
        !           689:   return status;
        !           690: }
        !           691: 
        !           692: DEFUN ("process-exit-status", Fprocess_exit_status, Sprocess_exit_status,
        !           693:        1, 1, 0,
        !           694:   "Return the exit status of PROCESS or the signal number that killed it.\n\
        !           695: If PROCESS has not yet exited or died, return 0.\n\
        !           696: If PROCESS is a net connection that was closed remotely, return 256.")
        !           697:   (proc)
        !           698:      register Lisp_Object proc;
        !           699: {
        !           700:   CHECK_PROCESS (proc, 0);
        !           701:   if (!NULL (XPROCESS (proc)->raw_status_low))
        !           702:     update_status (XPROCESS (proc));
        !           703:   if (XTYPE (XPROCESS (proc)->status) == Lisp_Cons)
        !           704:     return XCONS (XCONS (XPROCESS (proc)->status)->cdr)->car;
        !           705:   return make_number (0);
        !           706: }
        !           707: 
        !           708: DEFUN ("process-id", Fprocess_id, Sprocess_id, 1, 1, 0,
        !           709:   "Return the process id of PROCESS.\n\
        !           710: This is the pid of the Unix process which PROCESS uses or talks to.\n\
        !           711: For a network connection, this value is nil.")
        !           712:   (proc)
        !           713:      register Lisp_Object proc;
        !           714: {
        !           715:   CHECK_PROCESS (proc, 0);
        !           716:   return XPROCESS (proc)->pid;
        !           717: }
        !           718: 
        !           719: DEFUN ("process-name", Fprocess_name, Sprocess_name, 1, 1, 0,
        !           720:   "Return the name of PROCESS, as a string.\n\
        !           721: This is the name of the program invoked in PROCESS,\n\
        !           722: possibly modified to make it unique among process names.")
        !           723:   (proc)
        !           724:      register Lisp_Object proc;
        !           725: {
        !           726:   CHECK_PROCESS (proc, 0);
        !           727:   return XPROCESS (proc)->name;
        !           728: }
        !           729: 
        !           730: DEFUN ("process-command", Fprocess_command, Sprocess_command, 1, 1, 0,
        !           731:   "Return the command that was executed to start PROCESS.\n\
        !           732: This is a list of strings, the first string being the program executed\n\
        !           733: and the rest of the strings being the arguments given to it.\n\
        !           734: For a non-child channel, this is nil.")
        !           735:   (proc)
        !           736:      register Lisp_Object proc;
        !           737: {
        !           738:   CHECK_PROCESS (proc, 0);
        !           739:   return XPROCESS (proc)->command;
        !           740: }
        !           741: 
        !           742: DEFUN ("set-process-buffer", Fset_process_buffer, Sset_process_buffer,
        !           743:   2, 2, 0,
        !           744:   "Set buffer associated with PROCESS to BUFFER (a buffer, or nil).")
        !           745:   (proc, buffer)
        !           746:      register Lisp_Object proc, buffer;
        !           747: {
        !           748:   CHECK_PROCESS (proc, 0);
        !           749:   if (!NULL (buffer))
        !           750:     CHECK_BUFFER (buffer, 1);
        !           751:   XPROCESS (proc)->buffer = buffer;
        !           752:   return buffer;
        !           753: }
        !           754: 
        !           755: DEFUN ("process-buffer", Fprocess_buffer, Sprocess_buffer,
        !           756:   1, 1, 0,
        !           757:   "Return the buffer PROCESS is associated with.\n\
        !           758: Output from PROCESS is inserted in this buffer\n\
        !           759: unless PROCESS has a filter.")
        !           760:   (proc)
        !           761:      register Lisp_Object proc;
        !           762: {
        !           763:   CHECK_PROCESS (proc, 0);
        !           764:   return XPROCESS (proc)->buffer;
        !           765: }
        !           766: 
        !           767: DEFUN ("process-mark", Fprocess_mark, Sprocess_mark,
        !           768:   1, 1, 0,
        !           769:   "Return the marker for the end of the last output from PROCESS.")
        !           770:   (proc)
        !           771:      register Lisp_Object proc;
        !           772: {
        !           773:   CHECK_PROCESS (proc, 0);
        !           774:   return XPROCESS (proc)->mark;
        !           775: }
        !           776: 
        !           777: DEFUN ("set-process-filter", Fset_process_filter, Sset_process_filter,
        !           778:   2, 2, 0,
        !           779:   "Give PROCESS the filter function FILTER; nil means no filter.\n\
        !           780: When a process has a filter, each time it does output\n\
        !           781: the entire string of output is passed to the filter.\n\
        !           782: The filter gets two arguments: the process and the string of output.\n\
        !           783: If the process has a filter, its buffer is not used for output.")
        !           784:   (proc, filter)
        !           785:      register Lisp_Object proc, filter;
        !           786: {
        !           787:   CHECK_PROCESS (proc, 0);
        !           788:   XPROCESS (proc)->filter = filter;
        !           789:   return filter;
        !           790: }
        !           791: 
        !           792: DEFUN ("process-filter", Fprocess_filter, Sprocess_filter,
        !           793:   1, 1, 0,
        !           794:   "Returns the filter function of PROCESS; nil if none.\n\
        !           795: See set-process-filter for more info on filter functions.")
        !           796:   (proc)
        !           797:      register Lisp_Object proc;
        !           798: {
        !           799:   CHECK_PROCESS (proc, 0);
        !           800:   return XPROCESS (proc)->filter;
        !           801: }
        !           802: 
        !           803: DEFUN ("set-process-sentinel", Fset_process_sentinel, Sset_process_sentinel,
        !           804:   2, 2, 0,
        !           805:   "Give PROCESS the sentinel SENTINEL; nil for none.\n\
        !           806: The sentinel is called as a function when the process changes state.\n\
        !           807: It gets two arguments: the process, and a string describing the change.")
        !           808:   (proc, sentinel)
        !           809:      register Lisp_Object proc, sentinel;
        !           810: {
        !           811:   CHECK_PROCESS (proc, 0);
        !           812:   XPROCESS (proc)->sentinel = sentinel;
        !           813:   return sentinel;
        !           814: }
        !           815: 
        !           816: DEFUN ("process-sentinel", Fprocess_sentinel, Sprocess_sentinel,
        !           817:   1, 1, 0,
        !           818:   "Return the sentinel of PROCESS; nil if none.\n\
        !           819: See set-process-sentinel for more info on sentinels.")
        !           820:   (proc)
        !           821:      register Lisp_Object proc;
        !           822: {
        !           823:   CHECK_PROCESS (proc, 0);
        !           824:   return XPROCESS (proc)->sentinel;
        !           825: }
        !           826: 
        !           827: DEFUN ("process-kill-without-query", Fprocess_kill_without_query,
        !           828:   Sprocess_kill_without_query, 1, 2, 0,
        !           829:   "Say no query needed if PROCESS is running when Emacs is exited.\n\
        !           830: Optional second argument if non-nil says to require a query.\n\
        !           831: Value is t if a query was formerly required.")
        !           832:   (proc, value)
        !           833:      register Lisp_Object proc, value;
        !           834: {
        !           835:   Lisp_Object tem;
        !           836:   CHECK_PROCESS (proc, 0);
        !           837:   tem = XPROCESS (proc)->kill_without_query;
        !           838:   XPROCESS (proc)->kill_without_query = Fnull (value);
        !           839:   return Fnull (tem);
        !           840: }
        !           841: 
        !           842: Lisp_Object
        !           843: list_processes_1 ()
        !           844: {
        !           845:   register Lisp_Object tail, tem;
        !           846:   Lisp_Object proc, minspace, tem1;
        !           847:   register struct buffer *old = current_buffer;
        !           848:   register struct Lisp_Process *p;
        !           849:   register int state;
        !           850:   char tembuf[80];
        !           851: 
        !           852:   XFASTINT (minspace) = 1;
        !           853: 
        !           854:   set_buffer_internal (XBUFFER (Vstandard_output));
        !           855:   Fbuffer_flush_undo (Vstandard_output);
        !           856: 
        !           857:   current_buffer->truncate_lines = Qt;
        !           858: 
        !           859:   write_string ("\
        !           860: Proc         Status   Buffer         Command\n\
        !           861: ----         ------   ------         -------\n", -1);
        !           862: 
        !           863:   for (tail = Vprocess_alist; !NULL (tail); tail = Fcdr (tail))
        !           864:     {
        !           865:       Lisp_Object symbol;
        !           866: 
        !           867:       proc = Fcdr (Fcar (tail));
        !           868:       p = XPROCESS (proc);
        !           869:       if (NULL (p->childp))
        !           870:        continue;
        !           871: 
        !           872:       Finsert (1, &p->name);
        !           873:       Findent_to (make_number (13), minspace);
        !           874: 
        !           875:       if (!NULL (p->raw_status_low))
        !           876:        update_status (p);
        !           877:       symbol = p->status;
        !           878:       if (XTYPE (p->status) == Lisp_Cons)
        !           879:        symbol = XCONS (p->status)->car;
        !           880: 
        !           881:       if (EQ (symbol, Qsignal))
        !           882:        {
        !           883:          Lisp_Object tem;
        !           884:          tem = Fcar (Fcdr (p->status));
        !           885:          if (XINT (tem) < NSIG)
        !           886:            write_string (sys_siglist [XINT (tem)], -1);
        !           887:          else
        !           888:            Fprinc (symbol, Qnil);
        !           889:        }
        !           890:       else if (NETCONN_P (proc))
        !           891:        {
        !           892:          if (EQ (symbol, Qrun))
        !           893:            write_string ("open", -1);
        !           894:          else if (EQ (symbol, Qexit))
        !           895:            write_string ("closed", -1);
        !           896:          else
        !           897:            Fprinc (symbol, Qnil);
        !           898:        }
        !           899:       else
        !           900:        Fprinc (symbol, Qnil);
        !           901: 
        !           902:       if (EQ (symbol, Qexit))
        !           903:        {
        !           904:          Lisp_Object tem;
        !           905:          tem = Fcar (Fcdr (p->status));
        !           906:          if (XFASTINT (tem))
        !           907:            {
        !           908:              sprintf (tembuf, " %d", XFASTINT (tem));
        !           909:              write_string (tembuf, -1);
        !           910:            }
        !           911:        }
        !           912: 
        !           913:       if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
        !           914:        remove_process (proc);
        !           915: 
        !           916:       Findent_to (make_number (22), minspace);
        !           917:       if (NULL (p->buffer))
        !           918:        InsStr ("(none)");
        !           919:       else if (NULL (XBUFFER (p->buffer)->name))
        !           920:        InsStr ("(Killed)");
        !           921:       else
        !           922:        Finsert (1, &XBUFFER (p->buffer)->name);
        !           923: 
        !           924:       Findent_to (make_number (37), minspace);
        !           925: 
        !           926:       if (NETCONN_P (proc))
        !           927:         {
        !           928:          sprintf (tembuf, "(network stream connection to %s)\n",
        !           929:                   XSTRING (p->childp)->data);
        !           930:          InsStr (tembuf);
        !           931:         }
        !           932:       else 
        !           933:        {
        !           934:          tem = p->command;
        !           935:          while (1)
        !           936:            {
        !           937:              tem1 = Fcar (tem);
        !           938:              Finsert (1, &tem1);
        !           939:              tem = Fcdr (tem);
        !           940:              if (NULL (tem))
        !           941:                break;
        !           942:              InsStr (" ");
        !           943:            }
        !           944:          InsStr ("\n");
        !           945:        }
        !           946:     }
        !           947: 
        !           948:   return Qnil;
        !           949: }
        !           950: 
        !           951: DEFUN ("list-processes", Flist_processes, Slist_processes, 0, 0, "",
        !           952:   "Display a list of all processes.\n\
        !           953: \(Any processes listed as Exited or Signaled are actually eliminated\n\
        !           954: after the listing is made.)")
        !           955:   ()
        !           956: {
        !           957:   internal_with_output_to_temp_buffer ("*Process List*",
        !           958:                                       list_processes_1, Qnil);
        !           959:   return Qnil;
        !           960: }
        !           961: 
        !           962: DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0,
        !           963:   "Return a list of all processes.")
        !           964:   ()
        !           965: {
        !           966:   return Fmapcar (Qcdr, Vprocess_alist);
        !           967: }
        !           968: 
        !           969: DEFUN ("start-process", Fstart_process, Sstart_process, 3, MANY, 0,
        !           970:   "Start a program in a subprocess.  Return the process object for it.\n\
        !           971: Args are NAME BUFFER PROGRAM &rest PROGRAM-ARGS\n\
        !           972: NAME is name for process.  It is modified if necessary to make it unique.\n\
        !           973: BUFFER is the buffer or (buffer-name) to associate with the process.\n\
        !           974:  Process output goes at end of that buffer, unless you specify\n\
        !           975:  an output stream or filter function to handle the output.\n\
        !           976:  BUFFER may be also nil, meaning that this process is not associated\n\
        !           977:  with any buffer\n\
        !           978: Third arg is program file name.  It is searched for as in the shell.\n\
        !           979: Remaining arguments are strings to give program as arguments.")
        !           980:   (nargs, args)
        !           981:      int nargs;
        !           982:      register Lisp_Object *args;
        !           983: {
        !           984:   Lisp_Object buffer, name, program, proc, tem;
        !           985:   register unsigned char **new_argv;
        !           986:   register int i;
        !           987: 
        !           988:   buffer = args[1];
        !           989:   if (!NULL (buffer))
        !           990:     buffer = Fget_buffer_create (buffer);
        !           991: 
        !           992:   name = args[0];
        !           993:   CHECK_STRING (name, 0);
        !           994: 
        !           995:   program = args[2];
        !           996: 
        !           997:   CHECK_STRING (program, 2);
        !           998: 
        !           999:   new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
        !          1000: 
        !          1001:   for (i = 3; i < nargs; i++)
        !          1002:     {
        !          1003:       tem = args[i];
        !          1004:       CHECK_STRING (tem, i);
        !          1005:       new_argv[i - 2] = XSTRING (tem)->data;
        !          1006:     }
        !          1007:   new_argv[i - 2] = 0;
        !          1008:   new_argv[0] = XSTRING (program)->data;
        !          1009: 
        !          1010:   /* If program file name is not absolute, search our path for it */
        !          1011:   if (new_argv[0][0] != '/')
        !          1012:     {
        !          1013:       tem = Qnil;
        !          1014:       openp (Vexec_path, program, "", &tem, 1);
        !          1015:       if (NULL (tem))
        !          1016:        report_file_error ("Searching for program", Fcons (program, Qnil));
        !          1017:       new_argv[0] = XSTRING (tem)->data;
        !          1018:     }
        !          1019: 
        !          1020:   proc = make_process (name);
        !          1021: 
        !          1022:   XPROCESS (proc)->childp = Qt;
        !          1023:   XPROCESS (proc)->command_channel_p = Qnil;
        !          1024:   XPROCESS (proc)->buffer = buffer;
        !          1025:   XPROCESS (proc)->sentinel = Qnil;
        !          1026:   XPROCESS (proc)->filter = Qnil;
        !          1027:   XPROCESS (proc)->command = Flist (nargs - 2, args + 2);
        !          1028: 
        !          1029:   create_process (proc, new_argv);
        !          1030: 
        !          1031:   return proc;
        !          1032: }
        !          1033: 
        !          1034: create_process_1 (signo)
        !          1035:      int signo;
        !          1036: {
        !          1037: #ifdef USG
        !          1038:   /* USG systems forget handlers when they are used;
        !          1039:      must reestablish each time */
        !          1040:   signal (signo, create_process_1);
        !          1041: #endif /* USG */
        !          1042: }
        !          1043: 
        !          1044: #if 0  /* This doesn't work; see the note before sigchld_handler.  */
        !          1045: #ifdef USG
        !          1046: #ifdef SIGCHLD
        !          1047: /* Mimic blocking of signals on system V, which doesn't really have it.  */
        !          1048: 
        !          1049: /* Nonzero means we got a SIGCHLD when it was supposed to be blocked.  */
        !          1050: int sigchld_deferred;
        !          1051: 
        !          1052: create_process_sigchld ()
        !          1053: {
        !          1054:   signal (SIGCHLD, create_process_sigchld);
        !          1055: 
        !          1056:   sigchld_deferred = 1;
        !          1057: }
        !          1058: #endif
        !          1059: #endif
        !          1060: #endif
        !          1061: 
        !          1062: create_process (process, new_argv)
        !          1063:      Lisp_Object process;
        !          1064:      char **new_argv;
        !          1065: {
        !          1066:   int pid, inchannel, outchannel, forkin, forkout;
        !          1067:   int sv[2];
        !          1068: #ifdef SIGCHLD
        !          1069:   int (*sigchld)();
        !          1070: #endif
        !          1071:   char **env;
        !          1072:   int pty_flag = 0;
        !          1073:   extern char **environ;
        !          1074: 
        !          1075: #ifdef MAINTAIN_ENVIRONMENT
        !          1076:   env = (char **) alloca (size_of_current_environ ());
        !          1077:   get_current_environ (env);
        !          1078: #else
        !          1079:   env = environ;
        !          1080: #endif /* MAINTAIN_ENVIRONMENT */
        !          1081: 
        !          1082:   inchannel = outchannel = -1;
        !          1083: 
        !          1084: #ifdef HAVE_PTYS
        !          1085:   if (EQ (Vprocess_connection_type, Qt))
        !          1086:     outchannel = inchannel = allocate_pty ();
        !          1087: 
        !          1088:   if (inchannel >= 0)
        !          1089:     {
        !          1090: #ifndef USG
        !          1091:       /* On USG systems it does not work to open
        !          1092:         the pty's tty here and then close and reopen it in the child.  */
        !          1093: #ifdef O_NOCTTY
        !          1094:       /* Don't let this terminal become our controlling terminal
        !          1095:         (in case we don't have one).  */
        !          1096:       forkout = forkin = open (pty_name, O_RDWR | O_NOCTTY, 0);
        !          1097: #else
        !          1098:       forkout = forkin = open (pty_name, O_RDWR, 0);
        !          1099: #endif
        !          1100:       if (forkin < 0)
        !          1101:        report_file_error ("Opening pty", Qnil);
        !          1102: #else
        !          1103:       forkin = forkout = -1;
        !          1104: #endif
        !          1105:       pty_flag = 1;
        !          1106:     }
        !          1107:   else
        !          1108: #endif /* HAVE_PTYS */
        !          1109: #ifdef SKTPAIR
        !          1110:     {
        !          1111:       if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
        !          1112:        report_file_error ("Opening socketpair", Qnil);
        !          1113:       outchannel = inchannel = sv[0];
        !          1114:       forkout = forkin = sv[1];
        !          1115:     }
        !          1116: #else /* not SKTPAIR */
        !          1117:     {
        !          1118:       int temp;
        !          1119:       temp = pipe (sv);
        !          1120:       if (temp < 0) goto io_failure;
        !          1121:       inchannel = sv[0];
        !          1122:       forkout = sv[1];
        !          1123:       temp = pipe (sv);
        !          1124:       if (temp < 0) goto io_failure;
        !          1125:       outchannel = sv[1];
        !          1126:       forkin = sv[0];
        !          1127:     }
        !          1128: #endif /* not SKTPAIR */
        !          1129: 
        !          1130: #if 0
        !          1131:   /* Replaced by close_process_descs */
        !          1132:   set_exclusive_use (inchannel);
        !          1133:   set_exclusive_use (outchannel);
        !          1134: #endif
        !          1135: 
        !          1136: /* Stride people say it's a mystery why this is needed
        !          1137:    as well as the O_NDELAY, but that it fails without this.  */
        !          1138: #if defined (STRIDE) || (defined (pfa) && defined (HAVE_PTYS))
        !          1139:   {
        !          1140:     int one = 1;
        !          1141:     ioctl (inchannel, FIONBIO, &one);
        !          1142:   }
        !          1143: #endif
        !          1144: 
        !          1145: #ifdef O_NONBLOCK
        !          1146:   fcntl (inchannel, F_SETFL, O_NONBLOCK);
        !          1147: #else
        !          1148: #ifdef O_NDELAY
        !          1149:   fcntl (inchannel, F_SETFL, O_NDELAY);
        !          1150: #endif
        !          1151: #endif
        !          1152: 
        !          1153:   XFASTINT (XPROCESS (process)->infd) = inchannel;
        !          1154:   XFASTINT (XPROCESS (process)->outfd) = outchannel;
        !          1155:   /* Record the tty descriptor used in the subprocess.  */
        !          1156: #ifdef SYSV4_PTYS
        !          1157:   /* On system V.4, if using a pty, we need to keep a descriptor
        !          1158:      for the tty that the inferior uses, in order to get the pgrp.
        !          1159:      If this uses too many descriptors, we could instead save the tty name
        !          1160:      and reopen it to send signals.  */
        !          1161:   if (pty_flag)
        !          1162:     {
        !          1163:       int temp = dup (forkin);
        !          1164:       if (temp < 0) goto io_failure;
        !          1165:       XFASTINT (XPROCESS (process)->subtty) = temp;
        !          1166:     }
        !          1167:   else
        !          1168: #endif
        !          1169:     XPROCESS (process)->subtty = Qnil;
        !          1170:   XPROCESS (process)->pty_flag = (pty_flag ? Qt : Qnil);
        !          1171:   XPROCESS (process)->status = Qrun;
        !          1172:   /* Record this as an active process, with its channels.
        !          1173:      As a result, child_setup will close Emacs's side of the pipes.  */
        !          1174:   chan_process[inchannel] = process;
        !          1175: 
        !          1176:   /* Delay interrupts until we have a chance to store
        !          1177:      the new fork's pid in its process structure */
        !          1178: #ifdef SIGCHLD
        !          1179: #ifdef BSD4_1
        !          1180:   sighold (SIGCHLD);
        !          1181: #else /* not BSD4_1 */
        !          1182: #ifdef HPUX
        !          1183:   sigsetmask (sigmask (SIGCHLD));
        !          1184: #else /* not HPUX */
        !          1185: #if defined (BSD) || defined (UNIPLUS)
        !          1186:   sigsetmask (sigmask (SIGCHLD));
        !          1187: #else /* ordinary USG */
        !          1188: #if 0
        !          1189:   sigchld_deferred = 0;
        !          1190:   sigchld = (int (*)()) signal (SIGCHLD, create_process_sigchld);
        !          1191: #endif
        !          1192: #endif /* ordinary USG */
        !          1193: #endif /* not HPUX */
        !          1194: #endif /* not BSD4_1 */
        !          1195: #endif /* SIGCHLD */
        !          1196: 
        !          1197:   /* Until we store the proper pid, enable sigchld_handler
        !          1198:      to recognize an unknown pid as standing for this process.  */
        !          1199:   XSETINT (XPROCESS (process)->pid, -1);
        !          1200:   /* Turn on the bit for our input from this process now,
        !          1201:      so that even if the process terminates very soon,
        !          1202:      we can clear the bit properly on termination.
        !          1203:      If fork fails, remove_process will clear the bit.  */
        !          1204:   FD_SET (inchannel, &input_wait_mask);
        !          1205: 
        !          1206:   {
        !          1207:     /* child_setup must clobber environ on systems with true vfork.
        !          1208:        Protect it from permanent change.  */
        !          1209:     char **save_environ = environ;
        !          1210: 
        !          1211:     pid = vfork ();
        !          1212:     if (pid == 0)
        !          1213:       {
        !          1214:        int xforkin = forkin;
        !          1215:        int xforkout = forkout;
        !          1216: 
        !          1217: #if 0 /* This was probably a mistake--it duplicates code later on,
        !          1218:         but fails to handle all the cases.  */
        !          1219:        /* Make SIGCHLD work again in the child.  */
        !          1220:        sigsetmask (SIGEMPTYMASK);
        !          1221: #endif
        !          1222: 
        !          1223:        /* Make the pty be the controlling terminal of the process.  */
        !          1224: #ifdef HAVE_PTYS
        !          1225:        /* First, disconnect its current controlling terminal.  */
        !          1226: #ifdef HAVE_SETSID
        !          1227:        setsid ();
        !          1228: #ifdef TIOCSCTTY
        !          1229:        /* Make the pty's terminal the controlling terminal.  */
        !          1230:        if (pty_flag && (ioctl (xforkin, TIOCSCTTY, 0) < 0))
        !          1231:          abort ();
        !          1232: #endif
        !          1233: #else /* not HAVE_SETSID */
        !          1234: #ifdef USG
        !          1235:        /* It's very important to call setpgrp() here and no time
        !          1236:           afterwards.  Otherwise, we lose our controlling tty which
        !          1237:           is set when we open the pty. */
        !          1238:        setpgrp ();
        !          1239: #endif /* USG */
        !          1240: #endif /* not HAVE_SETSID */
        !          1241: #ifdef TIOCNOTTY
        !          1242:        /* In 4.3BSD, the TIOCSPGRP bug has been fixed, and now you
        !          1243:           can do TIOCSPGRP only to the process's controlling tty.  */
        !          1244:        if (pty_flag)
        !          1245:          {
        !          1246:            /* I wonder: would just ioctl (0, TIOCNOTTY, 0) work here? 
        !          1247:               I can't test it since I don't have 4.3.  */
        !          1248:            int j = open ("/dev/tty", O_RDWR, 0);
        !          1249:            ioctl (j, TIOCNOTTY, 0);
        !          1250:            close (j);
        !          1251: #ifndef USG
        !          1252:            /* In order to get a controlling terminal on some versions
        !          1253:               of BSD, it is necessary to put the process in pgrp 0
        !          1254:               before it opens the terminal.  */
        !          1255:            setpgrp (0, 0);
        !          1256: #endif
        !          1257:          }
        !          1258: #endif /* TIOCNOTTY */
        !          1259: 
        !          1260: #if !defined (RTU) && !defined (UNIPLUS)
        !          1261: /*** There is a suggestion that this ought to be a
        !          1262:      conditional on TIOCSPGRP.  */
        !          1263:        /* Now close the pty (if we had it open) and reopen it.
        !          1264:           This makes the pty the controlling terminal of the subprocess.  */
        !          1265:        if (pty_flag)
        !          1266:          {
        !          1267:            /* I wonder if close (open (pty_name, ...)) would work?  */
        !          1268:            if (xforkin >= 0)
        !          1269:              close (xforkin);
        !          1270:            xforkout = xforkin = open (pty_name, O_RDWR, 0);
        !          1271: 
        !          1272:            if (xforkin < 0)
        !          1273:              abort ();
        !          1274:          }
        !          1275: #endif /* not UNIPLUS and not RTU */
        !          1276: #ifdef SETUP_SLAVE_PTY
        !          1277:        if (pty_flag)
        !          1278:          {
        !          1279:            SETUP_SLAVE_PTY;
        !          1280:          }
        !          1281: #endif /* SETUP_SLAVE_PTY */
        !          1282: #ifdef AIX
        !          1283:        /* On AIX, we've disabled SIGHUP above once we start a child on a pty.
        !          1284:           Now reenable it in the child, so it will die when we want it to.  */
        !          1285:        if (pty_flag)
        !          1286:          signal (SIGHUP, SIG_DFL);
        !          1287: #endif
        !          1288: #endif /* HAVE_PTYS */
        !          1289: #ifdef SIGCHLD
        !          1290: #ifdef BSD4_1
        !          1291:        sigrelse (SIGCHLD);
        !          1292: #else /* not BSD4_1 */
        !          1293: #if defined (BSD) || defined (UNIPLUS) || defined (HPUX)
        !          1294:        sigsetmask (SIGEMPTYMASK);
        !          1295: #else /* ordinary USG */
        !          1296: #if 0
        !          1297:        signal (SIGCHLD, sigchld);
        !          1298: #endif
        !          1299: #endif /* ordinary USG */
        !          1300: #endif /* not BSD4_1 */
        !          1301: #endif /* SIGCHLD */
        !          1302:        if (pty_flag)
        !          1303:          child_setup_tty (xforkout);
        !          1304:        child_setup (xforkin, xforkout, xforkout, new_argv, env);
        !          1305:       }
        !          1306:     environ = save_environ;
        !          1307:   }
        !          1308: 
        !          1309:   if (pid < 0)
        !          1310:     {
        !          1311:       remove_process (process);
        !          1312:       report_file_error ("Doing vfork", Qnil);
        !          1313:     }
        !          1314: 
        !          1315:   XFASTINT (XPROCESS (process)->pid) = pid;
        !          1316: 
        !          1317:   /* If the subfork execv fails, and it exits,
        !          1318:      this close hangs.  I don't know why.
        !          1319:      So have an interrupt jar it loose.  */
        !          1320:   stop_polling ();
        !          1321:   signal (SIGALRM, create_process_1);
        !          1322:   alarm (1);
        !          1323:   if (forkin >= 0)
        !          1324:     close (forkin);
        !          1325:   alarm (0);
        !          1326:   start_polling ();
        !          1327:   if (forkin != forkout && forkout >= 0)
        !          1328:     close (forkout);
        !          1329: 
        !          1330: #ifdef SIGCHLD
        !          1331: #ifdef BSD4_1
        !          1332:   sigrelse (SIGCHLD);
        !          1333: #else /* not BSD4_1 */
        !          1334: #if defined (BSD) || defined (UNIPLUS) || defined (HPUX)
        !          1335:   sigsetmask (SIGEMPTYMASK);
        !          1336: #else /* ordinary USG */
        !          1337: #if 0
        !          1338:   signal (SIGCHLD, sigchld);
        !          1339:   /* Now really handle any of these signals
        !          1340:      that came in during this function.  */
        !          1341:   if (sigchld_deferred)
        !          1342:     kill (getpid (), SIGCHLD);
        !          1343: #endif
        !          1344: #endif /* ordinary USG */
        !          1345: #endif /* not BSD4_1 */
        !          1346: #endif /* SIGCHLD */
        !          1347:   return;
        !          1348: 
        !          1349: io_failure:
        !          1350:   {
        !          1351:     int temp = errno;
        !          1352:     close (forkin);
        !          1353:     close (forkout);
        !          1354:     close (inchannel);
        !          1355:     close (outchannel);
        !          1356:     errno = temp;
        !          1357:     report_file_error ("Opening pty or pipe", Qnil);
        !          1358:   }
        !          1359: }
        !          1360: 
        !          1361: #ifdef HAVE_SOCKETS
        !          1362: 
        !          1363: /* open a TCP network connection to a given HOST/SERVICE.  Treated
        !          1364:    exactly like a normal process when reading and writing.  Only
        !          1365:    differences are in status display and process deletion.  A network
        !          1366:    connection has no PID; you cannot signal it.  All you can do is
        !          1367:    deactivate and close it via delete-process */
        !          1368: 
        !          1369: DEFUN ("open-network-stream", Fopen_network_stream, Sopen_network_stream, 
        !          1370:        4, 4, 0, 
        !          1371:   "Open a TCP connection for a service to a host.\n\
        !          1372: Returns a subprocess-object to represent the connection.\n\
        !          1373: Input and output work as for subprocesses; `delete-process' closes it.\n\
        !          1374: Args are NAME BUFFER HOST SERVICE.\n\
        !          1375: NAME is name for process.  It is modified if necessary to make it unique.\n\
        !          1376: BUFFER is the buffer (or buffer-name) to associate with the process.\n\
        !          1377:  Process output goes at end of that buffer, unless you specify\n\
        !          1378:  an output stream or filter function to handle the output.\n\
        !          1379:  BUFFER may be also nil, meaning that this process is not associated\n\
        !          1380:  with any buffer\n\
        !          1381: Third arg is name of the host to connect to.\n\
        !          1382: Fourth arg SERVICE is name of the service desired, or an integer\n\
        !          1383:  specifying a port number to connect to.")
        !          1384:    (name, buffer, host, service)
        !          1385:       Lisp_Object name, buffer, host, service;
        !          1386: {
        !          1387:   Lisp_Object proc;
        !          1388:   register int i;
        !          1389:   struct sockaddr_in address;
        !          1390:   struct servent *svc_info;
        !          1391:   struct hostent *host_info;
        !          1392:   int s, outch, inch;
        !          1393:   char errstring[80];
        !          1394:   int port;
        !          1395:   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
        !          1396: 
        !          1397:   GCPRO4 (name, buffer, host, service);
        !          1398:   CHECK_STRING (name, 0);
        !          1399:   CHECK_STRING (host, 0);
        !          1400:   if (XTYPE (service) == Lisp_Int)
        !          1401:     port = htons ((unsigned short) XINT (service));
        !          1402:   else
        !          1403:     {
        !          1404:       CHECK_STRING (service, 0);
        !          1405:       svc_info = getservbyname (XSTRING (service)->data, "tcp");
        !          1406:       if (svc_info == 0)
        !          1407:        error ("Unknown service \"%s\"", XSTRING (service)->data);
        !          1408:       port = svc_info->s_port;
        !          1409:     }
        !          1410: 
        !          1411:   bzero (&address, sizeof address);
        !          1412:   address.sin_addr.s_addr = inet_addr (XSTRING (host)->data);
        !          1413:   if (address.sin_addr.s_addr != -1)
        !          1414:     address.sin_family = AF_INET;
        !          1415:   else
        !          1416:     {
        !          1417:       host_info = gethostbyname (XSTRING (host)->data);
        !          1418:       if (host_info == 0)
        !          1419:        error ("Unknown host \"%s\"", XSTRING (host)->data);
        !          1420:       bcopy (host_info->h_addr, (char *) &address.sin_addr, host_info->h_length);
        !          1421:       address.sin_family = host_info->h_addrtype;
        !          1422:     }
        !          1423:   address.sin_port = port;
        !          1424: 
        !          1425:   s = socket (address.sin_family, SOCK_STREAM, 0);
        !          1426:   if (s < 0) 
        !          1427:     report_file_error ("error creating socket", Fcons (name, Qnil));
        !          1428: 
        !          1429:   /* Kernel bugs (on Ultrix at least) cause lossage (not just EINTR)
        !          1430:      when connect is interrupted.  So let's not let it get interrupted.  */
        !          1431:   if (interrupt_input)
        !          1432:     unrequest_sigio ();
        !          1433:   stop_polling ();
        !          1434: 
        !          1435:   while (1)
        !          1436:     {
        !          1437:       int value = connect (s, &address, sizeof address);
        !          1438:       /* Continue if successeful.  */
        !          1439:       if (value != -1)
        !          1440:        break;
        !          1441:       /* Report a "real" error.  */
        !          1442:       if (errno != EINTR)
        !          1443:        {
        !          1444:          close (s);
        !          1445:          error ("Host \"%s\" not responding", XSTRING (host)->data);
        !          1446:        }
        !          1447:       /* Loop around after temporary error.  */
        !          1448:     }
        !          1449: 
        !          1450:   if (interrupt_input)
        !          1451:     request_sigio ();
        !          1452:   start_polling ();
        !          1453: 
        !          1454:   inch = s;
        !          1455:   outch = dup (s);
        !          1456:   if (outch < 0) 
        !          1457:     report_file_error ("error duplicating socket", Fcons (name, Qnil));
        !          1458: 
        !          1459:   if (!NULL (buffer))
        !          1460:     buffer = Fget_buffer_create (buffer);
        !          1461:   proc = make_process (name);
        !          1462: 
        !          1463:   chan_process[inch] = proc;
        !          1464: 
        !          1465: #ifdef O_NONBLOCK
        !          1466:   fcntl (inch, F_SETFL, O_NONBLOCK);
        !          1467: #else
        !          1468: #ifdef O_NDELAY
        !          1469:   fcntl (inch, F_SETFL, O_NDELAY);
        !          1470: #endif
        !          1471: #endif
        !          1472: 
        !          1473:   XPROCESS (proc)->childp = host;
        !          1474:   XPROCESS (proc)->command_channel_p = Qnil;
        !          1475:   XPROCESS (proc)->buffer = buffer;
        !          1476:   XPROCESS (proc)->sentinel = Qnil;
        !          1477:   XPROCESS (proc)->filter = Qnil;
        !          1478:   XPROCESS (proc)->command = Qnil;
        !          1479:   XPROCESS (proc)->pid = Qnil;
        !          1480:   XPROCESS (proc)->kill_without_query = Qt;
        !          1481:   XFASTINT (XPROCESS (proc)->infd) = s;
        !          1482:   XFASTINT (XPROCESS (proc)->outfd) = outch;
        !          1483:   XPROCESS (proc)->status = Qrun;
        !          1484:   FD_SET (inch, &input_wait_mask);
        !          1485: 
        !          1486:   UNGCPRO;
        !          1487:   return proc;
        !          1488: }
        !          1489: #endif /* HAVE_SOCKETS */
        !          1490: 
        !          1491: deactivate_process (proc)
        !          1492:      Lisp_Object proc;
        !          1493: {
        !          1494:   register int inchannel, outchannel;
        !          1495:   register struct Lisp_Process *p = XPROCESS (proc);
        !          1496: 
        !          1497:   inchannel = XFASTINT (p->infd);
        !          1498:   outchannel = XFASTINT (p->outfd);
        !          1499: 
        !          1500:   if (inchannel)
        !          1501:     {
        !          1502:       /* Beware SIGCHLD hereabouts. */
        !          1503:       flush_pending_output (inchannel);
        !          1504:       close (inchannel);
        !          1505:       if (outchannel  &&  outchannel != inchannel)
        !          1506:        close (outchannel);
        !          1507: 
        !          1508:       XFASTINT (p->infd) = 0;
        !          1509:       XFASTINT (p->outfd) = 0;
        !          1510:       chan_process[inchannel] = Qnil;
        !          1511:       FD_CLR (inchannel, &input_wait_mask);
        !          1512:     }
        !          1513: }
        !          1514: 
        !          1515: /* Close all descriptors currently in use for communication
        !          1516:    with subprocess.  This is used in a newly-forked subprocess
        !          1517:    to get rid of irrelevant descriptors.  */
        !          1518: 
        !          1519: close_process_descs ()
        !          1520: {
        !          1521:   int i;
        !          1522:   for (i = 0; i < MAXDESC; i++)
        !          1523:     {
        !          1524:       Lisp_Object process;
        !          1525:       process = chan_process[i];
        !          1526:       if (!NULL (process))
        !          1527:        {
        !          1528:          int in = XFASTINT (XPROCESS (process)->infd);
        !          1529:          int out = XFASTINT (XPROCESS (process)->outfd);
        !          1530: 
        !          1531:          if (in != 0)
        !          1532:            close (in);
        !          1533:          if (out != 0 && out != in)
        !          1534:            close (out);
        !          1535:          if (!NULL (XPROCESS (process)->subtty))
        !          1536:            close (XFASTINT (XPROCESS (process)->subtty));
        !          1537:        }
        !          1538:     }
        !          1539: }
        !          1540: 
        !          1541: DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output,
        !          1542:   0, 1, 0,
        !          1543:   "Allow any pending output from subprocesses to be read by Emacs.\n\
        !          1544: It is read into the process' buffers or given to their filter functions.\n\
        !          1545: Non-nil arg PROCESS means do not return until some output has been received\n\
        !          1546: from PROCESS.")
        !          1547:   (proc)
        !          1548:      register Lisp_Object proc;
        !          1549: {
        !          1550:   if (NULL (proc))
        !          1551:     wait_reading_process_input (-1, 0, 0);
        !          1552:   else
        !          1553:     {
        !          1554:       proc = get_process (proc);
        !          1555:       wait_reading_process_input (0, XPROCESS (proc), 0);
        !          1556:     }
        !          1557:   return Qnil;
        !          1558: }
        !          1559: 
        !          1560: /* This variable is different from waiting_for_input in keyboard.c.
        !          1561:    It is used to communicate to a lisp process-filter/sentinel (via the
        !          1562:    function Fwaiting_for_user_input_p below) whether emacs was waiting
        !          1563:    for user-input when that process-filter was called.
        !          1564:    waiting_for_input cannot be used as that is by definition 0 when
        !          1565:    lisp code is being evalled */
        !          1566: static int waiting_for_user_input_p;
        !          1567: 
        !          1568: /* Read and dispose of subprocess output
        !          1569:  while waiting for timeout to elapse and/or keyboard input to be available.
        !          1570: 
        !          1571:  time_limit is the timeout in seconds, or zero for no limit.
        !          1572:  -1 means gobble data available immediately but don't wait for any.
        !          1573: 
        !          1574:  read_kbd is 1 to return when input is available.
        !          1575:  -1 means caller will actually read the input.
        !          1576:  A pointer to a struct Lisp_Process means wait until
        !          1577:  something arrives from that process.
        !          1578: 
        !          1579:  do_display means redisplay should be done to show
        !          1580:  subprocess output that arrives.  */
        !          1581: 
        !          1582: wait_reading_process_input (time_limit, read_kbd, do_display)
        !          1583:      int time_limit, read_kbd, do_display;
        !          1584: {
        !          1585:   register int channel, nfds, m;
        !          1586:   SELECT_TYPE Available;
        !          1587:   SELECT_TYPE Exception;
        !          1588:   int xerrno;
        !          1589:   Lisp_Object proc;
        !          1590: #ifdef HAVE_TIMEVAL
        !          1591:   struct timeval timeout, end_time, garbage;
        !          1592: #else
        !          1593:   long timeout, end_time, temp;
        !          1594: #endif /* not HAVE_TIMEVAL */
        !          1595:   SELECT_TYPE Atemp;
        !          1596:   int wait_channel = 0;
        !          1597:   struct Lisp_Process *wait_proc = 0;
        !          1598:   extern kbd_count;
        !          1599: 
        !          1600:   /* Detect when read_kbd is really the address of a Lisp_Process.  */
        !          1601:   if (read_kbd > 10 || read_kbd < -1)
        !          1602:     {
        !          1603:       wait_proc = (struct Lisp_Process *) read_kbd;
        !          1604:       wait_channel = XFASTINT (wait_proc->infd);
        !          1605:       read_kbd = 0;
        !          1606:     }
        !          1607:   waiting_for_user_input_p = read_kbd;
        !          1608: 
        !          1609:   /* Since we may need to wait several times,
        !          1610:      compute the absolute time to return at.  */
        !          1611:   if (time_limit)
        !          1612:     {
        !          1613: #ifdef HAVE_TIMEVAL
        !          1614:       gettimeofday (&end_time, &garbage);
        !          1615:       end_time.tv_sec += time_limit;
        !          1616: #else /* not HAVE_TIMEVAL */
        !          1617:       time (&end_time);
        !          1618:       end_time += time_limit;
        !          1619: #endif /* not HAVE_TIMEVAL */
        !          1620:     }
        !          1621: 
        !          1622: #if 0  /* Select emulator claims to preserve alarms.
        !          1623:          And there are many ways to get out of this function by longjmp.  */
        !          1624:   /* Turn off periodic alarms (in case they are in use)
        !          1625:      because the select emulator uses alarms.  */
        !          1626:   stop_polling ();
        !          1627: #endif
        !          1628: 
        !          1629:   while (1)
        !          1630:     {
        !          1631:       /* If calling from keyboard input, do not quit
        !          1632:         since we want to return C-g as an input character.
        !          1633:         Otherwise, do pending quit if requested.  */
        !          1634:       if (read_kbd >= 0)
        !          1635:        {
        !          1636: #if 0
        !          1637:          /* This is the same condition tested by QUIT.
        !          1638:             We need to resume polling if we are going to quit.  */
        !          1639:          if (!NULL (Vquit_flag) && NULL (Vinhibit_quit))
        !          1640:            {
        !          1641:              start_polling ();
        !          1642:              QUIT;
        !          1643:            }
        !          1644: #endif
        !          1645:          QUIT;
        !          1646:        }
        !          1647: 
        !          1648:       /* If status of something has changed, and no input is available,
        !          1649:         notify the user of the change right away */
        !          1650:       if (update_tick != process_tick && do_display)
        !          1651:        {
        !          1652:          Atemp = input_wait_mask;
        !          1653: #ifdef HAVE_TIMEVAL
        !          1654:          timeout.tv_sec=0; timeout.tv_usec=0;
        !          1655: #else /* not HAVE_TIMEVAL */
        !          1656:          timeout = 0;
        !          1657: #endif /* not HAVE_TIMEVAL */
        !          1658:          if (select (MAXDESC, &Atemp, 0, 0, &timeout) <= 0)
        !          1659:            status_notify ();
        !          1660:        }
        !          1661: 
        !          1662:       /* Don't wait for output from a non-running process.  */
        !          1663:       if (wait_proc != 0 && !NULL (wait_proc->raw_status_low))
        !          1664:        update_status (wait_proc);
        !          1665:       if (wait_proc != 0
        !          1666:          && ! EQ (wait_proc->status, Qrun))
        !          1667:        break;
        !          1668: 
        !          1669:       if (fix_screen_hook)
        !          1670:        (*fix_screen_hook) ();
        !          1671: 
        !          1672:       /* Compute time from now till when time limit is up */
        !          1673:       /* Exit if already run out */
        !          1674:       if (time_limit == -1)
        !          1675:        {
        !          1676:          /* -1 specified for timeout means
        !          1677:             gobble output available now
        !          1678:             but don't wait at all. */
        !          1679: #ifdef HAVE_TIMEVAL
        !          1680:          timeout.tv_sec = 0;
        !          1681:          timeout.tv_usec = 0;
        !          1682: #else
        !          1683:          timeout = 0;
        !          1684: #endif /* not HAVE_TIMEVAL */
        !          1685:        }
        !          1686:       else if (time_limit)
        !          1687:        {
        !          1688: #ifdef HAVE_TIMEVAL
        !          1689:          gettimeofday (&timeout, &garbage);
        !          1690: 
        !          1691:          /* In effect, timeout = end_time - timeout.
        !          1692:             Break if result would be negative.  */
        !          1693:          if (timeval_subtract (&timeout, end_time, timeout))
        !          1694:            break;
        !          1695: #else /* not HAVE_TIMEVAL */
        !          1696:           time (&temp);
        !          1697:          timeout = end_time - temp;
        !          1698:          if (timeout < 0)
        !          1699:            break;
        !          1700: #endif /* not HAVE_TIMEVAL */
        !          1701:        }
        !          1702:       else
        !          1703:        {
        !          1704: #ifdef HAVE_TIMEVAL
        !          1705:          /* If no real timeout, loop sleeping with a big timeout
        !          1706:             so that input interrupt can wake us up by zeroing it  */
        !          1707:          timeout.tv_sec = 100;
        !          1708:          timeout.tv_usec = 0;
        !          1709: #else /* not HAVE_TIMEVAL */
        !          1710:           timeout = 100000;    /* 100000 recognized by the select emulator */
        !          1711: #endif /* not HAVE_TIMEVAL */
        !          1712:        }
        !          1713: 
        !          1714:       /* Cause quitting and alarm signals to take immediate action,
        !          1715:         and cause input available signals to zero out timeout */
        !          1716:       if (read_kbd < 0)
        !          1717:        set_waiting_for_input (&timeout);
        !          1718: 
        !          1719:       /* Wait till there is something to do */
        !          1720: 
        !          1721:       Available = Exception = input_wait_mask;
        !          1722:       if (!read_kbd)
        !          1723:        FD_CLR (0, &Available);
        !          1724: 
        !          1725:       if (read_kbd && kbd_count)
        !          1726:        nfds = 0;
        !          1727:       else
        !          1728:        /* Since we don't do anything abt Exceptions,
        !          1729:           let's notw wake up for them.  */
        !          1730:        nfds = select (MAXDESC, &Available, 0, 0, &timeout);
        !          1731: #if 0
        !          1732: #ifdef IBMRTAIX
        !          1733:        nfds = select (MAXDESC, &Available, 0, 0, &timeout);
        !          1734: #else
        !          1735: #ifdef HPUX
        !          1736:        nfds = select (MAXDESC, &Available, 0, 0, &timeout);
        !          1737: #else
        !          1738:        nfds = select (MAXDESC, &Available, 0, &Exception, &timeout);
        !          1739: #endif
        !          1740: #endif
        !          1741: #endif /* 0 */
        !          1742:       xerrno = errno;
        !          1743: 
        !          1744:       if (fix_screen_hook)
        !          1745:        (*fix_screen_hook) ();
        !          1746: 
        !          1747:       /* Make C-g and alarm signals set flags again */
        !          1748:       clear_waiting_for_input ();
        !          1749: 
        !          1750:       /* If we woke up due to SIGWINCH, actually change size now.  */
        !          1751:       if (read_kbd)
        !          1752:        do_pending_window_change ();
        !          1753: 
        !          1754:       if (time_limit && nfds == 0)     /* timeout elapsed */
        !          1755:        break;
        !          1756:       if (nfds < 0)
        !          1757:        {
        !          1758:          if (xerrno == EINTR)
        !          1759:            FD_ZERO (&Available);
        !          1760: #ifdef ALLIANT
        !          1761:          /* This happens for no known reason on ALLIANT.
        !          1762:             I am guessing that this is the right response. -- RMS.  */
        !          1763:          else if (xerrno == EFAULT)
        !          1764:            FD_ZERO (&Available);
        !          1765: #endif
        !          1766:          else if (xerrno == EBADF)
        !          1767: #ifdef AIX
        !          1768:          /* AIX will return EBADF on a call to select involving a ptc if the
        !          1769:             associated pts isn't open.  Since this will only happen just as
        !          1770:             a child is dying, just ignore the situation -- SIGCHLD will come
        !          1771:             along quite quickly, and after cleanup the ptc will no longer be
        !          1772:             checked, so this error will stop recurring.  */
        !          1773:            FD_ZERO (&Available);     /* Cannot depend on values returned.  */
        !          1774: #else /* not AIX */
        !          1775:            abort ();
        !          1776: #endif /* not AIX */
        !          1777:          else
        !          1778:            error("select error: %s", sys_errlist[xerrno]);
        !          1779:        }
        !          1780: #ifdef SIGIO
        !          1781: #if defined (sun) || defined (APOLLO)
        !          1782:       else if (nfds > 0 && FD_ISSET (0, &Available) && interrupt_input)
        !          1783:        /* System sometimes fails to deliver SIGIO.  */
        !          1784:        kill (getpid (), SIGIO);
        !          1785: #endif
        !          1786: #endif
        !          1787: 
        !          1788:       /* Check for keyboard input */
        !          1789:       /* If there is any, return immediately
        !          1790:         to give it higher priority than subprocesses */
        !          1791: 
        !          1792:       if (read_kbd && detect_input_pending ())
        !          1793:        break;
        !          1794: 
        !          1795:       /* If checking input just got us a size-change event from X,
        !          1796:         obey it now if we should.  */
        !          1797:       if (read_kbd)
        !          1798:        do_pending_window_change ();
        !          1799: 
        !          1800:       /* If screen size has changed, redisplay now
        !          1801:         for either sit-for or keyboard input.  */
        !          1802:       if (read_kbd && screen_garbaged)
        !          1803:        redisplay_preserve_echo_area ();
        !          1804: 
        !          1805: #ifdef vipc
        !          1806:       /* Check for connection from other process */
        !          1807: 
        !          1808:       if (FD_ISSET (comm_server, &Available))
        !          1809:        {
        !          1810:          FD_CLR (comm_server, &Available);
        !          1811:          create_commchan ();
        !          1812:        }
        !          1813: #endif /* vipc */
        !          1814: 
        !          1815:       /* Check for data from a process or a command channel */
        !          1816: 
        !          1817:       for (channel = 3; channel < MAXDESC; channel++)
        !          1818:        {
        !          1819:          if (FD_ISSET (channel, &Available))
        !          1820:            {
        !          1821:              int nread;
        !          1822: 
        !          1823:              FD_CLR (channel, &Available);
        !          1824:              /* If waiting for this channel,
        !          1825:                 arrange to return as soon as no more input
        !          1826:                 to be processed.  No more waiting.  */
        !          1827:              if (wait_channel == channel)
        !          1828:                {
        !          1829:                  wait_channel = 0;
        !          1830:                  time_limit = -1;
        !          1831:                }
        !          1832:              proc = chan_process[channel];
        !          1833:              if (NULL (proc))
        !          1834:                continue;
        !          1835: 
        !          1836: #ifdef vipc
        !          1837:              /* It's a command channel */
        !          1838:              if (!NULL (XPROCESS (proc)->command_channel_p))
        !          1839:                {
        !          1840:                  ProcessCommChan (channel, proc);
        !          1841:                  if (NULL (XPROCESS (proc)->command_channel_p))
        !          1842:                    {
        !          1843:                      /* It has ceased to be a command channel! */
        !          1844:                      int bytes_available;
        !          1845:                      if (ioctl (channel, FIONREAD, &bytes_available) < 0)
        !          1846:                        bytes_available = 0;
        !          1847:                      if (bytes_available)
        !          1848:                        FD_SET (channel, &Available);
        !          1849:                    }
        !          1850:                  continue;
        !          1851:                }
        !          1852: #endif /* vipc */
        !          1853: 
        !          1854:              /* Read data from the process, starting with our
        !          1855:                 buffered-ahead character if we have one.  */
        !          1856: 
        !          1857:              nread = read_process_output (proc, channel);
        !          1858:              if (nread > 0)
        !          1859:                {
        !          1860:                  /* Since read_process_output can run a filter,
        !          1861:                     which can call accept-process-output,
        !          1862:                     don't try to read from any other processes
        !          1863:                     before doing the select again.  */
        !          1864:                  FD_ZERO (&Available);
        !          1865: 
        !          1866:                  if (do_display)
        !          1867:                    redisplay_preserve_echo_area ();
        !          1868:                }
        !          1869: #ifdef EWOULDBLOCK
        !          1870:              else if (nread == -1 && errno == EWOULDBLOCK)
        !          1871:                ;
        !          1872: #else
        !          1873: #ifdef O_NONBLOCK
        !          1874:              else if (nread == -1 && errno == EAGAIN)
        !          1875:                ;
        !          1876: #else
        !          1877: #ifdef O_NDELAY
        !          1878:              else if (nread == -1 && errno == EAGAIN)
        !          1879:                ;
        !          1880:              /* Note that we cannot distinguish between no input
        !          1881:                 available now and a closed pipe.
        !          1882:                 With luck, a closed pipe will be accompanied by
        !          1883:                 subprocess termination and SIGCHLD.  */
        !          1884:              else if (nread == 0 && !NETCONN_P (proc))
        !          1885:                ;
        !          1886: #endif /* O_NDELAY */
        !          1887: #endif /* O_NONBLOCK */
        !          1888: #endif /* EWOULDBLOCK */
        !          1889: #ifdef HAVE_PTYS
        !          1890:              /* On some OSs with ptys, when the process on one end of
        !          1891:                 a pty exits, the other end gets an error reading with
        !          1892:                 errno = EIO instead of getting an EOF (0 bytes read).
        !          1893:                 Therefore, if we get an error reading and errno =
        !          1894:                 EIO, just continue, because the child process has
        !          1895:                 exited and should clean itself up soon (e.g. when we
        !          1896:                 get a SIGCHLD). */
        !          1897:              else if (nread == -1 && errno == EIO && !NETCONN_P (proc))
        !          1898:                ;
        !          1899: #endif /* HAVE_PTYS */
        !          1900: /* If we can detect process termination, don't consider the process
        !          1901:    gone just because its pipe is closed.  */
        !          1902: #ifdef SIGCHLD
        !          1903:              else if (nread == 0 && !NETCONN_P (proc))
        !          1904:                ;
        !          1905: #endif
        !          1906:              else
        !          1907:                {
        !          1908:                  /* Preserve status of processes already terminated.  */
        !          1909:                  XSETINT (XPROCESS (proc)->tick, ++process_tick);
        !          1910:                  deactivate_process (proc);
        !          1911:                  if (!NULL (XPROCESS (proc)->raw_status_low))
        !          1912:                    update_status (XPROCESS (proc));
        !          1913:                  if (EQ (XPROCESS (proc)->status, Qrun))
        !          1914:                    XPROCESS (proc)->status
        !          1915:                      = Fcons (Qexit, Fcons (make_number (256), Qnil));
        !          1916:                }
        !          1917:            }
        !          1918:        } /* end for */
        !          1919:     } /* end while */
        !          1920: 
        !          1921:   /* If calling from keyboard input, do not quit
        !          1922:      since we want to return C-g as an input character.
        !          1923:      Otherwise, do pending quit if requested.  */
        !          1924:   if (read_kbd >= 0)
        !          1925:     {
        !          1926:       /* Prevent input_pending from remaining set if we quit.  */
        !          1927:       clear_input_pending ();
        !          1928:       QUIT;
        !          1929:     }
        !          1930: }
        !          1931: 
        !          1932: /* Actually call the filter.  This gets the information via variables
        !          1933:    because internal_condition_case won't pass arguments.  */
        !          1934: 
        !          1935: Lisp_Object
        !          1936: run_filter ()
        !          1937: {
        !          1938:   return call2 (this_filter, filter_process, filter_string);
        !          1939: }
        !          1940: 
        !          1941: /* Read pending output from the process channel,
        !          1942:    starting with our buffered-ahead character if we have one.
        !          1943:    Yield number of characters read.
        !          1944: 
        !          1945:    This function reads at most 1024 characters.
        !          1946:    If you want to read all available subprocess output,
        !          1947:    you must call it repeatedly until it returns zero.  */
        !          1948: 
        !          1949: read_process_output (proc, channel)
        !          1950:      Lisp_Object proc;
        !          1951:      register int channel;
        !          1952: {
        !          1953:   register int nchars;
        !          1954:   char chars[1024];
        !          1955:   register Lisp_Object outstream;
        !          1956:   register struct buffer *old = current_buffer;
        !          1957:   register struct Lisp_Process *p = XPROCESS (proc);
        !          1958:   register int opoint;
        !          1959: 
        !          1960:   if (proc_buffered_char[channel] < 0)
        !          1961:     nchars = read (channel, chars, sizeof chars);
        !          1962:   else
        !          1963:     {
        !          1964:       chars[0] = proc_buffered_char[channel];
        !          1965:       proc_buffered_char[channel] = -1;
        !          1966:       nchars = read (channel, chars + 1, sizeof chars - 1);
        !          1967:       if (nchars < 0)
        !          1968:        nchars = 1;
        !          1969:       else
        !          1970:        nchars = nchars + 1;
        !          1971:     }
        !          1972: 
        !          1973:   if (nchars <= 0) return nchars;
        !          1974: 
        !          1975:   outstream = p->filter;
        !          1976:   if (!NULL (outstream))
        !          1977:     {
        !          1978:       int count = specpdl_ptr - specpdl;
        !          1979:       specbind (Qinhibit_quit, Qt);
        !          1980:       this_filter = outstream;
        !          1981:       filter_process = proc;
        !          1982:       filter_string = make_string (chars, nchars);
        !          1983:       call2 (this_filter, filter_process, filter_string);
        !          1984:       /*   internal_condition_case (run_filter, Qerror, Fidentity);  */
        !          1985:       unbind_to (count);
        !          1986:       return nchars;
        !          1987:     }
        !          1988: 
        !          1989:   /* If no filter, write into buffer if it isn't dead.  */
        !          1990:   if (!NULL (p->buffer) && !NULL (XBUFFER (p->buffer)->name))
        !          1991:     {
        !          1992:       Lisp_Object tem;
        !          1993: 
        !          1994:       Fset_buffer (p->buffer);
        !          1995:       opoint = point;
        !          1996: 
        !          1997:       /* Insert new output into buffer
        !          1998:         at the current end-of-output marker,
        !          1999:         thus preserving logical ordering of input and output.  */
        !          2000:       if (XMARKER (p->mark)->buffer)
        !          2001:        SET_PT (marker_position (p->mark));
        !          2002:       else
        !          2003:        SET_PT (ZV);
        !          2004:       if (point <= opoint)
        !          2005:        opoint += nchars;
        !          2006: 
        !          2007:       tem = current_buffer->read_only;
        !          2008:       current_buffer->read_only = Qnil;
        !          2009:       insert (chars, nchars);
        !          2010:       current_buffer->read_only = tem;
        !          2011:       Fset_marker (p->mark, make_number (point), p->buffer);
        !          2012:       update_mode_lines++;
        !          2013: 
        !          2014:       SET_PT (opoint);
        !          2015:       set_buffer_internal (old);
        !          2016:     }
        !          2017:   return nchars;
        !          2018: }
        !          2019: 
        !          2020: DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, Swaiting_for_user_input_p,
        !          2021:        0, 0, 0,
        !          2022:   "Returns non-NIL if emacs is waiting for input from the user.\n\
        !          2023: This is intended for use by asynchronous process output filters and sentinels.")
        !          2024:        ()
        !          2025: {
        !          2026:   return ((waiting_for_user_input_p) ? Qt : Qnil);
        !          2027: }
        !          2028: 
        !          2029: /* Sending data to subprocess */
        !          2030: 
        !          2031: jmp_buf send_process_frame;
        !          2032: 
        !          2033: send_process_trap ()
        !          2034: {
        !          2035: #ifdef BSD4_1
        !          2036:   sigrelse (SIGPIPE);
        !          2037:   sigrelse (SIGALRM);
        !          2038: #endif /* BSD4_1 */
        !          2039:   longjmp (send_process_frame, 1);
        !          2040: }
        !          2041: 
        !          2042: send_process (proc, buf, len)
        !          2043:      Lisp_Object proc;
        !          2044:      char *buf;
        !          2045:      int len;
        !          2046: {
        !          2047:   /* Don't use register vars; longjmp can lose them.  */
        !          2048:   int rv;
        !          2049:   unsigned char *procname = XSTRING (XPROCESS (proc)->name)->data;
        !          2050: 
        !          2051:   if (!NULL (XPROCESS (proc)->raw_status_low))
        !          2052:     update_status (XPROCESS (proc));
        !          2053:   if (! EQ (XPROCESS (proc)->status, Qrun))
        !          2054:     error ("Process %s not running", procname);
        !          2055: 
        !          2056:   if (!setjmp (send_process_frame))
        !          2057:     while (len > 0)
        !          2058:       {
        !          2059:        signal (SIGPIPE, send_process_trap);
        !          2060:        rv = write (XFASTINT (XPROCESS (proc)->outfd), buf, len);
        !          2061:        signal (SIGPIPE, SIG_DFL);
        !          2062:        if (rv < 0)
        !          2063:          {
        !          2064:            if (0
        !          2065: #ifdef EWOULDBLOCK
        !          2066:                || errno == EWOULDBLOCK
        !          2067: #endif
        !          2068: #ifdef EAGAIN
        !          2069:                || errno == EAGAIN
        !          2070: #endif
        !          2071:                )
        !          2072:              {
        !          2073:                /* It would be nice to accept process output here,
        !          2074:                   but that is difficult.  For example, it could
        !          2075:                   garbage what we are sending if that is from a buffer.  */
        !          2076:                immediate_quit = 1;
        !          2077:                QUIT;
        !          2078:                sleep (1);
        !          2079:                immediate_quit = 0;
        !          2080:                continue;
        !          2081:              }
        !          2082:            report_file_error ("writing to process", Fcons (proc, Qnil));
        !          2083:          }
        !          2084:        buf += rv;
        !          2085:        len -= rv;
        !          2086:       }
        !          2087:   else
        !          2088:     {
        !          2089:       XPROCESS (proc)->raw_status_low = Qnil;
        !          2090:       XPROCESS (proc)->raw_status_high = Qnil;
        !          2091:       XPROCESS (proc)->status = Fcons (Qexit, Fcons (make_number (256), Qnil));
        !          2092:       XSETINT (XPROCESS (proc)->tick, ++process_tick);
        !          2093:       deactivate_process (proc);
        !          2094:       error ("SIGPIPE raised on process %s; closed it", procname);
        !          2095:     }
        !          2096: }
        !          2097: 
        !          2098: DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
        !          2099:   3, 3, 0,
        !          2100:   "Send current contents of region as input to PROCESS.\n\
        !          2101: PROCESS may be a process name.\n\
        !          2102: Called from program, takes three arguments, PROCESS, START and END.")
        !          2103:   (process, start, end)
        !          2104:      Lisp_Object process, start, end;
        !          2105: {
        !          2106:   Lisp_Object proc;
        !          2107:   int start1;
        !          2108: 
        !          2109:   proc = get_process (process);
        !          2110:   validate_region (&start, &end);
        !          2111: 
        !          2112:   if (XINT (start) < GPT && XINT (end) > GPT)
        !          2113:     move_gap (start);
        !          2114: 
        !          2115:   start1 = XINT (start);
        !          2116:   send_process (proc, &FETCH_CHAR (start1), XINT (end) - XINT (start));
        !          2117: 
        !          2118:   return Qnil;
        !          2119: }
        !          2120: 
        !          2121: DEFUN ("process-send-string", Fprocess_send_string, Sprocess_send_string,
        !          2122:   2, 2, 0,
        !          2123:   "Send PROCESS the contents of STRING as input.\n\
        !          2124: PROCESS may be a process name.")
        !          2125:   (process, string)
        !          2126:      Lisp_Object process, string;
        !          2127: {
        !          2128:   Lisp_Object proc;
        !          2129:   CHECK_STRING (string, 1);
        !          2130:   proc = get_process (process);
        !          2131:   send_process (proc, XSTRING (string)->data, XSTRING (string)->size);
        !          2132:   return Qnil;
        !          2133: }
        !          2134: 
        !          2135: /* send a signal number SIGNO to PROCESS.
        !          2136:    CURRENT_GROUP means send to the process group that currently owns
        !          2137:    the terminal being used to communicate with PROCESS.
        !          2138:    This is used for various commands in shell mode.
        !          2139:    If NOMSG is zero, insert signal-announcements into process's buffers
        !          2140:    right away.  */
        !          2141: 
        !          2142: process_send_signal (process, signo, current_group, nomsg)
        !          2143:      Lisp_Object process;
        !          2144:      int signo;
        !          2145:      Lisp_Object current_group;
        !          2146:      int nomsg;
        !          2147: {
        !          2148:   Lisp_Object proc;
        !          2149:   register struct Lisp_Process *p;
        !          2150:   int gid;
        !          2151:   int no_pgrp = 0;
        !          2152: 
        !          2153:   proc = get_process (process);
        !          2154:   p = XPROCESS (proc);
        !          2155: 
        !          2156:   if (!EQ (p->childp, Qt))
        !          2157:     error ("Process %s is not a subprocess",
        !          2158:           XSTRING (p->name)->data);
        !          2159:   if (!XFASTINT (p->infd))
        !          2160:     error ("Process %s is not active",
        !          2161:           XSTRING (p->name)->data);
        !          2162: 
        !          2163:   if (NULL (p->pty_flag))
        !          2164:     current_group = Qnil;
        !          2165: 
        !          2166: #ifdef TIOCGPGRP               /* Not sure about this! (fnf) */
        !          2167:   /* If we are using pgrps, get a pgrp number and make it negative.  */
        !          2168:   if (!NULL (current_group))
        !          2169:     {
        !          2170:       /* If possible, send signals to the entire pgrp
        !          2171:         by sending an input character to it.  */
        !          2172: #ifndef SIGNALS_VIA_CHARACTERS
        !          2173: #if defined (TIOCGLTC) && defined (TIOCGETC)
        !          2174:       struct tchars c;
        !          2175:       struct ltchars lc;
        !          2176: 
        !          2177:       switch (signo)
        !          2178:        {
        !          2179:        case SIGINT:
        !          2180:          ioctl (XFASTINT (p->infd), TIOCGETC, &c);
        !          2181:          send_process (proc, &c.t_intrc, 1);
        !          2182:          return Qnil;
        !          2183:        case SIGQUIT:
        !          2184:          ioctl (XFASTINT (p->infd), TIOCGETC, &c);
        !          2185:          send_process (proc, &c.t_quitc, 1);
        !          2186:          return Qnil;
        !          2187: #ifdef SIGTSTP
        !          2188:        case SIGTSTP:
        !          2189:          ioctl (XFASTINT (p->infd), TIOCGLTC, &lc);
        !          2190:          send_process (proc, &lc.t_suspc, 1);
        !          2191:          return Qnil;
        !          2192: #endif
        !          2193:        }
        !          2194: #endif /* have TIOCGLTC and have TIOCGETC */
        !          2195: #endif /* not SIGNALS_VIA_CHARACTERS */
        !          2196:       /* It is possible that the following code would work
        !          2197:         on other kinds of USG systems, not just on the IRIS.
        !          2198:         This should be tried in Emacs 19.  */
        !          2199: #ifdef SIGNALS_VIA_CHARACTERS
        !          2200:       struct termio t;
        !          2201:       switch (signo)
        !          2202:        {
        !          2203:        case SIGINT:
        !          2204:          ioctl (XFASTINT (p->infd), TCGETA, &t);
        !          2205:          send_process (proc, &t.c_cc[VINTR], 1);
        !          2206:          return Qnil;
        !          2207:        case SIGQUIT:
        !          2208:          ioctl (XFASTINT (p->infd), TCGETA, &t);
        !          2209:          send_process (proc, &t.c_cc[VQUIT], 1);
        !          2210:          return Qnil;
        !          2211: #ifdef SIGTSTP
        !          2212:        case SIGTSTP:
        !          2213:          ioctl (XFASTINT (p->infd), TCGETA, &t);
        !          2214:          send_process (proc, &t.c_cc[VSWTCH], 1);
        !          2215:          return Qnil;
        !          2216: #endif
        !          2217:        }
        !          2218: #endif /* SIGNALS_VIA_CHARACTERS */
        !          2219: 
        !          2220:       /* Get the pgrp using the tty itself, if we have that.
        !          2221:         Otherwise, use the pty to get the pgrp.  */
        !          2222: #if defined (pfa)
        !          2223:       /* TICGPGRP symbol defined in sys/ioctl.h at E50.
        !          2224:         But, TIOCGPGRP does not work on E50.
        !          2225:         This way, we will use -1, since the ioctl won't change it.
        !          2226:         ([email protected].)  */
        !          2227:       gid = -1;
        !          2228: #endif
        !          2229:       if (!NULL (p->subtty))
        !          2230:        ioctl (XFASTINT (p->subtty), TIOCGPGRP, &gid);
        !          2231:       else
        !          2232:        ioctl (XFASTINT (p->infd), TIOCGPGRP, &gid);
        !          2233:       if (gid == -1)
        !          2234:        no_pgrp = 1;
        !          2235:       else
        !          2236:        gid = - gid;
        !          2237:     }
        !          2238:   else
        !          2239:     gid = - XFASTINT (p->pid);
        !          2240: #else /* not using pgrps */
        !          2241:   /* Can't select pgrps on this system, so we know that
        !          2242:      the child itself heads the pgrp.  */
        !          2243:   gid = - XFASTINT (p->pid);
        !          2244: #endif /* not using pgrps */
        !          2245: 
        !          2246:   switch (signo)
        !          2247:     {
        !          2248: #ifdef SIGCONT
        !          2249:     case SIGCONT:
        !          2250:       p->raw_status_low = Qnil;
        !          2251:       p->raw_status_high = Qnil;
        !          2252:       p->status = Qrun;
        !          2253:       XSETINT (p->tick, ++process_tick);
        !          2254:       if (!nomsg)
        !          2255:        status_notify ();
        !          2256:       break;
        !          2257: #endif
        !          2258:     case SIGINT:
        !          2259:     case SIGQUIT:
        !          2260:     case SIGKILL:
        !          2261:       flush_pending_output (XFASTINT (p->infd));
        !          2262:       break;
        !          2263:     }
        !          2264: 
        !          2265:   /* If we don't have process groups, send the signal to the immediate subprocess.
        !          2266:      That isn't really right, but it's better than any obvious alternative.  */
        !          2267:   if (no_pgrp)
        !          2268:     {
        !          2269:       kill (XFASTINT (p->pid), signo);
        !          2270:       return;
        !          2271:     }
        !          2272: 
        !          2273:   /* gid may be a pid, or minus a pgrp's number */
        !          2274: #ifdef TIOCSIGSEND
        !          2275:   if (!NULL (current_group))
        !          2276:     ioctl (XFASTINT (p->infd), TIOCSIGSEND, signo);
        !          2277:   else
        !          2278:     {
        !          2279:       gid = - XFASTINT (p->pid);
        !          2280:       kill (gid, signo);
        !          2281:     }
        !          2282: #else /* no TIOCSIGSEND */
        !          2283: #ifdef BSD
        !          2284:   /* On bsd, [man says] kill does not accept a negative number to kill a pgrp.
        !          2285:      Must do that differently.  */
        !          2286:   killpg (-gid, signo);
        !          2287: #else /* Not BSD.  */
        !          2288:   kill (gid, signo);
        !          2289: #endif /* Not BSD.  */
        !          2290: #endif /* no TIOCSIGSEND */
        !          2291: }
        !          2292: 
        !          2293: DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0,
        !          2294:   "Interrupt process PROCESS.  May be process or name of one.\n\
        !          2295: Nil or no arg means current buffer's process.\n\
        !          2296: Second arg CURRENT-GROUP non-nil means send signal to\n\
        !          2297: the current process-group of the process's controlling terminal\n\
        !          2298: rather than to the process's own process group.\n\
        !          2299: If the process is a shell, this means interrupt current subjob\n\
        !          2300: rather than the shell.")
        !          2301:   (process, current_group)
        !          2302:      Lisp_Object process, current_group;
        !          2303: {
        !          2304:   process_send_signal (process, SIGINT, current_group, 0);
        !          2305:   return process;
        !          2306: }
        !          2307: 
        !          2308: DEFUN ("kill-process", Fkill_process, Skill_process, 0, 2, 0,
        !          2309:   "Kill process PROCESS.  May be process or name of one.\n\
        !          2310: See function interrupt-process for more details on usage.")
        !          2311:   (process, current_group)
        !          2312:      Lisp_Object process, current_group;
        !          2313: {
        !          2314:   process_send_signal (process, SIGKILL, current_group, 0);
        !          2315:   return process;
        !          2316: }
        !          2317: 
        !          2318: DEFUN ("quit-process", Fquit_process, Squit_process, 0, 2, 0,
        !          2319:   "Send QUIT signal to process PROCESS.  May be process or name of one.\n\
        !          2320: See function interrupt-process for more details on usage.")
        !          2321:   (process, current_group)
        !          2322:      Lisp_Object process, current_group;
        !          2323: {
        !          2324:   process_send_signal (process, SIGQUIT, current_group, 0);
        !          2325:   return process;
        !          2326: }
        !          2327: 
        !          2328: DEFUN ("stop-process", Fstop_process, Sstop_process, 0, 2, 0,
        !          2329:   "Stop process PROCESS.  May be process or name of one.\n\
        !          2330: See function interrupt-process for more details on usage.")
        !          2331:   (process, current_group)
        !          2332:      Lisp_Object process, current_group;
        !          2333: {
        !          2334: #ifndef SIGTSTP
        !          2335:   error ("no SIGTSTP support");
        !          2336: #else
        !          2337:   process_send_signal (process, SIGTSTP, current_group, 0);
        !          2338: #endif
        !          2339:   return process;
        !          2340: }
        !          2341: 
        !          2342: DEFUN ("continue-process", Fcontinue_process, Scontinue_process, 0, 2, 0,
        !          2343:   "Continue process PROCESS.  May be process or name of one.\n\
        !          2344: See function interrupt-process for more details on usage.")
        !          2345:   (process, current_group)
        !          2346:      Lisp_Object process, current_group;
        !          2347: {
        !          2348: #ifdef SIGCONT
        !          2349:     process_send_signal (process, SIGCONT, current_group, 0);
        !          2350: #else
        !          2351:     error ("no SIGCONT support");
        !          2352: #endif
        !          2353:   return process;
        !          2354: }
        !          2355: 
        !          2356: DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0,
        !          2357:   "Make PROCESS see end-of-file in its input.\n\
        !          2358: Eof comes after any text already sent to it.\n\
        !          2359: nil or no arg means current buffer's process.")
        !          2360:   (process)
        !          2361:      Lisp_Object process;
        !          2362: {
        !          2363:   Lisp_Object proc;
        !          2364: 
        !          2365:   proc = get_process (process);
        !          2366:   /* Sending a zero-length record is supposed to mean eof
        !          2367:      when TIOCREMOTE is turned on.  */
        !          2368: #ifdef DID_REMOTE
        !          2369:   {
        !          2370:     char buf[1];
        !          2371:     write (XFASTINT (XPROCESS (proc)->outfd), buf, 0);
        !          2372:   }
        !          2373: #else /* did not do TOICREMOTE */
        !          2374:   if (!NULL (XPROCESS (proc)->pty_flag))
        !          2375:     send_process (proc, "\004", 1);
        !          2376:   else
        !          2377:     {
        !          2378:       close (XPROCESS (proc)->outfd);
        !          2379:       XFASTINT (XPROCESS (proc)->outfd) = open ("/dev/null", O_WRONLY);
        !          2380:     }
        !          2381: 
        !          2382: #endif /* did not do TOICREMOTE */
        !          2383:   return process;
        !          2384: }
        !          2385: 
        !          2386: /* Kill all processes associated with `buffer'.
        !          2387:  If `buffer' is nil, kill all processes  */
        !          2388: 
        !          2389: kill_buffer_processes (buffer)
        !          2390:      Lisp_Object buffer;
        !          2391: {
        !          2392:   Lisp_Object tail, proc;
        !          2393: 
        !          2394:   for (tail = Vprocess_alist; XGCTYPE (tail) == Lisp_Cons;
        !          2395:        tail = XCONS (tail)->cdr)
        !          2396:     {
        !          2397:       proc = XCONS (XCONS (tail)->car)->cdr;
        !          2398:       if (XGCTYPE (proc) == Lisp_Process
        !          2399:          && (NULL (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
        !          2400:        {
        !          2401:          if (NETCONN_P (proc))
        !          2402:            deactivate_process (proc);
        !          2403:          else if (XFASTINT (XPROCESS (proc)->infd))
        !          2404:            process_send_signal (proc, SIGHUP, Qnil, 1);
        !          2405:        }
        !          2406:     }
        !          2407: }
        !          2408: 
        !          2409: /* On receipt of a signal that a child status has changed,
        !          2410:  loop asking about children with changed statuses until
        !          2411:  the system says there are no more.
        !          2412:    All we do is change the status;
        !          2413:  we do not run sentinels or print notifications.
        !          2414:  That is saved for the next time keyboard input is done,
        !          2415:  in order to avoid timing errors.  */
        !          2416: 
        !          2417: /** WARNING: this can be called during garbage collection.
        !          2418:  Therefore, it must not be fooled by the presence of mark bits in
        !          2419:  Lisp objects.  */
        !          2420: 
        !          2421: /** USG WARNING:  Although it is not obvious from the documentation
        !          2422:  in signal(2), on a USG system the SIGCLD handler MUST NOT call
        !          2423:  signal() before executing at least one wait(), otherwise the handler
        !          2424:  will be called again, resulting in an infinite loop.  The relevant
        !          2425:  portion of the documentation reads "SIGCLD signals will be queued
        !          2426:  and the signal-catching function will be continually reentered until
        !          2427:  the queue is empty".  Invoking signal() causes the kernel to reexamine
        !          2428:  the SIGCLD queue.   Fred Fish, UniSoft Systems Inc. */
        !          2429: 
        !          2430: sigchld_handler (signo)
        !          2431:      int signo;
        !          2432: {
        !          2433:   int old_errno = errno;
        !          2434:   Lisp_Object proc;
        !          2435:   register struct Lisp_Process *p;
        !          2436: 
        !          2437: #ifdef BSD4_1
        !          2438:   extern int synch_process_pid;
        !          2439:   extern int sigheld;
        !          2440:   sigheld |= sigbit (SIGCHLD);
        !          2441: #endif
        !          2442: 
        !          2443:   while (1)
        !          2444:     {
        !          2445:       register int pid;
        !          2446:       WAITTYPE w;
        !          2447:       Lisp_Object tail;
        !          2448: 
        !          2449: #ifdef WNOHANG
        !          2450: #ifndef WUNTRACED
        !          2451: #define WUNTRACED 0
        !          2452: #endif /* no WUNTRACED */
        !          2453:       /* Keep trying to get a status until we get a definitive result.  */
        !          2454:       do 
        !          2455:        {
        !          2456:          errno = 0;
        !          2457:          pid = wait3 (&w, WNOHANG | WUNTRACED, 0);
        !          2458:        }
        !          2459:       while (pid <= 0 && errno == EINTR);
        !          2460: 
        !          2461:       if (pid <= 0)
        !          2462:        {
        !          2463:          /* A real failure.  We have done all our job, so return.  */
        !          2464: 
        !          2465:          /* USG systems forget handlers when they are used;
        !          2466:             must reestablish each time */
        !          2467: #ifdef USG
        !          2468:          signal (signo, sigchld_handler);   /* WARNING - must come after wait3() */
        !          2469: #endif
        !          2470: #ifdef  BSD4_1
        !          2471:          sigheld &= ~sigbit (SIGCHLD);
        !          2472:          sigrelse (SIGCHLD);
        !          2473: #endif
        !          2474:          errno = old_errno;
        !          2475:          return;
        !          2476:        }
        !          2477: #else
        !          2478:       pid = wait (&w);
        !          2479: #endif /* no WNOHANG */
        !          2480: 
        !          2481: #ifdef BSD4_1
        !          2482:       if (synch_process_pid == pid)
        !          2483:        synch_process_pid = 0;         /* Zero it to show process has died. */
        !          2484: #endif
        !          2485: 
        !          2486:       /* Find the process that signaled us, and record its status.  */
        !          2487: 
        !          2488:       p = 0;
        !          2489:       for (tail = Vprocess_alist; XSYMBOL (tail) != XSYMBOL (Qnil); tail = XCONS (tail)->cdr)
        !          2490:        {
        !          2491:          proc = XCONS (XCONS (tail)->car)->cdr;
        !          2492:          p = XPROCESS (proc);
        !          2493:          if (EQ (p->childp, Qt) && XFASTINT (p->pid) == pid)
        !          2494:            break;
        !          2495:          p = 0;
        !          2496:        }
        !          2497: 
        !          2498:       /* If we don't recognize the pid number,
        !          2499:         look for a process being created.  */
        !          2500: 
        !          2501:       if (p == 0)
        !          2502:        for (tail = Vprocess_alist; XSYMBOL (tail) != XSYMBOL (Qnil); tail = XCONS (tail)->cdr)
        !          2503:          {
        !          2504:            proc = XCONS (XCONS (tail)->car)->cdr;
        !          2505:            p = XPROCESS (proc);
        !          2506:            if (XINT (p->pid) == -1)
        !          2507:              break;
        !          2508:            p = 0;
        !          2509:          }
        !          2510: 
        !          2511:       /* Change the status of the process that was found.  */
        !          2512: 
        !          2513:       if (p != 0)
        !          2514:        {
        !          2515:          union { int i; WAITTYPE wt; } u;
        !          2516: 
        !          2517:          XSETINT (p->tick, ++process_tick);
        !          2518:          u.wt = w;
        !          2519:          XFASTINT (p->raw_status_low) = u.i & 0xffff;
        !          2520:          XFASTINT (p->raw_status_high) = u.i >> 16;
        !          2521: 
        !          2522:          /* If process has terminated, stop waiting for its output.  */
        !          2523:          if (WIFSIGNALED (w) || WIFEXITED (w))
        !          2524:            if (p->infd)
        !          2525:              FD_CLR (p->infd, &input_wait_mask);
        !          2526:        }
        !          2527:       else
        !          2528:        {
        !          2529:          /* Report the status of the synchronous process.  */
        !          2530:          if (WIFEXITED (w))
        !          2531:            synch_process_retcode = WRETCODE (w);
        !          2532:          else if (WIFSIGNALED (w))
        !          2533:            synch_process_death = sys_siglist[WTERMSIG (w)];
        !          2534:        }
        !          2535: 
        !          2536:       /* On some systems, we must return right away.
        !          2537:         If any more processes want to signal us, we will
        !          2538:         get another signal.
        !          2539:         Otherwise (on systems that have WNOHANG), loop around
        !          2540:         to use up all the processes that have something to tell us.  */
        !          2541: #if defined (USG) && ! (defined (HPUX) && defined (WNOHANG))
        !          2542: #ifdef USG
        !          2543:       signal (signo, sigchld_handler);
        !          2544: #endif
        !          2545:       errno = old_errno;
        !          2546:       return;
        !          2547: #endif /* USG, but not HPUX with WNOHANG */
        !          2548:     }
        !          2549: }
        !          2550: 
        !          2551: /* Report all recent events of a change in process status
        !          2552:    (either run the sentinel or output a message).
        !          2553:    This is done while Emacs is waiting for keyboard input.  */
        !          2554: 
        !          2555: status_notify ()
        !          2556: {
        !          2557:   register Lisp_Object proc, buffer;
        !          2558:   Lisp_Object tail = Qnil;
        !          2559:   Lisp_Object msg = Qnil;
        !          2560:   struct gcpro gcpro1, gcpro2;
        !          2561: 
        !          2562:   /* We need to gcpro tail; if read_process_output calls a filter
        !          2563:      which deletes a process and removes the cons to which tail points
        !          2564:      from Vprocess_alist, tail becomes an unprotected reference.  */
        !          2565:   GCPRO2 (tail, msg);
        !          2566: 
        !          2567:   for (tail = Vprocess_alist; !NULL (tail); tail = Fcdr (tail))
        !          2568:     {
        !          2569:       Lisp_Object symbol;
        !          2570:       register struct Lisp_Process *p;
        !          2571: 
        !          2572:       proc = Fcdr (Fcar (tail));
        !          2573:       p = XPROCESS (proc);
        !          2574: 
        !          2575:       if (XINT (p->tick) != XINT (p->update_tick))
        !          2576:        {
        !          2577:          XSETINT (p->update_tick, XINT (p->tick));
        !          2578: 
        !          2579:          /* If process is still active, read any output that remains.  */
        !          2580:          if (XFASTINT (p->infd))
        !          2581:            while (read_process_output (proc, XFASTINT (p->infd)) > 0);
        !          2582: 
        !          2583:          buffer = p->buffer;
        !          2584: 
        !          2585:          /* Get the text to use for the message.  */
        !          2586:          if (!NULL (p->raw_status_low))
        !          2587:            update_status (p);
        !          2588:          msg = status_message (p->status);
        !          2589: 
        !          2590:          /* If process is terminated, deactivate it or delete it.  */
        !          2591:          symbol = p->status;
        !          2592:          if (XTYPE (p->status) == Lisp_Cons)
        !          2593:            symbol = XCONS (p->status)->car;
        !          2594: 
        !          2595:          if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)
        !          2596:              || EQ (symbol, Qclosed))
        !          2597:            {
        !          2598:              if (delete_exited_processes)
        !          2599:                remove_process (proc);
        !          2600:              else
        !          2601:                deactivate_process (proc);
        !          2602:            }
        !          2603: 
        !          2604:          /* Now output the message suitably.  */
        !          2605:          if (!NULL (p->sentinel))
        !          2606:            exec_sentinel (proc, msg);
        !          2607:          /* Don't bother with a message in the buffer
        !          2608:             when a process becomes runnable.  */
        !          2609:          else if (!EQ (symbol, Qrun) && !NULL (buffer))
        !          2610:            {
        !          2611:              Lisp_Object ro = XBUFFER (buffer)->read_only;
        !          2612:              Lisp_Object tem;
        !          2613:              struct buffer *old = current_buffer;
        !          2614:              int opoint;
        !          2615: 
        !          2616:              /* Avoid error if buffer is deleted
        !          2617:                 (probably that's why the process is dead, too) */
        !          2618:              if (NULL (XBUFFER (buffer)->name))
        !          2619:                continue;
        !          2620:              Fset_buffer (buffer);
        !          2621:              opoint = point;
        !          2622:              /* Insert new output into buffer
        !          2623:                 at the current end-of-output marker,
        !          2624:                 thus preserving logical ordering of input and output.  */
        !          2625:              if (XMARKER (p->mark)->buffer)
        !          2626:                SET_PT (marker_position (p->mark));
        !          2627:              else
        !          2628:                SET_PT (ZV);
        !          2629:              if (point <= opoint)
        !          2630:                opoint += XSTRING (msg)->size + XSTRING (p->name)->size + 10;
        !          2631: 
        !          2632:              tem = current_buffer->read_only;
        !          2633:              current_buffer->read_only = Qnil;
        !          2634:              InsStr ("\nProcess ");
        !          2635:              Finsert (1, &p->name);
        !          2636:              InsStr (" ");
        !          2637:              Finsert (1, &msg);
        !          2638:              current_buffer->read_only = tem;
        !          2639:              Fset_marker (p->mark, make_number (point), p->buffer);
        !          2640: 
        !          2641:              SET_PT (opoint);
        !          2642:              set_buffer_internal (old);
        !          2643:            }
        !          2644:        }
        !          2645:     } /* end for */
        !          2646: 
        !          2647:   update_mode_lines++;  /* in case buffers use %s in mode-line-format */
        !          2648:   redisplay_preserve_echo_area ();
        !          2649: 
        !          2650:   update_tick = process_tick;
        !          2651: 
        !          2652:   UNGCPRO;
        !          2653: }
        !          2654: 
        !          2655: exec_sentinel (proc, reason)
        !          2656:      Lisp_Object proc, reason;
        !          2657: {
        !          2658:   Lisp_Object sentinel;
        !          2659:   register struct Lisp_Process *p = XPROCESS (proc);
        !          2660:   int count = specpdl_ptr - specpdl;
        !          2661: 
        !          2662:   sentinel = p->sentinel;
        !          2663:   if (NULL (sentinel))
        !          2664:     return;
        !          2665: 
        !          2666:   p->sentinel = Qnil;
        !          2667:   specbind (Qinhibit_quit, Qt);
        !          2668:   this_filter = sentinel;
        !          2669:   filter_process = proc;
        !          2670:   filter_string = reason;
        !          2671:   call2 (this_filter, filter_process, filter_string);
        !          2672: /*   internal_condition_case (run_filter, Qerror, Fidentity);  */
        !          2673:   unbind_to (count);
        !          2674:   p->sentinel = sentinel;
        !          2675: }
        !          2676: 
        !          2677: init_process ()
        !          2678: {
        !          2679:   register int i;
        !          2680: 
        !          2681: #ifdef SIGCHLD
        !          2682: #ifndef CANNOT_DUMP
        !          2683:   if (! noninteractive || initialized)
        !          2684: #endif
        !          2685:     signal (SIGCHLD, sigchld_handler);
        !          2686: #endif
        !          2687: 
        !          2688:   FD_ZERO (&input_wait_mask);
        !          2689:   FD_SET (0, &input_wait_mask);
        !          2690:   Vprocess_alist = Qnil;
        !          2691:   for (i = 0; i < MAXDESC; i++)
        !          2692:     {
        !          2693:       chan_process[i] = Qnil;
        !          2694:       proc_buffered_char[i] = -1;
        !          2695:     }
        !          2696: }
        !          2697: 
        !          2698: syms_of_process ()
        !          2699: {
        !          2700:   Qprocessp = intern ("processp");
        !          2701:   staticpro (&Qprocessp);
        !          2702:   Qrun = intern ("run");
        !          2703:   staticpro (&Qrun);
        !          2704:   Qstop = intern ("stop");
        !          2705:   staticpro (&Qstop);
        !          2706:   Qsignal = intern ("signal");
        !          2707:   staticpro (&Qsignal);
        !          2708: 
        !          2709:   /* Qexit is already staticpro'd by syms_of_eval; don't staticpro it
        !          2710:      here again.
        !          2711: 
        !          2712:      Qexit = intern ("exit");
        !          2713:      staticpro (&Qexit); */
        !          2714: 
        !          2715:   Qopen = intern ("open");
        !          2716:   staticpro (&Qopen);
        !          2717:   Qclosed = intern ("closed");
        !          2718:   staticpro (&Qclosed);
        !          2719: 
        !          2720:   staticpro (&Vprocess_alist);
        !          2721: 
        !          2722:   DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
        !          2723:     "*Non-nil means delete processes immediately when they exit.\n\
        !          2724: nil means don't delete them until `list-processes' is run.");
        !          2725: 
        !          2726:   delete_exited_processes = 1;
        !          2727: 
        !          2728:   DEFVAR_LISP ("process-connection-type", &Vprocess_connection_type,
        !          2729:     "Control type of device used to communicate with subprocesses.\n\
        !          2730: Values are nil to use a pipe, t for a pty (or pipe if ptys not supported).\n\
        !          2731: Value takes effect when `start-process' is called.");
        !          2732:   Vprocess_connection_type = Qt;
        !          2733: 
        !          2734:   defsubr (&Sprocessp);
        !          2735:   defsubr (&Sget_process);
        !          2736:   defsubr (&Sget_buffer_process);
        !          2737:   defsubr (&Sdelete_process);
        !          2738:   defsubr (&Sprocess_status);
        !          2739:   defsubr (&Sprocess_exit_status);
        !          2740:   defsubr (&Sprocess_id);
        !          2741:   defsubr (&Sprocess_name);
        !          2742:   defsubr (&Sprocess_command);
        !          2743:   defsubr (&Sset_process_buffer);
        !          2744:   defsubr (&Sprocess_buffer);
        !          2745:   defsubr (&Sprocess_mark);
        !          2746:   defsubr (&Sset_process_filter);
        !          2747:   defsubr (&Sprocess_filter);
        !          2748:   defsubr (&Sset_process_sentinel);
        !          2749:   defsubr (&Sprocess_sentinel);
        !          2750:   defsubr (&Sprocess_kill_without_query);
        !          2751:   defsubr (&Slist_processes);
        !          2752:   defsubr (&Sprocess_list);
        !          2753:   defsubr (&Sstart_process);
        !          2754: #ifdef HAVE_SOCKETS
        !          2755:   defsubr (&Sopen_network_stream);
        !          2756: #endif /* HAVE_SOCKETS */
        !          2757:   defsubr (&Saccept_process_output);
        !          2758:   defsubr (&Sprocess_send_region);
        !          2759:   defsubr (&Sprocess_send_string);
        !          2760:   defsubr (&Sinterrupt_process);
        !          2761:   defsubr (&Skill_process);
        !          2762:   defsubr (&Squit_process);
        !          2763:   defsubr (&Sstop_process);
        !          2764:   defsubr (&Scontinue_process);
        !          2765:   defsubr (&Sprocess_send_eof);
        !          2766:   defsubr (&Swaiting_for_user_input_p);
        !          2767: }
        !          2768: 
        !          2769: #endif /* subprocesses */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.