1 /* -*- mode: C; mode: fold; -*- */
2 /* Copyright (c) 1992, 1998, 2000, 2002, 2003, 2004, 2005, 2006 John E. Davis
3  * This file is part of JED editor library source.
4  *
5  * You may distribute this file under the terms the GNU General Public
6  * License.  See the file COPYING for more information.
7  */
8 #include "config.h"
9 #include "jed-feat.h"
10 
11 #include <stdio.h>
12 
13 #if defined(__QNX__) && defined(__WATCOMC__)
14 # include <env.h>
15 #endif
16 
17 #if JED_HAS_SUBPROCESSES
18 /* Everything else here is in this '#if' */
19 
20 /*{{{ Include Files */
21 
22 #include <string.h>
23 #include <errno.h>
24 #include <signal.h>
25 
26 #ifdef __os2__
27 # include <io.h>
28 # include <process.h>
29 #endif
30 
31 #if defined(__BORLANDC__) && (__BORLANDC__>>8)==5 /* [JMS:MISC] - needed for open/close in BC v5 */
32 # include <io.h>
33 # include <dos.h>
34 #endif
35 
36 #include <slang.h>
37 
38 #include "jdmacros.h"
39 
40 #ifdef HAVE_UNISTD_H
41 # include <unistd.h>
42 # include <fcntl.h>
43 #endif
44 
45 #include <sys/types.h>
46 #ifdef HAVE_SYS_WAIT_H
47 # include <sys/wait.h>
48 #endif
49 #ifdef HAVE_SYS_FCNTL_H
50 # include <sys/fcntl.h>
51 #endif
52 #ifndef WEXITSTATUS
53 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
54 #endif
55 #ifndef WIFEXITED
56 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
57 #endif
58 
59 #ifdef REALLY_HAVE_TERMIOS_H
60 # if !defined(__os2__) && !defined(__APPLE__)
61 #  define USE_PTY
62 # endif
63 #endif
64 
65 #include "buffer.h"
66 #include "ins.h"
67 #include "ledit.h"
68 #include "misc.h"
69 #include "jprocess.h"
70 #include "paste.h"
71 #include "sysdep.h"
72 #include "sig.h"
73 #include "cmds.h"
74 
75 /*}}}*/
76 
77 #define MAX_TTY_SLAVE_NAME	256
78 
79 int Num_Subprocesses;
80 int Max_Subprocess_FD;
81 
82 /* This also servers as a lookup table for actual system pids to the
83  * pseudo-pids used here.  See, e.g., jed_get_child_status for usage in this
84  * fashion.
85  */
86 int Subprocess_Read_fds [MAX_PROCESSES][3];
87 /* 0 is actual fd, 1 is our rep, 2 will be set to 1 if an EIO is present */
88 
89 volatile int Child_Status_Changed_Flag;/* if this is non-zero, editor
90 					* should call the appropriate
91 					* function below to call slang
92 					* handlers.
93 					*/
94 typedef struct /*{{{*/
95 {
96    int flags;			       /* This is zero if the process is gone
97 					* and the status is nolonger avail */
98 #define PROCESS_RUNNING		1
99 #define PROCESS_STOPPED		2
100 #define PROCESS_ALIVE		3
101 #define PROCESS_EXITED		4
102 #define PROCESS_SIGNALLED	8
103    int return_status;		       /* This value depends on the flags */
104 
105    int status_changed;		       /* non-zero if status changed. */
106    int rd, wd;			       /* read/write descriptors */
107    int is_pty;
108    int pid;			       /* real process pid */
109    int output_type;
110 #define PROCESS_USE_BUFFER	1
111 #define PROCESS_USE_SLANG	2
112 #define PROCESS_SAVE_POINT	4
113 #define PROCESS_AT_POINT	8
114    Buffer *buffer;		       /* buffer associated with process */
115    SLang_Name_Type *slang_fun;	       /* function to pass output to */
116    SLang_MMT_Type *umark;	       /* marks point of last output */
117    int process_flags;
118 #define USE_CURRENT_BUFFER	0x1    /* use the current buffer instead of
119 					* the one associated with the process
120 					*/
121 
122    SLang_Name_Type *status_change_fun; /* call this if process status changes
123 					* The function should be declared like
124 					* define fun (pid, flags, status);
125 					* The flags parameter corresponds to
126 					* the flags field in this struct and
127 					* the pid is NOT the pid of this struct.
128 					* status depends upon flags.
129 					*/
130    int quietly_kill_on_exit;
131 }
132 /*}}}*/
133 Process_Type;
134 
135 static Process_Type Processes[MAX_PROCESSES];
136 
signal_safe_close(int fd)137 static int signal_safe_close (int fd)
138 {
139    while (-1 == close (fd))
140      {
141 #ifdef EINTR
142 	if (errno == EINTR)
143 	  continue;
144 #endif
145 	return -1;
146      }
147    return 0;
148 }
149 
signal_safe_open(char * file,int mode)150 static int signal_safe_open (char *file, int mode)
151 {
152    int fd;
153 
154    while (-1 == (fd = open (file, mode)))
155      {
156 #ifdef EINTR
157 	if (errno == EINTR)
158 	  continue;
159 #endif
160 #ifdef EAGAIN
161 	if (errno == EAGAIN)
162 	  {
163 	     sleep (1);
164 	     continue;
165 	  }
166 #endif
167 	return -1;
168      }
169    return fd;
170 }
171 
signal_safe_fcntl(int fd,int cmd,int arg)172 static int signal_safe_fcntl (int fd, int cmd, int arg)
173 {
174    int ret;
175 
176    while (-1 == (ret = fcntl (fd, cmd, arg)))
177      {
178 #ifdef EINTR
179 	if (errno == EINTR)
180 	  continue;
181 #endif
182 #ifdef EAGAIN
183 	if (errno == EAGAIN)
184 	  {
185 	     sleep (1);
186 	     continue;
187 	  }
188 #endif
189 	return -1;
190      }
191    return ret;
192 }
193 
signal_safe_dup2(int fd1,int fd2)194 static int signal_safe_dup2 (int fd1, int fd2)
195 {
196    while (-1 == dup2 (fd1, fd2))
197      {
198 #ifdef EINTR
199 	if (errno == EINTR)
200 	  continue;
201 #endif
202 	return -1;
203      }
204    return 0;
205 }
206 
207 
get_process(int fd)208 static Process_Type *get_process (int fd) /*{{{*/
209 {
210    Process_Type *p;
211 
212    if ((fd >= 0) && (fd < MAX_PROCESSES)
213        && (p = &Processes[fd], p->flags != 0))
214      return p;
215 
216    jed_verror ("process '%d' does not exist.", fd);
217    return NULL;
218 }
219 
220 /*}}}*/
221 
call_slang_status_change_hook(Process_Type * p)222 static void call_slang_status_change_hook (Process_Type *p) /*{{{*/
223 {
224    Buffer *cbuf = CBuf;
225    if ((p->status_change_fun == NULL) || (p->buffer == NULL)) return;
226 
227    cbuf->locked++;
228    if (0 == (p->process_flags & USE_CURRENT_BUFFER))
229      switch_to_buffer (p->buffer);
230    SLang_push_integer ((int) (p - Processes));
231    SLang_push_integer (p->flags);
232    SLang_push_integer (p->return_status);
233    SLexecute_function (p->status_change_fun);
234    touch_screen ();
235    if ((0 == (p->process_flags & USE_CURRENT_BUFFER)) && (CBuf != cbuf))
236      switch_to_buffer (cbuf);
237    cbuf->locked--;
238 }
239 
240 /*}}}*/
241 
242 #if 1
jed_signal_process(int * fd,int * sig)243 int jed_signal_process (int *fd, int *sig) /*{{{*/
244 {
245    Process_Type *p;
246    if (NULL == (p = get_process (*fd))) return -1;
247 
248    kill (p->pid, *sig);
249    return 0;
250 }
251 
jed_signal_fg_process(int * fd,int * sig)252 int jed_signal_fg_process (int *fd, int *sig) /*{{{*/
253 {
254    int pid;
255 
256    Process_Type *p;
257    if (NULL == (p = get_process (*fd))) return -1;
258 
259 #ifdef HAVE_TCGETPGRP
260    pid = tcgetpgrp (p->rd);
261    if (pid == -1)
262 #endif
263      pid = p->pid;
264 
265    (void) kill (-pid, *sig);
266    return 0;
267 }
268 
269 /*}}}*/
270 #endif
271 
close_rd_and_wd(Process_Type * p)272 static void close_rd_and_wd (Process_Type *p) /*{{{*/
273 {
274    if (p->rd != -1)
275      {
276 	signal_safe_close (p->rd);
277 	p->rd = -1;
278      }
279    if (p->wd != -1)
280      {
281 	if (p->is_pty == 0) signal_safe_close (p->wd);
282 	p->wd = -1;
283      }
284 }
285 
286 /*}}}*/
287 
288 /* This routine is called to clean up after the process has exited.
289  * After getting the exit status, we call a slang hook and if the
290  * process is dead, adjust the process arrays to delete the process.
291  */
get_process_status(Process_Type * p)292 static void get_process_status (Process_Type *p) /*{{{*/
293 {
294    int i;
295    int fd, slfd;
296 
297    /* Call slang to let it know what happened.  Do it first before we
298     * really shut it down to give the hook a chance to query the state of
299     * it before it returns.
300     */
301    call_slang_status_change_hook (p);
302    if (p->flags & PROCESS_ALIVE) return;
303 
304    /* Process is dead.  So perform clean up. */
305    close_rd_and_wd (p);
306 
307    if (p->buffer != NULL) p->buffer->subprocess = 0;
308    slfd = (int) (p - Processes);
309 
310    if (p->umark != NULL) SLang_free_mmt (p->umark);
311 
312 #if SLANG_VERSION > 10400
313    SLang_free_function (p->slang_fun);
314    SLang_free_function (p->status_change_fun);
315 #endif
316 
317    memset ((char *)p, 0, sizeof (Process_Type));
318    p->rd = p->wd = -1;
319 
320    /* Adjust the array of read descriptors */
321 
322    i = 0;
323 
324    while (i < Num_Subprocesses)
325      {
326 	if (Subprocess_Read_fds[i][1] == slfd)
327 	  break;
328 
329 	i++;
330      }
331    fd = Subprocess_Read_fds [i][0];
332 
333    Num_Subprocesses--;
334    while (i < Num_Subprocesses)
335      {
336 	Subprocess_Read_fds[i][0] = Subprocess_Read_fds[i + 1][0];
337 	Subprocess_Read_fds[i][1] = Subprocess_Read_fds[i + 1][1];
338 	Subprocess_Read_fds[i][2] = Subprocess_Read_fds[i + 1][2];
339 	i++;
340      }
341 
342 
343    if (Max_Subprocess_FD == fd)
344      {
345 	i = 0;
346 	fd = -1;
347 	while (i < Num_Subprocesses)
348 	  {
349 	     if (Subprocess_Read_fds[i][0] > fd)
350 	       fd = Subprocess_Read_fds[i][0];
351 	     i++;
352 	  }
353 	Max_Subprocess_FD = fd;
354      }
355 }
356 
357 /*}}}*/
358 
jed_close_process(int * fd)359 int jed_close_process (int *fd) /*{{{*/
360 {
361    Process_Type *p;
362 
363    if (NULL == (p = get_process (*fd))) return -1;
364 
365    close_rd_and_wd (p);
366 
367    kill (-p->pid, SIGINT);
368 
369    /* This is probably a bad idea.  It is better to check to see if it still
370     * around and the set a flag indicating that the user wants it killed.
371     */
372 
373    /* Did we kill it? Make sure. */
374    kill (-p->pid, SIGKILL);
375 
376    if (p->buffer != NULL) p->buffer->subprocess = 0;
377 
378    /* This next function wraps things up --- no need to.  Let handler do it. */
379    /* get_process_status (p); */
380    return 0;
381 }
382 
383 /*}}}*/
384 
jed_kill_process(int fd)385 void jed_kill_process (int fd) /*{{{*/
386 {
387    /* This function is called when the buffer is going to be destroyed */
388    Processes[fd].buffer = NULL;
389    jed_close_process (&fd);
390 }
391 
392 /*}}}*/
393 
jed_get_child_status(void)394 void jed_get_child_status (void) /*{{{*/
395 {
396    Process_Type *p, *pmax;
397 
398    Ignore_User_Abort++;
399    if (SLang_get_error ())
400      {
401 	Ignore_User_Abort--;
402 	return;
403      }
404 
405    /* FIXME: We should block SIGCHLD before trying to access this flag,
406     * or anything in this function for that matter.
407     */
408    Child_Status_Changed_Flag--;
409 
410    get_process_input (&Number_Zero);
411    p = Processes;
412    pmax = p + MAX_PROCESSES;
413 
414    while (p < pmax)
415      {
416 	if (p->flags && p->status_changed)
417 	  {
418 	     read_process_input ((int) (p - Processes));
419 	     p->status_changed--;
420 	     get_process_status (p);
421 	  }
422 	p++;
423      }
424 
425    Ignore_User_Abort--;
426 
427 }
428 
429 /*}}}*/
430 
child_signal_handler(int sig)431 static void child_signal_handler (int sig) /*{{{*/
432 {
433    int status;
434    int found;
435    int save_errno = errno;
436 
437    (void) sig;
438 
439    do
440      {
441 	Process_Type *p, *pmax;
442 
443 	found = 0;
444 
445 	p = Processes;
446 	pmax = p + MAX_PROCESSES;
447 	while (p < pmax)
448 	  {
449 	     int pid;
450 
451 	     if ((pid = p->pid) <= 0)
452 	       {
453 		  p++;
454 		  continue;
455 	       }
456 
457 	     while ((-1 == (pid = (int) waitpid (p->pid, &status, WNOHANG | WUNTRACED)))
458 		    && (errno == EINTR))
459 	       ;
460 
461 	     if (p->pid == pid)
462 	       {
463 		  int return_status;
464 
465 		  found++;
466 
467 		  if (WIFEXITED (status))
468 		    {
469 		       return_status = WEXITSTATUS (status);
470 		       status = PROCESS_EXITED;
471 		    }
472 		  else if (WIFSIGNALED (status))
473 		    {
474 		       return_status = WTERMSIG (status);
475 		       status = PROCESS_SIGNALLED;
476 		    }
477 #ifdef WIFSTOPPED
478 		  else if (WIFSTOPPED (status))
479 		    {
480 		       return_status = WSTOPSIG(status);
481 		       status = PROCESS_STOPPED;
482 		    }
483 #endif
484 		  p->flags = status;
485 		  p->status_changed++;
486 		  p->return_status = return_status;
487 	       }
488 	     p++;
489 	  }
490      }
491    while (found != 0);
492 
493    SLsignal_intr (SIGCHLD, child_signal_handler);
494    errno = save_errno;
495    Child_Status_Changed_Flag++;
496 }
497 
498 /*}}}*/
499 
500 #ifdef USE_PTY
501 # include "pty.c"
502 #endif
503 
get_master_slave_fds(int * slave_read,int * slave_write,int * master_read,int * master_write,char * slave_tty_name,int * is_pty,int want_pty)504 static int get_master_slave_fds (int *slave_read, int *slave_write,
505 				 int *master_read, int *master_write,
506 				 char *slave_tty_name, int *is_pty,
507 				 int want_pty)
508 {
509 #ifdef USE_PTY
510    if (want_pty)
511      {
512 	int master;
513 
514 	if (-1 == pty_open_master_pty (&master, slave_tty_name))
515 	  return -1;
516 
517 	*master_read = *master_write = master;
518 	*slave_read = *slave_write = -1;
519 
520 	*is_pty = 1;
521      }
522    else
523      {
524 #endif
525 	int fds0[2], fds1[2];
526 
527 	if (-1 == pipe (fds0))
528 	  return -1;
529 
530 	if (-1 == pipe (fds1))
531 	  {
532 	     signal_safe_close (fds0[0]);
533 	     signal_safe_close (fds0[1]);
534 	     return -1;
535 	  }
536 	*master_read = fds0[0];
537 	*slave_write = fds0[1];
538 	*master_write = fds1[1];
539 	*slave_read = fds1[0];
540 	*slave_tty_name = 0;
541 	*is_pty = 0;
542 #ifdef USE_PTY
543      }
544 #endif
545    return 0;
546 }
547 
548 
my_setenv(char * what,char * value)549 static void my_setenv (char *what, char *value)
550 {
551 #ifdef HAVE_SETENV
552    (void) setenv (what, value, 1);
553 #else
554 # ifdef HAVE_PUTENV
555    char buf[512];
556    SLsnprintf (buf, sizeof (buf), "%s=%s", what, value);
557    (void) putenv (buf);
558 # endif
559 #endif
560 }
561 
my_unsetenv(char * what)562 static void my_unsetenv (char *what)
563 {
564 #ifdef HAVE_UNSETENV
565    unsetenv (what);
566 #endif
567 }
568 
569 
570 #ifdef __os2__
open_process(char * pgm,char ** argv,int want_pty)571 static int open_process (char *pgm, char **argv, int want_pty) /*{{{*/
572 {
573     int val;
574     int pd;
575    int slave_read, slave_write, master_read, master_write, org_fd[3];
576    int pid, i;
577    Process_Type *p;
578    SLang_MMT_Type *mmt;
579    char slave_tty_name [MAX_TTY_SLAVE_NAME];
580    int max_write_tries;
581    SLSig_Fun_Type *sig_orig[NSIG];
582 
583    if (Jed_Secure_Mode)
584      {
585 	msg_error ("Access to shell denied.");
586 	return -1;
587      }
588 
589    pd = 0; while ((pd < MAX_PROCESSES) && Processes[pd].flags) pd++;
590    if (pd == MAX_PROCESSES) return -1;
591    p = &Processes[pd];
592 
593    SLMEMSET ((char *) p, 0, sizeof (Process_Type));
594 
595    if (NULL == (mmt = jed_make_user_object_mark ()))
596      return -1;
597 
598    if (-1 == get_master_slave_fds (&slave_read, &slave_write,
599 				   &master_read, &master_write,
600 				   slave_tty_name, &p->is_pty, want_pty))
601      {
602 	SLang_free_mmt (mmt);
603 	return -1;
604      }
605 
606    SLsignal_intr (SIGCHLD, child_signal_handler);
607 
608      {
609 	char ch;
610 
611 	/* At this point the slave tty is in raw mode.  Make sure that
612 	 * the read to synchronize with the parent blocks.
613 	 */
614 	val = signal_safe_fcntl (slave_read, F_GETFL, 0);
615 	signal_safe_fcntl (slave_read, F_SETFL, val & ~O_NONBLOCK);
616 
617 	signal_safe_fcntl (slave_read, F_SETFL, val);
618 
619 
620 	org_fd[0] = dup(0);
621 	org_fd[1] = dup(1);
622 	org_fd[2] = dup(2);
623 
624 	signal_safe_close (0);
625 	signal_safe_close (1);
626 	signal_safe_close (2);
627 
628 	signal_safe_dup2(slave_read, 0);	/* stdin */
629 	signal_safe_dup2 (slave_write, 1);	/* stdout */
630 	signal_safe_dup2 (slave_write, 2);	/* stderr */
631 
632 	signal_safe_close (slave_read);
633 	signal_safe_close (slave_write);
634 	setvbuf (stdout, NULL, _IONBF, 0);
635 
636 	for (i=1 ; i<NSIG ; i++)
637 	  sig_orig[i] = SLsignal(i, SIG_DFL);
638 
639 	pid = spawnvp (P_SESSION | P_MINIMIZE | P_BACKGROUND, pgm, argv);
640 
641 	for (i=1 ; i<NSIG ; i++)
642 	  SLsignal(i, sig_orig[i]);
643 	signal_safe_close (0);
644 	signal_safe_close (1);
645 	signal_safe_close (2);
646 	signal_safe_dup2(org_fd[0], 0);
647 	signal_safe_dup2(org_fd[1], 1);
648 	signal_safe_dup2(org_fd[2], 2);
649 	signal_safe_close (org_fd[0]);
650 	signal_safe_close (org_fd[1]);
651 	signal_safe_close (org_fd[2]);
652 	signal_safe_close (slave_read);
653 	signal_safe_close (slave_write);
654 
655 	if (pid < 0)
656 	  {
657 	     signal_safe_close (master_read);
658 	     signal_safe_close (master_write);
659 	     p->flags = 0;
660 	     SLang_free_mmt (mmt);
661 	     return -1;
662 
663 	  }
664 	p->pid = pid;
665      }
666 
667 
668 
669    p->flags = PROCESS_RUNNING;
670    p->rd = master_read;
671    p->wd = master_write;
672 
673    Subprocess_Read_fds[Num_Subprocesses][0] = master_read;
674    Subprocess_Read_fds[Num_Subprocesses][1] = pd;
675    Subprocess_Read_fds[Num_Subprocesses][2] = 0;
676    if (master_read > Max_Subprocess_FD) Max_Subprocess_FD = master_read;
677    Num_Subprocesses += 1;
678 
679    val = signal_safe_fcntl (master_read, F_GETFL, 0);
680    val |= O_NONBLOCK;
681    signal_safe_fcntl (master_read, F_SETFL, val);
682 
683    CBuf->subprocess = pd + 1;
684 
685    /* Processing options */
686    p->buffer = CBuf;
687    p->output_type = PROCESS_USE_BUFFER;
688    p->umark = mmt;
689    SLang_inc_mmt (mmt);	       /* tell slang we are keeping a copy */
690 
691    return pd;
692 }
693 /*}}}*/
694 #else	/* unix and compatible OS */
695 
696 static volatile int SigUsr_Flag;
sigusr_handler(int sig)697 static void sigusr_handler (int sig)
698 {
699    (void) sig;
700 
701    SigUsr_Flag = 1;
702 }
703 
704 static sigset_t Old_Signal_Mask, Zero_Signal_Mask;
705 
init_child_parent_sync(void)706 static int init_child_parent_sync (void)
707 {
708    sigset_t new_mask;
709 
710    if (SIG_ERR == SLsignal (SIGUSR1, sigusr_handler))
711      return -1;
712 
713    /* Get a copy of the current signal mask */
714    while ((-1 == sigprocmask (SIG_BLOCK, NULL, &Zero_Signal_Mask))
715 	  && (errno == EINTR))
716      ;
717    /* and remove SIGUSR1 from it. */
718    sigdelset (&Zero_Signal_Mask, SIGUSR1);
719 
720    /* Add SIGUSR1 to the set of currently blocked signals */
721    sigemptyset (&new_mask);
722    sigaddset (&new_mask, SIGUSR1);
723 
724    while ((-1 == sigprocmask (SIG_BLOCK, &new_mask, &Old_Signal_Mask))
725 	  && (errno == EINTR))
726      ;
727 
728    SigUsr_Flag = 0;
729    return 0;
730 }
731 
wait_for_parent(void)732 static void wait_for_parent (void)
733 {
734    /* Suspend this process and wait for a signal.  All signals are allowed
735     * here.
736     */
737    while (SigUsr_Flag == 0)
738      sigsuspend (&Zero_Signal_Mask);
739 }
740 
tell_parent_to_go(pid_t pid)741 static void tell_parent_to_go (pid_t pid)
742 {
743    SigUsr_Flag = 0;
744    kill (pid, SIGUSR1);
745 
746    while ((-1 == sigprocmask (SIG_SETMASK, &Old_Signal_Mask, NULL))
747 	  && (errno == EINTR))
748      ;
749 }
750 
tell_child_to_go(pid_t pid)751 static void tell_child_to_go (pid_t pid)
752 {
753    SigUsr_Flag = 0;
754    kill (pid, SIGUSR1);
755 
756    /* Now wait for the child to setup the pty */
757    while (SigUsr_Flag == 0)
758      sigsuspend (&Zero_Signal_Mask);
759 
760    while ((-1 == sigprocmask (SIG_SETMASK, &Old_Signal_Mask, NULL))
761 	  && (errno == EINTR))
762      ;
763 }
764 
set_non_blocking_io(int fd)765 static int set_non_blocking_io (int fd)
766 {
767    int val;
768 
769    val = signal_safe_fcntl (fd, F_GETFL, 0);
770    return signal_safe_fcntl (fd, F_SETFL, val | O_NONBLOCK);
771 }
772 
773 #ifdef SIGTRAP
sigtrap_handler(int sig)774 static void sigtrap_handler (int sig)
775 {
776    (void) sig;
777 }
778 #endif
779 
open_process(char * pgm,char ** argv,int want_pty)780 static int open_process (char *pgm, char **argv, int want_pty) /*{{{*/
781 {
782    int pd;
783    int slave_read, slave_write, master_read, master_write;
784    int pid, jed_pid, i;
785    Process_Type *p;
786    SLang_MMT_Type *mmt;
787    char slave_tty_name [MAX_TTY_SLAVE_NAME];
788 
789    if (Jed_Secure_Mode)
790      {
791 	msg_error ("Access to shell denied.");
792 	return -1;
793      }
794 
795    pd = 0; while ((pd < MAX_PROCESSES) && Processes[pd].flags) pd++;
796    if (pd == MAX_PROCESSES) return -1;
797    p = &Processes[pd];
798 
799    SLMEMSET ((char *) p, 0, sizeof (Process_Type));
800 
801    if (NULL == (mmt = jed_make_user_object_mark ()))
802      return -1;
803 
804    if (-1 == get_master_slave_fds (&slave_read, &slave_write,
805 				   &master_read, &master_write,
806 				   slave_tty_name, &p->is_pty, want_pty))
807      {
808 	SLang_free_mmt (mmt);
809 	return -1;
810      }
811 
812    SLsignal_intr (SIGCHLD, child_signal_handler);
813 
814    jed_pid = getpid ();		       /* used by slave */
815 
816    if ((-1 == init_child_parent_sync ())
817        || ((pid = fork ()) < 0))
818      {
819 	signal_safe_close (master_read);
820 	if (p->is_pty == 0)
821 	  {
822 	     signal_safe_close (slave_read);
823 	     signal_safe_close (master_write);
824 	     signal_safe_close (slave_write);
825 	  }
826 	p->flags = 0;
827 	SLang_free_mmt (mmt);
828 	return -1;
829      }
830    p->pid = pid;
831 
832    /* Make the child its own process group leader.  Do it here too because
833     * we are not sure which one will run first.  We have to do this because
834     * if not, a ^G will be sent to ALL child subprocesses possibly killing
835     * them unless they catch the signal.  This call means that the INTR signal
836     * will not be sent to any child processes sent by this fork.
837     */
838    if (p->is_pty == 0)
839      setpgid(pid, pid);
840 
841    if (pid == 0)
842      {
843 	/* child code */
844 	wait_for_parent ();
845 
846 	if (p->is_pty == 0)
847 	  signal_safe_close (master_write);	       /* close write end of 0 */
848 	signal_safe_close (master_read);	       /* close read end of 1 */
849 
850 #ifdef USE_PTY
851 	/* Call set setsid so that the child will become the session leader.
852 	 * This has the side effect that we will loose the controlling
853 	 * terminal.  For this reason, the pty slave is opened after setsid
854 	 * and then for good luck, the controlling terminal is set
855 	 * via the TIOCSCTTY ioctl.
856 	 */
857 	if (p->is_pty)
858 	  {
859 	     if (-1 == setsid ())
860 	       fprintf (stderr, "child: setsid failed.\n");
861 
862 	     if (-1 == pty_open_slave_pty (slave_tty_name, &slave_read))
863 	       {
864 		  tell_parent_to_go (jed_pid);
865 		  fprintf (stderr, "child: failed to open slave.");
866 		  _exit (1);
867 	       }
868 	     slave_write = slave_read;
869 
870 	     /* (void) pty_setup_slave_term (slave_read, 0); */
871 	  }
872 #endif	/* USE_PTY */
873 	tell_parent_to_go (jed_pid);
874 
875 #ifdef USE_PTY
876 	/* Put tty back into cbreak mode. */
877 	if (p->is_pty) (void) pty_setup_slave_term (slave_read, 0);
878 #endif
879 	if ((signal_safe_dup2(slave_read, 0) < 0)     /* stdin */
880 	    || (signal_safe_dup2 (slave_write, 1) < 0) /* stdout */
881 	    || (signal_safe_dup2 (slave_write, 2) < 0)) /* stderr */
882 	  {
883 	     fprintf (stderr, "dup2 failed. errno = %d\n", errno);
884 	     _exit (1);
885 	  }
886 
887 	my_setenv ("TERM", "unknown");
888 	my_unsetenv ("TERMCAP");
889 
890 	for (i = 0; i < 32; i++)
891 	  {
892 #ifdef SIGTRAP
893 	/* Under Linux, subprocesses fail if run under the debugger because
894 	 * something sends this child a SIGTRAP.  Let's try ignoring it.
895 	 */
896 	     if (i == SIGTRAP)
897 	       SLsignal (i, sigtrap_handler);
898 	     else
899 #endif
900 	       SLsignal (i, SIG_DFL);
901 	  }
902 #ifdef SIGTRAP
903 	SLsignal (SIGTRAP, SIG_DFL);
904 #endif
905 	if (execvp (pgm, argv) < 0)
906 	  {
907 	     fprintf (stderr, "execvp of %s failed!\r\n", pgm);
908 	     _exit (1);
909 	  }
910      }
911 
912    /* parent */
913    if (p->is_pty == 0)
914      {
915 	signal_safe_close (slave_read);
916 	signal_safe_close (slave_write);
917      }
918 
919    p->flags = PROCESS_RUNNING;
920    p->rd = master_read;
921    p->wd = master_write;
922 
923    Subprocess_Read_fds[Num_Subprocesses][0] = master_read;
924    Subprocess_Read_fds[Num_Subprocesses][1] = pd;
925    Subprocess_Read_fds[Num_Subprocesses][2] = 0;
926    if (master_read > Max_Subprocess_FD) Max_Subprocess_FD = master_read;
927    Num_Subprocesses += 1;
928 
929    CBuf->subprocess = pd + 1;
930 
931    /* Processing options */
932    p->buffer = CBuf;
933    p->output_type = PROCESS_USE_BUFFER;
934    p->umark = mmt;
935    SLang_inc_mmt (mmt);	       /* tell slang we are keeping a copy */
936 
937    set_non_blocking_io (master_read);
938    set_non_blocking_io (master_write);
939 
940    /* Tell child it is ok to go. */
941    tell_child_to_go (pid);
942    return pd;
943 }
944 
945 /*}}}*/
946 #endif				       /* __os2__ */
947 
flag_fd_as_eio_error(int fd)948 static int flag_fd_as_eio_error (int fd)
949 {
950    unsigned int i, n;
951 
952    n = Num_Subprocesses;
953    for (i = 0; i < n; i++)
954      {
955 	if (Subprocess_Read_fds[i][0] == fd)
956 	  {
957 	     Subprocess_Read_fds[i][2] = 1;
958 	     return 0;
959 	  }
960      }
961    return -1;
962 }
963 
964 /* This function is only called when we are reading characters from the
965  * keyboard.  Keyboard input has the highest priority and this is called only
966  * if there is no input ready.
967  *
968  * It might also get called by the hooks that it calls.  As a result, it must
969  * be reentrant.
970  *
971  * It is possible for the user to press Ctrl-G while this routine is executing.
972  * This could cause slang hooks to fail.  It would probably be better to
973  * block SIGINT for the duration of this routine.
974  */
read_process_input(int fd)975 void read_process_input (int fd) /*{{{*/
976 {
977    unsigned char buf[513];	       /* last byte for 0 char */
978    int n;
979    Buffer *b = CBuf, *pbuf;
980    Process_Type *p;
981    int otype, total;
982 
983    /* Should never happen */
984    if (NULL == (p = get_process (fd)))
985      {
986 	return;
987      }
988 
989    Ignore_User_Abort++;
990    if (SLang_get_error ())
991      {
992 	Ignore_User_Abort--;
993 	return;
994      }
995 
996    otype = p->output_type;
997    pbuf = p->buffer;
998 
999    if (pbuf != NULL)
1000      {
1001 	if (0 == (p->process_flags & USE_CURRENT_BUFFER))
1002 	  switch_to_buffer (pbuf);
1003 	pbuf->locked++;
1004      }
1005 
1006    total = 0;
1007    if (otype & PROCESS_SAVE_POINT) push_spot ();
1008    while ((n = read (p->rd, buf, 512)) > 0)
1009      {
1010 	total += n;
1011 	if (p->buffer == NULL) continue;
1012 
1013 	if (otype & PROCESS_USE_BUFFER)
1014 	  {
1015 	     if (0 == (otype & PROCESS_AT_POINT)) eob ();
1016 	     (void) jed_insert_nbytes (buf, n);
1017 	     jed_move_user_object_mark (p->umark);
1018 	  }
1019 	else if (otype == PROCESS_USE_SLANG)
1020 	  {
1021 	     buf[n] = 0;
1022 	     if ((-1 == SLang_push_integer ((int) (p - Processes)))
1023 		 || (-1 == SLang_push_string ((char *) buf))
1024 		 || (-1 == SLexecute_function (p->slang_fun)))
1025 	       {
1026 		  /* It looks like the contents of buf may be lost */
1027 		  break;
1028 	       }
1029 	  }
1030      }
1031 
1032    if (n == -1)
1033      {
1034 #ifdef EIO
1035 	if (errno == EIO)
1036 	  (void) flag_fd_as_eio_error (p->rd);
1037 #endif
1038      }
1039 
1040    if (otype & PROCESS_SAVE_POINT) pop_spot ();
1041    else if (otype & PROCESS_USE_BUFFER) move_window_marks (0);
1042 
1043    if (p->buffer != NULL)
1044      {
1045 	if ((b != CBuf) && (0 == (p->process_flags & USE_CURRENT_BUFFER)))
1046 	  switch_to_buffer (b);
1047      }
1048 
1049    /* Since it was locked, it cannot be deleted.  So pbuf is still a good
1050     * pointer
1051     */
1052    if (pbuf != NULL)
1053      pbuf->locked--;
1054 
1055    if (total)
1056      {
1057 #ifdef __os2__
1058 	/* Why does OS/2 need this?? -- JED */
1059 	JWindow->trashed = 1;
1060 	update ((Line *)NULL, 0, 1, 0);
1061 #endif
1062 	touch_screen ();
1063      }
1064 
1065    Ignore_User_Abort--;
1066 }
1067 
1068 
1069 /*}}}*/
1070 
write_to_process(int fd,char * buf,unsigned int len)1071 static int write_to_process (int fd, char *buf, unsigned int len)
1072 {
1073    int n, ilen;
1074 
1075    if (len == 0)
1076      return 0;
1077 
1078    ilen = (int) len;
1079    n = 0;
1080    while (n < ilen)
1081      {
1082 	int dn;
1083 	int count = 0;
1084 
1085 	while (-1 == (dn =  write (fd, buf + n, ilen - n)))
1086 	  {
1087 	     if (errno == EINTR)
1088 	       continue;
1089 
1090 #ifdef EAGAIN
1091 	     if (errno == EAGAIN)
1092 	       {
1093 		  get_process_input (&Number_Zero);
1094 		  count++;
1095 		  if ((count % 10) == 0)
1096 		    {
1097 		       sleep (1);
1098 		       if (count > 20)
1099 			 return n;
1100 		    }
1101 		  continue;
1102 	       }
1103 #endif
1104 	     return -1;
1105 	  }
1106 
1107 	if (dn == 0)
1108 	  break;
1109 
1110 	n += dn;
1111      }
1112 
1113    return n;
1114 }
1115 
jed_send_process(int * fd,char * str)1116 int jed_send_process (int *fd, char *str) /*{{{*/
1117 {
1118    unsigned int len;
1119    Process_Type *p = get_process (*fd);
1120    if ((p == NULL) || (p->wd == -1)) return -1;
1121 
1122    len = strlen (str);
1123 
1124    if (len != (unsigned int) write_to_process (p->wd, str, len))
1125      jed_verror ("write to process failed");
1126 
1127    return len;
1128 }
1129 
1130 /*}}}*/
1131 
jed_send_process_eof(int * fd)1132 void jed_send_process_eof (int *fd) /*{{{*/
1133 {
1134    Process_Type *p = get_process (*fd);
1135 
1136    if (p == NULL)
1137      return;
1138 
1139    if (p->wd == -1)
1140      return;
1141 
1142    if (p->is_pty)
1143      write_to_process (p->wd, "\004", 1);
1144    else
1145      {
1146 	signal_safe_close (p->wd);
1147 	p->wd = -1;
1148      }
1149 }
1150 
1151 
1152 /*}}}*/
1153 
1154 /* If s is NULL, then f != NULL, or visa-versa */
set_process(Process_Type * p,char * what,char * s,SLang_Name_Type * f)1155 static int set_process (Process_Type *p, char *what, char *s, SLang_Name_Type *f) /*{{{*/
1156 {
1157    if (!strcmp (what, "output"))
1158      {
1159 	if (s != NULL)
1160 	  {
1161 	     if (0 == strcmp (s, "."))
1162 	       {
1163 		  p->output_type = PROCESS_AT_POINT | PROCESS_USE_BUFFER;
1164 		  return 0;
1165 	       }
1166 
1167 	     if (0 == strcmp (s, "@"))
1168 	       {
1169 		  p->output_type = PROCESS_SAVE_POINT | PROCESS_USE_BUFFER;
1170 		  return 0;
1171 	       }
1172 
1173 	     if (*s == 0)
1174 	       {
1175 		  p->output_type = PROCESS_USE_BUFFER;
1176 		  return 0;
1177 	       }
1178 
1179 	     if (NULL == (f = SLang_get_function (s)))
1180 	       return -1;
1181 	  }
1182 
1183 	p->output_type = PROCESS_USE_SLANG;
1184 	p->slang_fun = f;
1185 	return 0;
1186      }
1187    else if (!strcmp (what, "signal"))
1188      {
1189 	if ((s != NULL)
1190 	    && (NULL == (f = SLang_get_function (s))))
1191 	  return -1;
1192 
1193 	p->status_change_fun = f;
1194 	return 0;
1195      }
1196 
1197    jed_verror ("set_process: %s not supported", what);
1198    return -1;
1199 }
1200 
1201 /*}}}*/
1202 
jed_set_process(void)1203 void jed_set_process (void)
1204 {
1205    int pd;
1206    char *what, *s;
1207    Process_Type *p;
1208    SLang_Name_Type *f;
1209 
1210    f = NULL;
1211    what = NULL;
1212    s = NULL;
1213 
1214    if (SLang_peek_at_stack () == SLANG_REF_TYPE)
1215      {
1216 	if (NULL == (f = SLang_pop_function ()))
1217 	  return;
1218      }
1219    else if (-1 == SLang_pop_slstring (&s))
1220      return;
1221 
1222    if ((0 == SLang_pop_slstring (&what))
1223        && (0 == SLang_pop_integer (&pd))
1224        && (NULL != (p = get_process (pd)))
1225        && (0 == set_process (p, what, s, f)))
1226      f = NULL;
1227 
1228    SLang_free_slstring (what);
1229    SLang_free_slstring (s);
1230 #if SLANG_VERSION > 10400
1231    SLang_free_function (f);
1232 #endif
1233 }
1234 
1235 
jed_set_process_flags(int * fd,int * oflags)1236 void jed_set_process_flags (int *fd, int *oflags)
1237 {
1238    Process_Type *p;
1239    if (NULL == (p = get_process (*fd)))
1240      return;
1241 
1242    p->process_flags = *oflags;
1243 }
1244 
jed_get_process_flags(int * fd)1245 int jed_get_process_flags (int *fd)
1246 {
1247    Process_Type *p;
1248    if (NULL == (p = get_process (*fd)))
1249      return -1;
1250 
1251    return p->process_flags;
1252 }
1253 
jed_get_process_mark(int * fd)1254 void jed_get_process_mark (int *fd) /*{{{*/
1255 {
1256    Process_Type *p;
1257    if (NULL == (p = get_process (*fd))) return;
1258 
1259    SLang_push_mmt (p->umark);
1260 }
1261 
1262 /*}}}*/
1263 
open_process_of_type(int nargs,int wantpty)1264 static int open_process_of_type (int nargs, int wantpty) /*{{{*/
1265 {
1266    int fd = -1;
1267    char *argv[502];
1268    int n = nargs;
1269 
1270    if (CBuf->subprocess)
1271      {
1272 	msg_error ("There is already a process attached to this buffer.");
1273 	return -1;
1274      }
1275 
1276    if ((n > 500) || (n < 0))
1277      {
1278 	msg_error ("Arguments out of range.");
1279 	return -1;
1280      }
1281 
1282    n++;				       /* for argv0 since *np does not include
1283 					* it.
1284 					*/
1285    argv[n] = NULL;
1286    while (n--)
1287      {
1288 	if (SLang_pop_slstring (&argv[n]))
1289 	  {
1290 	     n++;
1291 	     goto free_return;
1292 	  }
1293      }
1294    n = 0;
1295 
1296    if ((fd = open_process(argv[0], argv, wantpty)) < 0)
1297      {
1298 	jed_verror ("Unable to open %s process.", argv[0]);
1299      }
1300 
1301    /* free up the argument strings */
1302    free_return:
1303 
1304    while (n <= nargs)
1305      {
1306 	SLang_free_slstring (argv[n]);
1307 	n++;
1308      }
1309 
1310    return fd;
1311 }
1312 
1313 /*}}}*/
1314 
jed_open_process(int * np)1315 int jed_open_process (int *np)
1316 {
1317    return open_process_of_type (*np, 1);
1318 }
1319 
jed_open_process_pipe(int * np)1320 int jed_open_process_pipe (int *np)
1321 {
1322    return open_process_of_type (*np, 0);
1323 }
1324 
1325 
jed_block_child_signal(int block)1326 void jed_block_child_signal (int block) /*{{{*/
1327 {
1328    static sigset_t new_mask, old_mask;
1329 
1330    if (block)
1331      {
1332 	sigemptyset (&new_mask);
1333 	sigaddset (&new_mask, SIGCHLD);
1334 	(void) sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
1335 	return;
1336      }
1337 
1338    (void) sigprocmask (SIG_SETMASK, &old_mask, NULL);
1339 }
1340 
1341 /*}}}*/
1342 
1343 /* Jed only calls these in pairs so that this should be fine. */
jed_popen(char * cmd,char * type)1344 FILE *jed_popen (char *cmd, char *type) /*{{{*/
1345 {
1346    FILE *pp;
1347 
1348    jed_block_child_signal (1);
1349    pp = popen (cmd, type);
1350    if (pp == NULL)
1351      jed_block_child_signal (0);
1352    return pp;
1353 }
1354 
1355 /*}}}*/
1356 
jed_pclose(FILE * fp)1357 int jed_pclose (FILE *fp) /*{{{*/
1358 {
1359    int ret;
1360 
1361    if (fp == NULL)
1362      return -1;
1363 
1364    ret = pclose (fp);
1365    jed_block_child_signal (0);
1366 
1367    return ret;
1368 }
1369 
1370 /*}}}*/
1371 
1372 #if 0
1373 /* These are my versions of popen/pclose.  For some reason, the popen/pclose
1374  * do not work on SunOS when there are subprocesses.  I think it has
1375  * something to do with the way pclose is waiting.
1376  * See Steven's book for more information.
1377  */
1378 #ifndef OPEN_MAX
1379 #define OPEN_MAX 256
1380 #endif
1381 static pid_t Popen_Child_Pids[OPEN_MAX];
1382 FILE *jed_popen(char *cmd, char *type) /*{{{*/
1383 {
1384    int i, pfd[2], fd;
1385    pid_t pid;
1386    FILE	*fp;
1387 
1388    if (((*type != 'r') && (*type != 'w')) || (*(type + 1) != 0))
1389      {
1390 	errno = EINVAL;		/* required by POSIX.2 */
1391 	return(NULL);
1392      }
1393 
1394    if (pipe(pfd) < 0) return(NULL);	/* errno set by pipe() or fork() */
1395    if ((pid = fork()) < 0) return(NULL);
1396 
1397    if (pid == 0)
1398      {				       /* child */
1399 	if (*type == 'r')
1400 	  {
1401 	     signal_safe_close(pfd[0]);
1402 	     if (pfd[1] != 1) signal_safe_dup2(pfd[1], 1);
1403 	     signal_safe_close(pfd[1]);
1404 	  }
1405 	else
1406 	  {
1407 	     signal_safe_close(pfd[1]);
1408 	     if (pfd[0] != 0)
1409 	       {
1410 		  signal_safe_dup2(pfd[0], STDIN_FILENO);
1411 		  signal_safe_close(pfd[0]);
1412 	       }
1413 	  }
1414 
1415 	/* POSIX requires that all streams open by previous popen
1416 	 * be closed.
1417 	 */
1418 	for (i = 0; i < OPEN_MAX; i++)
1419 	  {
1420 	     if (Popen_Child_Pids[i] > 0) signal_safe_close(i);
1421 	  }
1422 
1423 	execl("/bin/sh", "sh", "-c", cmd, (char *) 0);
1424 	_exit(127);
1425      }
1426 
1427    /* parent */
1428    if (*type == 'r')
1429      {
1430 	signal_safe_close(pfd[1]);
1431 	if (NULL == (fp = fdopen(pfd[0], type)))
1432 	  return(NULL);
1433      }
1434    else
1435      {
1436 	signal_safe_close(pfd[0]);
1437 	if (NULL == (fp = fdopen(pfd[1], type)))
1438 	  return(NULL);
1439      }
1440 
1441    fd = fileno (fp);
1442    if (fd >= OPEN_MAX)
1443      {
1444 #ifdef EMFILE
1445 	errno = EMFILE;
1446 #endif
1447 	fclose (fp);
1448 	return NULL;
1449      }
1450    Popen_Child_Pids [fd] = pid;
1451    return(fp);
1452 }
1453 
1454 /*}}}*/
1455 int jed_pclose(FILE *fp) /*{{{*/
1456 {
1457    int	fd, stat;
1458    pid_t pid;
1459    int ret;
1460 
1461    fd = fileno(fp);
1462    if ((fd >= OPEN_MAX)
1463        || (fd < 0)
1464        || (0 == (pid = Popen_Child_Pids[fd])))
1465      return -1;
1466 
1467    Popen_Child_Pids [fd] = 0;
1468 
1469    if (fclose(fp) == EOF) return(-1);
1470 
1471    /* This is the part that the SunOS pclose was apparantly screwing up. */
1472    while (-1 == waitpid(pid, &stat, 0))
1473      {
1474 	if (errno != EINTR)
1475 	  return -1;
1476 
1477 	(void) SLang_handle_interrupt ();
1478      }
1479 
1480    ret = WEXITSTATUS(stat);
1481    if (WIFEXITED (stat))
1482      return ret;
1483 
1484    return -1;
1485 }
1486 
1487 /*}}}*/
1488 #endif
1489 
1490 
jed_query_process_at_exit(int * pid,int * query)1491 void jed_query_process_at_exit (int *pid, int *query)
1492 {
1493    Process_Type *p;
1494 
1495    if (NULL == (p = get_process (*pid)))
1496      return;
1497 
1498    p->quietly_kill_on_exit = (*query == 0);
1499 }
1500 
1501 
jed_processes_ok_to_exit(void)1502 int jed_processes_ok_to_exit (void)
1503 {
1504    Process_Type *p, *pmax;
1505    int num;
1506    char buf[64];
1507 
1508    if (Num_Subprocesses == 0)
1509      return 1;
1510 
1511    num = 0;
1512    p = Processes;
1513    pmax = p + MAX_PROCESSES;
1514 
1515    while (p < pmax)
1516      {
1517 	if ((p->flags & PROCESS_ALIVE)
1518 	    && (0 == p->quietly_kill_on_exit))
1519 	  num++;
1520 	p++;
1521      }
1522 
1523    if (num == 0)
1524      return 1;
1525 
1526    sprintf (buf, "%d Subprocesses exist.  Exit anyway", num);
1527    return jed_get_y_n (buf);
1528 }
1529 
jed_fork_monitor(void)1530 int jed_fork_monitor (void)
1531 {
1532    pid_t pid;
1533    int i;
1534 
1535    while (-1 == (pid = fork ()))
1536      {
1537 	if (errno == EINTR)
1538 	  continue;
1539 
1540 	fprintf (stderr, "Unable to fork: errno=%d\n", errno);
1541 	return -1;
1542      }
1543 
1544    if (pid != 0)
1545      return 0;
1546 
1547    pid = getppid ();
1548 
1549    for (i = 1; i < 32; i++)
1550      (void) SLsignal (i, SIG_IGN);
1551 
1552    SLsignal (SIGQUIT, SIG_DFL);
1553    SLsignal (SIGTERM, SIG_DFL);
1554    SLsignal (SIGCONT, SIG_DFL);
1555    SLsignal (SIGTSTP, SIG_DFL);
1556 
1557    for (i = 0; i < 256; i++)
1558      {
1559 	while ((-1 == close (i))
1560 	       && (errno == EINTR))
1561 	  ;
1562      }
1563 
1564    while (1)
1565      {
1566 	if ((-1 == kill (pid, 0))
1567 	    && (errno == ESRCH))
1568 	  _exit (0);
1569 
1570 	sleep (10);
1571      }
1572 }
1573 
1574 #endif 				       /* JED_HAS_SUBPROCESSES */
1575