1/*
2 * $Id: papstatus.c,v 1.7 2009-10-14 01:38:28 didg Exp $
3 *
4 * Copyright (c) 1990,1991 Regents of The University of Michigan.
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify, and distribute this software and
8 * its documentation for any purpose and without fee is hereby granted,
9 * provided that the above copyright notice appears in all copies and
10 * that both that copyright notice and this permission notice appear
11 * in supporting documentation, and that the name of The University
12 * of Michigan not be used in advertising or publicity pertaining to
13 * distribution of the software without specific, written prior
14 * permission. This software is supplied as is without expressed or
15 * implied warranties of any kind.
16 *
17 *	Research Systems Unix Group
18 *	The University of Michigan
19 *	c/o Mike Clark
20 *	535 W. William Street
21 *	Ann Arbor, Michigan
22 *	+1-313-763-0525
23 *	netatalk@itd.umich.edu
24 */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif /* HAVE_CONFIG_H */
29
30#include <sys/types.h>
31#include <sys/time.h>
32#include <sys/uio.h>
33#include <sys/file.h>
34#include <netatalk/endian.h>
35#include <netatalk/at.h>
36#include <errno.h>
37#include <atalk/atp.h>
38#include <atalk/pap.h>
39#include <atalk/nbp.h>
40#include <atalk/util.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44
45#define _PATH_PAPRC	".paprc"
46
47/* Forward Declaration */
48static void getstatus(ATP atp, struct sockaddr_at *sat);
49
50static void usage(char *path)
51{
52    char	*p;
53
54    if (( p = strrchr( path, '/' )) == NULL ) {
55	p = path;
56    } else {
57	p++;
58    }
59    fprintf( stderr,
60	"Usage:\t%s [ -A address ] [ -p printername ]\n", p );
61    exit( 1 );
62}
63
64static char *
65paprc(void)
66{
67    static char	s[ 32 + 1 + 32 + 1 + 32 ];
68    char	*name = NULL;
69    FILE	*f;
70
71    if (( f = fopen( _PATH_PAPRC, "r" )) == NULL ) {
72	return( NULL );
73    }
74    while ( fgets( s, sizeof( s ), f ) != NULL ) {
75	s[ strlen( s ) - 1 ] = '\0';	/* remove trailing newline */
76	if ( *s == '#' ) {
77	    continue;
78	}
79	name = s;
80	break;
81    }
82    fclose( f );
83    return( name );
84}
85
86static char			*printer = NULL;
87
88static char			cbuf[ 8 ];
89static struct nbpnve		nn;
90
91int main( int ac, char **av)
92{
93    ATP			atp;
94    int			wait, c, err = 0;
95    char		*obj = NULL, *type = "LaserWriter", *zone = "*";
96    struct at_addr      addr;
97
98    extern char		*optarg;
99    extern int		optind;
100
101    memset(&addr, 0, sizeof(addr));
102    while (( c = getopt( ac, av, "p:s:A:" )) != EOF ) {
103	switch ( c ) {
104	case 'A':
105  	    if (!atalk_aton(optarg, &addr)) {
106	      fprintf(stderr, "Bad address.\n");
107	      exit(1);
108	    }
109	    break;
110	case 'p' :
111	    printer = optarg;
112	    break;
113
114	default :
115	    fprintf( stderr, "Unknown option: '%c'\n", c );
116	    err++;
117	}
118    }
119    if ( err ) {
120	usage( *av );
121    }
122    if ( printer == NULL && (( printer = paprc()) == NULL )) {
123	usage( *av );
124    }
125
126    /*
127     * Open connection.
128     */
129    if ( nbp_name( printer, &obj, &type, &zone ) < 0 ) {
130	fprintf( stderr, "%s: Bad name\n", printer );
131	exit( 1 );
132    }
133    if ( obj == NULL ) {
134	fprintf( stderr, "%s: Bad name\n", printer );
135	exit( 1 );
136    }
137    if ( nbp_lookup( obj, type, zone, &nn, 1, &addr ) <= 0 ) {
138	if ( errno != 0 ) {
139	    perror( "nbp_lookup" );
140	} else {
141	    fprintf( stderr, "%s:%s@%s: NBP Lookup failed\n", obj, type, zone );
142	}
143	exit( 1 );
144    }
145
146    if (( atp = atp_open( ATADDR_ANYPORT, &addr )) == NULL ) {
147	perror( "atp_open" );
148	exit( 1 );
149    }
150
151    if ( optind == ac ) {
152	getstatus( atp, &nn.nn_sat );
153	exit( 0 );
154    }
155    if ( optind - ac > 1 ) {
156	usage( *av );
157    }
158    wait = atoi( av[ optind ] );
159    for (;;) {
160	getstatus( atp, &nn.nn_sat );
161	sleep( wait );
162    }
163
164    return 0;
165}
166
167static void getstatus(ATP atp, struct sockaddr_at *sat)
168{
169    struct iovec	iov;
170    struct atp_block	atpb;
171    char		rbuf[ ATP_MAXDATA ];
172
173    cbuf[ 0 ] = 0;
174    cbuf[ 1 ] = PAP_SENDSTATUS;
175    cbuf[ 2 ] = cbuf[ 3 ] = 0;
176
177    atpb.atp_saddr = sat;
178    atpb.atp_sreqdata = cbuf;
179    atpb.atp_sreqdlen = 4;		/* bytes in SendStatus request */
180    atpb.atp_sreqto = 2;		/* retry timer */
181    atpb.atp_sreqtries = 5;		/* retry count */
182    if ( atp_sreq( atp, &atpb, 1, ATP_XO ) < 0 ) {
183	perror( "atp_sreq" );
184	exit( 1 );
185    }
186
187    iov.iov_base = rbuf;
188    iov.iov_len = sizeof( rbuf );
189    atpb.atp_rresiov = &iov;
190    atpb.atp_rresiovcnt = 1;
191    if ( atp_rresp( atp, &atpb ) < 0 ) {
192	perror( "atp_rresp" );
193	exit( 1 );
194    }
195
196    /* sanity */
197    if ( iov.iov_len < 8 ||
198	    rbuf[ 1 ] != PAP_STATUS ) {
199	fprintf( stderr, "Bad response!\n" );
200	return;	/* This is weird, since TIDs must match... */
201    }
202
203    printf( "%.*s\n", (int)iov.iov_len - 9, (char *) iov.iov_base + 9 );
204}
205