⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
    {      tem = Qnil;      openp (Vexec_path, program, "", &tem, 1);      if (NULL (tem))	report_file_error ("Searching for program", Fcons (program, Qnil));      new_argv[0] = XSTRING (tem)->data;    }  proc = make_process (name);  XPROCESS (proc)->childp = Qt;  XPROCESS (proc)->command_channel_p = Qnil;  XPROCESS (proc)->buffer = buffer;  XPROCESS (proc)->sentinel = Qnil;  XPROCESS (proc)->filter = Qnil;  XPROCESS (proc)->command = Flist (nargs - 2, args + 2);  create_process (proc, new_argv);  return proc;}create_process_1 (signo)     int signo;{#ifdef USG  /* USG systems forget handlers when they are used;     must reestablish each time */  signal (signo, create_process_1);#endif /* USG */}#if 0  /* This doesn't work; see the note before sigchld_handler.  */#ifdef USG#ifdef SIGCHLD/* Mimic blocking of signals on system V, which doesn't really have it.  *//* Nonzero means we got a SIGCHLD when it was supposed to be blocked.  */int sigchld_deferred;create_process_sigchld (){  signal (SIGCHLD, create_process_sigchld);  sigchld_deferred = 1;}#endif#endif#endifcreate_process (process, new_argv)     Lisp_Object process;     char **new_argv;{  int pid, inchannel, outchannel, forkin, forkout;  int sv[2];#ifdef SIGCHLD  int (*sigchld)();#endif  char **env;  int pty_flag = 0;  extern char **environ;#ifdef MAINTAIN_ENVIRONMENT  env = (char **) alloca (size_of_current_environ ());  get_current_environ (env);#else  env = environ;#endif /* MAINTAIN_ENVIRONMENT */  inchannel = outchannel = -1;#ifdef HAVE_PTYS  if (EQ (Vprocess_connection_type, Qt))    outchannel = inchannel = allocate_pty ();  if (inchannel >= 0)    {#ifndef USG      /* On USG systems it does not work to open	 the pty's tty here and then close and reopen it in the child.  */      forkout = forkin = open (pty_name, O_RDWR, 0);      if (forkin < 0)	report_file_error ("Opening pty", Qnil);#else      forkin = forkout = -1;#endif      pty_flag = 1;    }  else#endif /* HAVE_PTYS */#ifdef SKTPAIR    {      if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv) < 0)	report_file_error ("Opening socketpair", Qnil);      outchannel = inchannel = sv[0];      forkout = forkin = sv[1];    }#else /* not SKTPAIR */    {      pipe (sv);      inchannel = sv[0];      forkout = sv[1];      pipe (sv);      outchannel = sv[1];      forkin = sv[0];    }#endif /* not SKTPAIR */#if 0  /* Replaced by close_process_descs */  set_exclusive_use (inchannel);  set_exclusive_use (outchannel);#endif/* Stride people say it's a mystery why this is needed   as well as the O_NDELAY, but that it fails without this.  */#ifdef STRIDE  {    int one = 1;    ioctl (inchannel, FIONBIO, &one);  }#endif#ifdef O_NONBLOCK  fcntl (inchannel, F_SETFL, O_NONBLOCK);#else#ifdef O_NDELAY  fcntl (inchannel, F_SETFL, O_NDELAY);#endif#endif  /* Record this as an active process, with its channels.     As a result, child_setup will close Emacs's side of the pipes.  */  chan_process[inchannel] = process;  XFASTINT (XPROCESS (process)->infd) = inchannel;  XFASTINT (XPROCESS (process)->outfd) = outchannel;  XPROCESS (process)->pty_flag = (pty_flag ? Qt : Qnil);  XPROCESS (process)->status = Qrun;  /* Delay interrupts until we have a chance to store     the new fork's pid in its process structure */#ifdef SIGCHLD#ifdef BSD4_1  sighold (SIGCHLD);#else /* not BSD4_1 */#ifdef HPUX  sigsetmask (1 << (SIGCHLD - 1));#else /* not HPUX */#if defined (BSD) || defined (UNIPLUS)  sigsetmask (1 << (SIGCHLD - 1));#else /* ordinary USG */#if 0  sigchld_deferred = 0;  sigchld = (int (*)()) signal (SIGCHLD, create_process_sigchld);#endif#endif /* ordinary USG */#endif /* not HPUX */#endif /* not BSD4_1 */#endif /* SIGCHLD */  /* Until we store the proper pid, enable sigchld_handler     to recognize an unknown pid as standing for this process.  */  XSETINT (XPROCESS (process)->pid, -1);  {    /* child_setup must clobber environ on systems with true vfork.       Protect it from permanent change.  */    char **save_environ = environ;    pid = vfork ();    if (pid == 0)      {	int xforkin = forkin;	int xforkout = forkout;#if 0 /* This was probably a mistake--it duplicates code later on,	 but fails to handle all the cases.  */	/* Make SIGCHLD work again in the child.  */	sigsetmask (0);#endif	/* Make the pty be the controlling terminal of the process.  */#ifdef HAVE_PTYS	/* First, disconnect its current controlling terminal.  */#ifdef HAVE_SETSID	setsid ();#ifdef TIOCSCTTY	/* Make the pty's terminal the controlling terminal.  */	if (pty_flag && (ioctl (xforkin, TIOCSCTTY, 0) < 0))	  abort ();#endif#else /* not HAVE_SETSID */#ifdef USG	/* It's very important to call setpgrp() here and no time	   afterwards.  Otherwise, we lose our controlling tty which	   is set when we open the pty. */	setpgrp ();#endif /* USG */#endif /* not HAVE_SETSID */#ifdef TIOCNOTTY	/* In 4.3BSD, the TIOCSPGRP bug has been fixed, and now you	   can do TIOCSPGRP only to the process's controlling tty.  */	if (pty_flag)	  {	    /* I wonder: would just ioctl (0, TIOCNOTTY, 0) work here? 	       I can't test it since I don't have 4.3.  */	    int j = open ("/dev/tty", O_RDWR, 0);	    ioctl (j, TIOCNOTTY, 0);	    close (j);#ifndef USG	    /* In order to get a controlling terminal on some versions	       of BSD, it is necessary to put the process in pgrp 0	       before it opens the terminal.  */	    setpgrp (0, 0);#endif	  }#endif /* TIOCNOTTY */#if !defined (RTU) && !defined (UNIPLUS)/*** There is a suggestion that this ought to be a     conditional on TIOCSPGRP.  */	/* Now close the pty (if we had it open) and reopen it.	   This makes the pty the controlling terminal of the subprocess.  */	if (pty_flag)	  {	    /* I wonder if close (open (pty_name, ...)) would work?  */	    if (xforkin >= 0)	      close (xforkin);	    xforkout = xforkin = open (pty_name, O_RDWR, 0);	    if (xforkin < 0)	      abort ();	  }#endif /* not UNIPLUS and not RTU */#ifdef SETUP_SLAVE_PTY	SETUP_SLAVE_PTY;#endif /* SETUP_SLAVE_PTY */#ifdef AIX	/* On AIX, we've disabled SIGHUP above once we start a child on a pty.	   Now reenable it in the child, so it will die when we want it to.  */	if (pty_flag)	  signal (SIGHUP, SIG_DFL);#endif#endif /* HAVE_PTYS */#ifdef SIGCHLD#ifdef BSD4_1	sigrelse (SIGCHLD);#else /* not BSD4_1 */#if defined (BSD) || defined (UNIPLUS) || defined (HPUX)	sigsetmask (0);#else /* ordinary USG */	signal (SIGCHLD, sigchld);#endif /* ordinary USG */#endif /* not BSD4_1 */#endif /* SIGCHLD */	child_setup_tty (xforkout);	child_setup (xforkin, xforkout, xforkout, new_argv, env);      }    environ = save_environ;  }  if (pid < 0)    {      remove_process (process);      report_file_error ("Doing vfork", Qnil);    }  XFASTINT (XPROCESS (process)->pid) = pid;  FD_SET (inchannel, &input_wait_mask);  /* If the subfork execv fails, and it exits,     this close hangs.  I don't know why.     So have an interrupt jar it loose.  */  stop_polling ();  signal (SIGALRM, create_process_1);  alarm (1);  if (forkin >= 0)    close (forkin);  alarm (0);  start_polling ();  if (forkin != forkout && forkout >= 0)    close (forkout);#ifdef SIGCHLD#ifdef BSD4_1  sigrelse (SIGCHLD);#else /* not BSD4_1 */#if defined (BSD) || defined (UNIPLUS) || defined (HPUX)  sigsetmask (0);#else /* ordinary USG */#if 0  signal (SIGCHLD, sigchld);  /* Now really handle any of these signals     that came in during this function.  */  if (sigchld_deferred)    kill (getpid (), SIGCHLD);#endif#endif /* ordinary USG */#endif /* not BSD4_1 */#endif /* SIGCHLD */}#ifdef HAVE_SOCKETS/* open a TCP network connection to a given HOST/SERVICE.  Treated   exactly like a normal process when reading and writing.  Only   differences are in status display and process deletion.  A network   connection has no PID; you cannot signal it.  All you can do is   deactivate and close it via delete-process */DEFUN ("open-network-stream", Fopen_network_stream, Sopen_network_stream,        4, 4, 0,   "Open a TCP connection for a service to a host.\n\Returns a subprocess-object to represent the connection.\n\Input and output work as for subprocesses; `delete-process' closes it.\n\Args are NAME BUFFER HOST SERVICE.\n\NAME is name for process.  It is modified if necessary to make it unique.\n\BUFFER is the buffer (or buffer-name) to associate with the process.\n\ Process output goes at end of that buffer, unless you specify\n\ an output stream or filter function to handle the output.\n\ BUFFER may be also nil, meaning that this process is not associated\n\ with any buffer\n\Third arg is name of the host to connect to.\n\Fourth arg SERVICE is name of the service desired, or an integer\n\ specifying a port number to connect to.")   (name, buffer, host, service)      Lisp_Object name, buffer, host, service;{  Lisp_Object proc;  register int i;  struct sockaddr_in address;  struct servent *svc_info;  struct hostent *host_info;  int s, outch, inch;  char errstring[80];  int port;  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;  GCPRO4 (name, buffer, host, service);  CHECK_STRING (name, 0);  CHECK_STRING (host, 0);  if (XTYPE(service) == Lisp_Int)    port = htons ((unsigned short) XINT (service));  else    {      CHECK_STRING (service, 0);      svc_info = getservbyname (XSTRING (service)->data, "tcp");      if (svc_info == 0)	error ("Unknown service \"%s\"", XSTRING (service)->data);      port = svc_info->s_port;    }  host_info = gethostbyname (XSTRING (host)->data);  if (host_info == 0)    error ("Unknown host \"%s\"", XSTRING(host)->data);  bzero (&address, sizeof address);  bcopy (host_info->h_addr, (char *) &address.sin_addr, host_info->h_length);  address.sin_family = host_info->h_addrtype;  address.sin_port = port;  s = socket (host_info->h_addrtype, SOCK_STREAM, 0);  if (s < 0)     report_file_error ("error creating socket", Fcons (name, Qnil));  if (connect (s, &address, sizeof address) == -1)    {      close (s);      error ("Host \"%s\" not responding", XSTRING (host)->data);    }  inch = s;  outch = dup (s);  if (outch < 0)     report_file_error ("error duplicating socket", Fcons (name, Qnil));  if (!NULL (buffer))    buffer = Fget_buffer_create (buffer);  proc = make_process (name);  chan_process[inch] = proc;#ifdef O_NONBLOCK  fcntl (inch, F_SETFL, O_NONBLOCK);#else#ifdef O_NDELAY  fcntl (inch, F_SETFL, O_NDELAY);#endif#endif  XPROCESS (proc)->childp = host;  XPROCESS (proc)->command_channel_p = Qnil;  XPROCESS (proc)->buffer = buffer;  XPROCESS (proc)->sentinel = Qnil;  XPROCESS (proc)->filter = Qnil;  XPROCESS (proc)->command = Qnil;  XPROCESS (proc)->pid = Qnil;  XPROCESS (proc)->kill_without_query = Qt;  XFASTINT (XPROCESS (proc)->infd) = s;  XFASTINT (XPROCESS (proc)->outfd) = outch;  XPROCESS (proc)->status = Qrun;  FD_SET (inch, &input_wait_mask);  UNGCPRO;  return proc;}#endif	/* HAVE_SOCKETS */deactivate_process (proc)     Lisp_Object proc;{  register int inchannel, outchannel;  register struct Lisp_Process *p = XPROCESS (proc);  inchannel = XFASTINT (p->infd);  outchannel = XFASTINT (p->outfd);  if (inchannel)    {      /* Beware SIGCHLD hereabouts. */      flush_pending_output (inchannel);      close (inchannel);      if (outchannel  &&  outchannel != inchannel) 	close (outchannel);      XFASTINT (p->infd) = 0;      XFASTINT (p->outfd) = 0;      chan_process[inchannel] = Qnil;      FD_CLR (inchannel, &input_wait_mask);    }}/* Close all descriptors currently in use for communication   with subprocess.  This is used in a newly-forked subprocess   to get rid of irrelevant descriptors.  */close_process_descs (){  int i;  for (i = 0; i < MAXDESC; i++)    {      Lisp_Object process;      process = chan_process[i];      if (!NULL (process))	{	  int in = XFASTINT (XPROCESS (process)->infd);	  int out = XFASTINT (XPROCESS (process)->outfd);	  close (in);	  if (in != out)	    close (out);	}    }}DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output,  0, 1, 0,  "Allow any pending output from subprocesses to be read by Emacs.\n\It is read into the process' buffers or given to their filter functions.\n\Non-nil arg PROCESS means do not return until some output has been received\n\from PROCESS.")  (proc)     register Lisp_Object proc;{  if (NULL (proc))    wait_reading_process_input (-1, 0, 0);  else    {      proc = get_process (proc);      wait_reading_process_input (0, XPROCESS (proc), 0);    }  return Qnil;}/* This variable is different from waiting_for_input in keyboard.c.   It is used to communicate to a lisp process-filter/sentinel (via the   function Fwaiting_for_user_input_p below) whether emacs was waiting   for user-input when that process-filter was called.   waiting_for_input cannot be used as that is by definition 0 when   lisp code is being evalled */static int waiting_for_user_input_p;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -