~ubuntu-branches/ubuntu/precise/netatalk/precise

« back to all changes in this revision

Viewing changes to etc/papd/lp.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Rittau
  • Date: 2004-01-19 12:43:49 UTC
  • Revision ID: james.westby@ubuntu.com-20040119124349-es563jbp0hk0ae51
Tags: upstream-1.6.4
ImportĀ upstreamĀ versionĀ 1.6.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: lp.c,v 1.14 2002/09/29 23:29:13 sibaz Exp $
 
3
 *
 
4
 * Copyright (c) 1990,1994 Regents of The University of Michigan.
 
5
 * All Rights Reserved.  See COPYRIGHT.
 
6
 *
 
7
 * Portions:
 
8
 * Copyright (c) 1983 Regents of the University of California.
 
9
 * All rights reserved.
 
10
 *
 
11
 * Redistribution and use in source and binary forms, with or without
 
12
 * modification, are permitted provided that the following conditions
 
13
 * are met:
 
14
 * 1. Redistributions of source code must retain the above copyright
 
15
 *    notice, this list of conditions and the following disclaimer.
 
16
 * 2. Redistributions in binary form must reproduce the above copyright
 
17
 *    notice, this list of conditions and the following disclaimer in the
 
18
 *    documentation and/or other materials provided with the distribution.
 
19
 * 3. All advertising materials mentioning features or use of this software
 
20
 *    must display the following acknowledgement:
 
21
 *      This product includes software developed by the University of
 
22
 *      California, Berkeley and its contributors.
 
23
 * 4. Neither the name of the University nor the names of its contributors
 
24
 *    may be used to endorse or promote products derived from this software
 
25
 *    without specific prior written permission.
 
26
 *
 
27
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
28
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
29
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
30
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
31
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
32
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
33
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
34
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
35
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
36
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
37
 * SUCH DAMAGE.
 
38
 */
 
39
 
 
40
/*
 
41
 * Interface to lpr system.
 
42
 */
 
43
 
 
44
#ifdef HAVE_CONFIG_H
 
45
#include "config.h"
 
46
#endif /* HAVE_CONFIG_H */
 
47
 
 
48
#include <sys/param.h>
 
49
#include <atalk/logger.h>
 
50
#include <sys/time.h>
 
51
#include <sys/socket.h>
 
52
#include <sys/stat.h>
 
53
#include <ctype.h>
 
54
#ifdef HAVE_UNISTD_H
 
55
#include <unistd.h>
 
56
#endif /* HAVE_UNISTD_H */
 
57
 
 
58
#if defined( sun ) && defined( __svr4__ )
 
59
#include </usr/ucbinclude/sys/file.h>
 
60
#else /* sun && __svr4__ */
 
61
#include <sys/file.h>
 
62
#endif /* sun && __svr4__ */
 
63
#include <sys/un.h>
 
64
#include <netinet/in.h>
 
65
#undef s_net
 
66
#include <netatalk/at.h>
 
67
#include <atalk/atp.h>
 
68
#include <atalk/paths.h>
 
69
 
 
70
#ifdef ABS_PRINT
 
71
#include <math.h>
 
72
#endif /* ABS_PRINT */
 
73
 
 
74
#include <stdio.h>
 
75
#include <stdlib.h>
 
76
#include <string.h>
 
77
#include <netdb.h>
 
78
#ifdef HAVE_FCNTL_H
 
79
#include <fcntl.h>
 
80
#endif /* HAVE_FCNTL_H */
 
81
#include <pwd.h>
 
82
 
 
83
#include "printer.h"
 
84
#include "file.h"
 
85
#include "lp.h"
 
86
 
 
87
/* These functions aren't used outside of lp.c */
 
88
int lp_conn_inet();
 
89
int lp_disconn_inet( int );
 
90
int lp_conn_unix();
 
91
int lp_disconn_unix( int );
 
92
 
 
93
char    hostname[ MAXHOSTNAMELEN ];
 
94
 
 
95
extern struct sockaddr_at *sat;
 
96
 
 
97
struct lp {
 
98
    int                 lp_flags;
 
99
    FILE                *lp_stream;
 
100
    int                 lp_seq;
 
101
    char                lp_letter;
 
102
    char                *lp_person;
 
103
    char                *lp_host;
 
104
    char                *lp_job;
 
105
} lp;
 
106
#define LP_INIT         (1<<0)
 
107
#define LP_OPEN         (1<<1)
 
108
#define LP_PIPE         (1<<2)
 
109
#define LP_CONNECT      (1<<3)
 
110
#define LP_QUEUE        (1<<4)
 
111
 
 
112
void lp_person( person )
 
113
    char        *person;
 
114
{
 
115
    if ( lp.lp_person != NULL ) {
 
116
        free( lp.lp_person );
 
117
    }
 
118
    if (( lp.lp_person = (char *)malloc( strlen( person ) + 1 )) == NULL ) {
 
119
        LOG(log_error, logtype_papd, "malloc: %m" );
 
120
        exit( 1 );
 
121
    }
 
122
    strcpy( lp.lp_person, person );
 
123
}
 
124
 
 
125
#ifdef ABS_PRINT
 
126
int lp_pagecost()
 
127
{
 
128
    char        cost[ 22 ];
 
129
    char        balance[ 22 ];
 
130
    int         err;
 
131
 
 
132
    if ( lp.lp_person == NULL ) {
 
133
        return( -1 );
 
134
    }
 
135
    err = ABS_canprint( lp.lp_person, printer->p_role, printer->p_srvid,
 
136
            cost, balance );
 
137
    printer->p_pagecost = floor( atof( cost ) * 10000.0 );
 
138
    printer->p_balance = atof( balance ) + atof( cost );
 
139
    return( err < 0 ? -1 : 0 );
 
140
}
 
141
#endif /* ABS_PRINT */
 
142
 
 
143
void lp_host( host )
 
144
    char        *host;
 
145
{
 
146
    if ( lp.lp_host != NULL ) {
 
147
        free( lp.lp_host );
 
148
    }
 
149
    if (( lp.lp_host = (char *)malloc( strlen( host ) + 1 )) == NULL ) {
 
150
        LOG(log_error, logtype_papd, "malloc: %m" );
 
151
        exit( 1 );
 
152
    }
 
153
    strcpy( lp.lp_host, host );
 
154
}
 
155
 
 
156
void lp_job( job )
 
157
    char        *job;
 
158
{
 
159
    char        *p, *q;
 
160
 
 
161
    if ( lp.lp_job != NULL ) {
 
162
        free( lp.lp_job );
 
163
    }
 
164
    if (( lp.lp_job = (char *)malloc( strlen( job ) + 1 )) == NULL ) {
 
165
        LOG(log_error, logtype_papd, "malloc: %m" );
 
166
        exit( 1 );
 
167
    }
 
168
    for ( p = job, q = lp.lp_job; *p != '\0'; p++, q++ ) {
 
169
        if ( !isascii( *p ) || !isprint( *p ) || *p == '\\' ) {
 
170
            *q = '.';
 
171
        } else {
 
172
            *q = *p;
 
173
        }
 
174
    }
 
175
    *q = '\0';
 
176
}
 
177
 
 
178
int lp_init( out, sat )
 
179
    struct papfile      *out;
 
180
    struct sockaddr_at  *sat;
 
181
{
 
182
    int         fd, n, len;
 
183
    char        *cp, buf[ BUFSIZ ];
 
184
    struct stat st;
 
185
    int         authenticated = 0;
 
186
#ifdef ABS_PRINT
 
187
    char        cost[ 22 ];
 
188
    char        balance[ 22 ];
 
189
#endif /* ABS_PRINT */
 
190
 
 
191
    if ( printer->p_flags & P_AUTH ) {
 
192
        authenticated = 0;
 
193
 
 
194
        /* cap style "log on to afp server before printing" authentication */
 
195
 
 
196
        if ( printer->p_authprintdir && (printer->p_flags & P_AUTH_CAP) ) {
 
197
            int addr_net = ntohs( sat->sat_addr.s_net );
 
198
            int addr_node  = sat->sat_addr.s_node;
 
199
            char addr_filename[256];
 
200
            char auth_string[256];
 
201
            char *username, *afpdpid;
 
202
            struct stat cap_st;
 
203
            FILE *cap_file;
 
204
 
 
205
            memset( auth_string, 0, 256 );
 
206
            sprintf(addr_filename, "%s/net%d.%dnode%d", 
 
207
                printer->p_authprintdir, addr_net/256, addr_net%256, 
 
208
                addr_node);
 
209
            if (stat(addr_filename, &cap_st) == 0) {
 
210
                if ((cap_file = fopen(addr_filename, "r")) != NULL) {
 
211
                    if (fgets(auth_string, 256, cap_file) != NULL) {
 
212
                        username = auth_string;
 
213
                        if ((afpdpid = strrchr( auth_string, ':' )) != NULL) {
 
214
                            *afpdpid = '\0';
 
215
                            afpdpid++;
 
216
                        }
 
217
                        if (getpwnam(username) != NULL ) {
 
218
                            LOG(log_info, logtype_papd, "CAP authenticated %s", username);
 
219
                            lp_person(username);
 
220
                            authenticated = 1;
 
221
                        } else {
 
222
                            LOG(log_info, logtype_papd, "CAP error: invalid username: '%s'", username);
 
223
                        }
 
224
                    } else {
 
225
                        LOG(log_info, logtype_papd, "CAP error: could not read username");
 
226
                    }
 
227
                } else {
 
228
                    LOG(log_info, logtype_papd, "CAP error: %m");
 
229
                }
 
230
            } else {
 
231
                LOG(log_info, logtype_papd, "CAP error: %m");
 
232
            }
 
233
        }
 
234
 
 
235
        if ( printer->p_flags & P_AUTH_PSSP ) {
 
236
            if ( lp.lp_person != NULL ) {
 
237
                authenticated = 1;
 
238
            }
 
239
        }
 
240
 
 
241
        if ( authenticated == 0 ) {
 
242
            LOG(log_error, logtype_papd, "lp_init: must authenticate" );
 
243
            spoolerror( out, "Authentication required." );
 
244
            return( -1 );
 
245
        }
 
246
 
 
247
#ifdef ABS_PRINT
 
248
        if (( printer->p_flags & P_ACCOUNT ) && printer->p_pagecost > 0 &&
 
249
                ! ABS_canprint( lp.lp_person, printer->p_role,
 
250
                printer->p_srvid, cost, balance )) {
 
251
            LOG(log_error, logtype_papd, "lp_init: no ABS funds" );
 
252
            spoolerror( out, "No ABS funds available." );
 
253
            return( -1 );
 
254
        }
 
255
#endif /* ABS_PRINT */
 
256
    }
 
257
 
 
258
    if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
 
259
        LOG(log_error, logtype_papd, "gethostname: %m" );
 
260
        exit( 1 );
 
261
    }
 
262
 
 
263
    if ( lp.lp_flags & LP_INIT ) {
 
264
        LOG(log_error, logtype_papd, "lp_init: already inited, die!" );
 
265
        abort();
 
266
    }
 
267
 
 
268
    lp.lp_flags = 0;
 
269
    lp.lp_stream = NULL;
 
270
    lp.lp_letter = 'A';
 
271
 
 
272
    if ( printer->p_flags & P_SPOOLED ) {
 
273
        /* check if queuing is enabled: mode & 010 on lock file */
 
274
        if ( stat( printer->p_lock, &st ) < 0 ) {
 
275
            LOG(log_error, logtype_papd, "lp_init: %s: %m", printer->p_lock );
 
276
            spoolerror( out, NULL );
 
277
            return( -1 );
 
278
        }
 
279
        if ( st.st_mode & 010 ) {
 
280
            LOG(log_info, logtype_papd, "lp_init: queuing is disabled" );
 
281
            spoolerror( out, "Queuing is disabled." );
 
282
            return( -1 );
 
283
        }
 
284
 
 
285
        if (( fd = open( ".seq", O_RDWR|O_CREAT, 0661 )) < 0 ) {
 
286
            LOG(log_error, logtype_papd, "lp_init: can't create .seq" );
 
287
            spoolerror( out, NULL );
 
288
            return( -1 );
 
289
        }
 
290
 
 
291
        if ( flock( fd, LOCK_EX ) < 0 ) {
 
292
            LOG(log_error, logtype_papd, "lp_init: can't lock .seq" );
 
293
            spoolerror( out, NULL );
 
294
            return( -1 );
 
295
        }
 
296
 
 
297
        n = 0;
 
298
        if (( len = read( fd, buf, sizeof( buf ))) < 0 ) {
 
299
            LOG(log_error, logtype_papd, "lp_init read: %m" );
 
300
            spoolerror( out, NULL );
 
301
            return( -1 );
 
302
        }
 
303
        if ( len > 0 ) {
 
304
            for ( cp = buf; len; len--, cp++ ) {
 
305
                if ( *cp < '0' || *cp > '9' ) {
 
306
                    break;
 
307
                }
 
308
                n = n * 10 + ( *cp - '0' );
 
309
            }
 
310
        }
 
311
        lp.lp_seq = n;
 
312
 
 
313
        n = ( n + 1 ) % 1000;
 
314
        sprintf( buf, "%03d\n", n );
 
315
        lseek( fd, 0L, 0 );
 
316
        write( fd, buf, strlen( buf ));
 
317
        close( fd );
 
318
    } else {
 
319
        lp.lp_flags |= LP_PIPE;
 
320
        lp.lp_seq = getpid();
 
321
    }
 
322
 
 
323
    lp.lp_flags |= LP_INIT;
 
324
    return( 0 );
 
325
}
 
326
 
 
327
int lp_open( out, sat )
 
328
    struct papfile      *out;
 
329
    struct sockaddr_at  *sat;
 
330
{
 
331
    char        name[ MAXPATHLEN ];
 
332
    int         fd;
 
333
    struct passwd       *pwent;
 
334
 
 
335
    if (( lp.lp_flags & LP_INIT ) == 0 && lp_init( out, sat ) != 0 ) {
 
336
        return( -1 );
 
337
    }
 
338
    if ( lp.lp_flags & LP_OPEN ) {
 
339
        LOG(log_error, logtype_papd, "lp_open already open" );
 
340
        abort();
 
341
    }
 
342
 
 
343
    if ( lp.lp_flags & LP_PIPE ) {
 
344
        /* go right to program */
 
345
        if (lp.lp_person != NULL) {
 
346
            if((pwent = getpwnam(lp.lp_person)) != NULL) {
 
347
                if(setreuid(pwent->pw_uid, pwent->pw_uid) != 0) {
 
348
                    LOG(log_info, logtype_papd, "setreuid error: %m");
 
349
                }
 
350
            } else {
 
351
                LOG(log_info, logtype_papd, "Error getting username (%s)", lp.lp_person);
 
352
            }
 
353
        }
 
354
        if (( lp.lp_stream = popen( printer->p_printer, "w" )) == NULL ) {
 
355
            LOG(log_error, logtype_papd, "lp_open popen %s: %m", printer->p_printer );
 
356
            spoolerror( out, NULL );
 
357
            return( -1 );
 
358
        }
 
359
    } else {
 
360
        sprintf( name, "df%c%03d%s", lp.lp_letter++, lp.lp_seq, hostname );
 
361
 
 
362
        if (( fd = open( name, O_WRONLY|O_CREAT|O_EXCL, 0660 )) < 0 ) {
 
363
            LOG(log_error, logtype_papd, "lp_open %s: %m", name );
 
364
            spoolerror( out, NULL );
 
365
            return( -1 );
 
366
        }
 
367
 
 
368
        if (lp.lp_person != NULL) {
 
369
            if ((pwent = getpwnam(lp.lp_person)) == NULL) {
 
370
                LOG(log_error, logtype_papd, "getpwnam %s: no such user", lp.lp_person);
 
371
                spoolerror( out, NULL );
 
372
                return( -1 );
 
373
            }
 
374
        } else {
 
375
            if ((pwent = getpwnam(printer->p_operator)) == NULL) {
 
376
                LOG(log_error, logtype_papd, "getpwnam %s: no such user", printer->p_operator);
 
377
                spoolerror( out, NULL );
 
378
                return( -1 );
 
379
            }
 
380
        }
 
381
 
 
382
        if (fchown(fd, pwent->pw_uid, -1) < 0) {
 
383
            LOG(log_error, logtype_papd, "chown %s %s: %m", pwent->pw_name, name);
 
384
            spoolerror( out, NULL );
 
385
            return( -1 );
 
386
        }
 
387
 
 
388
        if (( lp.lp_stream = fdopen( fd, "w" )) == NULL ) {
 
389
            LOG(log_error, logtype_papd, "lp_open fdopen: %m" );
 
390
            spoolerror( out, NULL );
 
391
            return( -1 );
 
392
        }
 
393
    }
 
394
    lp.lp_flags |= LP_OPEN;
 
395
 
 
396
    return( 0 );
 
397
}
 
398
 
 
399
int lp_close()
 
400
{
 
401
    if (( lp.lp_flags & LP_INIT ) == 0 || ( lp.lp_flags & LP_OPEN ) == 0 ) {
 
402
        return 0;
 
403
    }
 
404
    fclose( lp.lp_stream );
 
405
    lp.lp_stream = NULL;
 
406
    lp.lp_flags &= ~LP_OPEN;
 
407
    return 0;
 
408
}
 
409
 
 
410
int lp_write( buf, len )
 
411
    char        *buf;
 
412
    int         len;
 
413
{
 
414
    if (( lp.lp_flags & LP_OPEN ) == 0 ) {
 
415
        return( -1 );
 
416
    }
 
417
 
 
418
    if ( fwrite( buf, 1, len, lp.lp_stream ) != len ) {
 
419
        LOG(log_error, logtype_papd, "lp_write: %m" );
 
420
        abort();
 
421
    }
 
422
    return( 0 );
 
423
}
 
424
 
 
425
int lp_cancel()
 
426
{
 
427
    char        name[ MAXPATHLEN ];
 
428
    char        letter;
 
429
 
 
430
    if (( lp.lp_flags & LP_INIT ) == 0 || lp.lp_letter == 'A' ) {
 
431
        return 0;
 
432
    }
 
433
 
 
434
    if ( lp.lp_flags & LP_OPEN ) {
 
435
        lp_close();
 
436
    }
 
437
 
 
438
    for ( letter = 'A'; letter < lp.lp_letter; letter++ ) {
 
439
        sprintf( name, "df%c%03d%s", letter, lp.lp_seq, hostname );
 
440
        if ( unlink( name ) < 0 ) {
 
441
            LOG(log_error, logtype_papd, "lp_cancel unlink %s: %m", name );
 
442
        }
 
443
    }
 
444
 
 
445
    return 0;
 
446
}
 
447
 
 
448
/*
 
449
 * Create printcap control file, signal printer.  Errors here should
 
450
 * remove queue files.
 
451
 *
 
452
 * XXX piped?
 
453
 */
 
454
int lp_print()
 
455
{
 
456
    char                buf[ MAXPATHLEN ];
 
457
    char                tfname[ MAXPATHLEN ];
 
458
    char                cfname[ MAXPATHLEN ];
 
459
    char                letter;
 
460
    int                 fd, n, s;
 
461
    FILE                *cfile;
 
462
 
 
463
    if (( lp.lp_flags & LP_INIT ) == 0 || lp.lp_letter == 'A' ) {
 
464
        return 0;
 
465
    }
 
466
    lp_close();
 
467
 
 
468
    if ( printer->p_flags & P_SPOOLED ) {
 
469
        sprintf( tfname, "tfA%03d%s", lp.lp_seq, hostname );
 
470
        if (( fd = open( tfname, O_WRONLY|O_EXCL|O_CREAT, 0660 )) < 0 ) {
 
471
            LOG(log_error, logtype_papd, "lp_print %s: %m", tfname );
 
472
            return 0;
 
473
        }
 
474
        if (( cfile = fdopen( fd, "w" )) == NULL ) {
 
475
            LOG(log_error, logtype_papd, "lp_print %s: %m", tfname );
 
476
            return 0;
 
477
        }
 
478
        fprintf( cfile, "H%s\n", hostname );    /* XXX lp_host? */
 
479
 
 
480
        if ( lp.lp_person ) {
 
481
            fprintf( cfile, "P%s\n", lp.lp_person );
 
482
        } else {
 
483
            fprintf( cfile, "P%s\n", printer->p_operator );
 
484
        }
 
485
 
 
486
        if ( lp.lp_job && *lp.lp_job ) {
 
487
            fprintf( cfile, "J%s\n", lp.lp_job );
 
488
            fprintf( cfile, "T%s\n", lp.lp_job );
 
489
        } else {
 
490
            fprintf( cfile, "JMac Job\n" );
 
491
            fprintf( cfile, "TMac Job\n" );
 
492
        }
 
493
 
 
494
        fprintf( cfile, "C%s\n", hostname );    /* XXX lp_host? */
 
495
 
 
496
        if ( lp.lp_person ) {
 
497
            fprintf( cfile, "L%s\n", lp.lp_person );
 
498
        } else {
 
499
            fprintf( cfile, "L%s\n", printer->p_operator );
 
500
        }
 
501
 
 
502
        for ( letter = 'A'; letter < lp.lp_letter; letter++ ) {
 
503
            fprintf( cfile, "fdf%c%03d%s\n", letter, lp.lp_seq, hostname );
 
504
            fprintf( cfile, "Udf%c%03d%s\n", letter, lp.lp_seq, hostname );
 
505
        }
 
506
 
 
507
        if ( lp.lp_job && *lp.lp_job ) {
 
508
            fprintf( cfile, "N%s\n", lp.lp_job );
 
509
        } else {
 
510
            fprintf( cfile, "NMac Job\n" );
 
511
        }
 
512
        fclose( cfile );
 
513
 
 
514
        sprintf( cfname, "cfA%03d%s", lp.lp_seq, hostname );
 
515
        if ( link( tfname, cfname ) < 0 ) {
 
516
            LOG(log_error, logtype_papd, "lp_print can't link %s to %s: %m", cfname,
 
517
                    tfname );
 
518
            return 0;
 
519
        }
 
520
        unlink( tfname );
 
521
 
 
522
        if (( s = lp_conn_unix()) < 0 ) {
 
523
            LOG(log_error, logtype_papd, "lp_print: lp_conn_unix: %m" );
 
524
            return 0;
 
525
        }
 
526
 
 
527
        sprintf( buf, "\1%s\n", printer->p_printer );
 
528
        n = strlen( buf );
 
529
        if ( write( s, buf, n ) != n ) {
 
530
            LOG(log_error, logtype_papd, "lp_print write: %m" );
 
531
            return 0;
 
532
        }
 
533
        if ( read( s, buf, 1 ) != 1 ) {
 
534
            LOG(log_error, logtype_papd, "lp_print read: %m" );
 
535
            return 0;
 
536
        }
 
537
 
 
538
        lp_disconn_unix( s );
 
539
 
 
540
        if ( buf[ 0 ] != '\0' ) {
 
541
            LOG(log_error, logtype_papd, "lp_print lpd said %c: %m", buf[ 0 ] );
 
542
            return 0;
 
543
        }
 
544
    }
 
545
    LOG(log_info, logtype_papd, "lp_print queued" );
 
546
    return 0;
 
547
}
 
548
 
 
549
int lp_disconn_unix( fd )
 
550
{
 
551
    return( close( fd ));
 
552
}
 
553
 
 
554
int lp_conn_unix()
 
555
{
 
556
    int                 s;
 
557
    struct sockaddr_un  saun;
 
558
 
 
559
    if (( s = socket( AF_UNIX, SOCK_STREAM, 0 )) < 0 ) {
 
560
        LOG(log_error, logtype_papd, "lp_conn_unix socket: %m" );
 
561
        return( -1 );
 
562
    }
 
563
    memset( &saun, 0, sizeof( struct sockaddr_un ));
 
564
    saun.sun_family = AF_UNIX;
 
565
    strcpy( saun.sun_path, _PATH_DEVPRINTER );
 
566
    if ( connect( s, (struct sockaddr *)&saun,
 
567
            strlen( saun.sun_path ) + 2 ) < 0 ) {
 
568
        LOG(log_error, logtype_papd, "lp_conn_unix connect %s: %m", saun.sun_path );
 
569
        close( s );
 
570
        return( -1 );
 
571
    }
 
572
 
 
573
    return( s );
 
574
}
 
575
 
 
576
int lp_disconn_inet( int fd )
 
577
{
 
578
    return( close( fd ));
 
579
}
 
580
 
 
581
int lp_conn_inet()
 
582
{
 
583
    int                 privfd, port = IPPORT_RESERVED - 1;
 
584
    struct sockaddr_in  sin;
 
585
    struct servent      *sp;
 
586
    struct hostent      *hp;
 
587
 
 
588
    if (( sp = getservbyname( "printer", "tcp" )) == NULL ) {
 
589
        LOG(log_error, logtype_papd, "printer/tcp: unknown service\n" );
 
590
        return( -1 );
 
591
    }
 
592
 
 
593
    if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
 
594
        LOG(log_error, logtype_papd, "gethostname: %m" );
 
595
        exit( 1 );
 
596
    }
 
597
 
 
598
    if (( hp = gethostbyname( hostname )) == NULL ) {
 
599
        LOG(log_error, logtype_papd, "%s: unknown host\n", hostname );
 
600
        return( -1 );
 
601
    }
 
602
 
 
603
    if (( privfd = rresvport( &port )) < 0 ) {
 
604
        LOG(log_error, logtype_papd, "lp_connect: socket: %m" );
 
605
        close( privfd );
 
606
        return( -1 );
 
607
    }
 
608
 
 
609
    memset( &sin, 0, sizeof( struct sockaddr_in ));
 
610
    sin.sin_family = AF_INET;
 
611
/*    sin.sin_addr.s_addr = htonl( INADDR_LOOPBACK ); */
 
612
    memcpy( &sin.sin_addr, hp->h_addr, hp->h_length );
 
613
    sin.sin_port = sp->s_port;
 
614
 
 
615
    if ( connect( privfd, (struct sockaddr *)&sin,
 
616
            sizeof( struct sockaddr_in )) < 0 ) {
 
617
        LOG(log_error, logtype_papd, "lp_connect: %m" );
 
618
        close( privfd );
 
619
        return( -1 );
 
620
    }
 
621
 
 
622
    return( privfd );
 
623
}
 
624
 
 
625
int lp_rmjob( job )
 
626
    int         job;
 
627
{
 
628
    char        buf[ 1024 ];
 
629
    int         n, s;
 
630
 
 
631
    if (( s = lp_conn_inet()) < 0 ) {
 
632
        LOG(log_error, logtype_papd, "lp_rmjob: %m" );
 
633
        return( -1 );
 
634
    }
 
635
 
 
636
    if ( lp.lp_person == NULL ) {
 
637
        return( -1 );
 
638
    }
 
639
 
 
640
    sprintf( buf, "\5%s %s %d\n", printer->p_printer, lp.lp_person, job );
 
641
    n = strlen( buf );
 
642
    if ( write( s, buf, n ) != n ) {
 
643
        LOG(log_error, logtype_papd, "lp_rmjob write: %m" );
 
644
        lp_disconn_inet( s );
 
645
        return( -1 );
 
646
    }
 
647
    while (( n = read( s, buf, sizeof( buf ))) > 0 ) {
 
648
        LOG(log_debug, logtype_papd, "read %.*s", n, buf );
 
649
    }
 
650
 
 
651
    lp_disconn_inet( s );
 
652
    return( 0 );
 
653
}
 
654
 
 
655
char    *kw_rank = "Rank";
 
656
char    *kw_active = "active";
 
657
 
 
658
char    *tag_rank = "rank: ";
 
659
char    *tag_owner = "owner: ";
 
660
char    *tag_job = "job: ";
 
661
char    *tag_files = "files: ";
 
662
char    *tag_size = "size: ";
 
663
char    *tag_status = "status: ";
 
664
 
 
665
int lp_queue( out )
 
666
    struct papfile      *out;
 
667
{
 
668
    char                        buf[ 1024 ], *start, *stop, *p, *q;
 
669
    int                         linelength, crlflength;
 
670
    static struct papfile       pf;
 
671
    int                         n, len, s;
 
672
        
 
673
    if (( s = lp_conn_unix()) < 0 ) {
 
674
        LOG(log_error, logtype_papd, "lp_queue: %m" );
 
675
        return( -1 );
 
676
    }
 
677
 
 
678
    sprintf( buf, "\3%s\n", printer->p_printer );
 
679
    n = strlen( buf );
 
680
    if ( write( s, buf, n ) != n ) {
 
681
        LOG(log_error, logtype_papd, "lp_queue write: %m" );
 
682
        lp_disconn_unix( s );
 
683
        return( -1 );
 
684
    }
 
685
    pf.pf_state = PF_BOT;
 
686
 
 
687
    while (( n = read( s, buf, sizeof( buf ))) > 0 ) {
 
688
        append( &pf, buf, n );
 
689
    }
 
690
 
 
691
    for (;;) {
 
692
        if ( markline( &pf, &start, &linelength, &crlflength ) > 0 ) {
 
693
            /* parse */
 
694
            stop = start + linelength;
 
695
            for ( p = start; p < stop; p++ ) {
 
696
                if ( *p == ' ' || *p == '\t' ) {
 
697
                    break;
 
698
                }
 
699
            }
 
700
            if ( p >= stop ) {
 
701
                CONSUME( &pf , linelength + crlflength);
 
702
                continue;
 
703
            }
 
704
 
 
705
            /*
 
706
             * Keys: "Rank", a number, "active"
 
707
             * Anything else is status.
 
708
             */
 
709
            len = p - start;
 
710
            if ( len == strlen( kw_rank ) &&
 
711
                    strncmp( kw_rank, start, len ) == 0 ) {
 
712
                CONSUME( &pf, linelength + crlflength );
 
713
                continue;
 
714
            }
 
715
            if (( len == strlen( kw_active ) &&
 
716
                    strncmp( kw_active, start, len ) == 0 ) ||
 
717
                    isdigit( *start )) {                /* a job line */
 
718
                append( out, tag_rank, strlen( tag_rank ));
 
719
                append( out, start, p - start );
 
720
                append( out, "\n", 1 );
 
721
 
 
722
                for ( ; p < stop; p++ ) {
 
723
                    if ( *p != ' ' && *p != '\t' ) {
 
724
                        break;
 
725
                    }
 
726
                }
 
727
                for ( q = p; p < stop; p++ ) {
 
728
                    if ( *p == ' ' || *p == '\t' ) {
 
729
                        break;
 
730
                    }
 
731
                }
 
732
                if ( p >= stop ) {
 
733
                    append( out, ".\n", 2 );
 
734
                    CONSUME( &pf, linelength + crlflength );
 
735
                    continue;
 
736
                }
 
737
                append( out, tag_owner, strlen( tag_owner ));
 
738
                append( out, q, p - q );
 
739
                append( out, "\n", 1 );
 
740
 
 
741
                for ( ; p < stop; p++ ) {
 
742
                    if ( *p != ' ' && *p != '\t' ) {
 
743
                        break;
 
744
                    }
 
745
                }
 
746
                for ( q = p; p < stop; p++ ) {
 
747
                    if ( *p == ' ' || *p == '\t' ) {
 
748
                        break;
 
749
                    }
 
750
                }
 
751
                if ( p >= stop ) {
 
752
                    append( out, ".\n", 2 );
 
753
                    CONSUME( &pf , linelength + crlflength );
 
754
                    continue;
 
755
                }
 
756
                append( out, tag_job, strlen( tag_job ));
 
757
                append( out, q, p - q );
 
758
                append( out, "\n", 1 );
 
759
 
 
760
                for ( ; p < stop; p++ ) {
 
761
                    if ( *p != ' ' && *p != '\t' ) {
 
762
                        break;
 
763
                    }
 
764
                }
 
765
                for ( q = p, p = stop; p > q; p-- ) {
 
766
                    if ( *p == ' ' || *p == '\t' ) {
 
767
                        break;
 
768
                    }
 
769
                }
 
770
                for ( ; p > q; p-- ) {
 
771
                    if ( *p != ' ' && *p != '\t' ) {
 
772
                        break;
 
773
                    }
 
774
                }
 
775
                for ( ; p > q; p-- ) {
 
776
                    if ( *p == ' ' || *p == '\t' ) {
 
777
                        break;
 
778
                    }
 
779
                }
 
780
                if ( p <= q ) {
 
781
                    append( out, ".\n", 2 );
 
782
                    CONSUME( &pf, linelength + crlflength );
 
783
                    continue;
 
784
                }
 
785
                append( out, tag_files, strlen( tag_files ));
 
786
                append( out, q, p - q );
 
787
                append( out, "\n", 1 );
 
788
 
 
789
                for ( ; p < stop; p++ ) {
 
790
                    if ( *p != ' ' && *p != '\t' ) {
 
791
                        break;
 
792
                    }
 
793
                }
 
794
                append( out, tag_size, strlen( tag_size ));
 
795
                append( out, p, stop - p );
 
796
                append( out, "\n.\n", 3 );
 
797
 
 
798
                CONSUME( &pf, linelength + crlflength );
 
799
                continue;
 
800
            }
 
801
 
 
802
            /* status */
 
803
            append( out, tag_status, strlen( tag_status ));
 
804
            append( out, start, linelength );
 
805
            append( out, "\n.\n", 3 );
 
806
 
 
807
            CONSUME( &pf, linelength + crlflength );
 
808
        } else {
 
809
            append( out, "*\n", 2 );
 
810
            lp_disconn_unix( s );
 
811
            return( 0 );
 
812
        }
 
813
    }
 
814
}