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 65246209Scharniermain(int argc, char *argv[]) 661553Srgrimes{ 671553Srgrimes register struct cmd *c; 681553Srgrimes 691553Srgrimes openlog("timedc", LOG_ODELAY, LOG_AUTH); 701553Srgrimes 711553Srgrimes /* 721553Srgrimes * security dictates! 731553Srgrimes */ 7430642Scharnier if (priv_resources() < 0) 7530642Scharnier errx(1, "could not get privileged resources"); 76220970Ssimon if (setuid(getuid()) != 0) 77220970Ssimon err(1, "setuid()"); 781553Srgrimes 791553Srgrimes if (--argc > 0) { 801553Srgrimes c = getcmd(*++argv); 811553Srgrimes if (c == (struct cmd *)-1) { 821553Srgrimes printf("?Ambiguous command\n"); 831553Srgrimes exit(1); 841553Srgrimes } 851553Srgrimes if (c == 0) { 861553Srgrimes printf("?Invalid command\n"); 871553Srgrimes exit(1); 881553Srgrimes } 891553Srgrimes if (c->c_priv && getuid()) { 901553Srgrimes printf("?Privileged command\n"); 911553Srgrimes exit(1); 921553Srgrimes } 931553Srgrimes (*c->c_handler)(argc, argv); 941553Srgrimes exit(0); 951553Srgrimes } 961553Srgrimes 971553Srgrimes fromatty = isatty(fileno(stdin)); 981553Srgrimes if (setjmp(toplevel)) 991553Srgrimes putchar('\n'); 1001553Srgrimes (void) signal(SIGINT, intr); 1011553Srgrimes for (;;) { 1021553Srgrimes if (fromatty) { 1031553Srgrimes printf("timedc> "); 1041553Srgrimes (void) fflush(stdout); 1051553Srgrimes } 106230044Skevlo if (fgets(cmdline, sizeof(cmdline), stdin) == NULL) 1071553Srgrimes quit(); 1081553Srgrimes if (cmdline[0] == 0) 1091553Srgrimes break; 1101553Srgrimes makeargv(); 1111553Srgrimes if (margv[0] == 0) 1121553Srgrimes continue; 1131553Srgrimes c = getcmd(margv[0]); 1141553Srgrimes if (c == (struct cmd *)-1) { 1151553Srgrimes printf("?Ambiguous command\n"); 1161553Srgrimes continue; 1171553Srgrimes } 1181553Srgrimes if (c == 0) { 1191553Srgrimes printf("?Invalid command\n"); 1201553Srgrimes continue; 1211553Srgrimes } 1221553Srgrimes if (c->c_priv && getuid()) { 1231553Srgrimes printf("?Privileged command\n"); 1241553Srgrimes continue; 1251553Srgrimes } 1261553Srgrimes (*c->c_handler)(margc, margv); 1271553Srgrimes } 1281553Srgrimes return 0; 1291553Srgrimes} 1301553Srgrimes 1311553Srgrimesvoid 132246209Scharnierintr(int signo __unused) 1331553Srgrimes{ 1341553Srgrimes if (!fromatty) 1351553Srgrimes exit(0); 1361553Srgrimes longjmp(toplevel, 1); 1371553Srgrimes} 1381553Srgrimes 1391553Srgrimes 1401553Srgrimesstatic struct cmd * 141246209Scharniergetcmd(char *name) 1421553Srgrimes{ 1431553Srgrimes register char *p, *q; 1441553Srgrimes register struct cmd *c, *found; 1451553Srgrimes register int nmatches, longest; 1461553Srgrimes extern int NCMDS; 1471553Srgrimes 1481553Srgrimes longest = 0; 1491553Srgrimes nmatches = 0; 1501553Srgrimes found = 0; 1511553Srgrimes for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 1521553Srgrimes p = c->c_name; 1531553Srgrimes for (q = name; *q == *p++; q++) 1541553Srgrimes if (*q == 0) /* exact match? */ 1551553Srgrimes return(c); 1561553Srgrimes if (!*q) { /* the name was a prefix */ 1571553Srgrimes if (q - name > longest) { 1581553Srgrimes longest = q - name; 1591553Srgrimes nmatches = 1; 1601553Srgrimes found = c; 1611553Srgrimes } else if (q - name == longest) 1621553Srgrimes nmatches++; 1631553Srgrimes } 1641553Srgrimes } 1651553Srgrimes if (nmatches > 1) 1661553Srgrimes return((struct cmd *)-1); 1671553Srgrimes return(found); 1681553Srgrimes} 1691553Srgrimes 1701553Srgrimes/* 1711553Srgrimes * Slice a string up into argc/argv. 1721553Srgrimes */ 1731553Srgrimesvoid 174246209Scharniermakeargv(void) 1751553Srgrimes{ 1761553Srgrimes register char *cp; 1771553Srgrimes register char **argp = margv; 1781553Srgrimes 1791553Srgrimes margc = 0; 180120995Stjr for (cp = cmdline; margc < MAX_MARGV - 1 && *cp; ) { 1811553Srgrimes while (isspace(*cp)) 1821553Srgrimes cp++; 1831553Srgrimes if (*cp == '\0') 1841553Srgrimes break; 1851553Srgrimes *argp++ = cp; 1861553Srgrimes margc += 1; 1871553Srgrimes while (*cp != '\0' && !isspace(*cp)) 1881553Srgrimes cp++; 1891553Srgrimes if (*cp == '\0') 1901553Srgrimes break; 1911553Srgrimes *cp++ = '\0'; 1921553Srgrimes } 1931553Srgrimes *argp++ = 0; 1941553Srgrimes} 1951553Srgrimes 1961553Srgrimes#define HELPINDENT (sizeof ("directory")) 1971553Srgrimes 1981553Srgrimes/* 1991553Srgrimes * Help command. 2001553Srgrimes */ 2011553Srgrimesvoid 202246209Scharnierhelp(int argc, char *argv[]) 2031553Srgrimes{ 2041553Srgrimes register struct cmd *c; 2051553Srgrimes 2061553Srgrimes if (argc == 1) { 2071553Srgrimes register int i, j, w; 2081553Srgrimes int columns, width = 0, lines; 2091553Srgrimes extern int NCMDS; 2101553Srgrimes 2111553Srgrimes printf("Commands may be abbreviated. Commands are:\n\n"); 2121553Srgrimes for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 2131553Srgrimes int len = strlen(c->c_name); 2141553Srgrimes 2151553Srgrimes if (len > width) 2161553Srgrimes width = len; 2171553Srgrimes } 2181553Srgrimes width = (width + 8) &~ 7; 2191553Srgrimes columns = 80 / width; 2201553Srgrimes if (columns == 0) 2211553Srgrimes columns = 1; 2221553Srgrimes lines = (NCMDS + columns - 1) / columns; 2231553Srgrimes for (i = 0; i < lines; i++) { 2241553Srgrimes for (j = 0; j < columns; j++) { 2251553Srgrimes c = cmdtab + j * lines + i; 2261553Srgrimes printf("%s", c->c_name); 2271553Srgrimes if (c + lines >= &cmdtab[NCMDS]) { 2281553Srgrimes printf("\n"); 2291553Srgrimes break; 2301553Srgrimes } 2311553Srgrimes w = strlen(c->c_name); 2321553Srgrimes while (w < width) { 2331553Srgrimes w = (w + 8) &~ 7; 2341553Srgrimes putchar('\t'); 2351553Srgrimes } 2361553Srgrimes } 2371553Srgrimes } 2381553Srgrimes return; 2391553Srgrimes } 2401553Srgrimes while (--argc > 0) { 2411553Srgrimes register char *arg; 2421553Srgrimes arg = *++argv; 2431553Srgrimes c = getcmd(arg); 2441553Srgrimes if (c == (struct cmd *)-1) 2451553Srgrimes printf("?Ambiguous help command %s\n", arg); 2461553Srgrimes else if (c == (struct cmd *)0) 2471553Srgrimes printf("?Invalid help command %s\n", arg); 2481553Srgrimes else 2491553Srgrimes printf("%-*s\t%s\n", (int)HELPINDENT, 2501553Srgrimes c->c_name, c->c_help); 2511553Srgrimes } 2521553Srgrimes} 253