Function: make-pipe-process

make-pipe-process is a function defined in process.c.

Signature

(make-pipe-process &rest ARGS)

Documentation

Create and return a bidirectional pipe process.

In Emacs, pipes are represented by process objects, so input and output work as for subprocesses, and delete-process closes a pipe. However, a pipe process has no process id, it cannot be signaled, and the status codes are different from normal processes.

Arguments are specified as keyword/argument pairs. The following arguments are defined:

:name NAME -- NAME is the name of the process. It is modified if necessary to make it unique.

:buffer BUFFER -- BUFFER is the buffer (or buffer-name) to associate
with the process. Process output goes at the end of that buffer, unless you specify a filter function to handle the output. If BUFFER is not given, the value of NAME is used.

:coding CODING -- If CODING is a symbol, it specifies the coding
system used for both reading and writing for this process. If CODING is a cons (DECODING . ENCODING), DECODING is used for reading, and ENCODING is used for writing.

:noquery BOOL -- When exiting Emacs, query the user if BOOL is nil and
the process is running. If BOOL is not given, query before exiting.

:stop BOOL -- Start process in the stopped state if BOOL non-nil.
In the stopped state, a pipe process does not accept incoming data, but you can send outgoing data. The stopped state is cleared by continue-process and set by stop-process.

:filter FILTER -- Install FILTER as the process filter.

:sentinel SENTINEL -- Install SENTINEL as the process sentinel.

Probably introduced at or before Emacs version 28.1.

Source Code

// Defined in /usr/src/emacs/src/process.c
{
  Lisp_Object proc, contact;
  struct Lisp_Process *p;
  Lisp_Object name, buffer;
  Lisp_Object tem;
  ptrdiff_t specpdl_count;
  int inchannel, outchannel;

  if (nargs == 0)
    return Qnil;

  contact = Flist (nargs, args);

  name = Fplist_get (contact, QCname);
  CHECK_STRING (name);
  proc = make_process (name);
  specpdl_count = SPECPDL_INDEX ();
  record_unwind_protect (remove_process, proc);
  p = XPROCESS (proc);

  if (emacs_pipe (p->open_fd + SUBPROCESS_STDIN) != 0
      || emacs_pipe (p->open_fd + READ_FROM_SUBPROCESS) != 0)
    report_file_error ("Creating pipe", Qnil);
  outchannel = p->open_fd[WRITE_TO_SUBPROCESS];
  inchannel = p->open_fd[READ_FROM_SUBPROCESS];

  if (FD_SETSIZE <= inchannel || FD_SETSIZE <= outchannel)
    report_file_errno ("Creating pipe", Qnil, EMFILE);

  fcntl (inchannel, F_SETFL, O_NONBLOCK);
  fcntl (outchannel, F_SETFL, O_NONBLOCK);

#ifdef WINDOWSNT
  register_aux_fd (inchannel);
#endif

  /* Record this as an active process, with its channels.  */
  eassert (0 <= inchannel && inchannel < FD_SETSIZE);
  chan_process[inchannel] = proc;
  p->infd = inchannel;
  p->outfd = outchannel;

  if (inchannel > max_desc)
    max_desc = inchannel;

  buffer = Fplist_get (contact, QCbuffer);
  if (NILP (buffer))
    buffer = name;
  buffer = Fget_buffer_create (buffer, Qnil);
  pset_buffer (p, buffer);

  pset_childp (p, contact);
  pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist)));
  pset_type (p, Qpipe);
  pset_sentinel (p, Fplist_get (contact, QCsentinel));
  pset_filter (p, Fplist_get (contact, QCfilter));
  eassert (NILP (p->log));
  if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
    p->kill_without_query = 1;
  if (tem = Fplist_get (contact, QCstop), !NILP (tem))
    pset_command (p, Qt);
  eassert (! p->pty_flag);

  if (!EQ (p->command, Qt))
    add_process_read_fd (inchannel);
  p->adaptive_read_buffering
    = (NILP (Vprocess_adaptive_read_buffering) ? 0
       : EQ (Vprocess_adaptive_read_buffering, Qt) ? 1 : 2);

  /* Make the process marker point into the process buffer (if any).  */
  update_process_mark (p);

  {
    /* Setup coding systems for communicating with the network stream.  */

    /* Qt denotes we have not yet called Ffind_operation_coding_system.  */
    Lisp_Object coding_systems = Qt;
    Lisp_Object val;

    tem = Fplist_get (contact, QCcoding);
    val = Qnil;
    if (!NILP (tem))
      {
	val = tem;
	if (CONSP (val))
	  val = XCAR (val);
      }
    else if (!NILP (Vcoding_system_for_read))
      val = Vcoding_system_for_read;
    else if ((!NILP (buffer) && NILP (BVAR (XBUFFER (buffer), enable_multibyte_characters)))
	     || (NILP (buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters))))
      /* We dare not decode end-of-line format by setting VAL to
	 Qraw_text, because the existing Emacs Lisp libraries
	 assume that they receive bare code including a sequence of
	 CR LF.  */
      val = Qnil;
    else
      {
	if (CONSP (coding_systems))
	  val = XCAR (coding_systems);
	else if (CONSP (Vdefault_process_coding_system))
	  val = XCAR (Vdefault_process_coding_system);
	else
	  val = Qnil;
      }
    pset_decode_coding_system (p, val);

    if (!NILP (tem))
      {
	val = tem;
	if (CONSP (val))
	  val = XCDR (val);
      }
    else if (!NILP (Vcoding_system_for_write))
      val = Vcoding_system_for_write;
    else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
      val = Qnil;
    else
      {
	if (CONSP (coding_systems))
	  val = XCDR (coding_systems);
	else if (CONSP (Vdefault_process_coding_system))
	  val = XCDR (Vdefault_process_coding_system);
	else
	  val = Qnil;
      }
    pset_encode_coding_system (p, val);
  }
  /* This may signal an error.  */
  setup_process_coding_systems (proc);

  pset_decoding_buf (p, empty_unibyte_string);
  eassert (p->decoding_carryover == 0);
  pset_encoding_buf (p, empty_unibyte_string);

  specpdl_ptr = specpdl + specpdl_count;

  return proc;
}