1/***************************************************************************
2 * LPRng - An Extended Print Spooler System
3 *
4 * Copyright 1988-2003, Patrick Powell, San Diego, CA
5 *     papowell@lprng.com
6 * See LICENSE for conditions of use.
7 *
8 ***************************************************************************/
9
10 static char *const _id =
11"$Id: monitor.c,v 1.1.1.1 2008/10/15 03:28:27 james26_jang Exp $";
12
13
14#include "lp.h"
15#include "linelist.h"
16#include "getopt.h"
17#include "linksupport.h"
18#include "getqueue.h"
19/**** ENDINCLUDE ****/
20
21/*
22 * Monitor for TCP/UDP data
23 *  Opens a UDP or TCP socket and waits for data to be sent to it.
24 *
25 *  monitor [-t] [-u] [port]
26 *   port is an integer number or a service name in the services database
27 *   default is to use UDP.
28 */
29
30
31extern int errno;
32
33int udp_open( int port );
34int tcp_open( int port );
35
36void Decode( char *in );
37
38char buffer[1024*64];
39int use_tcp = 1;
40int use_udp = 1;
41int port_num = 2001;
42int udp_fd = -1;
43int tcp_fd = -1;
44fd_set readfds;
45fd_set testfds;
46int debug;
47
48char *prog = "???";
49
50/*****************************************************************
51 * Command line options and Debugging information
52 * Getopt is a modified version of the standard getopt(3) command
53 *  line parsing routine. See getopt.c for details
54 *****************************************************************/
55
56/* use this before any error printing, sets up program Name */
57
58struct info {
59	char *buffer;
60	int len;
61	int max_len;
62};
63
64struct info *inbuffers;
65int max_in_buffers;
66
67void Add_buffer( int n )
68{
69	int len = max_in_buffers, count;
70
71	if(debug)FPRINTF(STDERR, "Add_buffer: start n %d, inbuffers 0x%lx, max_in_buffers %d\n",
72		n, Cast_ptr_to_long(inbuffers), max_in_buffers );
73	if( max_in_buffers <= n ){
74		max_in_buffers = n+1;
75		count = sizeof(inbuffers[0])*max_in_buffers;
76		inbuffers = realloc( inbuffers, count );
77		if( inbuffers == 0 ){
78			FPRINTF(STDERR,"Add_buffer: realloc %d failed\n", n );
79			exit(1);
80		}
81		for( count = len; count < max_in_buffers; ++count ){
82			memset(inbuffers+count,0,sizeof(inbuffers[0]));
83		}
84	}
85	if(debug)FPRINTF(STDERR,"Add_buffer: end n %d, inbuffers 0x%lx, max_in_buffers %d\n",
86		n, Cast_ptr_to_long(inbuffers), max_in_buffers );
87}
88
89void Clear_buffer( int n )
90{
91	struct info *in;
92	if(debug)FPRINTF(STDERR,"Clear_buffer: n %d\n", n );
93	Add_buffer( n );
94	in = inbuffers+n;
95	in->len = 0;
96}
97
98struct info *Save_outbuf_len( int n,  char *str, int len )
99{
100	struct info *in;
101
102	if(debug)FPRINTF(STDERR,"Save_outbuf_len: n %d, len %d\n", n, len );
103	Add_buffer(n);
104	in = inbuffers+n;
105	if(debug)FPRINTF(STDERR,
106		"Save_outbuf_len: start inbuffers 0x%lx, in 0x%lx, buffer 0x%lx, len %d, max_len %d\n",
107		Cast_ptr_to_long(inbuffers), Cast_ptr_to_long(in),
108		Cast_ptr_to_long(in->buffer), in->len, in->max_len );
109	if( len + in->len >= in->max_len ){
110		in->max_len += len;
111		in->buffer = realloc( in->buffer, in->max_len+1 );
112		if( in->buffer == 0 ){
113			FPRINTF(STDERR,"Put_oubuf_len: realloc %d failed\n", in->max_len );
114			exit(1);
115		}
116	}
117	memcpy(in->buffer+in->len, str, len+1 );
118	in->len += len;
119	if(debug)FPRINTF(STDERR,
120		"Save_outbuf_len: start inbuffers 0x%lx, in 0x%lx, buffer 0x%lx, len %d, max_len %d\n",
121		Cast_ptr_to_long(inbuffers), Cast_ptr_to_long(in),
122		Cast_ptr_to_long(in->buffer), in->len, in->max_len );
123	return( in );
124}
125
126void usage(void)
127{
128	char *s;
129
130	if( (s = safestrrchr( prog, '/')) ){
131		prog  = s+1;
132	}
133	FPRINTF( STDERR, "usage: %s [-u] [-t] [port]\n", prog );
134	FPRINTF( STDERR, "  -u = use UDP\n" );
135	FPRINTF( STDERR, "  -t = use TCP (default)\n" );
136	FPRINTF( STDERR, "  -d = debug\n" );
137	FPRINTF( STDERR, "  port = port to use (%d default)\n", port_num  );
138	exit(1);
139}
140
141
142
143int main(int argc, char *argv[] )
144{
145	int n, i, c, err, max_port = 0;
146	char *portname, *s;
147	struct servent *servent;
148	struct info *in;
149
150	prog = argv[0];
151	Opterr = 1;
152	while( (n = Getopt(argc, argv, "dut")) != EOF ){
153		switch(n){
154		default:  usage(); break;
155		case 'u': use_udp = !use_udp; break;
156		case 't': use_tcp = !use_tcp; break;
157		case 'd': debug = 1; break;
158		}
159	}
160	i = argc - Optind;
161	if( i > 1 ) usage();
162	if( i == 1 ){
163		portname = argv[Optind];
164		n = atoi( portname );
165		if( n <= 0 ){
166			servent = getservbyname( portname, "udp" );
167			if( servent ){
168				n = ntohs( servent->s_port );
169			}
170		}
171		if( n <= 0 ){
172			FPRINTF( STDERR, "udp_open: bad port number '%s'\n",portname );
173			usage();
174		}
175		port_num = n;
176	}
177
178	if( !use_tcp && !use_udp ) use_udp = 1;
179	if( debug ){
180		FPRINTF(STDERR,"monitor: udp %d, tcp %d, port %d\n",
181			use_udp, use_tcp, port_num );
182	}
183
184	max_port = 0;
185	FD_ZERO( &readfds );
186	if( use_udp && (udp_fd = udp_open( port_num )) >= 0){
187		if( debug ) FPRINTF(STDERR,"monitor: udp port %d\n", udp_fd );
188		FD_SET(udp_fd, &readfds);
189		if( udp_fd >= max_port ) max_port = udp_fd+1;
190	}
191	if( use_tcp && (tcp_fd = tcp_open( port_num )) >= 0){
192		if( debug ) FPRINTF(STDERR,"monitor: tcp port %d\n", tcp_fd );
193		FD_SET(tcp_fd, &readfds);
194		if( tcp_fd >= max_port ) max_port = tcp_fd+1;
195	}
196	if( debug ){
197		FPRINTF(STDERR,"monitor: max_port %d\n", max_port );
198		for( i = 0; i < max_port; ++i ){
199			if( FD_ISSET(i, &readfds) ){
200				FPRINTF(STDERR,"monitor: initial on %d\n", i );
201			}
202		}
203	}
204
205
206	while(1){
207		FD_ZERO( &testfds );
208		for( i = 0; i < max_port; ++i ){
209			if( FD_ISSET(i, &readfds) ){
210				if( debug ) FPRINTF(STDERR,"monitor: waiting on %d\n", i );
211				FD_SET(i, &testfds);
212			}
213		}
214		if( debug ) FPRINTF(STDERR,"monitor: starting wait, max %d\n", i );
215		n = select( i,
216			FD_SET_FIX((fd_set *))&testfds,
217			FD_SET_FIX((fd_set *))0, FD_SET_FIX((fd_set *))0,
218			(struct timeval *)0 );
219		err = errno;
220		if( debug ) FPRINTF(STDERR,"monitor: select returned %d\n", n );
221		if( n < 0 ){
222			FPRINTF( STDERR, "select error - %s\n", Errormsg(errno) );
223			if( err != EINTR ) break;
224		}
225		if( n > 0 ) for( i = 0; i < max_port; ++i ){
226			if( FD_ISSET(i, &testfds) ){
227				if( debug ) FPRINTF(STDERR,"monitor: input on %d\n", i );
228				if( i == tcp_fd ){
229#if defined(HAVE_SOCKLEN_T)
230					socklen_t len;
231#else
232					int len;
233#endif
234					struct sockaddr_in sinaddr;
235					len = sizeof( sinaddr );
236					i = accept( tcp_fd, (struct sockaddr *)&sinaddr, &len );
237					if( i < 0 ){
238						FPRINTF( STDERR, "accept error - %s\n",
239							Errormsg(errno) );
240						continue;
241					}
242					FPRINTF( STDOUT, "connection from %s\n",
243						inet_ntoa( sinaddr.sin_addr ) );
244					if( i >= max_port ) max_port = i+1;
245					FD_SET(i, &readfds);
246				} else {
247					c = read( i, buffer, sizeof(buffer)-1 );
248					if( c == 0 ){
249						/* closed connection */
250						FPRINTF(STDOUT, "closed connection %d\n", i );
251						close( i );
252						FD_CLR(i, &readfds );
253						Clear_buffer(i);
254					} else if( c > 0 ){
255						buffer[c] = 0;
256						if(debug)FPRINTF( STDOUT, "recv port %d: %s\n", i, buffer );
257						Add_buffer(i);
258						in = Save_outbuf_len( i, buffer, c );
259						while( (s = safestrchr(in->buffer,'\n')) ){
260							*s++ = 0;
261							Decode(in->buffer);
262							memmove(in->buffer,s, safestrlen(s)+1 );
263							in->len = safestrlen(in->buffer);
264						}
265					} else {
266						FPRINTF( STDERR, "read error - %s\n",
267							Errormsg(errno) );
268						close( i );
269						FD_CLR(i, &readfds );
270					}
271				}
272			}
273		}
274	}
275	return(0);
276}
277
278void Decode( char *in )
279{
280	struct line_list l, cf, info;
281	char *s, *t, *header, *value;
282	int i;
283
284	Init_line_list(&l);
285	Init_line_list(&cf);
286	Init_line_list(&info);
287
288	FPRINTF(STDOUT,"****\n");
289	if( debug )FPRINTF(STDOUT, "Decode: %s\n", in );
290	if((s = safestrpbrk(in,Value_sep)) ){
291		*s++ = 0;
292		Unescape(s);
293		Free_line_list(&l);
294		Split(&l,s,Line_ends,1,Value_sep,1,1,1,0);
295		for( i = 0; i < l.count; ++i ){
296			t = l.list[i];
297			if( debug || safestrncasecmp(t,VALUE,5) ){
298				FPRINTF(STDOUT,"%s\n", t );
299			}
300		}
301		s = Find_str_value(&l,VALUE,Value_sep);
302		if( s ) Unescape(s);
303		if( !safestrcasecmp(in,TRACE) ){
304			FPRINTF(STDOUT,"TRACE: '%s'\n", s );
305		} else if( !safestrcasecmp(in,UPDATE) ){
306			FPRINTF(STDOUT,"UPDATE: '%s'\n", s );
307			Split(&info,s,Line_ends,0,0,0,0,0,0);
308			for( i = 0; i < info.count; ++i ){
309				header = info.list[i];
310				if( (value = safestrchr(header,'=')) ) *value++ = 0;
311				Unescape(value);
312				FPRINTF(STDOUT," [%d] %s='%s'\n", i, header, value );
313			}
314		} else if( !safestrcasecmp(in,PRSTATUS) ){
315			FPRINTF(STDOUT,"PRSTATUS: '%s'\n", s );
316		} else if( !safestrcasecmp(in,QUEUE) ){
317			FPRINTF(STDOUT,"QUEUE: '%s'\n", s );
318			Split(&info,s,Line_ends,0,0,0,0,0,0);
319			for( i = 0; i < info.count; ++i ){
320				header = info.list[i];
321				if( (value = safestrchr(header,'=')) ) *value++ = 0;
322				Unescape(value);
323				FPRINTF(STDOUT," [%d] %s='%s'\n", i, header, value );
324			}
325			Free_line_list(&info);
326		} else if( !safestrcasecmp(in,DUMP) ){
327			FPRINTF(STDOUT,"DUMP:\n");
328			Split(&info,s,Line_ends,0,0,0,0,0,0);
329			for( i = 0; i < info.count; ++i ){
330				header = info.list[i];
331				if( (value = safestrchr(header,'=')) ) *value++ = 0;
332				Unescape(value);
333				if(debug) FPRINTF(STDOUT," [%d] %s='%s'\n", i, header, value );
334				if( !safestrcasecmp(header,QUEUE) ){
335					FPRINTF(STDOUT," EXTRACT QUEUE '%s'\n",value);
336				} else if( !safestrcasecmp(header,UPDATE) ){
337					FPRINTF(STDOUT," EXTRACT UPDATE '%s'\n",value);
338				} else {
339					FPRINTF(STDOUT," EXTRACT '%s' '%s'\n",header, value);
340				}
341			}
342			Free_line_list(&info);
343		} else {
344			FPRINTF(STDOUT,"%s: '%s'\n", in, s );
345		}
346	}
347	Free_line_list(&l);
348	Free_line_list(&cf);
349	Free_line_list(&info);
350	FPRINTF(STDOUT,"\n");
351}
352int udp_open( int port )
353{
354	int i, fd, err;
355	struct sockaddr_in sinaddr;
356
357	sinaddr.sin_family = AF_INET;
358	sinaddr.sin_addr.s_addr = INADDR_ANY;
359	sinaddr.sin_port = htons( port );
360
361	fd = socket( AF_INET, SOCK_DGRAM, 0 );
362	Max_open(fd);
363	err = errno;
364	if( fd < 0 ){
365		FPRINTF(STDERR,"udp_open: socket call failed - %s\n", Errormsg(err) );
366		return( -1 );
367	}
368	i = -1;
369	i = bind( fd, (struct sockaddr *) & sinaddr, sizeof (sinaddr) );
370	err = errno;
371
372	if( i < 0 ){
373		FPRINTF(STDERR,"udp_open: bind to '%s port %d' failed - %s\n",
374			inet_ntoa( sinaddr.sin_addr ), ntohs( sinaddr.sin_port ),
375			Errormsg(errno) );
376		close(fd);
377		fd = -1;
378	}
379	if( fd == 0 ){
380		fd = dup(fd);
381		if( fd < 0 ){
382			FPRINTF(STDERR,"udp_open: dup failed - %s\n",
383				Errormsg(errno) );
384			close(fd);
385			fd = -1;
386		}
387	}
388	return( fd );
389}
390
391
392int tcp_open( int port )
393{
394	int i, fd, err;
395	struct sockaddr_in sinaddr;
396
397	sinaddr.sin_family = AF_INET;
398	sinaddr.sin_addr.s_addr = INADDR_ANY;
399	sinaddr.sin_port = htons( port );
400
401	fd = socket( AF_INET, SOCK_STREAM, 0 );
402#ifdef WINDOW_1
403int windowsize=1024;
404setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&windowsize, sizeof(windowsize));
405aaaaaa=fopen("/tmp/qqqqq", "a");
406fprintf(aaaaaa, " monitor: tcp_send\n");
407fclose(aaaaaa);
408#endif
409	Max_open(fd);
410	err = errno;
411	if( fd < 0 ){
412		FPRINTF(STDERR,"tcp_open: socket call failed - %s\n", Errormsg(err) );
413		return( -1 );
414	}
415	i = Link_setreuse( fd );
416	if( i >= 0 ) i = bind( fd, (struct sockaddr *) & sinaddr, sizeof (sinaddr) );
417	if( i >= 0 ) i = listen( fd, 10 );
418	err = errno;
419
420	if( i < 0 ){
421		FPRINTF(STDERR,"tcp_open: connect to '%s port %d' failed - %s\n",
422			inet_ntoa( sinaddr.sin_addr ), ntohs( sinaddr.sin_port ),
423			Errormsg(errno) );
424		close(fd);
425		fd = -1;
426	}
427	if( fd == 0 ){
428		fd = dup(fd);
429		if( fd < 0 ){
430			FPRINTF(STDERR,"tcp_open: dup failed - %s\n",
431				Errormsg(errno) );
432			close(fd);
433			fd = -1;
434		}
435	}
436	return( fd );
437}
438