1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #ifndef lint 10 static char copyright[] = 11 "@(#) Copyright (c) 1983, 1993\n\ 12 The Regents of the University of California. All rights reserved.\n"; 13 #endif /* not lint */ 14 15 #ifndef lint 16 static char sccsid[] = "@(#)lpc.c 8.3 (Berkeley) 04/28/95"; 17 #endif /* not lint */ 18 19 #include <sys/param.h> 20 21 #include <dirent.h> 22 #include <signal.h> 23 #include <setjmp.h> 24 #include <syslog.h> 25 #include <unistd.h> 26 #include <stdlib.h> 27 #include <stdio.h> 28 #include <ctype.h> 29 #include <string.h> 30 #include <grp.h> 31 #include <sys/param.h> 32 #include "lp.h" 33 #include "lpc.h" 34 #include "extern.h" 35 36 #ifndef LPR_OPER 37 #define LPR_OPER "operator" /* group name of lpr operators */ 38 #endif 39 40 /* 41 * lpc -- line printer control program 42 */ 43 44 int fromatty; 45 46 char cmdline[200]; 47 int margc; 48 char *margv[20]; 49 int top; 50 51 jmp_buf toplevel; 52 53 static void cmdscanner __P((int)); 54 static struct cmd *getcmd __P((char *)); 55 static void intr __P((int)); 56 static void makeargv __P((void)); 57 static int ingroup __P((char *)); 58 59 int 60 main(argc, argv) 61 int argc; 62 char *argv[]; 63 { 64 register struct cmd *c; 65 66 name = argv[0]; 67 openlog("lpd", 0, LOG_LPR); 68 69 if (--argc > 0) { 70 c = getcmd(*++argv); 71 if (c == (struct cmd *)-1) { 72 printf("?Ambiguous command\n"); 73 exit(1); 74 } 75 if (c == 0) { 76 printf("?Invalid command\n"); 77 exit(1); 78 } 79 if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) { 80 printf("?Privileged command\n"); 81 exit(1); 82 } 83 (*c->c_handler)(argc, argv); 84 exit(0); 85 } 86 fromatty = isatty(fileno(stdin)); 87 top = setjmp(toplevel) == 0; 88 if (top) 89 signal(SIGINT, intr); 90 for (;;) { 91 cmdscanner(top); 92 top = 1; 93 } 94 } 95 96 static void 97 intr(signo) 98 int signo; 99 { 100 if (!fromatty) 101 exit(0); 102 longjmp(toplevel, 1); 103 } 104 105 /* 106 * Command parser. 107 */ 108 static void 109 cmdscanner(top) 110 int top; 111 { 112 register struct cmd *c; 113 114 if (!top) 115 putchar('\n'); 116 for (;;) { 117 if (fromatty) { 118 printf("lpc> "); 119 fflush(stdout); 120 } 121 if (fgets(cmdline, sizeof(cmdline), stdin) == 0) 122 quit(0, NULL); 123 if (cmdline[0] == 0 || cmdline[0] == '\n') 124 break; 125 makeargv(); 126 c = getcmd(margv[0]); 127 if (c == (struct cmd *)-1) { 128 printf("?Ambiguous command\n"); 129 continue; 130 } 131 if (c == 0) { 132 printf("?Invalid command\n"); 133 continue; 134 } 135 if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) { 136 printf("?Privileged command\n"); 137 continue; 138 } 139 (*c->c_handler)(margc, margv); 140 } 141 longjmp(toplevel, 0); 142 } 143 144 static struct cmd * 145 getcmd(name) 146 register char *name; 147 { 148 register char *p, *q; 149 register struct cmd *c, *found; 150 register int nmatches, longest; 151 152 longest = 0; 153 nmatches = 0; 154 found = 0; 155 for (c = cmdtab; p = c->c_name; c++) { 156 for (q = name; *q == *p++; q++) 157 if (*q == 0) /* exact match? */ 158 return(c); 159 if (!*q) { /* the name was a prefix */ 160 if (q - name > longest) { 161 longest = q - name; 162 nmatches = 1; 163 found = c; 164 } else if (q - name == longest) 165 nmatches++; 166 } 167 } 168 if (nmatches > 1) 169 return((struct cmd *)-1); 170 return(found); 171 } 172 173 /* 174 * Slice a string up into argc/argv. 175 */ 176 static void 177 makeargv() 178 { 179 register char *cp; 180 register char **argp = margv; 181 182 margc = 0; 183 for (cp = cmdline; *cp;) { 184 while (isspace(*cp)) 185 cp++; 186 if (*cp == '\0') 187 break; 188 *argp++ = cp; 189 margc += 1; 190 while (*cp != '\0' && !isspace(*cp)) 191 cp++; 192 if (*cp == '\0') 193 break; 194 *cp++ = '\0'; 195 } 196 *argp++ = 0; 197 } 198 199 #define HELPINDENT (sizeof ("directory")) 200 201 /* 202 * Help command. 203 */ 204 void 205 help(argc, argv) 206 int argc; 207 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->c_name; 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 if (c->c_name) 232 printf("%s", c->c_name); 233 if (c + lines >= &cmdtab[NCMDS]) { 234 printf("\n"); 235 break; 236 } 237 w = strlen(c->c_name); 238 while (w < width) { 239 w = (w + 8) &~ 7; 240 putchar('\t'); 241 } 242 } 243 } 244 return; 245 } 246 while (--argc > 0) { 247 register char *arg; 248 arg = *++argv; 249 c = getcmd(arg); 250 if (c == (struct cmd *)-1) 251 printf("?Ambiguous help command %s\n", arg); 252 else if (c == (struct cmd *)0) 253 printf("?Invalid help command %s\n", arg); 254 else 255 printf("%-*s\t%s\n", HELPINDENT, 256 c->c_name, c->c_help); 257 } 258 } 259 260 /* 261 * return non-zero if the user is a member of the given group 262 */ 263 static int 264 ingroup(grname) 265 char *grname; 266 { 267 static struct group *gptr=NULL; 268 static gid_t groups[NGROUPS]; 269 register gid_t gid; 270 register int i; 271 272 if (gptr == NULL) { 273 if ((gptr = getgrnam(grname)) == NULL) { 274 fprintf(stderr, "Warning: unknown group '%s'\n", 275 grname); 276 return(0); 277 } 278 if (getgroups(NGROUPS, groups) < 0) { 279 perror("getgroups"); 280 exit(1); 281 } 282 } 283 gid = gptr->gr_gid; 284 for (i = 0; i < NGROUPS; i++) 285 if (gid == groups[i]) 286 return(1); 287 return(0); 288 } 289