1*d7da19caSderaadt /* $OpenBSD: misc.c,v 1.9 2024/07/01 18:43:50 deraadt Exp $ */
2bc5366b8Sreyk
3bc5366b8Sreyk /*
49cf8e0eaSreyk * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org>
5bc5366b8Sreyk *
6bc5366b8Sreyk * Permission to use, copy, modify, and distribute this software for any
7bc5366b8Sreyk * purpose with or without fee is hereby granted, provided that the above
8bc5366b8Sreyk * copyright notice and this permission notice appear in all copies.
9bc5366b8Sreyk *
10bc5366b8Sreyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11bc5366b8Sreyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12bc5366b8Sreyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13bc5366b8Sreyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14bc5366b8Sreyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15bc5366b8Sreyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16bc5366b8Sreyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17bc5366b8Sreyk */
18bc5366b8Sreyk
19bc5366b8Sreyk #include <sys/stat.h>
20bc5366b8Sreyk #include <sys/types.h>
21bc5366b8Sreyk #include <sys/utsname.h>
22bc5366b8Sreyk #include <sys/wait.h>
23bc5366b8Sreyk #include <sys/time.h>
24bc5366b8Sreyk
25bc5366b8Sreyk #include <stdio.h>
26bc5366b8Sreyk #include <stdlib.h>
27bc5366b8Sreyk #include <signal.h>
28bc5366b8Sreyk #include <string.h>
29bc5366b8Sreyk #include <unistd.h>
30bc5366b8Sreyk #include <ctype.h>
31bc5366b8Sreyk #include <errno.h>
32bc5366b8Sreyk #include <fcntl.h>
33bc5366b8Sreyk
34bc5366b8Sreyk #include "bgplg.h"
35bc5366b8Sreyk
36bc5366b8Sreyk static volatile pid_t child = -1;
37bc5366b8Sreyk
38bc5366b8Sreyk int
lg_checkperm(struct cmd * cmd)39bc5366b8Sreyk lg_checkperm(struct cmd *cmd)
40bc5366b8Sreyk {
41bc5366b8Sreyk struct stat stbuf;
42bc5366b8Sreyk
43bc5366b8Sreyk /* No external command to execute, this is always valid */
446020324cSflorian if (cmd->earg[0] == NULL)
45bc5366b8Sreyk return (1);
46bc5366b8Sreyk
47bc5366b8Sreyk /*
48bc5366b8Sreyk * Skip commands if the executable is missing or
49bc5366b8Sreyk * the permission mode has been set to zero (the default
50bc5366b8Sreyk * in a CGI environment).
51bc5366b8Sreyk */
52bc5366b8Sreyk if (stat(cmd->earg[0], &stbuf) != 0 ||
53bc5366b8Sreyk (stbuf.st_mode & ~S_IFMT) == 0)
54bc5366b8Sreyk return (0);
55bc5366b8Sreyk
56bc5366b8Sreyk return (1);
57bc5366b8Sreyk }
58bc5366b8Sreyk
59bc5366b8Sreyk int
lg_help(struct cmd * cmds,char ** argv)60bc5366b8Sreyk lg_help(struct cmd *cmds, char **argv)
61bc5366b8Sreyk {
62bc5366b8Sreyk u_int i;
63bc5366b8Sreyk
64bc5366b8Sreyk printf("valid commands:\n");
65bc5366b8Sreyk for (i = 0; cmds[i].name != NULL; i++) {
66bc5366b8Sreyk if (!lg_checkperm(&cmds[i]))
67bc5366b8Sreyk continue;
68bc5366b8Sreyk
69bc5366b8Sreyk printf(" %s", cmds[i].name);
70bc5366b8Sreyk if (cmds[i].minargs > 0)
71bc5366b8Sreyk printf(" { arg }");
72bc5366b8Sreyk else if (cmds[i].maxargs > 0)
73bc5366b8Sreyk printf(" [ arg ]");
74bc5366b8Sreyk printf("\n");
75bc5366b8Sreyk }
76bc5366b8Sreyk return (0);
77bc5366b8Sreyk }
78bc5366b8Sreyk
79bc5366b8Sreyk void
lg_sig_alarm(int sig)80bc5366b8Sreyk lg_sig_alarm(int sig)
81bc5366b8Sreyk {
82*d7da19caSderaadt int save_errno = errno;
83*d7da19caSderaadt
84bc5366b8Sreyk if (child != -1) {
85d8e0d0a2Ssthen /* Forcibly kill the child, no excuse... */
86bc5366b8Sreyk kill(child, SIGKILL);
87bc5366b8Sreyk }
88*d7da19caSderaadt errno = save_errno;
89bc5366b8Sreyk }
90bc5366b8Sreyk
91bc5366b8Sreyk int
lg_exec(const char * file,char ** new_argv)92bc5366b8Sreyk lg_exec(const char *file, char **new_argv)
93bc5366b8Sreyk {
94bc5366b8Sreyk int status = 0, ret = 0;
95bc5366b8Sreyk sig_t save_quit, save_int, save_chld;
96bc5366b8Sreyk struct itimerval it;
97bc5366b8Sreyk
98bc5366b8Sreyk if (new_argv == NULL)
99bc5366b8Sreyk return (EFAULT);
100bc5366b8Sreyk
101bc5366b8Sreyk save_quit = signal(SIGQUIT, SIG_IGN);
102bc5366b8Sreyk save_int = signal(SIGINT, SIG_IGN);
103bc5366b8Sreyk save_chld = signal(SIGCHLD, SIG_DFL);
104bc5366b8Sreyk
105bc5366b8Sreyk switch (child = fork()) {
106bc5366b8Sreyk case -1:
107bc5366b8Sreyk ret = errno;
108bc5366b8Sreyk goto done;
109bc5366b8Sreyk case 0:
110bc5366b8Sreyk signal(SIGQUIT, SIG_DFL);
111bc5366b8Sreyk signal(SIGINT, SIG_DFL);
112bc5366b8Sreyk signal(SIGCHLD, SIG_DFL);
113bc5366b8Sreyk
114bc5366b8Sreyk execvp(file, new_argv);
115bc5366b8Sreyk _exit(127);
116bc5366b8Sreyk break;
117bc5366b8Sreyk default:
118bc5366b8Sreyk /* Kill the process after a timeout */
119bc5366b8Sreyk signal(SIGALRM, lg_sig_alarm);
120bc5366b8Sreyk bzero(&it, sizeof(it));
121bc5366b8Sreyk it.it_value.tv_sec = BGPLG_TIMEOUT;
122bc5366b8Sreyk setitimer(ITIMER_REAL, &it, NULL);
123bc5366b8Sreyk
124bc5366b8Sreyk waitpid(child, &status, 0);
125bc5366b8Sreyk break;
126bc5366b8Sreyk }
127bc5366b8Sreyk
128bc5366b8Sreyk switch (ret) {
129bc5366b8Sreyk case -1:
130bc5366b8Sreyk ret = ECHILD;
131bc5366b8Sreyk break;
132bc5366b8Sreyk default:
133bc5366b8Sreyk if (WIFEXITED(status))
134bc5366b8Sreyk ret = WEXITSTATUS(status);
135bc5366b8Sreyk else
136bc5366b8Sreyk ret = ECHILD;
137bc5366b8Sreyk }
138bc5366b8Sreyk
139bc5366b8Sreyk done:
140bc5366b8Sreyk /* Disable the process timeout timer */
141bc5366b8Sreyk bzero(&it, sizeof(it));
142bc5366b8Sreyk setitimer(ITIMER_REAL, &it, NULL);
143bc5366b8Sreyk child = -1;
144bc5366b8Sreyk
145bc5366b8Sreyk signal(SIGQUIT, save_quit);
146bc5366b8Sreyk signal(SIGINT, save_int);
147bc5366b8Sreyk signal(SIGCHLD, save_chld);
148bc5366b8Sreyk signal(SIGALRM, SIG_DFL);
149bc5366b8Sreyk
150bc5366b8Sreyk return (ret);
151bc5366b8Sreyk }
152bc5366b8Sreyk
153bc5366b8Sreyk ssize_t
lg_strip(char * str)154bc5366b8Sreyk lg_strip(char *str)
155bc5366b8Sreyk {
156bc5366b8Sreyk size_t len;
157bc5366b8Sreyk
158bc5366b8Sreyk if ((len = strlen(str)) < 1)
159bc5366b8Sreyk return (0); /* XXX EINVAL? */
160bc5366b8Sreyk
1616d73225dSderaadt if (isspace((unsigned char)str[len - 1])) {
162bc5366b8Sreyk str[len - 1] = '\0';
163bc5366b8Sreyk return (lg_strip(str));
164bc5366b8Sreyk }
165bc5366b8Sreyk
166bc5366b8Sreyk return (strlen(str));
167bc5366b8Sreyk }
168