source: trunk/athena/bin/lpr/rmjob.c @ 7910

Revision 7910, 11.0 KB checked in by miki, 29 years ago (diff)
include posix.h for POSIX systems, to have the defines for flock flock on some systems requires file to be read-write
Line 
1/*
2 *      $Source: /afs/dev.mit.edu/source/repository/athena/bin/lpr/rmjob.c,v $
3 *      $Author: miki $
4 *      $Locker:  $
5 *      $Header: /afs/dev.mit.edu/source/repository/athena/bin/lpr/rmjob.c,v 1.8 1995-07-11 20:39:25 miki Exp $
6 */
7
8#ifndef lint
9static char *rcsid_rmjob_c = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/lpr/rmjob.c,v 1.8 1995-07-11 20:39:25 miki Exp $";
10#endif lint
11
12/*
13 * Copyright (c) 1983 Regents of the University of California.
14 * All rights reserved.  The Berkeley software License Agreement
15 * specifies the terms and conditions for redistribution.
16 */
17
18#ifndef lint
19static char sccsid[] = "@(#)rmjob.c     5.1 (Berkeley) 6/6/85";
20#endif not lint
21
22/*
23 * rmjob - remove the specified jobs from the queue.
24 */
25
26#include "lp.h"
27#if defined(POSIX) && !defined(ultrix)
28#include "posix.h"
29#endif
30
31/*
32 * Stuff for handling lprm specifications
33 */
34extern char     *user[];                /* users to process */
35extern int      users;                  /* # of users in user array */
36extern int      requ[];                 /* job number of spool entries */
37extern int      requests;               /* # of spool requests */
38extern char     *person;                /* name of person doing lprm */
39
40char    root[] = "root";
41int     all = 0;                /* eliminate all files (root only) */
42int     cur_daemon;             /* daemon's pid */
43char    current[40];            /* active control file name */
44int     assasinated = 0;        /* 1 means we've killed the lpd */
45
46#if defined(KERBEROS)
47extern int      use_kerberos;
48extern int      kerberos_override;
49short KA;
50KTEXT_ST kticket;
51long kerror;
52#endif /* KERBEROS */
53
54int     iscf();
55
56rmjob()
57{
58        register int i, nitems;
59#ifdef POSIX
60        struct dirent **files;
61#else
62        struct direct **files;
63#endif
64
65        assasinated = 0;        /* Haven't killed it yet! */
66        nitems = 0;             /* Items in the local spool area */
67       
68#ifdef HESIOD
69        if ((i = pgetent(line, printer)) <= 0) {
70                if (pralias(alibuf, printer))
71                        printer = alibuf;
72                if ((i = hpgetent(line, printer)) < 1)
73                        fatal("unknown printer");
74        }
75#else
76        if ((i = pgetent(line, printer)) < 0) {
77                fatal("cannot open printer description file");
78        } else if (i == 0)
79                fatal("unknown printer");
80#endif /* HESIOD */
81        if ((SD = pgetstr("sd", &bp)) == NULL)
82                SD = DEFSPOOL;
83        if ((LO = pgetstr("lo", &bp)) == NULL)
84                LO = DEFLOCK;
85        if ((LP = pgetstr("lp", &bp)) == NULL)
86                LP = DEFDEVLP;
87        if ((RP = pgetstr("rp", &bp)) == NULL)
88                RP = DEFLP;
89        RM = pgetstr("rm", &bp);
90
91#if defined(KERBEROS)
92        KA = pgetnum("ka");
93        if (KA > 0)
94            use_kerberos = 1;
95        else
96            use_kerberos = 0;
97        if (kerberos_override > -1)
98            use_kerberos = kerberos_override;
99#endif /* KERBEROS */
100
101        /*
102         * If the format was `lprm -' and the user isn't the super-user,
103         *  then fake things to look like he said `lprm user'.
104         */
105        if (users < 0) {
106                if (getuid() == 0)
107                        all = 1;        /* all files in local queue */
108                else {
109                        user[0] = person;
110                        users = 1;
111                }
112        }
113        if (!strcmp(person, "-all")) {
114                if (from == host)
115                        fatal("The login name \"-all\" is reserved");
116                all = 1;        /* all those from 'from' */
117                person = root;
118        }
119       
120        if (chdir(SD) < 0) {
121                if (RM == (char *)0)
122                        fatal("cannot chdir to spool directory");
123        } else if ((nitems = scandir(".", &files, iscf, NULL)) < 0)
124                fatal("cannot access spool directory");
125
126        if (nitems) {
127                /*
128                 * process the files
129                 */
130                for (i = 0; i < nitems; i++)
131                        process(files[i]->d_name);
132        }
133        chkremote();
134        /*
135         * Restart the printer daemon if it was killed
136         */
137        if (assasinated && !startdaemon(printer))
138                fatal("cannot restart printer daemon\n");
139
140        exit(0);
141}
142
143/*
144 * Process a lock file: collect the pid of the active
145 *  daemon and the file name of the active spool entry.
146 * Return boolean indicating existence of a lock file.
147 */
148lockchk(s)
149        char *s;
150{
151        register FILE *fp;
152        register int i, n;
153
154        cur_daemon = -1;        /* Initialize to no daemon */
155       
156        if ((fp = fopen(s, "r")) == NULL)
157                if (errno == EACCES)
158                        fatal("can't access lock file");
159                else
160                        return(0);
161        if (!getline(fp)) {
162                (void) fclose(fp);
163                return(0);              /* no daemon present */
164        }
165        cur_daemon = atoi(line);
166        if (kill(cur_daemon, 0) < 0) {
167                (void) fclose(fp);
168                return(0);              /* no daemon present */
169        }
170        for (i = 1; (n = fread(current, sizeof(char), sizeof(current), fp)) <= 0; i++) {
171                if (i > 5) {
172                        n = 1;
173                        break;
174                }
175                sleep(i);
176        }
177        current[n-1] = '\0';
178        (void) fclose(fp);
179        return(1);
180}
181
182/*
183 * Process a control file.
184 */
185process(file)
186        char *file;
187{
188        FILE *cfp;
189        int     flock_retry = 0;
190
191        if (!chk(file))
192                return;
193        if ((cfp = fopen(file, "r+")) == NULL)
194                fatal("cannot open %s", file);
195        while (flock(fileno(cfp), LOCK_EX|LOCK_NB) < 0) {
196                if (errno == EWOULDBLOCK) {
197                        /*
198                         * We couldn't get the lock; lpd must be
199                         * using the control file.  So try to
200                         * blow it away.
201                         *
202                         * Note: assasumes lockchk has already been
203                         * run, so cur_daemon contains valid
204                         * information.
205                         */
206                        if (!lockchk(LO))
207                                /* No daemon, must have just */
208                                /* exited.... */
209                                continue;
210                        syslog(LOG_DEBUG, "Killing printer daemon %d",
211                               cur_daemon);
212                        if (assasinated = kill(cur_daemon, SIGINT) == 0)
213                                sleep(1);
214                        else {
215                                syslog(LOG_ERR, "kill %d: %m", cur_daemon);
216#ifdef notdef
217                                fatal("cannot kill printer daemon");
218#endif
219                        }
220                        flock_retry++;
221                        if (flock_retry > 2)
222                                fatal("cannot obtain lock on control file");
223                } else {
224                        syslog(LOG_ERR, "%s: %s: %m", printer, file);
225                        return;
226                }
227        }
228        while (getline(cfp)) {
229                switch (line[0]) {
230                case 'U':  /* unlink associated files */
231                        if (from != host)
232                                printf("%s: ", host);
233                        printf(UNLINK(line+1) ? "cannot dequeue %s\n" :
234                                "%s dequeued\n", line+1);
235                }
236        }
237        (void) fclose(cfp);
238        if (from != host)
239                printf("%s: ", host);
240        printf(UNLINK(file) ? "cannot dequeue %s\n" : "%s dequeued\n", file);
241}
242
243/*
244 * Do the dirty work in checking
245 */
246chk(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        if ((cfp = fopen(file, "r")) == NULL)
266                return(0);
267        while (getline(cfp)) {
268                if (line[0] == 'P')
269                        break;
270        }
271        (void) fclose(cfp);
272        if (line[0] != 'P')
273                return(0);
274
275        if (users == 0 && requests == 0)
276                return(!strcmp(file, current) && isowner(line+1, file));
277        /*
278         * Check the request list
279         */
280        for (n = 0, cp = file+3; isdigit(*cp) && cp != file+6; )
281                n = n * 10 + (*cp++ - '0');
282        for (r = requ; r < &requ[requests]; r++)
283                if (*r == n && isowner(line+1, file))
284                        return(1);
285        /*
286         * Check to see if it's in the user list
287         */
288        for (u = user; u < &user[users]; u++)
289                if (!strcmp(*u, line+1) && isowner(line+1, file))
290                        return(1);
291        return(0);
292}
293
294/*
295 * If root is removing a file on the local machine, allow it.
296 * If root is removing a file from a remote machine, only allow
297 * files sent from the remote machine to be removed.
298 * Normal users can only remove the file from where it was sent.
299 */
300isowner(owner, file)
301        char *owner, *file;
302{
303        if (!strcmp(person, root) && (from == host || !strcmp(from, file+6)))
304                return(1);
305#ifdef KERBEROS
306        if (!strcmp(person, owner))
307                return(1);
308#else
309        if (!strcmp(person, owner) && !strcmp(from, file+6))
310                return(1);
311#endif /* KERBEROS */
312        if (from != host)
313                printf("%s: ", host);
314        printf("%s: Permission denied\n", file);
315        return(0);
316}
317
318/*
319 * Check to see if we are sending files to a remote machine. If we are,
320 * then try removing files on the remote machine.
321 */
322chkremote()
323{
324        register char *cp;
325        register int i, rem;
326        register int resp;
327        int n;
328        char buf[BUFSIZ];
329        char name[255];
330        struct hostent *hp;
331
332        /* get the name of the local host */
333        gethostname (name, sizeof(name) - 1);
334        name[sizeof(name)-1] = '\0';
335
336        /* get the network standard name of the local host */
337        hp = gethostbyname (name);
338        if (hp == (struct hostent *) NULL) {
339            printf ("unable to get hostname for local machine %s\n",
340                        name);
341            return;
342        } else strcpy (name, hp->h_name);
343
344        if (RM == (char *)0)
345                RM = name;
346        else {
347                /* get the network standard name of RM */
348                hp = gethostbyname (RM);
349                if (hp == (struct hostent *) NULL) {
350                        printf ("unable to get hostname for remote machine %s\n",
351                                RM);
352                        return;
353                }
354        }
355
356        /* if printer is not on local machine, ignore LP */
357        if (strcasecmp (name, hp->h_name) != 0)
358            LP = "";
359        else return;    /* local machine */
360
361        /*
362         * Flush stdout so the user can see what has been deleted
363         * while we wait (possibly) for the connection.
364         */
365        fflush(stdout);
366
367        sprintf(buf, "\5%s %s", RP, all ? "-all" : person);
368        cp = buf;
369        for (i = 0; i < users; i++) {
370                cp += strlen(cp);
371                *cp++ = ' ';
372                (void) strcpy(cp, user[i]);
373        }
374        for (i = 0; i < requests; i++) {
375                cp += strlen(cp);
376                (void) sprintf(cp, " %d", requ[i]);
377        }
378        (void) strcat(cp, "\n");
379        rem = getport(RM);
380        if (rem < 0) {
381                if (from != host)
382                        printf("%s: ", host);
383                printf("connection to %s is down\n", RM);
384        } else {
385#ifdef KERBEROS
386                if (use_kerberos) {
387                        /* If we require kerberos authentication,
388                         * then send credentials
389                         * over
390                         */
391                        (void) sprintf(line, "k%s\n", RP);
392                        n = strlen(line);
393                        if (write(rem, line, n) != n)
394                                fatal("Error sending kerberos opcode.\n");
395
396                        if ((resp = responser(rem)) != '\0') {
397                            fprintf(stderr,
398                                    "Remote printer does not support kerberos authentication\n");
399                            if(kerberos_override == 1)
400                                fprintf(stderr, "Try again without the -k flag\n");
401                            if(kerberos_override == -1)
402                                fprintf(stderr,"Try again using the -u option\n");
403                            exit(1);
404                        }
405                       
406                        kerror = krb_sendauth(0L, rem, &kticket, KLPR_SERVICE,
407                                              RM, (char *)krb_realmofhost(RM),
408                                              0, (MSG_DAT *) 0,
409                                              (CREDENTIALS *) 0,
410                                              (bit_64 *) 0,
411                                              (struct sockaddr_in *)0,
412                                              (struct sockaddr_in *)0,
413                                              "KLPRV0.1");
414                        if (kerror != KSUCCESS)
415                            fatal("Kerberos authentication failed. Use kinit and try again.\n");
416                        if ((resp = responser(rem)) != '\0') {
417                            if (resp == '\3')
418                                fatal("Authentication failed. Use kinit and then try again.\n");
419                            else fatal("Syncronization error.\n");
420                        }
421                    }
422#endif /* KERBEROS */
423                i = strlen(buf);
424                if (write(rem, buf, i) != i)
425                        fatal("Lost connection");
426                while ((i = read(rem, buf, sizeof(buf))) > 0)
427                        (void) fwrite(buf, 1, i, stdout);
428                (void) close(rem);
429        }
430}
431
432/*
433 * Return 1 if the filename begins with 'cf'
434 */
435iscf(d)
436#ifdef POSIX
437        struct dirent *d;
438#else
439        struct direct *d;
440#endif
441{
442        return(d->d_name[0] == 'c' && d->d_name[1] == 'f');
443}
444
445/*
446 * Check to make sure there have been no errors and that both programs
447 * are in sync with eachother.
448 * Return non-zero if the connection was lost.
449 */
450
451static responser(fd)
452int fd;
453{
454        char resp;
455
456        if (read(fd, &resp, 1) != 1) {
457                fprintf(stderr,"Lost connection to printer....\n");
458                return(-1);
459        }
460        return(resp);
461}
Note: See TracBrowser for help on using the repository browser.