~ubuntu-branches/ubuntu/hoary/lpr/hoary

« back to all changes in this revision

Viewing changes to common_source/rmjob.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-03-15 14:54:38 UTC
  • Revision ID: james.westby@ubuntu.com-20030315145438-3n1sxzrmv1g34n4t
Tags: upstream-2000.05.07
ImportĀ upstreamĀ versionĀ 2000.05.07

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      $OpenBSD: rmjob.c,v 1.9 1998/04/22 14:44:08 deraadt Exp $       */
 
2
 
 
3
/*
 
4
 * Copyright (c) 1983, 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. All advertising materials mentioning features or use of this software
 
16
 *    must display the following acknowledgement:
 
17
 *      This product includes software developed by the University of
 
18
 *      California, Berkeley and its contributors.
 
19
 * 4. Neither the name of the University nor the names of its contributors
 
20
 *    may be used to endorse or promote products derived from this software
 
21
 *    without specific prior written permission.
 
22
 *
 
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
33
 * SUCH DAMAGE.
 
34
 */
 
35
 
 
36
#ifndef lint
 
37
#if 0
 
38
static char sccsid[] = "@(#)rmjob.c     8.2 (Berkeley) 4/28/95";
 
39
#else
 
40
static char rcsid[] = "$OpenBSD: rmjob.c,v 1.9 1998/04/22 14:44:08 deraadt Exp $";
 
41
#endif
 
42
#endif /* not lint */
 
43
 
 
44
#include <sys/param.h>
 
45
 
 
46
#include <signal.h>
 
47
#include <errno.h>
 
48
#include <dirent.h>
 
49
#include <unistd.h>
 
50
#include <stdlib.h>
 
51
#include <stdio.h>
 
52
#include <string.h>
 
53
#include <ctype.h>
 
54
#include "lp.h"
 
55
#include "lp.local.h"
 
56
#include "pathnames.h"
 
57
 
 
58
/*
 
59
 * rmjob - remove the specified jobs from the queue.
 
60
 */
 
61
 
 
62
/*
 
63
 * Stuff for handling lprm specifications
 
64
 */
 
65
extern char     *user[];                /* users to process */
 
66
extern int      users;                  /* # of users in user array */
 
67
extern int      requ[];                 /* job number of spool entries */
 
68
extern int      requests;               /* # of spool requests */
 
69
extern char     *person;                /* name of person doing lprm */
 
70
 
 
71
static char     root[] = "root";
 
72
static int      all = 0;                /* eliminate all files (root only) */
 
73
static int      cur_daemon;             /* daemon's pid */
 
74
static char     current[40];            /* active control file name */
 
75
 
 
76
extern uid_t    uid, euid;              /* real and effective user id's */
 
77
 
 
78
static  void    do_unlink __P((char *));
 
79
 
 
80
void
 
81
rmjob()
 
82
{
 
83
        register int i, nitems;
 
84
        int assasinated = 0;
 
85
        struct dirent **files;
 
86
        char *cp;
 
87
 
 
88
        if ((i = cgetent(&bp, printcapdb, printer)) == -2)
 
89
                fatal("can't open printer description file");
 
90
        else if (i == -1)
 
91
                fatal("unknown printer");
 
92
        else if (i == -3)
 
93
                fatal("potential reference loop detected in printcap file");
 
94
        if (cgetstr(bp, "lp", &LP) < 0)
 
95
                LP = _PATH_DEFDEVLP;
 
96
        if (cgetstr(bp, "rp", &RP) < 0)
 
97
                RP = DEFLP;
 
98
        if (cgetstr(bp, "sd", &SD) < 0)
 
99
                SD = _PATH_DEFSPOOL;
 
100
        if (cgetstr(bp,"lo", &LO) < 0)
 
101
                LO = DEFLOCK;
 
102
        cgetstr(bp, "rm", &RM);
 
103
        if ((cp = checkremote()))
 
104
                printf("Warning: %s\n", cp);
 
105
 
 
106
        /*
 
107
         * If the format was `lprm -' and the user isn't the super-user,
 
108
         *  then fake things to look like he said `lprm user'.
 
109
         */
 
110
        if (users < 0) {
 
111
                if (getuid() == 0)
 
112
                        all = 1;        /* all files in local queue */
 
113
                else {
 
114
                        user[0] = person;
 
115
                        users = 1;
 
116
                }
 
117
        }
 
118
        if (!strcmp(person, "-all")) {
 
119
                if (from == host)
 
120
                        fatal("The login name \"-all\" is reserved");
 
121
                all = 1;        /* all those from 'from' */
 
122
                person = root;
 
123
        }
 
124
 
 
125
        seteuid(euid);
 
126
        if (chdir(SD) < 0)
 
127
                fatal("cannot chdir to spool directory");
 
128
        if ((nitems = scandir(".", &files, iscf, NULL)) < 0)
 
129
                fatal("cannot access spool directory");
 
130
        seteuid(uid);
 
131
 
 
132
        if (nitems) {
 
133
                /*
 
134
                 * Check for an active printer daemon (in which case we
 
135
                 *  kill it if it is reading our file) then remove stuff
 
136
                 *  (after which we have to restart the daemon).
 
137
                 */
 
138
                if (lockchk(LO) && chk(current)) {
 
139
                        seteuid(euid);
 
140
                        assasinated = kill(cur_daemon, SIGINT) == 0;
 
141
                        seteuid(uid);
 
142
                        if (!assasinated)
 
143
                                fatal("cannot kill printer daemon");
 
144
                }
 
145
                /*
 
146
                 * process the files
 
147
                 */
 
148
                for (i = 0; i < nitems; i++)
 
149
                        process(files[i]->d_name);
 
150
        }
 
151
        rmremote();
 
152
        /*
 
153
         * Restart the printer daemon if it was killed
 
154
         */
 
155
        if (assasinated && !startdaemon(printer))
 
156
                fatal("cannot restart printer daemon\n");
 
157
        exit(0);
 
158
}
 
159
 
 
160
/*
 
161
 * Process a lock file: collect the pid of the active
 
162
 *  daemon and the file name of the active spool entry.
 
163
 * Return boolean indicating existence of a lock file.
 
164
 */
 
165
int
 
166
lockchk(s)
 
167
        char *s;
 
168
{
 
169
        register FILE *fp;
 
170
        register int i, n;
 
171
 
 
172
        seteuid(euid);
 
173
        if ((fp = fopen(s, "r")) == NULL) {
 
174
                if (errno == EACCES)
 
175
                        fatal("can't access lock file");
 
176
                else
 
177
                        return(0);
 
178
        }
 
179
        seteuid(uid);
 
180
        if (!getline(fp)) {
 
181
                (void) fclose(fp);
 
182
                return(0);              /* no daemon present */
 
183
        }
 
184
        cur_daemon = atoi(line);
 
185
        if (kill(cur_daemon, 0) < 0 && errno != EPERM) {
 
186
                (void) fclose(fp);
 
187
                return(0);              /* no daemon present */
 
188
        }
 
189
        for (i = 1; (n = fread(current, sizeof(char), sizeof(current), fp)) <= 0; i++) {
 
190
                if (i > 5) {
 
191
                        n = 1;
 
192
                        break;
 
193
                }
 
194
                sleep(i);
 
195
        }
 
196
        current[n-1] = '\0';
 
197
        (void) fclose(fp);
 
198
        return(1);
 
199
}
 
200
 
 
201
/*
 
202
 * Process a control file.
 
203
 */
 
204
void
 
205
process(file)
 
206
        char *file;
 
207
{
 
208
        FILE *cfp;
 
209
 
 
210
        if (!chk(file))
 
211
                return;
 
212
        seteuid(euid);
 
213
        if ((cfp = fopen(file, "r")) == NULL)
 
214
                fatal("cannot open %s", file);
 
215
        seteuid(uid);
 
216
        while (getline(cfp)) {
 
217
                switch (line[0]) {
 
218
                case 'U':  /* unlink associated files */
 
219
                        if (strchr(line+1, '/') || strncmp(line+1, "df", 2))
 
220
                                break;
 
221
                        do_unlink(line+1);
 
222
                }
 
223
        }
 
224
        (void) fclose(cfp);
 
225
        do_unlink(file);
 
226
}
 
227
 
 
228
static void
 
229
do_unlink(file)
 
230
        char *file;
 
231
{
 
232
        int     ret;
 
233
 
 
234
        if (from != host)
 
235
                printf("%s: ", host);
 
236
        seteuid(euid);
 
237
        ret = unlink(file);
 
238
        seteuid(uid);
 
239
        printf(ret ? "cannot dequeue %s\n" : "%s dequeued\n", file);
 
240
}
 
241
 
 
242
/*
 
243
 * Do the dirty work in checking
 
244
 */
 
245
int
 
246
chk(file)
 
247
        char *file;
 
248
{
 
249
        register int *r, n;
 
250
        register char **u, *cp;
 
251
        FILE *cfp;
 
252
 
 
253
        /*
 
254
         * Check for valid cf file name (mostly checking current).
 
255
         */
 
256
        if (strlen(file) < 7 || file[0] != 'c' || file[1] != 'f')
 
257
                return(0);
 
258
 
 
259
        if (all && (from == host || !strcmp(from, file+6)))
 
260
                return(1);
 
261
 
 
262
        /*
 
263
         * get the owner's name from the control file.
 
264
         */
 
265
        seteuid(euid);
 
266
        if ((cfp = fopen(file, "r")) == NULL)
 
267
                return(0);
 
268
        seteuid(uid);
 
269
        while (getline(cfp)) {
 
270
                if (line[0] == 'P')
 
271
                        break;
 
272
        }
 
273
        (void) fclose(cfp);
 
274
        if (line[0] != 'P')
 
275
                return(0);
 
276
 
 
277
        if (users == 0 && requests == 0)
 
278
                return(!strcmp(file, current) && isowner(line+1, file));
 
279
        /*
 
280
         * Check the request list
 
281
         */
 
282
        for (n = 0, cp = file+3; isdigit(*cp); )
 
283
                n = n * 10 + (*cp++ - '0');
 
284
        for (r = requ; r < &requ[requests]; r++)
 
285
                if (*r == n && isowner(line+1, file))
 
286
                        return(1);
 
287
        /*
 
288
         * Check to see if it's in the user list
 
289
         */
 
290
        for (u = user; u < &user[users]; u++)
 
291
                if (!strcmp(*u, line+1) && isowner(line+1, file))
 
292
                        return(1);
 
293
        return(0);
 
294
}
 
295
 
 
296
/*
 
297
 * If root is removing a file on the local machine, allow it.
 
298
 * If root is removing a file from a remote machine, only allow
 
299
 * files sent from the remote machine to be removed.
 
300
 * Normal users can only remove the file from where it was sent.
 
301
 */
 
302
int
 
303
isowner(owner, file)
 
304
        char *owner, *file;
 
305
{
 
306
        if (!strcmp(person, root) && (from == host || !strcmp(from, file+6)))
 
307
                return(1);
 
308
        if (!strcmp(person, owner) && !strcmp(from, file+6))
 
309
                return(1);
 
310
        if (from != host)
 
311
                printf("%s: ", host);
 
312
        printf("%s: Permission denied\n", file);
 
313
        return(0);
 
314
}
 
315
 
 
316
/*
 
317
 * Check to see if we are sending files to a remote machine. If we are,
 
318
 * then try removing files on the remote machine.
 
319
 */
 
320
void
 
321
rmremote()
 
322
{
 
323
        register char *cp;
 
324
        register int i, rem;
 
325
        char buf[BUFSIZ];
 
326
 
 
327
        if (!remote)
 
328
                return; /* not sending to a remote machine */
 
329
 
 
330
        /*
 
331
         * Flush stdout so the user can see what has been deleted
 
332
         * while we wait (possibly) for the connection.
 
333
         */
 
334
        fflush(stdout);
 
335
 
 
336
        (void)snprintf(buf, sizeof(buf)-2, "\5%s %s", RP, all ? "-all" : person);
 
337
        cp = buf + strlen(buf);
 
338
        for (i = 0; i < users && cp-buf+1+strlen(user[i]) < sizeof buf - 2; i++) {
 
339
                cp += strlen(cp);
 
340
                *cp++ = ' ';
 
341
                strcpy(cp, user[i]);
 
342
        }
 
343
        for (i = 0; i < requests && cp-buf+10 < sizeof(buf) - 2; i++) {
 
344
                cp += strlen(cp);
 
345
                (void) sprintf(cp, " %d", requ[i]);
 
346
        }
 
347
        strcat(cp, "\n");
 
348
        rem = getport(RM, 0);
 
349
        if (rem < 0) {
 
350
                if (from != host)
 
351
                        printf("%s: ", host);
 
352
                printf("connection to %s is down\n", RM);
 
353
        } else {
 
354
                i = strlen(buf);
 
355
                if (write(rem, buf, i) != i)
 
356
                        fatal("Lost connection");
 
357
                while ((i = read(rem, buf, sizeof(buf))) > 0)
 
358
                        (void) fwrite(buf, 1, i, stdout);
 
359
                (void) close(rem);
 
360
        }
 
361
}
 
362
 
 
363
/*
 
364
 * Return 1 if the filename begins with 'cf'
 
365
 */
 
366
int
 
367
iscf(d)
 
368
        struct dirent *d;
 
369
{
 
370
        return(d->d_name[0] == 'c' && d->d_name[1] == 'f');
 
371
}