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. BUFFER may be also nil, meaning that this process is not associated with any buffer.

: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.

View in manual

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 buffer;
  Lisp_Object tem;
  int inchannel, outchannel;

  if (nargs == 0)
    return Qnil;
  CHECK_KEYWORD_ARGS (nargs);

  contact = Flist (nargs, args);

  Lisp_Object name = get_required_string_keyword_param (contact, QCname);
  proc = make_process (name);
  specpdl_ref 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;

  {
    Lisp_Object buffer_member = plist_member (contact, QCbuffer);
    if (NILP (buffer_member))
      buffer = name;
    else
      buffer = XCAR (XCDR (buffer_member));
  }
  if (!NILP (buffer))
    buffer = Fget_buffer_create (buffer, Qnil);
  pset_buffer (p, buffer);

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

  if (!EQ (p->command, Qt)
      && !EQ (p->filter, 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 = plist_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_ref_to_ptr (specpdl_count);

  return proc;
}