1198160Srrs/* $NetBSD: timedc.c,v 1.21 2008/07/21 13:37:00 lukem Exp $ */ 2198160Srrs 3198160Srrs/*- 4198160Srrs * Copyright (c) 1985, 1993 The Regents of the University of California. 5198160Srrs * All rights reserved. 6198160Srrs * 7198160Srrs * Redistribution and use in source and binary forms, with or without 8198160Srrs * modification, are permitted provided that the following conditions 9198160Srrs * are met: 10198160Srrs * 1. Redistributions of source code must retain the above copyright 11198160Srrs * notice, this list of conditions and the following disclaimer. 12198160Srrs * 2. Redistributions in binary form must reproduce the above copyright 13198160Srrs * notice, this list of conditions and the following disclaimer in the 14198160Srrs * documentation and/or other materials provided with the distribution. 15198160Srrs * 3. Neither the name of the University nor the names of its contributors 16198160Srrs * may be used to endorse or promote products derived from this software 17198160Srrs * without specific prior written permission. 18198160Srrs * 19198160Srrs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20198160Srrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21198160Srrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22198160Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23198160Srrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24198160Srrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25198160Srrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26198160Srrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27198160Srrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28211994Sjchandra * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29211994Sjchandra * SUCH DAMAGE. 30211994Sjchandra */ 31211994Sjchandra 32198160Srrs#include <sys/cdefs.h> 33198160Srrs#ifndef lint 34198160Srrs__COPYRIGHT("@(#) Copyright (c) 1985, 1993\ 35198160Srrs The Regents of the University of California. All rights reserved."); 36198160Srrs#endif /* not lint */ 37208165Srrs 38208165Srrs#ifndef lint 39208165Srrs#if 0 40198160Srrsstatic char sccsid[] = "@(#)timedc.c 8.1 (Berkeley) 6/6/93"; 41204130Srrs#else 42204130Srrs__RCSID("$NetBSD: timedc.c,v 1.21 2008/07/21 13:37:00 lukem Exp $"); 43204130Srrs#endif 44204130Srrs#endif /* not lint */ 45211893Sjchandra 46211893Sjchandra#include "timedc.h" 47211893Sjchandra#include <ctype.h> 48211893Sjchandra#include <setjmp.h> 49204130Srrs#include <signal.h> 50198625Srrs#include <stdlib.h> 51#include <string.h> 52#include <syslog.h> 53#include <unistd.h> 54#include <fcntl.h> 55#include <pwd.h> 56#include <err.h> 57 58int trace = 0; 59FILE *fd = 0; 60int margc; 61int fromatty; 62#define MAX_MARGV 20 63char *margv[MAX_MARGV]; 64char cmdline[200]; 65jmp_buf toplevel; 66static const struct cmd *getcmd(char *); 67static int drop_privileges(void); 68 69int 70main(int argc, char *argv[]) 71{ 72 const struct cmd *c; 73 74 fcntl(3, F_CLOSEM); 75 openlog("timedc", 0, LOG_AUTH); 76 77 /* 78 * security dictates! 79 */ 80 if (priv_resources() < 0) 81 errx(EXIT_FAILURE, "Could not get privileged resources"); 82 if (drop_privileges() < 0) 83 errx(EXIT_FAILURE, "Could not drop privileges"); 84 85 if (--argc > 0) { 86 c = getcmd(*++argv); 87 if (c == (struct cmd *)-1) { 88 printf("?Ambiguous command\n"); 89 exit(EXIT_FAILURE); 90 } 91 if (c == 0) { 92 printf("?Invalid command\n"); 93 exit(EXIT_FAILURE); 94 } 95 (*c->c_handler)(argc, argv); 96 exit(EXIT_SUCCESS); 97 } 98 99 fromatty = isatty(fileno(stdin)); 100 if (setjmp(toplevel)) 101 putchar('\n'); 102 (void) signal(SIGINT, intr); 103 for (;;) { 104 if (fromatty) { 105 printf("timedc> "); 106 (void) fflush(stdout); 107 } 108 if (fgets(cmdline, sizeof(cmdline), stdin) == NULL) 109 quit(0, NULL); 110 if (cmdline[0] == 0) 111 break; 112 if (makeargv()) { 113 printf("?Too many arguments\n"); 114 continue; 115 } 116 if (margv[0] == 0) 117 continue; 118 c = getcmd(margv[0]); 119 if (c == (struct cmd *)-1) { 120 printf("?Ambiguous command\n"); 121 continue; 122 } 123 if (c == 0) { 124 printf("?Invalid command\n"); 125 continue; 126 } 127 (*c->c_handler)(margc, margv); 128 } 129 return 0; 130} 131 132void 133intr(int signo) 134{ 135 (void) signo; 136 if (!fromatty) 137 exit(EXIT_SUCCESS); 138 longjmp(toplevel, 1); 139} 140 141 142static const struct cmd * 143getcmd(char *name) 144{ 145 const char *p; 146 char *q; 147 const struct cmd *c, *found; 148 int nmatches, longest; 149 extern const struct cmd cmdtab[]; 150 extern int NCMDS; 151 152 longest = 0; 153 nmatches = 0; 154 found = 0; 155 for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 156 p = c->c_name; 157 for (q = name; *q == *p++; q++) 158 if (*q == 0) /* exact match? */ 159 return(c); 160 if (!*q) { /* the name was a prefix */ 161 if (q - name > longest) { 162 longest = q - name; 163 nmatches = 1; 164 found = c; 165 } else if (q - name == longest) 166 nmatches++; 167 } 168 } 169 if (nmatches > 1) 170 return((struct cmd *)-1); 171 return(found); 172} 173 174/* 175 * Slice a string up into argc/argv. 176 */ 177int 178makeargv(void) 179{ 180 char *cp; 181 char **argp = margv; 182 183 margc = 0; 184 for (cp = cmdline; argp < &margv[MAX_MARGV - 1] && *cp;) { 185 while (isspace((unsigned char)*cp)) 186 cp++; 187 if (*cp == '\0') 188 break; 189 *argp++ = cp; 190 margc += 1; 191 while (*cp != '\0' && !isspace((unsigned char)*cp)) 192 cp++; 193 if (*cp == '\0') 194 break; 195 *cp++ = '\0'; 196 } 197 if (margc == MAX_MARGV - 1) 198 return 1; 199 *argp++ = 0; 200 return 0; 201} 202 203#define HELPINDENT (sizeof ("directory")) 204 205/* 206 * Help command. 207 */ 208void 209help(int argc, char *argv[]) 210{ 211 const struct cmd *c; 212 extern const struct cmd cmdtab[]; 213 214 if (argc == 1) { 215 int i, j, w; 216 int columns, width = 0, lines; 217 extern int NCMDS; 218 219 printf("Commands may be abbreviated. Commands are:\n\n"); 220 for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 221 int len = strlen(c->c_name); 222 223 if (len > width) 224 width = len; 225 } 226 width = (width + 8) &~ 7; 227 columns = 80 / width; 228 if (columns == 0) 229 columns = 1; 230 lines = (NCMDS + columns - 1) / columns; 231 for (i = 0; i < lines; i++) { 232 for (j = 0; j < columns; j++) { 233 c = cmdtab + j * lines + i; 234 printf("%s", c->c_name); 235 if (c + lines >= &cmdtab[NCMDS]) { 236 printf("\n"); 237 break; 238 } 239 w = strlen(c->c_name); 240 while (w < width) { 241 w = (w + 8) &~ 7; 242 putchar('\t'); 243 } 244 } 245 } 246 return; 247 } 248 while (--argc > 0) { 249 char *arg; 250 arg = *++argv; 251 c = getcmd(arg); 252 if (c == (struct cmd *)-1) 253 printf("?Ambiguous help command %s\n", arg); 254 else if (c == (struct cmd *)0) 255 printf("?Invalid help command %s\n", arg); 256 else 257 printf("%-*s\t%s\n", (int)HELPINDENT, 258 c->c_name, c->c_help); 259 } 260} 261 262static int 263drop_privileges(void) 264{ 265 static const char user[] = "_timedc"; 266 const struct passwd *pw; 267 uid_t uid; 268 gid_t gid; 269 270 if ((pw = getpwnam(user)) == NULL) { 271 warnx("getpwnam(\"%s\") failed", user); 272 return -1; 273 } 274 uid = pw->pw_uid; 275 gid = pw->pw_gid; 276 if (setgroups(1, &gid)) { 277 warn("setgroups"); 278 return -1; 279 } 280 if (setgid(gid)) { 281 warn("setgid"); 282 return -1; 283 } 284 if (setuid(uid)) { 285 warn("setuid"); 286 return -1; 287 } 288 return 0; 289} 290