Remove building with NOCRYPTO option
[minix.git] / external / bsd / nvi / dist / ex / ex_shell.c
blob778d86e5b63ae80842c0dfcb46725dc1c0f08e52
1 /* $NetBSD: ex_shell.c,v 1.3 2014/01/26 21:43:45 christos Exp $ */
2 /*-
3 * Copyright (c) 1992, 1993, 1994
4 * The Regents of the University of California. All rights reserved.
5 * Copyright (c) 1992, 1993, 1994, 1995, 1996
6 * Keith Bostic. All rights reserved.
8 * See the LICENSE file for redistribution information.
9 */
11 #include "config.h"
13 #include <sys/cdefs.h>
14 #if 0
15 #ifndef lint
16 static const char sccsid[] = "Id: ex_shell.c,v 10.42 2003/11/05 17:11:54 skimo Exp (Berkeley) Date: 2003/11/05 17:11:54 ";
17 #endif /* not lint */
18 #else
19 __RCSID("$NetBSD: ex_shell.c,v 1.3 2014/01/26 21:43:45 christos Exp $");
20 #endif
22 #include <sys/param.h>
23 #include <sys/queue.h>
24 #include <sys/wait.h>
26 #include <bitstring.h>
27 #include <ctype.h>
28 #include <errno.h>
29 #include <limits.h>
30 #include <signal.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
36 #include "../common/common.h"
38 static const char *sigmsg __P((int));
41 * ex_shell -- :sh[ell]
42 * Invoke the program named in the SHELL environment variable
43 * with the argument -i.
45 * PUBLIC: int ex_shell __P((SCR *, EXCMD *));
47 int
48 ex_shell(SCR *sp, EXCMD *cmdp)
50 int rval;
51 char buf[MAXPATHLEN];
53 /* We'll need a shell. */
54 if (opts_empty(sp, O_SHELL, 0))
55 return (1);
58 * XXX
59 * Assumes all shells use -i.
61 (void)snprintf(buf, sizeof(buf), "%s -i", O_STR(sp, O_SHELL));
63 /* Restore the window name. */
64 (void)sp->gp->scr_rename(sp, NULL, 0);
66 /* If we're still in a vi screen, move out explicitly. */
67 rval = ex_exec_proc(sp, cmdp, buf, NULL, !F_ISSET(sp, SC_SCR_EXWROTE));
69 /* Set the window name. */
70 (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
73 * !!!
74 * Historically, vi didn't require a continue message after the
75 * return of the shell. Match it.
77 F_SET(sp, SC_EX_WAIT_NO);
79 return (rval);
83 * ex_exec_proc --
84 * Run a separate process.
86 * PUBLIC: int ex_exec_proc __P((SCR *, EXCMD *, const char *, const char *, int));
88 int
89 ex_exec_proc(SCR *sp, EXCMD *cmdp, const char *cmd, const char *msg, int need_newline)
91 GS *gp;
92 const char *name;
93 pid_t pid;
95 gp = sp->gp;
97 /* We'll need a shell. */
98 if (opts_empty(sp, O_SHELL, 0))
99 return (1);
101 /* Enter ex mode. */
102 if (F_ISSET(sp, SC_VI)) {
103 if (gp->scr_screen(sp, SC_EX)) {
104 ex_wemsg(sp, cmdp->cmd->name, EXM_NOCANON);
105 return (1);
107 (void)gp->scr_attr(sp, SA_ALTERNATE, 0);
108 F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
111 /* Put out additional newline, message. */
112 if (need_newline)
113 (void)ex_puts(sp, "\n");
114 if (msg != NULL) {
115 (void)ex_puts(sp, msg);
116 (void)ex_puts(sp, "\n");
118 (void)ex_fflush(sp);
120 switch (pid = vfork()) {
121 case -1: /* Error. */
122 msgq(sp, M_SYSERR, "vfork");
123 return (1);
124 case 0: /* Utility. */
125 if (gp->scr_child)
126 gp->scr_child(sp);
127 if ((name = strrchr(O_STR(sp, O_SHELL), '/')) == NULL)
128 name = O_STR(sp, O_SHELL);
129 else
130 ++name;
131 execl(O_STR(sp, O_SHELL), name, "-c", cmd, (char *)NULL);
132 msgq_str(sp, M_SYSERR, O_STR(sp, O_SHELL), "execl: %s");
133 _exit(127);
134 /* NOTREACHED */
135 default: /* Parent. */
136 return (proc_wait(sp, (long)pid, cmd, 0, 0));
138 /* NOTREACHED */
142 * proc_wait --
143 * Wait for one of the processes.
145 * !!!
146 * The pid_t type varies in size from a short to a long depending on the
147 * system. It has to be cast into something or the standard promotion
148 * rules get you. I'm using a long based on the belief that nobody is
149 * going to make it unsigned and it's unlikely to be a quad.
151 * PUBLIC: int proc_wait __P((SCR *, long, const char *, int, int));
154 proc_wait(SCR *sp, long int pid, const char *cmd, int silent, int okpipe)
156 size_t len;
157 int nf, pstat;
158 char *p;
160 /* Wait for the utility, ignoring interruptions. */
161 for (;;) {
162 errno = 0;
163 if (waitpid((pid_t)pid, &pstat, 0) != -1)
164 break;
165 if (errno != EINTR) {
166 msgq(sp, M_SYSERR, "waitpid");
167 return (1);
172 * Display the utility's exit status. Ignore SIGPIPE from the
173 * parent-writer, as that only means that the utility chose to
174 * exit before reading all of its input.
176 if (WIFSIGNALED(pstat) && (!okpipe || WTERMSIG(pstat) != SIGPIPE)) {
177 for (; isblank((unsigned char)*cmd); ++cmd);
178 p = msg_print(sp, cmd, &nf);
179 len = strlen(p);
180 msgq(sp, M_ERR, "%.*s%s: received signal: %s%s",
181 (int)MIN(len, 20), p, len > 20 ? " ..." : "",
182 sigmsg(WTERMSIG(pstat)),
183 WCOREDUMP(pstat) ? "; core dumped" : "");
184 if (nf)
185 FREE_SPACE(sp, p, 0);
186 return (1);
189 if (WIFEXITED(pstat) && WEXITSTATUS(pstat)) {
191 * Remain silent for "normal" errors when doing shell file
192 * name expansions, they almost certainly indicate nothing
193 * more than a failure to match.
195 * Remain silent for vi read filter errors. It's historic
196 * practice.
198 if (!silent) {
199 for (; isblank((unsigned char)*cmd); ++cmd);
200 p = msg_print(sp, cmd, &nf);
201 len = strlen(p);
202 msgq(sp, M_ERR, "%.*s%s: exited with status %d",
203 (int)MIN(len, 20), p, len > 20 ? " ..." : "",
204 WEXITSTATUS(pstat));
205 if (nf)
206 FREE_SPACE(sp, p, 0);
208 return (1);
210 return (0);
214 * XXX
215 * The sys_siglist[] table in the C library has this information, but there's
216 * no portable way to get to it. (Believe me, I tried.)
218 typedef struct _sigs {
219 int number; /* signal number */
220 const char *message; /* related message */
221 } SIGS;
223 SIGS const sigs[] = {
224 #ifdef SIGABRT
225 { SIGABRT, "Abort trap" },
226 #endif
227 #ifdef SIGALRM
228 { SIGALRM, "Alarm clock" },
229 #endif
230 #ifdef SIGBUS
231 { SIGBUS, "Bus error" },
232 #endif
233 #ifdef SIGCLD
234 { SIGCLD, "Child exited or stopped" },
235 #endif
236 #ifdef SIGCHLD
237 { SIGCHLD, "Child exited" },
238 #endif
239 #ifdef SIGCONT
240 { SIGCONT, "Continued" },
241 #endif
242 #ifdef SIGDANGER
243 { SIGDANGER, "System crash imminent" },
244 #endif
245 #ifdef SIGEMT
246 { SIGEMT, "EMT trap" },
247 #endif
248 #ifdef SIGFPE
249 { SIGFPE, "Floating point exception" },
250 #endif
251 #ifdef SIGGRANT
252 { SIGGRANT, "HFT monitor mode granted" },
253 #endif
254 #ifdef SIGHUP
255 { SIGHUP, "Hangup" },
256 #endif
257 #ifdef SIGILL
258 { SIGILL, "Illegal instruction" },
259 #endif
260 #ifdef SIGINFO
261 { SIGINFO, "Information request" },
262 #endif
263 #ifdef SIGINT
264 { SIGINT, "Interrupt" },
265 #endif
266 #ifdef SIGIO
267 { SIGIO, "I/O possible" },
268 #endif
269 #ifdef SIGIOT
270 { SIGIOT, "IOT trap" },
271 #endif
272 #ifdef SIGKILL
273 { SIGKILL, "Killed" },
274 #endif
275 #ifdef SIGLOST
276 { SIGLOST, "Record lock" },
277 #endif
278 #ifdef SIGMIGRATE
279 { SIGMIGRATE, "Migrate process to another CPU" },
280 #endif
281 #ifdef SIGMSG
282 { SIGMSG, "HFT input data pending" },
283 #endif
284 #ifdef SIGPIPE
285 { SIGPIPE, "Broken pipe" },
286 #endif
287 #ifdef SIGPOLL
288 { SIGPOLL, "I/O possible" },
289 #endif
290 #ifdef SIGPRE
291 { SIGPRE, "Programming error" },
292 #endif
293 #ifdef SIGPROF
294 { SIGPROF, "Profiling timer expired" },
295 #endif
296 #ifdef SIGPWR
297 { SIGPWR, "Power failure imminent" },
298 #endif
299 #ifdef SIGRETRACT
300 { SIGRETRACT, "HFT monitor mode retracted" },
301 #endif
302 #ifdef SIGQUIT
303 { SIGQUIT, "Quit" },
304 #endif
305 #ifdef SIGSAK
306 { SIGSAK, "Secure Attention Key" },
307 #endif
308 #ifdef SIGSEGV
309 { SIGSEGV, "Segmentation fault" },
310 #endif
311 #ifdef SIGSOUND
312 { SIGSOUND, "HFT sound sequence completed" },
313 #endif
314 #ifdef SIGSTOP
315 { SIGSTOP, "Suspended (signal)" },
316 #endif
317 #ifdef SIGSYS
318 { SIGSYS, "Bad system call" },
319 #endif
320 #ifdef SIGTERM
321 { SIGTERM, "Terminated" },
322 #endif
323 #ifdef SIGTRAP
324 { SIGTRAP, "Trace/BPT trap" },
325 #endif
326 #ifdef SIGTSTP
327 { SIGTSTP, "Suspended" },
328 #endif
329 #ifdef SIGTTIN
330 { SIGTTIN, "Stopped (tty input)" },
331 #endif
332 #ifdef SIGTTOU
333 { SIGTTOU, "Stopped (tty output)" },
334 #endif
335 #ifdef SIGURG
336 { SIGURG, "Urgent I/O condition" },
337 #endif
338 #ifdef SIGUSR1
339 { SIGUSR1, "User defined signal 1" },
340 #endif
341 #ifdef SIGUSR2
342 { SIGUSR2, "User defined signal 2" },
343 #endif
344 #ifdef SIGVTALRM
345 { SIGVTALRM, "Virtual timer expired" },
346 #endif
347 #ifdef SIGWINCH
348 { SIGWINCH, "Window size changes" },
349 #endif
350 #ifdef SIGXCPU
351 { SIGXCPU, "Cputime limit exceeded" },
352 #endif
353 #ifdef SIGXFSZ
354 { SIGXFSZ, "Filesize limit exceeded" },
355 #endif
359 * sigmsg --
360 * Return a pointer to a message describing a signal.
362 static const char *
363 sigmsg(int signo)
365 static char buf[40];
366 const SIGS *sigp;
367 size_t n;
369 for (n = 0,
370 sigp = &sigs[0]; n < sizeof(sigs) / sizeof(sigs[0]); ++n, ++sigp)
371 if (sigp->number == signo)
372 return (sigp->message);
373 (void)snprintf(buf, sizeof(buf), "Unknown signal: %d", signo);
374 return (buf);