Remove unneeded SXE_SHLIB_STUFF
[sxemacs] / src / process.c
1 /* Asynchronous subprocess control for SXEmacs.
2    Copyright (C) 1985, 1986, 1987, 1988, 1992, 1993, 1994, 1995, 2003
3    Free Software Foundation, Inc.
4    Copyright (C) 1995 Sun Microsystems, Inc.
5    Copyright (C) 1995, 1996 Ben Wing.
6
7 This file is part of SXEmacs
8
9 SXEmacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 SXEmacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
21
22
23 /* This file has been Mule-ized except for `start-process-internal',
24    `open-network-stream-internal' and `open-multicast-group-internal'. */
25
26 /* This file has been split into process.c and process-unix.c by
27    Kirill M. Katsnelson <kkm@kis.ru>, so please bash him and not
28    the original author(s) */
29
30 #include <config.h>
31
32 #if !defined (NO_SUBPROCESSES)
33
34 /* The entire file is within this conditional */
35
36 #include "lisp.h"
37
38 #include "buffer.h"
39 #include "commands.h"
40 #include "events/events.h"
41 #include "ui/frame.h"
42 #include "hash.h"
43 #include "ui/insdel.h"
44 #include "lstream.h"
45 #include "opaque.h"
46 #include "process.h"
47 #include "procimpl.h"
48 #include "ui/window.h"
49 #ifdef FILE_CODING
50 #include "mule/file-coding.h"
51 #endif
52
53 #include "sysfile.h"
54 #include "sysproc.h"
55 #include "systime.h"
56 #include "syssignal.h"          /* Always include before systty.h */
57 #include "ui/systty.h"
58 #include "syswait.h"
59
60 #if defined(HAVE_OPENSSL) && defined(OPENSSL_SSL)
61 #include "openssl.h"
62 #endif
63 #include "dynacat.h"
64
65 Lisp_Object Qprocessp, Qprocess_live_p, Qprocess_readable_p;
66
67 /* Process methods */
68 struct process_methods the_process_methods;
69
70 /* a process object is a network connection when its pid field a cons
71    (name of name of port we are connected to . foreign host name) */
72 #ifdef HAVE_SOCKETS
73 /* valid objects to server stream host parameter */
74 Lisp_Object Qip_any, Qlocalhost;
75 #endif
76
77 /* Valid values of process->status_symbol */
78 Lisp_Object Qrun, Qstop;
79 /* Qrun => Qopen, Qexit => Qclosed for "network connection" processes */
80 Lisp_Object Qopen, Qclosed;
81 /* Protocol families */
82 Lisp_Object Qtcp, Qudp;
83
84 #ifdef HAVE_MULTICAST
85 Lisp_Object Qmulticast;         /* Will be used for occasional warnings */
86 #endif
87
88 /* t means use pty, nil means use a pipe,
89    maybe other values to come.  */
90 Lisp_Object Vprocess_connection_type;
91
92 /* Read comments to DEFVAR of this */
93 int windowed_process_io;
94
95 #ifdef PROCESS_IO_BLOCKING
96 /* List of port numbers or port names to set a blocking I/O mode.
97    Nil means set a non-blocking I/O mode [default]. */
98 Lisp_Object network_stream_blocking_port_list;
99 #endif                          /* PROCESS_IO_BLOCKING */
100
101 /* Number of events of change of status of a process.  */
102 volatile int process_tick;
103
104 /* Number of events for which the user or sentinel has been notified.  */
105 static int update_tick;
106
107 /* Nonzero means delete a process right away if it exits.  */
108 int delete_exited_processes;
109
110 /* Hash table which maps USIDs as returned by create_stream_pair_cb to
111    process objects. Processes are not GC-protected through this! */
112 struct hash_table *usid_to_process;
113 Lisp_Object Vusid_to_process;
114
115 /* List of process objects. */
116 Lisp_Object Vprocess_list;
117
118 extern Lisp_Object Vlisp_EXEC_SUFFIXES;
119 Lisp_Object Vnull_device;
120 \f
121 static Lisp_Object mark_process(Lisp_Object object)
122 {
123         Lisp_Process *process = XPROCESS(object);
124         MAYBE_PROCMETH(mark_process_data, (process));
125         mark_object(process->name);
126         mark_object(process->command);
127         mark_object(process->filter);
128         mark_object(process->sentinel);
129         mark_object(process->buffer);
130         mark_object(process->mark);
131         mark_object(process->pid);
132         mark_object(process->pipe_instream);
133         mark_object(process->pipe_outstream);
134 #ifdef FILE_CODING
135         mark_object(process->coding_instream);
136         mark_object(process->coding_outstream);
137 #endif
138         mark_object(process->process_type_data);
139         return process->status_symbol;
140 }
141
142 static void
143 print_process(Lisp_Object object, Lisp_Object printcharfun, int escapeflag)
144 {
145         Lisp_Process *process = XPROCESS(object);
146
147         if (print_readably)
148                 error("printing unreadable object #<process %s>",
149                       XSTRING_DATA(process->name));
150
151         if (!escapeflag) {
152                 print_internal(process->name, printcharfun, 0);
153         } else {
154                 /* int netp = network_connection_p(object); */
155                 int netp = ((process->process_type == PROCESS_TYPE_NETWORK) ||
156                             (process->process_type == PROCESS_TYPE_MULTICAST) ||
157                             (process->process_type == PROCESS_TYPE_SSL) ||
158                             (process->process_type == PROCESS_TYPE_NETWORK_SERVER_LISTEN));
159                 switch (process->process_type) {
160                 case PROCESS_TYPE_NETWORK:
161                         write_c_string(
162                                 GETTEXT("#<network connection "),
163                                 printcharfun);
164                         break;
165                 case PROCESS_TYPE_NETWORK_SERVER_LISTEN:
166                         write_c_string(
167                                 GETTEXT("#<network server accepting connections "),
168                                 printcharfun);
169                         break;
170                 case PROCESS_TYPE_MULTICAST:
171                         write_c_string(
172                                 GETTEXT("#<multicast network connection "),
173                                 printcharfun);
174                         break;
175                 case PROCESS_TYPE_SSL:
176                         write_c_string(
177                                 GETTEXT("#<secure network connection "),
178                                 printcharfun);
179                         break;
180                 case PROCESS_TYPE_PROC:
181                 default:
182                         write_c_string(
183                                 GETTEXT("#<process "),
184                                 printcharfun);
185                         break;
186                 }
187                 print_internal(process->name, printcharfun, 1);
188                 write_c_string((netp ? " " : " pid "), printcharfun);
189                 print_internal(process->pid, printcharfun, 1);
190                 write_c_string(" state:", printcharfun);
191                 print_internal(process->status_symbol, printcharfun, 1);
192                 MAYBE_PROCMETH(print_process_data, (process, printcharfun));
193                 write_c_string(">", printcharfun);
194         }
195 }
196
197 #ifdef HAVE_WINDOW_SYSTEM
198 extern void debug_process_finalization(Lisp_Process * p);
199 #endif                          /* HAVE_WINDOW_SYSTEM */
200
201 static void finalize_process(void *header, int for_disksave)
202 {
203         /* #### this probably needs to be tied into the tty event loop */
204         /* #### when there is one */
205         Lisp_Process *p = (Lisp_Process *) header;
206 #ifdef HAVE_WINDOW_SYSTEM
207         if (!for_disksave) {
208                 debug_process_finalization(p);
209         }
210 #endif                          /* HAVE_WINDOW_SYSTEM */
211
212         if (p->process_data) {
213                 MAYBE_PROCMETH(finalize_process_data, (p, for_disksave));
214                 if (!for_disksave)
215                         xfree(p->process_data);
216         }
217 }
218
219 DEFINE_LRECORD_IMPLEMENTATION("process", process,
220                               mark_process, print_process, finalize_process,
221                               0, 0, 0, Lisp_Process);
222 \f
223 /************************************************************************/
224 /*                       basic process accessors                        */
225 /************************************************************************/
226
227 /* Under FILE_CODING, this function returns low-level streams, connected
228    directly to the child process, rather than en/decoding FILE_CODING
229    streams */
230 void
231 get_process_streams(Lisp_Process * p, Lisp_Object * instr, Lisp_Object * outstr)
232 {
233         assert(p);
234         assert(NILP(p->pipe_instream) || LSTREAMP(p->pipe_instream));
235         assert(NILP(p->pipe_outstream) || LSTREAMP(p->pipe_outstream));
236         *instr = p->pipe_instream;
237         *outstr = p->pipe_outstream;
238 }
239
240 Lisp_Process *get_process_from_usid(USID usid)
241 {
242         const void *vval;
243
244         assert(usid != USID_ERROR && usid != USID_DONTHASH);
245
246         if (gethash((const void *)usid, usid_to_process, &vval)) {
247                 Lisp_Object process;
248                 CVOID_TO_LISP(process, vval);
249                 return XPROCESS(process);
250         } else 
251                 return 0;
252 }
253
254 int get_process_selected_p(Lisp_Process * p)
255 {
256         return p->selected;
257 }
258
259 void set_process_selected_p(Lisp_Process * p, int selected_p)
260 {
261         p->selected = !!selected_p;
262 }
263
264 int connected_via_filedesc_p(Lisp_Process * p)
265 {
266         /* In the bad old days of tooltalk this would return non-0 if
267          * there was a tooltalk connection.  So that really means that
268          * in 101 times out of 100 this would return 0 because nobody
269          * ever used tooltalk.  It is possible that one day this might
270          * need some d-bus love. */
271         return 0;
272 }
273
274 #ifdef HAVE_SOCKETS
275 int network_connection_p(Lisp_Object process)
276 {
277         return CONSP(XPROCESS(process)->pid);
278 }
279 #endif
280
281 DEFUN("processp", Fprocessp, 1, 1, 0,   /*
282 Return t if OBJECT is a process.
283 */
284       (object))
285 {
286         return PROCESSP(object) ? Qt : Qnil;
287 }
288
289 DEFUN("process-live-p", Fprocess_live_p, 1, 1, 0,       /*
290 Return t if OBJECT is a process that is alive.
291 */
292       (object))
293 {
294         return PROCESSP(object) && PROCESS_LIVE_P(XPROCESS(object))
295             ? Qt : Qnil;
296 }
297
298 #if 0
299 /* This is a reasonable definition for this new primitive.  Kyle sez:
300
301    "The patch looks OK to me except for the creation and exporting of the
302    Fprocess_readable_p function.  I don't think a new Lisp function
303    should be created until we know something actually needs it.  If
304    we later want to give process-readable-p different semantics it
305    may be hard to do it and stay compatible with what we hastily
306    create today."
307
308    He's right, not yet.  Let's discuss the semantics on XEmacs Design
309    before enabling this.
310 */
311 DEFUN("process-readable-p", Fprocess_readable_p, 1, 1, 0,       /*
312 Return t if OBJECT is a process from which input may be available.
313 */
314       (object))
315 {
316         return PROCESSP(object) && PROCESS_READABLE_P(XPROCESS(object))
317             ? Qt : Qnil;
318 }
319 #endif
320
321 DEFUN("process-list", Fprocess_list, 0, 0, 0,   /*
322 Return a list of all processes.
323 */
324       ())
325 {
326         return Fcopy_sequence(Vprocess_list);
327 }
328
329 DEFUN("get-process", Fget_process, 1, 1, 0,     /*
330 Return the process named PROCESS-NAME (a string), or nil if there is none.
331 PROCESS-NAME may also be a process; if so, the value is that process.
332 */
333       (process_name))
334 {
335         if (PROCESSP(process_name))
336                 return process_name;
337
338         if (!gc_in_progress)
339                 /* this only gets called during GC when emacs is going away as a result
340                    of a signal or crash. */
341                 CHECK_STRING(process_name);
342
343         {
344                 LIST_LOOP_2(process, Vprocess_list)
345                     if (internal_equal
346                         (process_name, XPROCESS(process)->name, 0))
347                         return process;
348         }
349         return Qnil;
350 }
351
352 DEFUN("get-buffer-process", Fget_buffer_process, 1, 1, 0,       /*
353 Return the (or, a) process associated with BUFFER.
354 BUFFER may be a buffer or the name of one.
355 */
356       (buffer))
357 {
358         if (NILP(buffer))
359                 return Qnil;
360         buffer = Fget_buffer(buffer);
361         if (NILP(buffer))
362                 return Qnil;
363
364         {
365                 LIST_LOOP_2(process, Vprocess_list)
366                     if (EQ(XPROCESS(process)->buffer, buffer))
367                         return process;
368         }
369         return Qnil;
370 }
371
372 /* This is how commands for the user decode process arguments.  It
373    accepts a process, a process name, a buffer, a buffer name, or nil.
374    Buffers denote the first process in the buffer, and nil denotes the
375    current buffer.  */
376
377 static Lisp_Object get_process(Lisp_Object name)
378 {
379         Lisp_Object buffer;
380
381 #ifdef I18N3
382         /* #### Look more closely into translating process names. */
383 #endif
384
385         /* This may be called during a GC from process_send_signal() from
386            kill_buffer_processes() if emacs decides to abort(). */
387         if (PROCESSP(name))
388                 return name;
389         else if (STRINGP(name)) {
390                 Lisp_Object object = Fget_process(name);
391                 if (PROCESSP(object))
392                         return object;
393
394                 buffer = Fget_buffer(name);
395                 if (BUFFERP(buffer))
396                         goto have_buffer_object;
397
398                 error("Process %s does not exist", XSTRING_DATA(name));
399         } else if (NILP(name)) {
400                 buffer = Fcurrent_buffer();
401                 goto have_buffer_object;
402         } else if (BUFFERP(name)) {
403                 Lisp_Object process;
404                 buffer = name;
405
406               have_buffer_object:
407                 process = Fget_buffer_process(buffer);
408                 if (PROCESSP(process))
409                         return process;
410
411                 error("Buffer %s has no process",
412                       XSTRING_DATA(XBUFFER(buffer)->name));
413         } else
414                 return get_process(Fsignal(Qwrong_type_argument,
415                                            (list2
416                                             (build_string
417                                              ("process or buffer or nil"),
418                                              name))));
419 }
420
421 DEFUN("process-id", Fprocess_id, 1, 1, 0,       /*
422 Return the process id of PROCESS.
423 This is the pid of the Unix process which PROCESS uses or talks to.
424 For a network connection, this value is a cons of
425 (foreign-network-port . foreign-host-name).
426 */
427       (process))
428 {
429         Lisp_Object pid;
430         CHECK_PROCESS(process);
431
432         pid = XPROCESS(process)->pid;
433         if (network_connection_p(process))
434                 /* return Qnil; */
435                 return Fcons(Fcar(pid), Fcdr(pid));
436         else
437                 return pid;
438 }
439
440 DEFUN("process-name", Fprocess_name, 1, 1, 0,   /*
441 Return the name of PROCESS, as a string.
442 This is the name of the program invoked in PROCESS,
443 possibly modified to make it unique among process names.
444 */
445       (process))
446 {
447         CHECK_PROCESS(process);
448         return XPROCESS(process)->name;
449 }
450
451 DEFUN("process-command", Fprocess_command, 1, 1, 0,     /*
452 Return the command that was executed to start PROCESS.
453 This is a list of strings, the first string being the program executed
454 and the rest of the strings being the arguments given to it.
455 */
456       (process))
457 {
458         CHECK_PROCESS(process);
459         return XPROCESS(process)->command;
460 }
461 \f
462 /************************************************************************/
463 /*                          creating a process                          */
464 /************************************************************************/
465
466 Lisp_Object make_process_internal(Lisp_Object name)
467 {
468         Lisp_Object val, name1;
469         int i;
470         Lisp_Process *p = alloc_lcrecord_type(Lisp_Process, &lrecord_process);
471
472         /* If name is already in use, modify it until it is unused.  */
473         name1 = name;
474         for (i = 1;; i++) {
475                 char suffix[24];
476                 int sz;
477                 Lisp_Object tem = Fget_process(name1);
478                 if (NILP(tem))
479                         break;
480                 sz = snprintf(suffix, sizeof(suffix), "<%d>", i);
481                 assert(sz>=0 && sz<sizeof(suffix));
482                 name1 = concat2(name, build_string(suffix));
483         }
484         name = name1;
485         p->name = name;
486
487         p->command = Qnil;
488         p->filter = Qnil;
489         p->sentinel = Qnil;
490         p->buffer = Qnil;
491         p->mark = Fmake_marker();
492         p->pid = Qnil;
493         p->status_symbol = Qrun;
494         p->exit_code = 0;
495         p->core_dumped = 0;
496         p->filter_does_read = 0;
497         p->kill_without_query = 0;
498         p->selected = 0;
499         p->tick = 0;
500         p->update_tick = 0;
501         p->pipe_instream = Qnil;
502         p->pipe_outstream = Qnil;
503 #ifdef FILE_CODING
504         p->coding_instream = Qnil;
505         p->coding_outstream = Qnil;
506 #endif
507         p->process_type = PROCESS_TYPE_PROC;
508         p->process_type_data = Qnil;
509
510         p->process_data = 0;
511         MAYBE_PROCMETH(alloc_process_data, (p));
512
513         XSETPROCESS(val, p);
514
515         Vprocess_list = Fcons(val, Vprocess_list);
516         return val;
517 }
518
519 void init_process_io_handles(Lisp_Process * p, void *in, void *out, int flags)
520 {
521         USID usid = event_stream_create_stream_pair(in, out,
522                                                     &p->pipe_instream,
523                                                     &p->pipe_outstream,
524                                                     flags);
525
526         if (usid == USID_ERROR)
527                 report_file_error("Setting up communication with subprocess",
528                                   Qnil);
529
530         if (usid != USID_DONTHASH) {
531                 Lisp_Object process = Qnil;
532                 XSETPROCESS(process, p);
533                 puthash((const void *)usid, LISP_TO_VOID(process),
534                         usid_to_process);
535         }
536
537         MAYBE_PROCMETH(init_process_io_handles, (p, in, out, flags));
538
539 #ifdef FILE_CODING
540         p->coding_instream = make_decoding_input_stream
541             (XLSTREAM(p->pipe_instream),
542              Fget_coding_system(Vcoding_system_for_read));
543         Lstream_set_character_mode(XLSTREAM(p->coding_instream));
544         p->coding_outstream = make_encoding_output_stream
545             (XLSTREAM(p->pipe_outstream),
546              Fget_coding_system(Vcoding_system_for_write));
547         /* CODE_CNTL (&out_state[outchannel]) |= CC_END; !!####
548            What's going on here? */
549 #endif                          /* FILE_CODING */
550 }
551
552 static void
553 create_process(Lisp_Object process, Lisp_Object * argv, int nargv,
554                Lisp_Object program, Lisp_Object cur_dir)
555 {
556         Lisp_Process *p = XPROCESS(process);
557         int pid;
558
559         /* *_create_process may change status_symbol, if the process
560            is a kind of "fire-and-forget" (no I/O, unwaitable) */
561         p->status_symbol = Qrun;
562         p->exit_code = 0;
563
564         pid = PROCMETH(create_process, (p, argv, nargv, program, cur_dir));
565
566         p->pid = make_int(pid);
567         if (PROCESS_READABLE_P(p))
568                 event_stream_select_process(p);
569 }
570
571 /* This function is the unwind_protect form for Fstart_process_internal.  If
572    PROCESS doesn't have its pid set, then we know someone has signalled
573    an error and the process wasn't started successfully, so we should
574    remove it from the process list.  */
575 static void remove_process(Lisp_Object process);
576 static Lisp_Object start_process_unwind(Lisp_Object process)
577 {
578         /* Was PROCESS started successfully?  */
579         if (EQ(XPROCESS(process)->pid, Qnil))
580                 remove_process(process);
581         return Qnil;
582 }
583
584 DEFUN("start-process-internal", Fstart_process_internal, 3, MANY, 0,    /*
585 Start a program in a subprocess.  Return the process object for it.
586 Args are NAME BUFFER PROGRAM &rest PROGRAM-ARGS
587 NAME is name for process.  It is modified if necessary to make it unique.
588 BUFFER is the buffer or (buffer-name) to associate with the process.
589 Process output goes at end of that buffer, unless you specify
590 an output stream or filter function to handle the output.
591 BUFFER may be also nil, meaning that this process is not associated
592 with any buffer
593 Third arg is program file name.  It is searched for as in the shell.
594 Remaining arguments are strings to give program as arguments.
595 If bound, `coding-system-for-read' and `coding-system-for-write' specify
596 the coding-system objects used in input from and output to the process.
597 */
598       (int nargs, Lisp_Object * args))
599 {
600         /* This function can call lisp */
601         /* !!#### This function has not been Mule-ized */
602         Lisp_Object buffer, name, program, process, current_dir;
603         Lisp_Object tem;
604         int i;
605         int speccount = specpdl_depth();
606         struct gcpro gcpro1, gcpro2, gcpro3;
607
608         name = args[0];
609         buffer = args[1];
610         program = args[2];
611         current_dir = Qnil;
612
613         /* Protect against various file handlers doing GCs below. */
614         GCPRO3(buffer, program, current_dir);
615
616         if (!NILP(buffer))
617                 buffer = Fget_buffer_create(buffer);
618
619         CHECK_STRING(name);
620         CHECK_STRING(program);
621         for (i = 3; i < nargs; ++i)
622                 CHECK_STRING(args[i]);
623
624         /* Make sure that the child will be able to chdir to the current
625            buffer's current directory, or its unhandled equivalent.  We
626            can't just have the child check for an error when it does the
627            chdir, since it's in a vfork.
628
629            Note: these assignments and calls are like this in order to insure
630            "caller protects args" GC semantics. */
631         current_dir = current_buffer->directory;
632         current_dir = Funhandled_file_name_directory(current_dir);
633         current_dir = expand_and_dir_to_file(current_dir, Qnil);
634
635 #if 0                           /* This loser breaks ange-ftp */
636         /* dmoore - if you re-enable this code, you have to gcprotect
637            current_buffer through the above calls. */
638         if (NILP(Ffile_accessible_directory_p(current_dir)))
639                 report_file_error("Setting current directory",
640                                   list1(current_buffer->directory));
641 #endif                          /* 0 */
642
643         /* If program file name is not absolute, search our path for it */
644         if (!IS_DIRECTORY_SEP(XSTRING_BYTE(program, 0))
645             && !(XSTRING_LENGTH(program) > 1
646                  && IS_DEVICE_SEP(XSTRING_BYTE(program, 1)))) {
647                 struct gcpro ngcpro1;
648
649                 tem = Qnil;
650                 NGCPRO1(tem);
651                 locate_file(Vexec_path, program, Vlisp_EXEC_SUFFIXES, &tem,
652                             X_OK);
653                 if (NILP(tem))
654                         report_file_error("Searching for program",
655                                           list1(program));
656                 program = Fexpand_file_name(tem, Qnil);
657                 NUNGCPRO;
658         } else {
659                 /* we still need to canonicalize it and ensure it has the proper
660                    ending, e.g. .exe */
661                 struct gcpro ngcpro1;
662
663                 tem = Qnil;
664                 NGCPRO1(tem);
665                 locate_file(list1(build_string("")), program,
666                             Vlisp_EXEC_SUFFIXES, &tem, X_OK);
667                 if (NILP(tem))
668                         report_file_error("Searching for program",
669                                           list1(program));
670                 program = tem;
671                 NUNGCPRO;
672         }
673
674         if (!NILP(Ffile_directory_p(program)))
675                 invalid_operation
676                     ("Specified program for new process is a directory",
677                      program);
678
679         process = make_process_internal(name);
680
681         XPROCESS(process)->buffer = buffer;
682         XPROCESS(process)->command = Flist(nargs - 2, args + 2);
683
684         /* Make the process marker point into the process buffer (if any).  */
685         if (!NILP(buffer))
686                 Fset_marker(XPROCESS(process)->mark,
687                             make_int(BUF_ZV(XBUFFER(buffer))), buffer);
688
689         /* If an error occurs and we can't start the process, we want to
690            remove it from the process list.  This means that each error
691            check in create_process doesn't need to call remove_process
692            itself; it's all taken care of here.  */
693         record_unwind_protect(start_process_unwind, process);
694
695         create_process(process, args + 3, nargs - 3, program, current_dir);
696
697         UNGCPRO;
698         return unbind_to(speccount, process);
699 }
700 \f
701 #ifdef HAVE_SOCKETS
702
703 /* #### The network support is fairly synthetical. What we actually
704    need is a single function, which supports all datagram, stream and
705    packet stream connections, arbitrary protocol families should they
706    be supported by the target system, multicast groups, in both data
707    and control rooted/nonrooted flavors, service quality etc whatever
708    is supported by the underlying network.
709
710    It must accept a property list describing the connection. The current
711    functions must then go to lisp and provide a suitable list for the
712    generalized connection function.
713
714    All modern UNIX other OSs support BSD sockets, and there are many
715    extensions available (Sockets 2 spec).
716
717    A todo is define a consistent set of properties abstracting a
718    network connection.   -kkm
719 */
720
721
722
723 DEFUN("network-process-listener", Fnetwork_process_listener, 1, 1, 0, /*
724 Returns the process that listened and accepted the given
725 network-process. Returns nil if process is closed or was not accepted
726 through a network server stream.
727
728 Args are PROCESS 
729
730 PROCESS should be a network-stream process accepted through a network
731 */
732       (process))
733 {
734
735         CHECK_PROCESS(process);
736         return MAYBE_LISP_PROCMETH(network_process_listener, (process));
737 }
738
739
740 /* Listen for a TCP network connection to a given SERVICE.  Treated
741    exactly like a normal process when reading and writing.  Only
742    differences are in status display and process deletion.  A network
743    connection has no PID; you cannot signal it.  All you can do is
744    deactivate and close it via delete-process. You must provide a
745    sentinel. */
746 DEFUN("open-network-server-stream-internal", Fopen_network_server_stream_internal, 4, 8, 0,     /*
747 Returns a process object to represent the listening connection. When a
748 new connection request arrives, it is automatically accepted. A
749 network-stream process is automatically created for that
750 connection. If needed a new buffer is also created. If given the
751 acceptor function is called. If defined filter and sentinel are set
752 for the new connection process .
753
754 Input and output work as for subprocesses; `delete-process' closes it.  
755
756 Args are NAME BUFFER HOST SERVICE &optional PROTOCOL ACCEPTOR .  
757
758 NAME is name for process.  It is modified if necessary to make it
759 unique.
760
761 BUFFER is the buffer (or buffer-name) to associate with the process.
762  Listening Process output goes at end of that buffer, unless you
763  specify an output stream or filter function to handle the output. No
764  real process output of listening process is expected. However the
765  name of this buffer will be used as a base for generating a new
766  buffer name for the accepted connections.  
767  The BUFFER may be also nil, meaning that this process is not
768  associated with any buffer. In this case a filter should be specified
769  otherwise there will be no way to retrieve the process output.  
770  BUFFER may also be 'auto in which case a buffer is automatically
771  created for the accepted connection.
772
773 Third arg HOST (a string) is the name of the IP to bind to, or its
774  IP address, If nil or ip_any will bind to all addresses on the
775  machine. When HOST is 'localhost listening connection will listen
776  to connections from the local machine only.
777 Fourth arg SERVICE is name of the service desired, or an integer
778  specifying a port number to connect to.
779 Fifth argument PROTOCOL is a network protocol.  Currently 'tcp
780  (Transmission Control Protocol) and 'udp (User Datagram Protocol) are
781  supported.  When omitted, 'tcp is assumed.
782 Sixt argument ACCEPTOR is a function which will be called upon connection
783  acceptance with the accepted connection process as the single argument.
784 Seventh argument FILTER is a function which will be set as filter for
785  the accepted connections automatically. See `set-process-filter' for
786  more details.  
787 Eight argument SENTINEL is a function which will be set as sentinel
788  the accepted connections automatically. see `set-process-sentinel'