11553Srgrimes/*- 21553Srgrimes * Copyright (c) 1985, 1993 31553Srgrimes * The Regents of the University of California. All rights reserved. 41553Srgrimes * 51553Srgrimes * Redistribution and use in source and binary forms, with or without 61553Srgrimes * modification, are permitted provided that the following conditions 71553Srgrimes * are met: 81553Srgrimes * 1. Redistributions of source code must retain the above copyright 91553Srgrimes * notice, this list of conditions and the following disclaimer. 101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111553Srgrimes * notice, this list of conditions and the following disclaimer in the 121553Srgrimes * documentation and/or other materials provided with the distribution. 131553Srgrimes * 4. Neither the name of the University nor the names of its contributors 141553Srgrimes * may be used to endorse or promote products derived from this software 151553Srgrimes * without specific prior written permission. 161553Srgrimes * 171553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271553Srgrimes * SUCH DAMAGE. 281553Srgrimes */ 291553Srgrimes 301553Srgrimes#ifndef lint 3130642Scharnierstatic const char copyright[] = 321553Srgrimes"@(#) Copyright (c) 1985, 1993\n\ 331553Srgrimes The Regents of the University of California. All rights reserved.\n"; 341553Srgrimes#endif /* not lint */ 351553Srgrimes 361553Srgrimes#ifndef lint 3730642Scharnier#if 0 381553Srgrimesstatic char sccsid[] = "@(#)timedc.c 8.1 (Berkeley) 6/6/93"; 3930642Scharnier#endif 4030642Scharnierstatic const char rcsid[] = 4150479Speter "$FreeBSD$"; 421553Srgrimes#endif /* not lint */ 431553Srgrimes 441553Srgrimes#include "timedc.h" 451553Srgrimes#include <ctype.h> 4630642Scharnier#include <err.h> 471553Srgrimes#include <setjmp.h> 4830642Scharnier#include <signal.h> 491553Srgrimes#include <stdlib.h> 50116078Simp#include <string.h> 511553Srgrimes#include <syslog.h> 5230642Scharnier#include <unistd.h> 531553Srgrimes 541553Srgrimesint trace = 0; 551553SrgrimesFILE *fd = 0; 561553Srgrimesint margc; 571553Srgrimesint fromatty; 58120995Stjr#define MAX_MARGV 20 59120995Stjrchar *margv[MAX_MARGV]; 601553Srgrimeschar cmdline[200]; 611553Srgrimesjmp_buf toplevel; 62173412Skevlostatic struct cmd *getcmd(char *); 631553Srgrimes 641553Srgrimesint 651553Srgrimesmain(argc, argv) 661553Srgrimes int argc; 671553Srgrimes char *argv[]; 681553Srgrimes{ 691553Srgrimes register struct cmd *c; 701553Srgrimes 711553Srgrimes openlog("timedc", LOG_ODELAY, LOG_AUTH); 721553Srgrimes 731553Srgrimes /* 741553Srgrimes * security dictates! 751553Srgrimes */ 7630642Scharnier if (priv_resources() < 0) 7730642Scharnier errx(1, "could not get privileged resources"); 78220970Ssimon if (setuid(getuid()) != 0) 79220970Ssimon err(1, "setuid()"); 801553Srgrimes 811553Srgrimes if (--argc > 0) { 821553Srgrimes c = getcmd(*++argv); 831553Srgrimes if (c == (struct cmd *)-1) { 841553Srgrimes printf("?Ambiguous command\n"); 851553Srgrimes exit(1); 861553Srgrimes } 871553Srgrimes if (c == 0) { 881553Srgrimes printf("?Invalid command\n"); 891553Srgrimes exit(1); 901553Srgrimes } 911553Srgrimes if (c->c_priv && getuid()) { 921553Srgrimes printf("?Privileged command\n"); 931553Srgrimes exit(1); 941553Srgrimes } 951553Srgrimes (*c->c_handler)(argc, argv); 961553Srgrimes exit(0); 971553Srgrimes } 981553Srgrimes 991553Srgrimes fromatty = isatty(fileno(stdin)); 1001553Srgrimes if (setjmp(toplevel)) 1011553Srgrimes putchar('\n'); 1021553Srgrimes (void) signal(SIGINT, intr); 1031553Srgrimes for (;;) { 1041553Srgrimes if (fromatty) { 1051553Srgrimes printf("timedc> "); 1061553Srgrimes (void) fflush(stdout); 1071553Srgrimes } 1081553Srgrimes if (fgets(cmdline, sizeof(cmdline), stdin) == 0) 1091553Srgrimes quit(); 1101553Srgrimes if (cmdline[0] == 0) 1111553Srgrimes break; 1121553Srgrimes makeargv(); 1131553Srgrimes if (margv[0] == 0) 1141553Srgrimes continue; 1151553Srgrimes c = getcmd(margv[0]); 1161553Srgrimes if (c == (struct cmd *)-1) { 1171553Srgrimes printf("?Ambiguous command\n"); 1181553Srgrimes continue; 1191553Srgrimes } 1201553Srgrimes if (c == 0) { 1211553Srgrimes printf("?Invalid command\n"); 1221553Srgrimes continue; 1231553Srgrimes } 1241553Srgrimes if (c->c_priv && getuid()) { 1251553Srgrimes printf("?Privileged command\n"); 1261553Srgrimes continue; 1271553Srgrimes } 1281553Srgrimes (*c->c_handler)(margc, margv); 1291553Srgrimes } 1301553Srgrimes return 0; 1311553Srgrimes} 1321553Srgrimes 1331553Srgrimesvoid 1341553Srgrimesintr(signo) 1351553Srgrimes int signo; 1361553Srgrimes{ 1371553Srgrimes if (!fromatty) 1381553Srgrimes exit(0); 1391553Srgrimes longjmp(toplevel, 1); 1401553Srgrimes} 1411553Srgrimes 1421553Srgrimes 1431553Srgrimesstatic struct cmd * 1441553Srgrimesgetcmd(name) 1451553Srgrimes char *name; 1461553Srgrimes{ 1471553Srgrimes register char *p, *q; 1481553Srgrimes register struct cmd *c, *found; 1491553Srgrimes register int nmatches, longest; 1501553Srgrimes extern int NCMDS; 1511553Srgrimes 1521553Srgrimes longest = 0; 1531553Srgrimes nmatches = 0; 1541553Srgrimes found = 0; 1551553Srgrimes for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 1561553Srgrimes p = c->c_name; 1571553Srgrimes for (q = name; *q == *p++; q++) 1581553Srgrimes if (*q == 0) /* exact match? */ 1591553Srgrimes return(c); 1601553Srgrimes if (!*q) { /* the name was a prefix */ 1611553Srgrimes if (q - name > longest) { 1621553Srgrimes longest = q - name; 1631553Srgrimes nmatches = 1; 1641553Srgrimes found = c; 1651553Srgrimes } else if (q - name == longest) 1661553Srgrimes nmatches++; 1671553Srgrimes } 1681553Srgrimes } 1691553Srgrimes if (nmatches > 1) 1701553Srgrimes return((struct cmd *)-1); 1711553Srgrimes return(found); 1721553Srgrimes} 1731553Srgrimes 1741553Srgrimes/* 1751553Srgrimes * Slice a string up into argc/argv. 1761553Srgrimes */ 1771553Srgrimesvoid 1781553Srgrimesmakeargv() 1791553Srgrimes{ 1801553Srgrimes register char *cp; 1811553Srgrimes register char **argp = margv; 1821553Srgrimes 1831553Srgrimes margc = 0; 184120995Stjr for (cp = cmdline; margc < MAX_MARGV - 1 && *cp; ) { 1851553Srgrimes while (isspace(*cp)) 1861553Srgrimes cp++; 1871553Srgrimes if (*cp == '\0') 1881553Srgrimes break; 1891553Srgrimes *argp++ = cp; 1901553Srgrimes margc += 1; 1911553Srgrimes while (*cp != '\0' && !isspace(*cp)) 1921553Srgrimes cp++; 1931553Srgrimes if (*cp == '\0') 1941553Srgrimes break; 1951553Srgrimes *cp++ = '\0'; 1961553Srgrimes } 1971553Srgrimes *argp++ = 0; 1981553Srgrimes} 1991553Srgrimes 2001553Srgrimes#define HELPINDENT (sizeof ("directory")) 2011553Srgrimes 2021553Srgrimes/* 2031553Srgrimes * Help command. 2041553Srgrimes */ 2051553Srgrimesvoid 2061553Srgrimeshelp(argc, argv) 2071553Srgrimes int argc; 2081553Srgrimes char *argv[]; 2091553Srgrimes{ 2101553Srgrimes register struct cmd *c; 2111553Srgrimes 2121553Srgrimes if (argc == 1) { 2131553Srgrimes register int i, j, w; 2141553Srgrimes int columns, width = 0, lines; 2151553Srgrimes extern int NCMDS; 2161553Srgrimes 2171553Srgrimes printf("Commands may be abbreviated. Commands are:\n\n"); 2181553Srgrimes for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 2191553Srgrimes int len = strlen(c->c_name); 2201553Srgrimes 2211553Srgrimes if (len > width) 2221553Srgrimes width = len; 2231553Srgrimes } 2241553Srgrimes width = (width + 8) &~ 7; 2251553Srgrimes columns = 80 / width; 2261553Srgrimes if (columns == 0) 2271553Srgrimes columns = 1; 2281553Srgrimes lines = (NCMDS + columns - 1) / columns; 2291553Srgrimes for (i = 0; i < lines; i++) { 2301553Srgrimes for (j = 0; j < columns; j++) { 2311553Srgrimes c = cmdtab + j * lines + i; 2321553Srgrimes printf("%s", c->c_name); 2331553Srgrimes if (c + lines >= &cmdtab[NCMDS]) { 2341553Srgrimes printf("\n"); 2351553Srgrimes break; 2361553Srgrimes } 2371553Srgrimes w = strlen(c->c_name); 2381553Srgrimes while (w < width) { 2391553Srgrimes w = (w + 8) &~ 7; 2401553Srgrimes putchar('\t'); 2411553Srgrimes } 2421553Srgrimes } 2431553Srgrimes } 2441553Srgrimes return; 2451553Srgrimes } 2461553Srgrimes while (--argc > 0) { 2471553Srgrimes register char *arg; 2481553Srgrimes arg = *++argv; 2491553Srgrimes c = getcmd(arg); 2501553Srgrimes if (c == (struct cmd *)-1) 2511553Srgrimes printf("?Ambiguous help command %s\n", arg); 2521553Srgrimes else if (c == (struct cmd *)0) 2531553Srgrimes printf("?Invalid help command %s\n", arg); 2541553Srgrimes else 2551553Srgrimes printf("%-*s\t%s\n", (int)HELPINDENT, 2561553Srgrimes c->c_name, c->c_help); 2571553Srgrimes } 2581553Srgrimes} 259