source: trunk/athena/bin/lpr/netsend.c @ 6365

Revision 6365, 8.4 KB checked in by probe, 32 years ago (diff)
Cleaned up indentation (cosmetic)
Line 
1/*
2 * Netsend - sends a file to a remote lpd.  Code is taken from
3 * printjob.c, with demon code references taken out.
4 *
5 *      $Source: /afs/dev.mit.edu/source/repository/athena/bin/lpr/netsend.c,v $
6 *      $Header: /afs/dev.mit.edu/source/repository/athena/bin/lpr/netsend.c,v 1.6 1992-11-09 00:51:18 probe Exp $
7 */
8
9#ifndef lint
10static char *rcsid_netsend_c = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/lpr/netsend.c,v 1.6 1992-11-09 00:51:18 probe Exp $";
11#endif lint
12
13#define TMPDIR "/tmp"
14
15/*
16 * Copyright (c) 1983 Regents of the University of California.
17 * All rights reserved.  The Berkeley software License Agreement
18 * specifies the terms and conditions for redistribution.
19 */
20
21
22/*
23 * printjob -- print jobs in the queue.
24 *
25 *      NOTE: the lock file is used to pass information to lpq and lprm.
26 *      it does not need to be removed because file locks are dynamic.
27 */
28
29#include "lp.h"
30
31#define DORETURN        0       /* absorb fork error */
32#define DOABORT         1       /* abort if dofork fails */
33/*
34 * Error tokens
35 */
36#define REPRINT         -2
37#define ERROR           -1
38#define OK              0
39#define FATALERR        1
40#define NOACCT          2
41#define FILTERERR       3
42#define ACCESS          4
43
44FILE    *cfp;                   /* control file */
45int     pfd;                    /* printer file descriptor */
46int     ofd;                    /* output filter file descriptor */
47int     ofilter;                /* id of output filter, if any */
48int     remote;                 /* true if sending files to remote */
49dev_t   fdev;                   /* device of file pointed to by symlink */
50ino_t   fino;                   /* inode of file pointed to by symlink */
51
52#if BUFSIZ != 1024
53#undef BUFSIZ
54#define BUFSIZ 1024
55#endif
56
57#ifdef KERBEROS
58KTEXT_ST kticket;
59long kerror;
60extern int kerberos_override;
61#endif KERBEROS
62
63/*
64 * Send the daemon control file (cf) and any data files.
65 * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
66 * 0 if all is well.
67 */
68sendit(file)
69        char *file;
70{
71        register int i, err = OK;
72        char *cp, last[BUFSIZ];
73
74        if (chdir(TMPDIR)) {
75                perror("cannot chdir to TMPDIR");
76                cleanup();
77        }
78        /*
79         * open control file
80         */
81        if ((cfp = fopen(file, "r")) == NULL) {
82                perror(file);
83                return(ERROR);
84        }
85        /*
86         *      read the control file for work to do
87         *
88         *      file format -- first character in the line is a command
89         *      rest of the line is the argument.
90         *      commands of interest are:
91         *
92         *            a-z -- "file name" name of file to print
93         *              U -- "unlink" name of file to remove
94         *                    (after we print it. (Pass 2 only)).
95         */
96
97        /*
98         * pass 1
99         */
100        while (getline(cfp)) {
101        again:
102                if (line[0] == 'S') {
103                        cp = line+1;
104                        i = 0;
105                        while (*cp >= '0' && *cp <= '9')
106                                i = i * 10 + (*cp++ - '0');
107                        fdev = i;
108                        cp++;
109                        i = 0;
110                        while (*cp >= '0' && *cp <= '9')
111                                i = i * 10 + (*cp++ - '0');
112                        fino = i;
113                        continue;
114                }
115                if (line[0] >= 'a' && line[0] <= 'z') {
116                        (void) strcpy(last, line);
117                        while (i = getline(cfp))
118                                if (strcmp(last, line))
119                                        break;
120                        switch (sendfile('\3', last+1)) {
121                        case OK:
122                                if (i)
123                                        goto again;
124                                break;
125                        case REPRINT:
126                                (void) fclose(cfp);
127                                return(REPRINT);
128                        case ERROR:
129                                err = ERROR;
130                        }
131                        break;
132                }
133        }
134        if (err == OK && sendfile('\2', file) > 0) {
135                (void) fclose(cfp);
136                return(REPRINT);
137        }
138        /*
139         * pass 2
140         */
141        fseek(cfp, 0L, 0);
142        while (getline(cfp))
143                if (line[0] == 'U')
144                        (void) UNLINK(line+1);
145        /*
146         * clean-up in case another control file exists
147         */
148        (void) fclose(cfp);
149        (void) UNLINK(file);
150        return(err);
151}
152
153/*
154 * Send a data file to the remote machine and spool it.
155 * Return positive if we should try resending.
156 */
157sendfile(type, file)
158        char type, *file;
159{
160        register int f, i, amt;
161        struct stat stb;
162        char buf[BUFSIZ];
163        int sizerr, resp;
164
165        if (stat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0)
166                return(ERROR);
167        (void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
168        amt = strlen(buf);
169        for (i = 0;  ; i++) {
170                if (write(pfd, buf, amt) != amt ||
171                    (resp = response()) < 0 || resp == '\1') {
172                        (void) close(f);
173                        return(REPRINT);
174                } else if (resp == '\0')
175                        break;
176                if (i>6) {
177                        fprintf(stderr,"The printer queue is full.  Please ");
178                        fprintf(stderr,"try again in a few minutes.\n");
179                        cleanup();
180                }
181                sleep(5);
182        }
183        sizerr = 0;
184        for (i = 0; i < stb.st_size; i += BUFSIZ) {
185                amt = BUFSIZ;
186                if (i + amt > stb.st_size)
187                        amt = stb.st_size - i;
188                if (sizerr == 0 && read(f, buf, amt) != amt)
189                        sizerr = 1;
190                if (write(pfd, buf, amt) != amt) {
191                        (void) close(f);
192                        return(REPRINT);
193                }
194        }
195        (void) close(f);
196        if (sizerr) {
197                fprintf(stderr,
198                        "Warning: %s was not printed - size sync problem\n",
199                        file);
200                /* tell recvjob to ignore this file */
201                (void) write(pfd, "\1", 1);
202                return(ERROR);
203        }
204        if (write(pfd, "", 1) != 1 || (resp=response())) {
205#ifdef PQUOTA
206            /* Gross but lpr didnt have any error returns. Something
207             * is better than nothing :)
208             */
209            if (resp == '\3') {
210                fprintf(stderr, "You are not known by the quota server and ");
211                fprintf(stderr, "are not allowed to print. \n");
212                fprintf(stderr, "See User Accounts to be added.\n");
213                cleanup();      /* Never returns */
214            } else if (resp == '\4') {
215                fprintf(stderr,
216                        "You are not allowed to print on this printer. Please contact Athena\n");
217                /* You cannot be over quota, because of policy... */
218                fprintf(stderr,
219                        "User Accounts (x3-1325) or your Cluster Manager for more information.\n");
220                cleanup();      /* Never returns */
221            } else if (resp == '\5') {
222                fprintf(stderr,
223                        "The account number is not known by the quota server.\n");
224                cleanup();      /* Never returns */
225            } else if (resp == '\6') {
226                fprintf(stderr, "You are not a member of the group account.\n");
227                fprintf(stderr,
228                        "See one of the group's administrator to be added.\n");
229                cleanup();
230            } else if (resp == '\7') {
231                fprintf(stderr,
232                        "You are marked for deletion on the quota server.");
233                fprintf(stderr,
234                        "\nContact User Accounts if you should not be.\n");
235                cleanup();      /* Never returns */
236            } else if (resp == '\10') {
237                fprintf(stderr,
238                        "The account number is marked as deleted on the quota server.");
239                fprintf(stderr,
240                        "\nContact User Accounts if it should not be.\n");
241                cleanup();      /* Never returns */
242            }
243#endif PQUOTA
244            return(REPRINT);
245        }
246        return(OK);
247}
248
249/*
250 * Check to make sure there have been no errors and that both programs
251 * are in sync with eachother.
252 * Return non-zero if the connection was lost.
253 */
254response()
255{
256        char resp;
257
258        if (read(pfd, &resp, 1) != 1) {
259                fprintf(stderr,"Lost connection to printer....\n");
260                return(-1);
261        }
262        return(resp);
263}
264
265/*
266 * Acquire line printer or remote connection.
267 */
268openpr()
269{
270    register int i, n;
271    int resp;
272
273    for (i = 0; ; i++) {
274        resp = -1;
275        pfd = getport(RM);
276        if (pfd >= 0) {
277#ifdef KERBEROS
278            if (use_kerberos) {
279                /* If we require kerberos authentication,
280                 * then send credentials
281                 * over
282                 */
283                (void) sprintf(line, "k%s\n", RP);
284                n = strlen(line);
285                if (write(pfd, line, n) != n) {
286                    fprintf(stderr,
287                            "Error sending kerberos opcode.\n");
288                    cleanup();
289                }
290                if ((resp = response()) != '\0') {
291                    fprintf(stderr,
292                            "Remote printer does not support kerberos authentication\n");
293                    if(kerberos_override == 1)
294                        fprintf(stderr, "Try again without the -k flag\n");
295                    if(kerberos_override == -1)
296                        fprintf(stderr, "Try again using the -u option\n");
297                    cleanup();
298                }
299                       
300
301                kerror = krb_sendauth(0L, pfd, &kticket, KLPR_SERVICE,
302                                      RM, (char *)krb_realmofhost(RM),
303                                      0, (MSG_DAT *) 0,
304                                      (CREDENTIALS *) 0,
305                                      (bit_64 *) 0,
306                                      (struct sockaddr_in *)0,
307                                      (struct sockaddr_in *)0,
308                                      "KLPRV0.1");
309                if (kerror != KSUCCESS) {
310                    fprintf(stderr, "Kerberos authentication failed. Use kinit and try again.\n");
311                    cleanup();
312                }
313                if ((resp = response()) != '\0') {
314                    if (resp == '\3')
315                        fprintf(stderr, "Authentication failed. Use kinit and then try again.\n");
316                    else fprintf(stderr, "Syncronization error.\n");
317                    cleanup();
318                }
319            }
320#endif KERBEROS
321            (void) sprintf(line, "\2%s\n", RP);
322            n = strlen(line);
323
324            if (write(pfd, line, n) == n &&
325                (resp = response()) == '\0')
326                break;
327            (void) close(pfd);
328        }
329
330#ifdef KERBEROS
331        if (resp == '\2') {
332            /* Should provide better error XXX */
333            fprintf(stderr, "Printer requires kerberos authentication\n");
334            cleanup();
335        }
336
337#endif                                          /* KERBEROS */
338                   
339        if (resp > 0) {
340            fprintf(stderr,     "Printer queue is disabled.\n");
341            cleanup();
342        }
343        if (i>6) {
344            fprintf(stderr, "Unable to contact printer server.\n");
345            cleanup();
346        }
347        sleep(5);
348    }
349    remote = 1;
350    ofd = pfd;
351    ofilter = 0;
352}
Note: See TracBrowser for help on using the repository browser.