rework initial error handling -- since we check for any screens on
[nvi.git] / ex / ex_shell.c
blob56b1a4673b6468db484900901b8a4f7cd200fe27
1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
6 */
8 #ifndef lint
9 static char sccsid[] = "$Id: ex_shell.c,v 8.17 1993/12/23 16:49:18 bostic Exp $ (Berkeley) $Date: 1993/12/23 16:49:18 $";
10 #endif /* not lint */
12 #include <sys/param.h>
13 #include <sys/stat.h>
15 #include <curses.h>
16 #include <errno.h>
17 #include <string.h>
18 #include <unistd.h>
20 #include "vi.h"
21 #include "excmd.h"
22 #include "../svi/svi_screen.h"
25 * ex_shell -- :sh[ell]
26 * Invoke the program named in the SHELL environment variable
27 * with the argument -i.
29 int
30 ex_shell(sp, ep, cmdp)
31 SCR *sp;
32 EXF *ep;
33 EXCMDARG *cmdp;
35 char buf[MAXPATHLEN];
37 (void)snprintf(buf, sizeof(buf), "%s -i", O_STR(sp, O_SHELL));
38 return (ex_exec_proc(sp, buf, "\n", NULL));
42 * ex_exec_proc --
43 * Run a separate process.
45 int
46 ex_exec_proc(sp, cmd, p1, p2)
47 SCR *sp;
48 char *cmd, *p1, *p2;
50 struct sigaction act, oact;
51 struct stat osb, sb;
52 struct termios term;
53 const char *name;
54 pid_t pid;
55 int isig, rval;
57 /* Clear the rest of the screen. */
58 if (sp->s_clear(sp))
59 return (1);
61 /* Save ex/vi terminal settings, and restore the original ones. */
62 EX_LEAVE(sp, isig, act, oact, sb, osb, term);
64 /* Put out various messages. */
65 if (p1 != NULL)
66 (void)write(STDOUT_FILENO, p1, strlen(p1));
67 if (p2 != NULL)
68 (void)write(STDOUT_FILENO, p2, strlen(p2));
71 switch (pid = vfork()) {
72 case -1: /* Error. */
73 msgq(sp, M_SYSERR, "vfork");
74 rval = 1;
75 goto err;
76 case 0: /* Utility. */
78 * The utility has default signal behavior. Don't bother
79 * using sigaction(2) 'cause we want the default behavior.
81 (void)signal(SIGINT, SIG_DFL);
82 (void)signal(SIGQUIT, SIG_DFL);
84 if ((name = strrchr(O_STR(sp, O_SHELL), '/')) == NULL)
85 name = O_STR(sp, O_SHELL);
86 else
87 ++name;
88 execl(O_STR(sp, O_SHELL), name, "-c", cmd, NULL);
89 msgq(sp, M_ERR, "Error: execl: %s: %s",
90 O_STR(sp, O_SHELL), strerror(errno));
91 _exit(127);
92 /* NOTREACHED */
95 rval = proc_wait(sp, (long)pid, cmd, 0);
97 /* Restore ex/vi terminal settings. */
98 err: EX_RETURN(sp, isig, act, oact, sb, osb, term);
101 * XXX
102 * EX_LEAVE/EX_RETURN only give us 1-second resolution on the tty
103 * changes. A fast '!' command, e.g. ":!pwd" can beat us to the
104 * refresh. When there's better resolution from the stat(2) timers,
105 * this can go away.
107 F_SET(sp, S_REFRESH);
109 return (rval);