1/*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1985, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#ifndef lint 33static const char copyright[] = 34"@(#) Copyright (c) 1985, 1993\n\ 35 The Regents of the University of California. All rights reserved.\n"; 36#endif /* not lint */ 37 38#ifndef lint 39#if 0 40static char sccsid[] = "@(#)timedc.c 8.1 (Berkeley) 6/6/93"; 41#endif 42static const char rcsid[] = 43 "$FreeBSD$"; 44#endif /* not lint */ 45 46#include "timedc.h" 47#include <ctype.h> 48#include <err.h> 49#include <setjmp.h> 50#include <signal.h> 51#include <stdlib.h> 52#include <string.h> 53#include <syslog.h> 54#include <unistd.h> 55 56int trace = 0; 57FILE *fd = NULL; 58int margc; 59int fromatty; 60#define MAX_MARGV 20 61char *margv[MAX_MARGV]; 62char cmdline[200]; 63jmp_buf toplevel; 64static struct cmd *getcmd(char *); 65 66int 67main(int argc, char *argv[]) 68{ 69 register struct cmd *c; 70 71 openlog("timedc", 0, LOG_AUTH); 72 73 /* 74 * security dictates! 75 */ 76 if (priv_resources() < 0) 77 errx(1, "could not get privileged resources"); 78 if (setuid(getuid()) != 0) 79 err(1, "setuid()"); 80 81 if (--argc > 0) { 82 c = getcmd(*++argv); 83 if (c == (struct cmd *)-1) { 84 printf("?Ambiguous command\n"); 85 exit(1); 86 } 87 if (c == NULL) { 88 printf("?Invalid command\n"); 89 exit(1); 90 } 91 if (c->c_priv && getuid()) { 92 printf("?Privileged command\n"); 93 exit(1); 94 } 95 (*c->c_handler)(argc, argv); 96 exit(0); 97 } 98 99 fromatty = isatty(fileno(stdin)); 100 if (fromatty) 101 printf("TIMEDC will be removed from FreeBSD-13, and will be " 102 "provided as a port (net/timed) or package (timed).\n"); 103 if (setjmp(toplevel)) 104 putchar('\n'); 105 (void) signal(SIGINT, intr); 106 for (;;) { 107 if (fromatty) { 108 printf("timedc> "); 109 (void) fflush(stdout); 110 } 111 if (fgets(cmdline, sizeof(cmdline), stdin) == NULL) 112 quit(); 113 if (cmdline[0] == 0) 114 break; 115 makeargv(); 116 if (margv[0] == NULL) 117 continue; 118 c = getcmd(margv[0]); 119 if (c == (struct cmd *)-1) { 120 printf("?Ambiguous command\n"); 121 continue; 122 } 123 if (c == NULL) { 124 printf("?Invalid command\n"); 125 continue; 126 } 127 if (c->c_priv && getuid()) { 128 printf("?Privileged command\n"); 129 continue; 130 } 131 (*c->c_handler)(margc, margv); 132 } 133 return 0; 134} 135 136void 137intr(int signo __unused) 138{ 139 if (!fromatty) 140 exit(0); 141 longjmp(toplevel, 1); 142} 143 144 145static struct cmd * 146getcmd(char *name) 147{ 148 register char *p, *q; 149 register struct cmd *c, *found; 150 register int nmatches, longest; 151 extern int NCMDS; 152 153 longest = 0; 154 nmatches = 0; 155 found = NULL; 156 for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 157 p = c->c_name; 158 for (q = name; *q == *p++; q++) 159 if (*q == 0) /* exact match? */ 160 return(c); 161 if (!*q) { /* the name was a prefix */ 162 if (q - name > longest) { 163 longest = q - name; 164 nmatches = 1; 165 found = c; 166 } else if (q - name == longest) 167 nmatches++; 168 } 169 } 170 if (nmatches > 1) 171 return((struct cmd *)-1); 172 return(found); 173} 174 175/* 176 * Slice a string up into argc/argv. 177 */ 178void 179makeargv(void) 180{ 181 register char *cp; 182 register char **argp = margv; 183 184 margc = 0; 185 for (cp = cmdline; margc < MAX_MARGV - 1 && *cp; ) { 186 while (isspace(*cp)) 187 cp++; 188 if (*cp == '\0') 189 break; 190 *argp++ = cp; 191 margc += 1; 192 while (*cp != '\0' && !isspace(*cp)) 193 cp++; 194 if (*cp == '\0') 195 break; 196 *cp++ = '\0'; 197 } 198 *argp++ = NULL; 199} 200 201#define HELPINDENT (sizeof ("directory")) 202 203/* 204 * Help command. 205 */ 206void 207help(int argc, char *argv[]) 208{ 209 register struct cmd *c; 210 211 if (argc == 1) { 212 register int i, j, w; 213 int columns, width = 0, lines; 214 extern int NCMDS; 215 216 printf("Commands may be abbreviated. Commands are:\n\n"); 217 for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 218 int len = strlen(c->c_name); 219 220 if (len > width) 221 width = len; 222 } 223 width = (width + 8) &~ 7; 224 columns = 80 / width; 225 if (columns == 0) 226 columns = 1; 227 lines = (NCMDS + columns - 1) / columns; 228 for (i = 0; i < lines; i++) { 229 for (j = 0; j < columns; j++) { 230 c = cmdtab + j * lines + i; 231 printf("%s", c->c_name); 232 if (c + lines >= &cmdtab[NCMDS]) { 233 printf("\n"); 234 break; 235 } 236 w = strlen(c->c_name); 237 while (w < width) { 238 w = (w + 8) &~ 7; 239 putchar('\t'); 240 } 241 } 242 } 243 return; 244 } 245 while (--argc > 0) { 246 register char *arg; 247 arg = *++argv; 248 c = getcmd(arg); 249 if (c == (struct cmd *)-1) 250 printf("?Ambiguous help command %s\n", arg); 251 else if (c == (struct cmd *)0) 252 printf("?Invalid help command %s\n", arg); 253 else 254 printf("%-*s\t%s\n", (int)HELPINDENT, 255 c->c_name, c->c_help); 256 } 257} 258