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