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.2 (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 "extern.h" 31 #include <sys/param.h> 32 #include <grp.h> 33 #include "lp.h" 34 #include "lpc.h" 35 #include "extern.h" 36 37 #ifndef LPR_OPER 38 #define LPR_OPER "operator" /* group name of lpr operators */ 39 #endif 40 41 /* 42 * lpc -- line printer control program 43 */ 44 45 int fromatty; 46 47 char cmdline[200]; 48 int margc; 49 char *margv[20]; 50 int top; 51 52 jmp_buf toplevel; 53 54 static void cmdscanner __P((int)); 55 static struct cmd *getcmd __P((char *)); 56 static void intr __P((int)); 57 static void makeargv __P((void)); 58 static int ingroup __P((char *)); 59 60 int 61 main(argc, argv) 62 int argc; 63 char *argv[]; 64 { 65 register struct cmd *c; 66 67 name = argv[0]; 68 openlog("lpd", 0, LOG_LPR); 69 70 if (--argc > 0) { 71 c = getcmd(*++argv); 72 if (c == (struct cmd *)-1) { 73 printf("?Ambiguous command\n"); 74 exit(1); 75 } 76 if (c == 0) { 77 printf("?Invalid command\n"); 78 exit(1); 79 } 80 if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) { 81 printf("?Privileged command\n"); 82 exit(1); 83 } 84 (*c->c_handler)(argc, argv); 85 exit(0); 86 } 87 fromatty = isatty(fileno(stdin)); 88 top = setjmp(toplevel) == 0; 89 if (top) 90 signal(SIGINT, intr); 91 for (;;) { 92 cmdscanner(top); 93 top = 1; 94 } 95 } 96 97 static void 98 intr(signo) 99 int signo; 100 { 101 if (!fromatty) 102 exit(0); 103 longjmp(toplevel, 1); 104 } 105 106 /* 107 * Command parser. 108 */ 109 static void 110 cmdscanner(top) 111 int top; 112 { 113 register struct cmd *c; 114 115 if (!top) 116 putchar('\n'); 117 for (;;) { 118 if (fromatty) { 119 printf("lpc> "); 120 fflush(stdout); 121 } 122 if (fgets(cmdline, sizeof(cmdline), stdin) == 0) 123 quit(0, NULL); 124 if (cmdline[0] == 0 || cmdline[0] == '\n') 125 break; 126 makeargv(); 127 c = getcmd(margv[0]); 128 if (c == (struct cmd *)-1) { 129 printf("?Ambiguous command\n"); 130 continue; 131 } 132 if (c == 0) { 133 printf("?Invalid command\n"); 134 continue; 135 } 136 if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) { 137 printf("?Privileged command\n"); 138 continue; 139 } 140 (*c->c_handler)(margc, margv); 141 } 142 longjmp(toplevel, 0); 143 } 144 145 static struct cmd * 146 getcmd(name) 147 register char *name; 148 { 149 register char *p, *q; 150 register struct cmd *c, *found; 151 register int nmatches, longest; 152 153 longest = 0; 154 nmatches = 0; 155 found = 0; 156 for (c = cmdtab; p = c->c_name; c++) { 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 */ 177 static void 178 makeargv() 179 { 180 register char *cp; 181 register char **argp = margv; 182 183 margc = 0; 184 for (cp = cmdline; *cp;) { 185 while (isspace(*cp)) 186 cp++; 187 if (*cp == '\0') 188 break; 189 *argp++ = cp; 190 margc += 1; 191 while (*cp != '\0' && !isspace(*cp)) 192 cp++; 193 if (*cp == '\0') 194 break; 195 *cp++ = '\0'; 196 } 197 *argp++ = 0; 198 } 199 200 #define HELPINDENT (sizeof ("directory")) 201 202 /* 203 * Help command. 204 */ 205 void 206 help(argc, argv) 207 int argc; 208 char *argv[]; 209 { 210 register struct cmd *c; 211 212 if (argc == 1) { 213 register int i, j, w; 214 int columns, width = 0, lines; 215 extern int NCMDS; 216 217 printf("Commands may be abbreviated. Commands are:\n\n"); 218 for (c = cmdtab; c->c_name; c++) { 219 int len = strlen(c->c_name); 220 221 if (len > width) 222 width = len; 223 } 224 width = (width + 8) &~ 7; 225 columns = 80 / width; 226 if (columns == 0) 227 columns = 1; 228 lines = (NCMDS + columns - 1) / columns; 229 for (i = 0; i < lines; i++) { 230 for (j = 0; j < columns; j++) { 231 c = cmdtab + j * lines + i; 232 if (c->c_name) 233 printf("%s", c->c_name); 234 if (c + lines >= &cmdtab[NCMDS]) { 235 printf("\n"); 236 break; 237 } 238 w = strlen(c->c_name); 239 while (w < width) { 240 w = (w + 8) &~ 7; 241 putchar('\t'); 242 } 243 } 244 } 245 return; 246 } 247 while (--argc > 0) { 248 register char *arg; 249 arg = *++argv; 250 c = getcmd(arg); 251 if (c == (struct cmd *)-1) 252 printf("?Ambiguous help command %s\n", arg); 253 else if (c == (struct cmd *)0) 254 printf("?Invalid help command %s\n", arg); 255 else 256 printf("%-*s\t%s\n", HELPINDENT, 257 c->c_name, c->c_help); 258 } 259 } 260 261 /* 262 * return non-zero if the user is a member of the given group 263 */ 264 static int 265 ingroup(grname) 266 char *grname; 267 { 268 static struct group *gptr=NULL; 269 static gid_t groups[NGROUPS]; 270 register gid_t gid; 271 register int i; 272 273 if (gptr == NULL) { 274 if ((gptr = getgrnam(grname)) == NULL) { 275 fprintf(stderr, "Warning: unknown group '%s'\n", 276 grname); 277 return(0); 278 } 279 if (getgroups(NGROUPS, groups) < 0) { 280 perror("getgroups"); 281 exit(1); 282 } 283 } 284 gid = gptr->gr_gid; 285 for (i = 0; i < NGROUPS; i++) 286 if (gid == groups[i]) 287 return(1); 288 return(0); 289 } 290