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