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