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