1 /* $OpenBSD: lprm.c,v 1.21 2015/01/16 06:40:18 deraadt Exp $ */ 2 /* $$NetBSD: lprm.c,v 1.9 1999/08/16 03:12:32 simonb Exp $ */ 3 4 /* 5 * Copyright (c) 1983, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 /* 35 * lprm - remove the current user's spool entry 36 * 37 * lprm [-] [[job #] [user] ...] 38 * 39 * Using information in the lock file, lprm will kill the 40 * currently active daemon (if necessary), remove the associated files, 41 * and startup a new daemon. Privileged users may remove anyone's spool 42 * entries, otherwise one can only remove their own. 43 */ 44 45 46 #include <ctype.h> 47 #include <signal.h> 48 #include <dirent.h> 49 #include <err.h> 50 #include <errno.h> 51 #include <pwd.h> 52 #include <stdlib.h> 53 #include <stdio.h> 54 #include <string.h> 55 #include <syslog.h> 56 #include <unistd.h> 57 #include <limits.h> 58 59 #include "lp.h" 60 #include "lp.local.h" 61 62 /* 63 * Stuff for handling job specifications 64 */ 65 char *person; /* name of person doing lprm */ 66 int requ[MAXREQUESTS]; /* job number of spool entries */ 67 int requests; /* # of spool requests */ 68 char *user[MAXUSERS]; /* users to process */ 69 int users; /* # of users in user array */ 70 volatile sig_atomic_t gotintr; /* set when we receive SIGINT */ 71 static char luser[LOGIN_NAME_MAX]; /* buffer for person */ 72 73 static __dead void usage(void); 74 75 int 76 main(int argc, char **argv) 77 { 78 struct passwd *pw; 79 char *cp; 80 long l; 81 int ch; 82 83 /* 84 * Simulate setuid daemon w/ PRIV_END called. 85 * We don't want lpr to actually be setuid daemon since that 86 * requires that the lpr binary be owned by user daemon, which 87 * is potentially unsafe. 88 */ 89 if ((pw = getpwuid(DEFUID)) == NULL) 90 errx(1, "daemon uid (%u) not in password file", DEFUID); 91 effective_uid = pw->pw_uid; 92 real_uid = getuid(); 93 effective_gid = pw->pw_gid; 94 real_gid = getgid(); 95 setresgid(real_gid, real_gid, effective_gid); 96 setresuid(real_uid, real_uid, effective_uid); 97 98 gethostname(host, sizeof(host)); 99 openlog("lprm", 0, LOG_LPR); 100 if ((pw = getpwuid(real_uid)) == NULL) 101 fatal("Who are you?"); 102 if (strlen(pw->pw_name) >= sizeof(luser)) 103 fatal("Your name is too long"); 104 strlcpy(luser, pw->pw_name, sizeof(luser)); 105 person = luser; 106 while ((ch = getopt(argc, argv, "P:w:-")) != -1) { 107 switch (ch) { 108 case '-': 109 users = -1; 110 break; 111 case 'P': 112 printer = optarg; 113 break; 114 case 'w': 115 l = strtol(optarg, &cp, 10); 116 if (*cp != '\0' || l < 0 || l >= INT_MAX) 117 errx(1, "wait time must be positive integer: %s", 118 optarg); 119 wait_time = (u_int)l; 120 if (wait_time < 30) 121 warnx("warning: wait time less than 30 seconds"); 122 break; 123 default: 124 usage(); 125 } 126 } 127 argc -= optind; 128 argv += optind; 129 130 if (printer == NULL && (printer = getenv("PRINTER")) == NULL) 131 printer = DEFLP; 132 if (users < 0 && argc != 0) 133 usage(); 134 while (argc > 0) { 135 if (isdigit((unsigned char)*argv[0])) { 136 if (requests >= MAXREQUESTS) 137 fatal("Too many requests"); 138 requ[requests++] = atoi(argv[0]); 139 } else { 140 if (users >= MAXUSERS) 141 fatal("Too many users"); 142 user[users++] = argv[0]; 143 } 144 argc--; 145 argv++; 146 } 147 148 rmjob(); 149 exit(0); 150 } 151 152 static __dead void 153 usage(void) 154 { 155 extern char *__progname; 156 157 fprintf(stderr, "usage: %s [-] [-Pprinter] [[job# ...] [user ...]]\n", 158 __progname); 159 exit(2); 160 } 161