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

« back to all changes in this revision

Viewing changes to bin/pap/pap.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: pap.c,v 1.8.2.1 2002/11/25 01:37:21 jmarcus Exp $
 
3
 *
 
4
 * Copyright (c) 1990,1994 Regents of The University of Michigan.
 
5
 * All Rights Reserved.  See COPYRIGHT.
 
6
 */
 
7
 
 
8
#ifdef HAVE_CONFIG_H
 
9
#include "config.h"
 
10
#endif /* HAVE_CONFIG_H */
 
11
 
 
12
#include <sys/types.h>
 
13
#include <sys/time.h>
 
14
#include <sys/uio.h>
 
15
#include <netatalk/endian.h>
 
16
#include <netatalk/at.h>
 
17
#include <atalk/atp.h>
 
18
#include <atalk/pap.h>
 
19
#include <atalk/nbp.h>
 
20
#include <atalk/util.h>
 
21
#ifdef HAVE_FCNTL_H
 
22
#include <fcntl.h>
 
23
#endif /* HAVE_FCNTL_H */
 
24
#include <stdio.h>
 
25
#include <string.h>
 
26
#include <string.h>
 
27
#include <stdlib.h>
 
28
#include <errno.h>
 
29
 
 
30
#define FUCKED
 
31
 
 
32
#define _PATH_PAPRC     ".paprc"
 
33
char    *nbpfailure = "AppleTalk printer offline";
 
34
 
 
35
/* Forward Declarations */
 
36
void updatestatus(char *s, int len);
 
37
int send_file(int fd, ATP atp, int lastfile);
 
38
 
 
39
void usage( path )
 
40
    char        *path;
 
41
{
 
42
    char        *p;
 
43
 
 
44
    if (( p = strrchr( path, '/' )) == NULL ) {
 
45
        p = path;
 
46
    } else {
 
47
        p++;
 
48
    }
 
49
    fprintf( stderr,
 
50
        "Usage:\t%s [ -A address ] [ -c ] [ -d ] [ -e ] [ -E ] [ -p printer ]\n"
 
51
        "    [ -s statusfile ] [ -w ] [ -W ] [ FILES ]\n"
 
52
        "  -A address    - printer Appletalk address\n"
 
53
        "  -c            - take cuts (lie about wait time)\n"
 
54
        "  -d            - enable debug\n"
 
55
        "  -e            - send stdout to stderr\n"
 
56
        "  -E            - don't wait for EOF from printer\n"
 
57
        "  -p printer    - printer name\n"
 
58
        "  -s statusfile - put current printer status in statusfile\n"
 
59
        "  -w            - wait for printer status = 'waiting'\n"
 
60
        "  -W            - wait for printer status = 'idle'\n"
 
61
        "  FILES         - send FILES to printer\n"
 
62
        , p );
 
63
    exit( 2 );
 
64
}
 
65
 
 
66
char *
 
67
paprc()
 
68
{
 
69
    static char s[ 32 + 1 + 32 + 1 + 32 ];
 
70
    char        *name = NULL;
 
71
    FILE        *f;
 
72
 
 
73
    if (( f = fopen( _PATH_PAPRC, "r" )) == NULL ) {
 
74
        if ( errno == ENOENT ) {
 
75
            return( NULL );
 
76
        } else {
 
77
            perror( _PATH_PAPRC );
 
78
            exit( 2 );
 
79
        }
 
80
    }
 
81
    while ( fgets( s, sizeof( s ), f ) != NULL ) {
 
82
        s[ strlen( s ) - 1 ] = '\0';    /* remove trailing newline */
 
83
        if ( *s == '#' ) {
 
84
            continue;
 
85
        }
 
86
        name = s;
 
87
        break;
 
88
    }
 
89
    fclose( f );
 
90
    return( name );
 
91
}
 
92
 
 
93
char                    *printer = NULL;
 
94
char                    *status = NULL;
 
95
int                     noeof = 0;
 
96
int                     waitforprinter = 0;
 
97
 
 
98
unsigned char           connid, quantum, oquantum = PAP_MAXQUANTUM;
 
99
struct sockaddr_at      sat;
 
100
 
 
101
char                    cbuf[ 8 ];
 
102
struct nbpnve           nn;
 
103
ATP                     satp;
 
104
 
 
105
char            fbuf[ PAP_MAXQUANTUM ][ 4 + PAP_MAXDATA ];
 
106
struct iovec    rfiov[ PAP_MAXQUANTUM ] = {
 
107
    { fbuf[ 0 ] + 4,    0 },
 
108
    { fbuf[ 1 ] + 4,    0 },
 
109
    { fbuf[ 2 ] + 4,    0 },
 
110
    { fbuf[ 3 ] + 4,    0 },
 
111
    { fbuf[ 4 ] + 4,    0 },
 
112
    { fbuf[ 5 ] + 4,    0 },
 
113
    { fbuf[ 6 ] + 4,    0 },
 
114
    { fbuf[ 7 ] + 4,    0 },
 
115
};
 
116
struct iovec    sniov[ PAP_MAXQUANTUM ] = {
 
117
    { fbuf[ 0 ],        0 },
 
118
    { fbuf[ 1 ],        0 },
 
119
    { fbuf[ 2 ],        0 },
 
120
    { fbuf[ 3 ],        0 },
 
121
    { fbuf[ 4 ],        0 },
 
122
    { fbuf[ 5 ],        0 },
 
123
    { fbuf[ 6 ],        0 },
 
124
    { fbuf[ 7 ],        0 },
 
125
};
 
126
 
 
127
char            nbuf[ PAP_MAXQUANTUM ][ 4 + PAP_MAXDATA ];
 
128
struct iovec    rniov[ PAP_MAXQUANTUM ] = {
 
129
    { nbuf[ 0 ],        0 },
 
130
    { nbuf[ 1 ],        0 },
 
131
    { nbuf[ 2 ],        0 },
 
132
    { nbuf[ 3 ],        0 },
 
133
    { nbuf[ 4 ],        0 },
 
134
    { nbuf[ 5 ],        0 },
 
135
    { nbuf[ 6 ],        0 },
 
136
    { nbuf[ 7 ],        0 },
 
137
};
 
138
struct iovec    sfiov[ PAP_MAXQUANTUM ] = {
 
139
    { nbuf[ 0 ] + 4,    0 },
 
140
    { nbuf[ 1 ] + 4,    0 },
 
141
    { nbuf[ 2 ] + 4,    0 },
 
142
    { nbuf[ 3 ] + 4,    0 },
 
143
    { nbuf[ 4 ] + 4,    0 },
 
144
    { nbuf[ 5 ] + 4,    0 },
 
145
    { nbuf[ 6 ] + 4,    0 },
 
146
    { nbuf[ 7 ] + 4,    0 },
 
147
};
 
148
 
 
149
int debug;
 
150
 
 
151
int main( ac, av )
 
152
    int         ac;
 
153
    char        **av;
 
154
{
 
155
    ATP                 atp;
 
156
    struct atp_block    atpb;
 
157
    int                 c, err = 0, fd, cuts = 0;
 
158
    char                *obj = NULL, *type = "LaserWriter", *zone = "*";
 
159
    struct timeval      stv, tv;
 
160
    char                rbuf[ ATP_MAXDATA ];
 
161
    struct iovec        iov;
 
162
    unsigned short      waiting, result;
 
163
    int                 connattempts = 10;
 
164
    int                 waitforidle = 0;
 
165
    struct at_addr      addr;
 
166
 
 
167
    extern char         *optarg;
 
168
    extern int          optind;
 
169
 
 
170
    memset(&addr, 0, sizeof(addr));
 
171
    while (( c = getopt( ac, av, "dWwcep:s:EA:" )) != EOF ) {
 
172
        switch ( c ) {
 
173
#ifdef FUCKED
 
174
        case 'w' :
 
175
            waitforprinter = 1;
 
176
            break;
 
177
 
 
178
        case 'W' :
 
179
            waitforidle = 1;
 
180
            break;
 
181
#endif /* FUCKED */
 
182
 
 
183
        /* enable debugging */
 
184
        case 'd' :
 
185
            debug++;
 
186
            break;
 
187
 
 
188
        case 'c' :
 
189
            cuts++;
 
190
            break;
 
191
 
 
192
        case 'e' :      /* send stdout to stderr */
 
193
            dup2( 2, 1 );
 
194
            break;
 
195
 
 
196
        case 'p' :
 
197
            printer = optarg;
 
198
            break;
 
199
 
 
200
        case 's' :
 
201
            status = optarg;
 
202
            break;
 
203
 
 
204
        case 'E' :
 
205
            noeof = 1;
 
206
            break;
 
207
           
 
208
        case 'A':
 
209
            if (!atalk_aton(optarg, &addr)) {
 
210
              fprintf(stderr, "Bad address.\n");
 
211
              exit(1);
 
212
            }
 
213
            break;
 
214
 
 
215
        default :
 
216
            err++;
 
217
        }
 
218
    }
 
219
    if ( err ) {
 
220
        usage( *av );
 
221
    }
 
222
    if ( printer == NULL && (( printer = paprc()) == NULL )) {
 
223
        fprintf( stderr, "No printer specified and ./.paprc not found.\n" );
 
224
        exit( 2 );
 
225
    }
 
226
 
 
227
    /*
 
228
     * Open connection.
 
229
     */
 
230
    if ( nbp_name( printer, &obj, &type, &zone ) < 0 ) {
 
231
        fprintf( stderr, "%s: Bad name\n", printer );
 
232
        exit( 2 );
 
233
    }
 
234
    if ( obj == NULL ) {
 
235
        fprintf( stderr, "%s: Bad name\n", printer );
 
236
        exit( 2 );
 
237
    }
 
238
 
 
239
    if ( nbp_lookup( obj, type, zone, &nn, 1, &addr ) <= 0 ) {
 
240
        if ( errno != 0 ) {
 
241
            perror( "nbp_lookup" );
 
242
            exit( 2 );
 
243
        }
 
244
        fprintf( stderr, "%s:%s@%s: NBP Lookup failed\n", obj, type, zone );
 
245
        exit( 1 );
 
246
    }
 
247
 
 
248
    if ( isatty( 1 )) {
 
249
        printf( "Trying %u.%d:%d ...\n", ntohs( nn.nn_sat.sat_addr.s_net ),
 
250
                nn.nn_sat.sat_addr.s_node, nn.nn_sat.sat_port );
 
251
    }
 
252
 
 
253
    if (( atp = atp_open( ATADDR_ANYPORT, &addr )) == NULL ) {
 
254
        perror( "atp_open" );
 
255
        exit( 2 );
 
256
    }
 
257
    if (( satp = atp_open( ATADDR_ANYPORT, &addr )) == NULL ) {
 
258
        perror( "atp_open" );
 
259
        exit( 2 );
 
260
    }
 
261
 
 
262
    while ( waitforidle ) {
 
263
        char    st_buf[ 1024 ]; /* XXX too big */
 
264
 
 
265
        cbuf[ 0 ] = 0;
 
266
        cbuf[ 1 ] = PAP_SENDSTATUS;
 
267
        cbuf[ 2 ] = cbuf[ 3 ] = 0;
 
268
        atpb.atp_saddr = &nn.nn_sat;
 
269
        atpb.atp_sreqdata = cbuf;
 
270
        atpb.atp_sreqdlen = 4;  /* bytes in SendStatus request */
 
271
        atpb.atp_sreqto = 2;            /* retry timer */
 
272
        atpb.atp_sreqtries = 5;         /* retry count */
 
273
        if ( atp_sreq( satp, &atpb, 1, 0 ) < 0 ) {
 
274
            perror( "atp_sreq" );
 
275
            exit( 1 );
 
276
        }
 
277
 
 
278
        if(debug){ printf( "SENDSTATUS >\n" ), fflush( stdout );}
 
279
 
 
280
        atpb.atp_saddr = &nn.nn_sat;
 
281
        rniov[ 0 ].iov_len = PAP_MAXDATA + 4;
 
282
        atpb.atp_rresiov = rniov;
 
283
        atpb.atp_rresiovcnt = 1;
 
284
        if ( atp_rresp( satp, &atpb ) < 0 ) {
 
285
            perror( "atp_rresp" );
 
286
            continue;
 
287
        }
 
288
 
 
289
#ifndef NONZEROSTATUS
 
290
        /*
 
291
         * The stinking LaserWriter IINTX puts crap in this
 
292
         * field.
 
293
         */
 
294
        if ( ((char *)rniov[ 0 ].iov_base)[ 0 ] != 0 ) {
 
295
            fprintf( stderr, "Bad status response!\n" );
 
296
            exit( 1 );
 
297
        }
 
298
#endif /* NONZEROSTATUS */
 
299
 
 
300
        if ( ((char *)rniov[ 0 ].iov_base)[ 1 ] != PAP_STATUS ||
 
301
                atpb.atp_rresiovcnt != 1 ) {
 
302
            fprintf( stderr, "Bad status response!\n" );
 
303
            exit( 1 );
 
304
        }
 
305
 
 
306
        if(debug){ printf( "< STATUS\n" ), fflush( stdout );}
 
307
 
 
308
        memcpy( st_buf, (char *) rniov[ 0 ].iov_base + 9, 
 
309
                ((char *)rniov[ 0 ].iov_base)[ 8 ] );
 
310
        st_buf[ (int) ((char *)rniov[ 0 ].iov_base)[ 8 ]] = '\0';
 
311
        if ( strstr( st_buf, "idle" ) != NULL ) {
 
312
            waitforidle = 0;
 
313
        } else {
 
314
            updatestatus( (char *) rniov[ 0 ].iov_base + 9,
 
315
                    ((char *)rniov[ 0 ].iov_base)[ 8 ] );
 
316
            sleep( 5 );
 
317
        }
 
318
    }
 
319
 
 
320
    cbuf[ 0 ] = connid = getpid() & 0xff;
 
321
    cbuf[ 1 ] = PAP_OPEN;
 
322
    cbuf[ 2 ] = cbuf[ 3 ] = 0;
 
323
    cbuf[ 4 ] = atp_sockaddr( atp )->sat_port;
 
324
    cbuf[ 5 ] = oquantum;       /* flow quantum */
 
325
    if ( gettimeofday( &stv, 0 ) < 0 ) {
 
326
        perror( "gettimeofday" );
 
327
        exit( 2 );
 
328
    }
 
329
    for (;;) {
 
330
        if ( cuts ) {
 
331
            waiting = 0xffff;
 
332
        } else {
 
333
            if ( gettimeofday( &tv, 0 ) < 0 ) {
 
334
                perror( "gettimeofday" );
 
335
                exit( 2 );
 
336
            }
 
337
            waiting = htons( tv.tv_sec - stv.tv_sec );
 
338
        }
 
339
        memcpy(cbuf +  6, &waiting, sizeof( waiting ));
 
340
 
 
341
        atpb.atp_saddr = &nn.nn_sat;
 
342
        atpb.atp_sreqdata = cbuf;
 
343
        atpb.atp_sreqdlen = 8;          /* bytes in OpenConn request */
 
344
        atpb.atp_sreqto = 2;            /* retry timer */
 
345
        atpb.atp_sreqtries = 5;         /* retry count */
 
346
        if ( atp_sreq( atp, &atpb, 1, ATP_XO ) < 0 ) {
 
347
            perror( "atp_sreq" );
 
348
            exit( 1 );
 
349
        }
 
350
 
 
351
        if(debug){ printf( "OPEN >\n" ), fflush( stdout );}
 
352
 
 
353
        iov.iov_base = rbuf;
 
354
        iov.iov_len = sizeof( rbuf );
 
355
        atpb.atp_rresiov = &iov;
 
356
        atpb.atp_rresiovcnt = 1;
 
357
        if ( atp_rresp( atp, &atpb ) < 0 ) {
 
358
            perror( "atp_rresp" );
 
359
            if ( connattempts-- <= 0 ) {
 
360
                fprintf( stderr, "Can't connect!\n" );
 
361
                exit( 1 );
 
362
            }
 
363
            continue;
 
364
        }
 
365
 
 
366
        /* sanity */
 
367
        if ( iov.iov_len < 8 || (unsigned char)rbuf[ 0 ] != connid ||
 
368
                rbuf[ 1 ] != PAP_OPENREPLY ) {
 
369
            fprintf( stderr, "Bad response!\n" );
 
370
            continue;   /* This is weird, since TIDs must match... */
 
371
        }
 
372
 
 
373
        if(debug){ printf( "< OPENREPLY\n" ), fflush( stdout );}
 
374
 
 
375
        if ( isatty( 1 )) {
 
376
            printf( "%.*s\n", (int)iov.iov_len - 9, (char *) iov.iov_base + 9 );
 
377
        }
 
378
        updatestatus( (char *) iov.iov_base + 9, iov.iov_len - 9 );
 
379
 
 
380
        memcpy( &result, rbuf +  6,  sizeof( result ));
 
381
        if ( result != 0 ) {
 
382
            sleep( 2 );
 
383
        } else {
 
384
            memcpy( &sat, &nn.nn_sat, sizeof( struct sockaddr_at ));
 
385
            sat.sat_port = rbuf[ 4 ];
 
386
            quantum = rbuf[ 5 ];
 
387
            break;
 
388
        }
 
389
    }
 
390
 
 
391
    if ( isatty( 1 )) {
 
392
        printf( "Connected to %.*s:%.*s@%.*s.\n",
 
393
                nn.nn_objlen, nn.nn_obj,
 
394
                nn.nn_typelen, nn.nn_type,
 
395
                nn.nn_zonelen, nn.nn_zone );
 
396
    }
 
397
 
 
398
    if ( optind == ac ) {
 
399
        send_file( 0, atp, 1 );
 
400
    } else {
 
401
        for (; optind < ac; optind++ ) {
 
402
            if ( strcmp( av[ optind ], "-" ) == 0 ) {
 
403
                fd = 0;
 
404
            } else if (( fd = open( av[ optind ], O_RDONLY )) < 0 ) {
 
405
                perror( av[ optind ] );
 
406
                continue;
 
407
            }
 
408
            send_file( fd, atp, ( optind == ac - 1 ) ? 1 : 0 );
 
409
            if ( fd != 0 ) {
 
410
                close( fd );
 
411
            }
 
412
        }
 
413
    }
 
414
 
 
415
    /*
 
416
     * Close connection.
 
417
     */
 
418
    cbuf[ 0 ] = connid;
 
419
    cbuf[ 1 ] = PAP_CLOSE;
 
420
    cbuf[ 2 ] = cbuf[ 3 ] = 0;
 
421
 
 
422
    atpb.atp_saddr = &sat;
 
423
    atpb.atp_sreqdata = cbuf;
 
424
    atpb.atp_sreqdlen = 4;              /* bytes in CloseConn request */
 
425
    atpb.atp_sreqto = 2;                /* retry timer */
 
426
    atpb.atp_sreqtries = 5;             /* retry count */
 
427
    if ( atp_sreq( atp, &atpb, 1, ATP_XO ) < 0 ) {
 
428
        perror( "atp_sreq" );
 
429
        exit( 1 );
 
430
    }
 
431
 
 
432
        if(debug){ printf( "CLOSE >\n" ), fflush( stdout );}
 
433
 
 
434
    iov.iov_base = rbuf;
 
435
    iov.iov_len = sizeof( rbuf );
 
436
    atpb.atp_rresiov = &iov;
 
437
    atpb.atp_rresiovcnt = 1;
 
438
    if ( atp_rresp( atp, &atpb ) < 0 ) {
 
439
        perror( "atp_rresp" );
 
440
        exit( 1 );
 
441
    }
 
442
 
 
443
    /* sanity */
 
444
    if ( iov.iov_len != 4 || rbuf[ 1 ] != PAP_CLOSEREPLY ) {
 
445
        fprintf( stderr, "Bad response!\n" );
 
446
        exit( 1 );
 
447
    }
 
448
 
 
449
#ifndef ZEROCONNID
 
450
    /*
 
451
     * The AGFA Viper Rip doesn't have the connection id in the close request.
 
452
     */
 
453
    if ((unsigned char)rbuf[ 0 ] != connid ) {
 
454
        fprintf( stderr, "Bad connid in close!\n" );
 
455
        exit( 1 );
 
456
    }
 
457
#endif /* ZEROCONNID */
 
458
 
 
459
        if(debug){ printf( "< CLOSEREPLY\n" ), fflush( stdout );}
 
460
 
 
461
    if ( isatty( 1 )) {
 
462
        printf( "Connection closed.\n" );
 
463
    }
 
464
    exit( 0 );
 
465
}
 
466
 
 
467
int             data = 0;
 
468
unsigned char   port;
 
469
u_int16_t       seq = 0, rseq = 1;
 
470
 
 
471
int send_file( fd, atp, lastfile )
 
472
    int                 fd;
 
473
    ATP                 atp;
 
474
    int                 lastfile;
 
475
{
 
476
    struct timeval      stv, tv;
 
477
    struct sockaddr_at  ssat;
 
478
    struct atp_block    atpb;
 
479
    fd_set              fds;
 
480
    int                 fiovcnt = 0, eof = 0, senteof = 0, to = 0;
 
481
    int                 cc, i;
 
482
    unsigned short      netseq;
 
483
 
 
484
    if ( gettimeofday( &stv, 0 ) < 0 ) {
 
485
        perror( "gettimeofday" );
 
486
        exit( 2 );
 
487
    }
 
488
 
 
489
    /*
 
490
     * Ask for more data.
 
491
     */
 
492
    cbuf[ 0 ] = connid;
 
493
    cbuf[ 1 ] = PAP_READ;
 
494
    if ( ++seq == 0 ) seq = 1;
 
495
    netseq = htons( seq );
 
496
    memcpy( cbuf +  2, &netseq, sizeof( netseq ));
 
497
    atpb.atp_saddr = &sat;
 
498
    atpb.atp_sreqdata = cbuf;
 
499
    atpb.atp_sreqdlen = 4;              /* bytes in SendData request */
 
500
    atpb.atp_sreqto = 15;               /* retry timer */
 
501
    atpb.atp_sreqtries = -1;            /* retry count */
 
502
    if ( atp_sreq( atp, &atpb, oquantum, ATP_XO ) < 0 ) {
 
503
        perror( "atp_sreq" );
 
504
        exit( 1 );
 
505
    }
 
506
 
 
507
        if(debug){ printf( "READ %d >\n", seq ), fflush( stdout );}
 
508
 
 
509
    for (;;) {
 
510
        if ( gettimeofday( &tv, 0 ) < 0 ) {
 
511
            perror( "gettimeofday" );
 
512
            exit( 2 );
 
513
        }
 
514
 
 
515
        if (( tv.tv_sec - stv.tv_sec ) >= 60 ) {
 
516
            stv = tv;
 
517
 
 
518
            /*
 
519
             * Send a tickle.
 
520
             */
 
521
            cbuf[ 0 ] = connid;
 
522
            cbuf[ 1 ] = PAP_TICKLE;
 
523
            cbuf[ 2 ] = cbuf[ 3 ] = 0;
 
524
            atpb.atp_saddr = &sat;
 
525
            atpb.atp_sreqdata = cbuf;
 
526
            atpb.atp_sreqdlen = 4;              /* bytes in Tickle request */
 
527
            atpb.atp_sreqto = 0;                /* retry timer */
 
528
            atpb.atp_sreqtries = 1;             /* retry count */
 
529
            if ( atp_sreq( satp, &atpb, 0, 0 ) < 0 ) {
 
530
                perror( "atp_sreq" );
 
531
                exit( 1 );
 
532
            }
 
533
 
 
534
        if(debug){ printf( "TICKLE >\n" ), fflush( stdout );}
 
535
        }
 
536
 
 
537
        tv.tv_sec = stv.tv_sec + 60 - tv.tv_sec;
 
538
        tv.tv_usec = 0;
 
539
 
 
540
        FD_ZERO( &fds );
 
541
        if ( !waitforprinter && !eof && fiovcnt == 0 ) {
 
542
            FD_SET( fd, &fds );
 
543
        }
 
544
        FD_SET( atp_fileno( atp ), &fds );
 
545
 
 
546
        if (( cc = select( FD_SETSIZE, &fds, 0, 0, &tv )) < 0 ) {
 
547
            perror( "select" );
 
548
            exit( 2 );
 
549
        }
 
550
 
 
551
        /*
 
552
         * A timeout has occured. Keep track of it.
 
553
         */
 
554
        if ( cc == 0 ) {
 
555
            if ( to++ > 2 ) {
 
556
                fprintf( stderr, "Connection timed out.\n" );
 
557
                exit( 1 );
 
558
            }
 
559
            continue;
 
560
        }
 
561
 
 
562
        /*
 
563
         * Read data.
 
564
         */
 
565
        if ( !fiovcnt && FD_ISSET( fd, &fds )) {
 
566
            for ( i = 0; i < quantum; i++ ) {
 
567
                rfiov[ i ].iov_len = PAP_MAXDATA;
 
568
            }
 
569
            if (( cc = readv( fd, rfiov, quantum )) < 0 ) {
 
570
                perror( "readv" );
 
571
                exit( 2 );
 
572
            }
 
573
            if ( cc == 0 ) {
 
574
                eof = 1;
 
575
            }
 
576
            fiovcnt = cc / PAP_MAXDATA + ( cc % PAP_MAXDATA > 0 );
 
577
            for ( i = 0; cc > 0; i++ ) {
 
578
                rfiov[ i ].iov_len = ( cc > PAP_MAXDATA ) ? PAP_MAXDATA : cc;
 
579
                cc -= ( cc > PAP_MAXDATA ) ? PAP_MAXDATA : cc;
 
580
            }
 
581
        }
 
582
 
 
583
        if ( FD_ISSET( atp_fileno( atp ), &fds )) {
 
584
            ssat = sat;
 
585
            ssat.sat_port = ATADDR_ANYPORT;
 
586
            switch( atp_rsel( atp, &ssat, ATP_TRESP | ATP_TREQ )) {
 
587
            case ATP_TREQ :
 
588
                atpb.atp_saddr = &ssat;
 
589
                atpb.atp_rreqdata = cbuf;
 
590
                atpb.atp_rreqdlen = sizeof( cbuf );
 
591
                if ( atp_rreq( atp, &atpb ) < 0 ) {
 
592
                    perror( "atp_rreq" );
 
593
                    exit( 1 );
 
594
                }
 
595
 
 
596
                if ( (unsigned char)cbuf[ 0 ] != connid ) {
 
597
                    break;
 
598
                }
 
599
 
 
600
                /* reset timeout counter for all valid requests */
 
601
                to = 0;
 
602
 
 
603
                switch ( cbuf[ 1 ] ) {
 
604
                case PAP_READ :
 
605
                    memcpy( cbuf +  2, &netseq, sizeof( netseq ));
 
606
        if(debug){ printf( "< READ %d\n", ntohs( netseq )), fflush( stdout );}
 
607
#ifdef notdef
 
608
                    if ( netseq != 0 ) {
 
609
                        if ( rseq != ntohs( netseq )) {
 
610
        if(debug){ printf( "| DUP %d\n", rseq ), fflush( stdout );}
 
611
                            break;
 
612
                        }
 
613
                        if ( rseq++ == 0xffff ) rseq = 1;
 
614
                    }
 
615
#endif /* notdef */
 
616
 
 
617
                    data = 1;
 
618
                    port = ssat.sat_port;
 
619
                    break;
 
620
 
 
621
                case PAP_CLOSE :
 
622
 
 
623
        if(debug){ printf( "< CLOSE\n" ), fflush( stdout );}
 
624
 
 
625
                    /*
 
626
                     * Respond to the close request, and fail.
 
627
                     */
 
628
                    sniov[ 0 ].iov_len = 4;
 
629
                    ((char *)sniov[ 0 ].iov_base)[ 0 ] = connid;
 
630
                    ((char *)sniov[ 0 ].iov_base)[ 1 ] = PAP_CLOSEREPLY;
 
631
                    ((char *)sniov[ 0 ].iov_base)[ 2 ] =
 
632
                            ((char *)sniov[ 0 ].iov_base)[ 3 ] = 0;
 
633
                    atpb.atp_sresiov = sniov;
 
634
                    atpb.atp_sresiovcnt = 1;
 
635
                    if ( atp_sresp( atp, &atpb ) < 0 ) {
 
636
                        perror( "atp_sresp" );
 
637
                        exit( 1 );
 
638
                    }
 
639
 
 
640
        if(debug){ printf( "CLOSEREPLY >\n" ), fflush( stdout );}
 
641
 
 
642
                    fprintf( stderr, "Connection closed by foreign host.\n" );
 
643
                    exit( 1 );
 
644
 
 
645
                case PAP_TICKLE :
 
646
 
 
647
        if(debug){ printf( "< TICKLE\n" ), fflush( stdout );}
 
648
 
 
649
                    break;
 
650
                default :
 
651
                    fprintf( stderr, "Bad PAP request!\n" );
 
652
                    exit( 1 );
 
653
                }
 
654
                break;
 
655
 
 
656
            case ATP_TRESP :
 
657
                /* reset timeout counter for all valid requests */
 
658
                to = 0;
 
659
 
 
660
                atpb.atp_saddr = &ssat;
 
661
                for ( i = 0; i < oquantum; i++ ) {
 
662
                    rniov[ i ].iov_len = PAP_MAXDATA + 4;
 
663
                }
 
664
                atpb.atp_rresiov = rniov;
 
665
                atpb.atp_rresiovcnt = oquantum;
 
666
                if ( atp_rresp( atp, &atpb ) < 0 ) {
 
667
                    perror( "atp_rresp" );
 
668
                    exit( 1 );
 
669
                }
 
670
 
 
671
#ifndef ZEROCONNID
 
672
                /*
 
673
                 * The HP LJIIISI w/ BridgePort LocalTalk card sends
 
674
                 * zero instead of the connid.
 
675
                 */
 
676
                if ( ((unsigned char *)rniov[ 0 ].iov_base)[ 0 ] != connid ) {
 
677
                    fprintf( stderr, "Bad data response!\n" );
 
678
                    exit( 1 );
 
679
                }
 
680
#endif /* ZEROCONNID */
 
681
                if ( ((char *)rniov[ 0 ].iov_base)[ 1 ] != PAP_DATA ) {
 
682
                    fprintf( stderr, "Bad data response!\n" );
 
683
                    exit( 1 );
 
684
                }
 
685
 
 
686
                for ( cc = 0, i = 0; i < atpb.atp_rresiovcnt; i++ ) {
 
687
                    sfiov[ i ].iov_len = rniov[ i ].iov_len - 4;
 
688
                    cc += sfiov[ i ].iov_len;
 
689
                }
 
690
                if ( cc && writev( 1, sfiov, atpb.atp_rresiovcnt ) < cc ) {
 
691
                    perror( "writev" );
 
692
                    exit( 2 );
 
693
                }
 
694
 
 
695
                /* eof */
 
696
                if ( ((char *)rniov[ 0 ].iov_base)[ 2 ] ) {
 
697
 
 
698
        if(debug){ printf( "< DATA (eof)\n" ), fflush( stdout );}
 
699
 
 
700
                    return( 0 );
 
701
                }
 
702
 
 
703
        if(debug){ printf( "< DATA\n" ), fflush( stdout );}
 
704
 
 
705
 
 
706
                /*
 
707
                 * Ask for more data.
 
708
                 */
 
709
                cbuf[ 0 ] = connid;
 
710
                cbuf[ 1 ] = PAP_READ;
 
711
                if ( ++seq == 0 ) seq = 1;
 
712
                netseq = htons( seq );
 
713
                memcpy( cbuf +  2, &netseq, sizeof( netseq ));
 
714
                atpb.atp_saddr = &sat;
 
715
                atpb.atp_sreqdata = cbuf;
 
716
                atpb.atp_sreqdlen = 4;          /* bytes in SendData request */
 
717
                atpb.atp_sreqto = 15;           /* retry timer */
 
718
                atpb.atp_sreqtries = -1;        /* retry count */
 
719
                if ( atp_sreq( atp, &atpb, oquantum, ATP_XO ) < 0 ) {
 
720
                    perror( "atp_sreq" );
 
721
                    exit( 1 );
 
722
                }
 
723
 
 
724
        if(debug){ printf( "READ %d >\n", seq ), fflush( stdout );}
 
725
 
 
726
                break;
 
727
 
 
728
            case 0:
 
729
 
 
730
        if(debug){ printf( "| RETRANS\n" ), fflush( stdout );}
 
731
 
 
732
                break;
 
733
 
 
734
            default:
 
735
                perror( "atp_rsel" );
 
736
                exit( 1 );
 
737
            }
 
738
        }
 
739
 
 
740
        /*
 
741
         * Send whatever is pending.
 
742
         */
 
743
        if ( !waitforprinter && !senteof && data && ( fiovcnt || eof )) {
 
744
            ssat.sat_port = port;
 
745
            atpb.atp_saddr = &ssat;
 
746
            if ( fiovcnt ) {
 
747
                for ( i = 0; i < fiovcnt; i++ ) {
 
748
                    sniov[ i ].iov_len = rfiov[ i ].iov_len + 4;
 
749
                    ((char *)sniov[ i ].iov_base)[ 0 ] = connid;
 
750
                    ((char *)sniov[ i ].iov_base)[ 1 ] = PAP_DATA;
 
751
                    senteof = ((char *)sniov[ i ].iov_base)[ 2 ] = eof;
 
752
                    ((char *)sniov[ i ].iov_base)[ 3 ] = 0;
 
753
                }
 
754
            } else {
 
755
                sniov[ 0 ].iov_len = 4;
 
756
                ((char *)sniov[ 0 ].iov_base)[ 0 ] = connid;
 
757
                ((char *)sniov[ 0 ].iov_base)[ 1 ] = PAP_DATA;
 
758
                senteof = ((char *)sniov[ 0 ].iov_base)[ 2 ] = eof;
 
759
                ((char *)sniov[ 0 ].iov_base)[ 3 ] = 0;
 
760
            }
 
761
            atpb.atp_sresiov = sniov;
 
762
            atpb.atp_sresiovcnt = fiovcnt ? fiovcnt : 1;
 
763
            if ( atp_sresp( atp, &atpb ) < 0 ) {
 
764
                perror( "atp_sresp" );
 
765
                exit( 1 );
 
766
            }
 
767
            data = fiovcnt = 0;
 
768
 
 
769
        if(debug){ printf( "DATA %s\n", eof ? "(eof) >" : ">" ), fflush( stdout );}
 
770
 
 
771
            /*
 
772
             * The Apple LaserWriter IIf, the HP LWIIISi, and IV, don't
 
773
             * seem to send us an EOF on large jobs.  To work around
 
774
             * this heinous protocol violation, we won't wait for their
 
775
             * EOF before closing.
 
776
             */
 
777
            if ( eof && noeof && lastfile ) {
 
778
                return( 0 );
 
779
            }
 
780
        } else {
 
781
            /*
 
782
             * If we can't send data right now, go ahead and get the
 
783
             * status. This is cool, because we get here reliably
 
784
             * if there is a problem.
 
785
             */
 
786
            cbuf[ 0 ] = 0;
 
787
            cbuf[ 1 ] = PAP_SENDSTATUS;
 
788
            cbuf[ 2 ] = cbuf[ 3 ] = 0;
 
789
            atpb.atp_saddr = &nn.nn_sat;
 
790
            atpb.atp_sreqdata = cbuf;
 
791
            atpb.atp_sreqdlen = 4;      /* bytes in SendStatus request */
 
792
            atpb.atp_sreqto = 2;                /* retry timer */
 
793
            atpb.atp_sreqtries = 5;             /* retry count */
 
794
            if ( atp_sreq( satp, &atpb, 1, 0 ) < 0 ) {
 
795
                perror( "atp_sreq" );
 
796
                exit( 1 );
 
797
            }
 
798
 
 
799
        if(debug){ printf( "SENDSTATUS >\n" ), fflush( stdout );}
 
800
 
 
801
            atpb.atp_saddr = &nn.nn_sat;
 
802
            rniov[ 0 ].iov_len = PAP_MAXDATA + 4;
 
803
            atpb.atp_rresiov = rniov;
 
804
            atpb.atp_rresiovcnt = 1;
 
805
            if ( atp_rresp( satp, &atpb ) < 0 ) {
 
806
                perror( "atp_rresp" );
 
807
                continue;
 
808
            }
 
809
 
 
810
#ifndef NONZEROSTATUS
 
811
            /*
 
812
             * The stinking LaserWriter IINTX puts crap in this
 
813
             * field.
 
814
             */
 
815
            if ( ((char *)rniov[ 0 ].iov_base)[ 0 ] != 0 ) {
 
816
                fprintf( stderr, "Bad status response!\n" );
 
817
                exit( 1 );
 
818
            }
 
819
#endif /* NONZEROSTATUS */
 
820
 
 
821
            if ( ((char *)rniov[ 0 ].iov_base)[ 1 ] != PAP_STATUS ||
 
822
                    atpb.atp_rresiovcnt != 1 ) {
 
823
                fprintf( stderr, "Bad status response!\n" );
 
824
                exit( 1 );
 
825
            }
 
826
 
 
827
        if(debug){ printf( "< STATUS\n" ), fflush( stdout );}
 
828
 
 
829
#ifdef FUCKED
 
830
            if ( waitforprinter ) {
 
831
                char    st_buf[ 1024 ]; /* XXX too big */
 
832
 
 
833
                memcpy( st_buf, (char *) rniov[ 0 ].iov_base + 9, 
 
834
                        ((char *)rniov[ 0 ].iov_base)[ 8 ] );
 
835
                st_buf[ (int) ((char *)rniov[ 0 ].iov_base)[ 8 ]] = '\0';
 
836
                if ( strstr( st_buf, "waiting" ) != NULL ) {
 
837
                    waitforprinter = 0;
 
838
                }
 
839
            }
 
840
#endif /* FUCKED */
 
841
 
 
842
            updatestatus( (char *) rniov[ 0 ].iov_base + 9,
 
843
                    ((char *)rniov[ 0 ].iov_base)[ 8 ] );
 
844
        }
 
845
    }
 
846
}
 
847
 
 
848
void updatestatus( s, len )
 
849
    char        *s;
 
850
    int         len;
 
851
{
 
852
    int                 fd = -1;
 
853
    struct iovec        iov[ 3 ];
 
854
 
 
855
    if ( status ) {
 
856
        if (( fd = open( status, O_WRONLY|O_TRUNC )) < 0 ) {
 
857
            perror( status );
 
858
            status = NULL;
 
859
        }
 
860
    }
 
861
 
 
862
    if ( fd < 0 ) {
 
863
        fd = 2;
 
864
    }
 
865
 
 
866
    iov[ 0 ].iov_base = "%%[ ";
 
867
    iov[ 0 ].iov_len = 4;
 
868
    iov[ 1 ].iov_base = s;
 
869
    iov[ 1 ].iov_len = len;
 
870
    iov[ 2 ].iov_base = " ]%%\n";
 
871
    iov[ 2 ].iov_len = 5;
 
872
 
 
873
    writev( fd, iov, 3 );
 
874
    if ( status ) {
 
875
        close( fd );
 
876
    }
 
877
}