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: lpd_status.c,v 1.1.1.1 2008/10/15 03:28:27 james26_jang Exp $"; 28 29 30#include "lp.h" 31#include "getopt.h" 32#include "gethostinfo.h" 33#include "proctitle.h" 34#include "getprinter.h" 35#include "getqueue.h" 36#include "child.h" 37#include "fileopen.h" 38#include "sendreq.h" 39#include "globmatch.h" 40#include "permission.h" 41#include "lockfile.h" 42#include "errorcodes.h" 43 44#include "lpd_jobs.h" 45#include "lpd_status.h" 46 47//extern char printerstatus[32];//JY1106 48 49/**** ENDINCLUDE ****/ 50 51/*************************************************************************** 52 * Commentary: 53 * Patrick Powell Tue May 2 09:32:50 PDT 1995 54 * 55 * Return status: 56 * status has two formats: short and long 57 * 58 * Status information is obtained from 3 places: 59 * 1. The status file 60 * 2. any additional progress files indicated in the status file 61 * 3. job queue 62 * 63 * The status file is maintained by the current unspooler process. 64 * It updates this file with the following information: 65 * 66 * PID of the unspooler process [line 1] 67 * active job and status file name 68 * active job and status file name 69 * 70 * Example 1: 71 * 3012 72 * cfa1024host status 73 * 74 * Example 2: 75 * 3015 76 * cfa1024host statusfd2 77 * cfa1026host statusfd1 78 * 79 * Format of the information reporting: 80 * 81 * 0 1 2 3 4 5 6 7 82 * 12345678901234567890123456789012345678901234567890123456789012345678901234 83 * Rank Owner/ID Class Job Files Size Time 84 * 1 papowell@astart4+322 A 322 /tmp/hi 3 17:33:47 85 * x Sx SxSx Sx Sx Sx X 86 * 87 ***************************************************************************/ 88 89#define RANKW 7 90#define OWNERW 29 91#define CLASSW 2 92#define JOBW 6 93#define FILEW 18 94#define SIZEW 6 95#define TIMEW 8 96 97 98int Job_status( int *sock, char *input ) 99{ 100 char *s, *t, *name, *hash_key; 101 int displayformat, status_lines = 0, i, n; 102 struct line_list l, listv; 103 struct line_list done_list; 104 char error[SMALLBUFFER], buffer[16]; 105 int db, dbflag; 106 107 FILE *READSTATUSFILE;//JY1120 108 char readbuffer[SMALLBUFFER];//JY1120 109 char *str_index;//JY1120 110 111#if !defined(JYWENG20031104status) 112 if( input && *input ) ++input;//JY1114 113 if(get_queue_name(input)) 114 { 115 printf("QueueName is not LPRServer\n"); 116 send_ack_packet(sock, ACK_FAIL);//JY1120 117 return(0); 118 } 119 else 120 printf("QueueName is LPRServer\n"); 121 122 int prnstatus=1; 123 char buffertosend[LARGEBUFFER]; 124 int fdPRNPARorUSB=0;/*JYWENG20031104*/ 125 if((check_par_usb_prn())== 1) 126 fdPRNPARorUSB=open("/dev/usb/lp0",O_RDWR); 127 else 128 fdPRNPARorUSB=open("/dev/lp0",O_RDWR); 129 130 if(fdPRNPARorUSB == 0) 131 { 132 printf("file descriptor not created\n"); 133 send_ack_packet(sock, ACK_FAIL);//JY1120 134 return(0); 135 } 136// ioctl(fdPRNPARorUSB, 0x060b, &prnstatus); 137// if(prnstatus == 0) 138//JY1120 139 if((READSTATUSFILE=fopen("/var/state/printstatus.txt", "r")) == NULL) 140 { 141 printf("open /var/state/printstatus.txt failed!\n"); 142 send_ack_packet(sock, ACK_FAIL);//JY1120 143 return(0); 144 } 145 while( fgets(readbuffer, SMALLBUFFER, READSTATUSFILE) != NULL) 146 { 147 if((str_index = strstr(readbuffer, "PRINTER_STATUS=\""))) 148 { 149 str_index += 16;//moving to status 150 strncpy(printerstatus, str_index, strlen(str_index) - 2 ); 151 } 152 } 153//JY1120 154 155 SNPRINTF(buffertosend, sizeof(buffertosend))"Status: %s\n", printerstatus); 156// else 157// SNPRINTF(buffertosend, sizeof(buffertosend))"Status: Off line\n"); 158// if( Write_fd_str( *sock, buffertosend ) < 0 ) cleanup(0); 159 if( write( *sock, buffertosend, strlen(buffertosend) ) < 0 ) cleanup(0); 160 exit(0);//JY1120 161 162#endif 163 164 165#ifdef REMOVE 166 Init_line_list(&l); 167 Init_line_list(&listv); 168 Init_line_list(&done_list); 169 db = Debug; 170 dbflag = DbgFlag; 171 172 Name = "Job_status"; 173 174 /* get the format */ 175 if( (s = safestrchr(input, '\n' )) ) *s = 0; 176 displayformat = *input++; 177 178 /* 179 * if we get a short/long request from these hosts, 180 * reverse the sense of question 181 */ 182 if( Reverse_lpq_status_DYN 183 && (displayformat == REQ_DSHORT || displayformat==REQ_DLONG) ){ 184 Free_line_list(&l); 185 Split(&l,Reverse_lpq_status_DYN,File_sep,0,0,0,0,0,0); 186 if( Match_ipaddr_value( &l, &RemoteHost_IP ) == 0 ){ 187 DEBUGF(DLPQ1)("Job_status: reversing status sense"); 188 if( displayformat == REQ_DSHORT ){ 189 displayformat = REQ_DLONG; 190 } else { 191 displayformat = REQ_DSHORT; 192 } 193 } 194 Free_line_list(&l); 195 } 196 /* 197 * we have a list of hosts with format of the form: 198 * Key=list; Key=list;... 199 * key is s for short, l for long 200 */ 201 DEBUGF(DLPQ1)("Job_status: Force_lpq_status_DYN '%s'", Force_lpq_status_DYN); 202 if( Force_lpq_status_DYN ){ 203 Free_line_list(&listv); 204 Split(&listv,Force_lpq_status_DYN,";",0,0,0,0,0,0); 205 for(i = 0; i < listv.count; ++i ){ 206 s = listv.list[i]; 207 if( (t = safestrpbrk(s,File_sep)) ) *t++ = 0; 208 Free_line_list(&l); 209 Split(&l,t,Value_sep,0,0,0,0,0,0); 210 DEBUGF(DLPQ1)("Job_status: Force_lpq_status '%s'='%s'", s,t); 211 if( Match_ipaddr_value( &l, &RemoteHost_IP ) == 0 ){ 212 DEBUGF(DLPQ1)("Job_status: forcing status '%s'", s); 213 if( safestrcasecmp(s,"s") == 0 ){ 214 displayformat = REQ_DSHORT; 215 } else if( safestrcasecmp(s,"l") == 0 ){ 216 displayformat = REQ_DLONG; 217 } 218 status_lines = Short_status_length_DYN; 219 break; 220 } 221 } 222 Free_line_list(&l); 223 Free_line_list(&listv); 224 } 225 226 /* 227 * check for short status to be returned 228 */ 229 230 if( Return_short_status_DYN && displayformat == REQ_DLONG ){ 231 Free_line_list(&l); 232 Split(&l,Return_short_status_DYN,File_sep,0,0,0,0,0,0); 233 if( Match_ipaddr_value( &l, &RemoteHost_IP ) == 0 ){ 234 status_lines = Short_status_length_DYN; 235 DEBUGF(DLPQ1)("Job_status: truncating status to %d", 236 status_lines); 237 } 238 Free_line_list(&l); 239 } 240 241 DEBUGF(DLPQ1)("Job_status: doing '%s'", input ); 242 Free_line_list(&l); 243 Split(&l,input,Whitespace,0,0,0,0,0,0); 244 if( l.count == 0 ){ 245 SNPRINTF( error, sizeof(error)) "zero length command line"); 246 goto error; 247 } 248 249 /* save l.list[0] */ 250 name = l.list[0]; 251 252 if( (s = Is_clean_name( name )) ){ 253 SNPRINTF( error, sizeof(error)) 254 _("printer '%s' has illegal character at '%s' in name"), name, s ); 255 goto error; 256 } 257 258 Set_DYN(&Printer_DYN,name); 259 setproctitle( "lpd %s '%s'", Name, name ); 260 SNPRINTF(buffer,sizeof(buffer))"%d",displayformat); 261 l.list[0] = buffer; 262 263 /* we have the hash key */ 264 hash_key = Join_line_list_with_sep(&l,"_"); 265 for( s = hash_key; (s = strpbrk(s,Whitespace)); ) *s = '_'; 266 267 DEBUGF(DLPQ1)("Job_status: arg '%s'", s ); 268 /* now we put back the l.list[0] value */ 269 270 l.list[0] = name; 271 /* free the values l.list[0] */ 272 Remove_line_list( &l, 0 ); 273 name = Printer_DYN; 274 275 if( l.count && (s = l.list[0]) && s[0] == '-' ){ 276 DEBUGF(DLPQ1)("Job_status: arg '%s'", s ); 277 Free_line_list(&listv); 278 Split(&listv,s+1,Arg_sep,1,Value_sep,1,1,0,0); 279 Remove_line_list( &l, 0 ); 280#ifdef ORIGINAL_DEBUG//JY@1020 281 DEBUGFC(DLPQ1)Dump_line_list( "Job_status: args", &listv ); 282#endif 283 if( (n = Find_flag_value(&listv,"lines",Value_sep)) ) status_lines = n; 284 DEBUGF(DLPQ1)("Job_status: status_lines '%d'", status_lines ); 285 Free_line_list(&listv); 286 } 287 if( safestrcasecmp( name, ALL ) ){ 288 DEBUGF(DLPQ1)("Job_status: checking printcap entry '%s'", name ); 289 Get_queue_status( &l, sock, displayformat, status_lines, 290 &done_list, Max_status_size_DYN, hash_key ); 291 } else { 292 /* we work our way down the printcap list, checking for 293 ones that have a spool queue */ 294 /* note that we have already tried to get the 'all' list */ 295 296 Get_all_printcap_entries(); 297 for( i = 0; i < All_line_list.count; ++i ){ 298 Set_DYN(&Printer_DYN, All_line_list.list[i] ); 299 Debug = db; 300 DbgFlag = dbflag; 301 Get_queue_status( &l, sock, displayformat, status_lines, 302 &done_list, Max_status_size_DYN, hash_key ); 303 } 304 } 305 Free_line_list( &l ); 306 Free_line_list( &listv ); 307 Free_line_list( &done_list ); 308 DEBUGF(DLPQ3)("Job_status: DONE" ); 309 return(0); 310 311 error: 312 DEBUGF(DLPQ2)("Job_status: error msg '%s'", error ); 313 i = safestrlen(error); 314 if( (i = safestrlen(error)) >= (int)sizeof(error)-2 ){ 315 i = sizeof(error) - 2; 316 } 317 error[i++] = '\n'; 318 error[i] = 0; 319 Free_line_list( &l ); 320 Free_line_list( &listv ); 321 Free_line_list( &done_list ); 322 if( Write_fd_str( *sock, error ) < 0 ) cleanup(0); 323 DEBUGF(DLPQ3)("Job_status: done" ); 324#endif 325 return(0); 326} 327 328#ifdef REMOVE 329/*************************************************************************** 330 * void Get_queue_status 331 * sock - used to send information 332 * displayformat - REQ_DSHORT, REQ_DLONG, REQ_VERBOSE 333 * tokens - arguments 334 * - get the printcap entry (if any) 335 * - check the control file for current status 336 * - find and report the spool queue entries 337 ***************************************************************************/ 338void Get_queue_status( struct line_list *tokens, int *sock, 339 int displayformat, int status_lines, struct line_list *done_list, 340 int max_size, char *hash_key ) 341{ 342 char msg[SMALLBUFFER], buffer[SMALLBUFFER], error[SMALLBUFFER], 343 number[LINEBUFFER], header[LARGEBUFFER]; 344 char sizestr[SIZEW+TIMEW+32]; 345 char *pr, *s, *t, *path, *identifier, 346 *jobname, *joberror, *class, *priority, *d_identifier, 347 *job_time, *d_error, *d_dest, *openname, *hf_name, *filenames, 348 *tempfile = 0, *file = 0, *end_of_name; 349 struct line_list outbuf, info, lineinfo, cache, cache_info; 350 int status = 0, len, ix, nx, flag, count, held, move, 351 server_pid, unspooler_pid, fd, nodest, 352 printable, dcount, destinations = 0, 353 d_copies, d_copy_done, permission, jobnumber, db, dbflag, 354 matches, tempfd, savedfd, lockfd, delta, err, cache_index, 355 total_held, total_move, jerror, jdone; 356 double jobsize; 357 struct stat statb; 358 struct job job; 359 time_t modified = 0; 360 time_t timestamp = 0; 361 time_t now = time( (void *)0 ); 362 363 cache_index = -1; 364 365#ifdef ORIGINAL_DEBUG//JY@1020 366 DEBUG1("Get_queue_status: sock fd %d, checking '%s'", *sock, Printer_DYN ); 367 if(DEBUGL1)Dump_line_list( "Get_queue_status: done_list", done_list ); 368#endif 369 370 /* set printer name and printcap variables */ 371 372 Init_job(&job); 373 Init_line_list(&info); 374 Init_line_list(&lineinfo); 375 Init_line_list(&outbuf); 376 Init_line_list(&cache); 377 Init_line_list(&cache_info); 378 /* for caching */ 379 tempfile = 0; 380 savedfd = tempfd = lockfd = -1; 381 382 Check_max(tokens,2); 383 tokens->list[tokens->count] = 0; 384 msg[0] = 0; 385 header[0] = 0; 386 error[0] = 0; 387 pr = s = 0; 388 389 safestrncpy(buffer,Printer_DYN); 390 status = Setup_printer( Printer_DYN, error, sizeof(error), 0); 391 if( status ){ 392 if( error[0] == 0 ){ 393 SNPRINTF(error,sizeof(error))"Nonexistent printer '%s'", Printer_DYN); 394 } 395 goto error; 396 } 397 398 db = Debug; 399 dbflag = DbgFlag; 400 s = Find_str_value(&Spool_control,DEBUG,Value_sep); 401 if( !s ) s = New_debug_DYN; 402 Parse_debug( s, 0 ); 403 if( !(DLPQMASK & DbgFlag) ){ 404 Debug = db; 405 DbgFlag = dbflag; 406 } else { 407 int odb, odbf; 408 odb = Debug; 409 odbf = DbgFlag; 410 Debug = db; 411 DbgFlag = dbflag; 412 if( Log_file_DYN ){ 413 fd = Trim_status_file( -1, Log_file_DYN, Max_log_file_size_DYN, 414 Min_log_file_size_DYN ); 415 if( fd > 0 && fd != 2 ){ 416 dup2(fd,2); 417 close(fd); 418 close(fd); 419 } 420 } 421 Debug = odb; 422 DbgFlag = odbf; 423 } 424 425 DEBUGF(DLPQ3)("Get_queue_status: sock fd %d, Setup_printer status %d '%s'", *sock, status, error ); 426 /* set up status */ 427 if( Find_exists_value(done_list,Printer_DYN,Value_sep ) ){ 428 return; 429 } 430 Add_line_list(done_list,Printer_DYN,Value_sep,1,1); 431 432 /* check for permissions */ 433 434 Perm_check.service = 'Q'; 435 Perm_check.printer = Printer_DYN; 436 437 permission = Perms_check( &Perm_line_list, &Perm_check, 0, 0 ); 438 DEBUGF(DLPQ1)("Job_status: permission '%s'", perm_str(permission)); 439 if( permission == P_REJECT ){ 440 SNPRINTF( error, sizeof(error)) 441 _("%s: no permission to show status"), Printer_DYN ); 442 goto error; 443 } 444 445 /* check to see if we have any cached information */ 446 if( Lpq_status_cached_DYN > 0 && Lpq_status_file_DYN ){ 447 fd = -1; 448 do{ 449 DEBUGF(DLPQ1)("Job_status: getting lock on '%s'", Lpq_status_file_DYN); 450 lockfd = Checkwrite( Lpq_status_file_DYN, &statb, O_RDWR, 1, 0 ); 451 if( lockfd < 0 ){ 452 LOGERR_DIE(LOG_INFO)"Get_queue_status: cannot open '%s'", 453 Lpq_status_file_DYN); 454 } 455 if( Do_lock(lockfd, 0) < 0 ){ 456 DEBUGF(DLPQ1)("Get_queue_status: did not get lock"); 457 Do_lock(lockfd, 1); 458 DEBUGF(DLPQ1)("Get_queue_status: lock released"); 459 close(lockfd); lockfd = -1; 460 } 461 }while( lockfd < 0 ); 462 DEBUGF(DLPQ1)("Get_queue_status: lock succeeded"); 463 Free_line_list(&cache); 464 Get_fd_image_and_split(lockfd, 0,0,&cache,Line_ends,0,0,0,0,0,0); 465#ifdef ORIGINAL_DEBUG//JY@1020 466 DEBUGFC(DLPQ3)Dump_line_list("Get_queue_status- cache", &cache ); 467 DEBUGF(DLPQ3)("Get_queue_status: cache hash_key '%s'", hash_key ); 468#endif 469 file = 0; 470 nx = -1; 471 if( cache.count < Lpq_status_cached_DYN ){ 472 Check_max(&cache,Lpq_status_cached_DYN-cache.count); 473 for( ix = cache.count; ix < Lpq_status_cached_DYN; ++ix ){ 474 cache.list[ix] = 0; 475 } 476 cache.count = ix; 477 } 478 for( ix = 0; file == 0 && ix < cache.count; ++ix ){ 479 if( (s = cache.list[ix]) ){ 480 if( (t = safestrchr(s,'=')) ){ 481 *t = 0; 482 if( !strcmp(hash_key,s) ){ 483 file = t+1; 484 cache_index = ix; 485 } 486 *t = '='; 487 } 488 } 489 } 490 /* if we have a file name AND it is not stale then we use it */ 491 DEBUGF(DLPQ3)("Get_queue_status: found in cache '%s'", file ); 492 fd = -1; 493 if( file ){ 494 Split(&cache_info,file,Arg_sep,1,Value_sep,1,1,0,0); 495 file = Find_str_value(&cache_info,FILENAMES,Value_sep); 496 } 497#ifdef ORIGINAL_DEBUG//JY@1020 498 DEBUGFC(DLPQ3)Dump_line_list("Get_queue_status: cache_info", &cache_info ); 499#endif 500 if( file && (fd = Checkread( file, &statb )) > 0 ){ 501 modified = statb.st_mtime; 502 delta = now - modified; 503 if( Lpq_status_stale_DYN && delta > Lpq_status_stale_DYN ){ 504 /* we cannot use it */ 505 close(fd); fd = -1; 506 } 507 } 508 if( fd > 0 ){ 509 modified = 0; 510 if( Queue_status_file_DYN && stat(Queue_status_file_DYN,&statb) == 0 ){ 511 modified = statb.st_mtime; 512 } 513 timestamp = Find_flag_value(&cache_info,QUEUE_STATUS_FILE,Value_sep); 514 delta = modified - timestamp; 515 DEBUGF(DLPQ3)("Get_queue_status: queue status '%s', modified %lx, timestamp %lx, delta %d", 516 Queue_status_file_DYN, (long)(modified), (long)(timestamp), delta ); 517 if( delta > Lpq_status_interval_DYN ){ 518 /* we need to refresh the data */ 519 close(fd); fd = -1; 520 } 521 } 522 523 if( fd > 0 ){ 524 if( Status_file_DYN && stat(Status_file_DYN,&statb) == 0 ){ 525 modified = statb.st_mtime; 526 } 527 timestamp = Find_flag_value(&cache_info,PRSTATUS,Value_sep); 528 delta = modified - timestamp; 529 DEBUGF(DLPQ3)("Get_queue_status: pr status '%s', modified %lx, timestamp %lx, delta %d", 530 Status_file_DYN, (long)(modified), (long)(timestamp), delta ); 531 if( delta > Lpq_status_interval_DYN ){ 532 /* we need to refresh the data */ 533 close(fd); fd = -1; 534 } 535 } 536 537 if( fd > 0 ){ 538 DEBUGF(DLPQ3)("Get_queue_status: reading cached status from fd '%d'", fd ); 539 /* We can read the status from the cached data */ 540 while( (ix = read( fd, buffer, sizeof(buffer)-1 )) > 0 ){ 541 if( write( *sock, buffer, ix ) < 0 ){ 542 cleanup(0); 543 } 544 } 545 close(fd); fd = -1; 546 goto remote; 547 } 548 /* OK, we have to cache the status in a file */ 549 tempfd = Make_temp_fd( &tempfile ); 550 savedfd = *sock; 551 *sock = tempfd; 552 } 553 554 end_of_name = 0; 555 if( displayformat != REQ_DSHORT ){ 556 SNPRINTF( header, sizeof(header)) "%s: ", 557 Server_queue_name_DYN?"Server Printer":"Printer" ); 558 } 559 len = safestrlen(header); 560 SNPRINTF( header+len, sizeof(header)-len) "%s@%s", 561 Printer_DYN, Report_server_as_DYN?Report_server_as_DYN:ShortHost_FQDN ); 562 if( safestrcasecmp( buffer, Printer_DYN ) ){ 563 len = safestrlen(header); 564 SNPRINTF( header+len, sizeof(header)-len) _(" (originally %s)"), buffer ); 565 } 566 end_of_name = header+safestrlen(header); 567 568 if( status ){ 569 len = safestrlen( header ); 570 if( displayformat == REQ_VERBOSE ){ 571 safestrncat( header, _("\n Error: ") ); 572 len = safestrlen( header ); 573 } 574 if( error[0] ){ 575 SNPRINTF( header+len, sizeof(header)-len) 576 _(" - %s"), error ); 577 } else if( !Spool_dir_DYN ){ 578 SNPRINTF( header+len, sizeof(header)-len) 579 _(" - printer %s@%s not in printcap"), Printer_DYN, 580 Report_server_as_DYN?Report_server_as_DYN:ShortHost_FQDN ); 581 } else { 582 SNPRINTF( header+len, sizeof(header)-len) 583 _(" - printer %s@%s has bad printcap entry"), Printer_DYN, 584 Report_server_as_DYN?Report_server_as_DYN:ShortHost_FQDN ); 585 } 586 safestrncat( header, "\n" ); 587 DEBUGF(DLPQ3)("Get_queue_status: forward header '%s'", header ); 588 if( Write_fd_str( *sock, header ) < 0 ) cleanup(0); 589 header[0] = 0; 590 goto done; 591 } 592 if( displayformat == REQ_VERBOSE ){ 593 safestrncat( header, "\n" ); 594 if( Write_fd_str( *sock, header ) < 0 ) cleanup(0); 595 header[0] = 0; 596 } 597 598 /* get the spool entries */ 599 Free_line_list( &outbuf ); 600 Scan_queue( &Spool_control, &Sort_order, &printable,&held,&move,0,0,0,0,0 ); 601 /* check for done jobs, remove any if there are some */ 602 if( Remove_done_jobs() ){ 603 Scan_queue( &Spool_control, &Sort_order, &printable,&held,&move,0,0,0,0,0 ); 604 } 605 606#ifdef ORIGINAL_DEBUG//JY@1020 607 DEBUGF(DLPQ3)("Get_queue_status: total files %d", Sort_order.count ); 608 DEBUGFC(DLPQ3)Dump_line_list("Get_queue_status- Sort_order", &Sort_order ); 609#endif 610 611 612 /* set up the short format for folks */ 613 614 if( displayformat == REQ_DLONG && Sort_order.count > 0 ){ 615 /* 616 Rank Owner/ID Class Job Files Size Time 617 */ 618 Add_line_list(&outbuf, 619" Rank Owner/ID Class Job Files Size Time" 620 ,0,0,0); 621 } 622 error[0] = 0; 623 624 matches = 0; 625 total_held = 0; 626 total_move = 0; 627 for( count = 0; count < Sort_order.count; ++count ){ 628 int printable, held, move; 629 printable = held = move = 0; 630 Free_job(&job); 631 Get_hold_file(&job, Sort_order.list[count] ); 632 Job_printable(&job,&Spool_control, &printable,&held,&move,&jerror,&jdone); 633 DEBUGF(DLPQ3)("Get_queue_status: printable %d, held %d, move %d, error %d, done %d", 634 printable, held, move, jerror, jdone ); 635#ifdef ORIGINAL_DEBUG//JY@1020 636 DEBUGFC(DLPQ4)Dump_job("Get_queue_status - info", &job ); 637#endif 638 if( job.info.count == 0 ) continue; 639 640 if( tokens->count && Patselect( tokens, &job.info, 0) ){ 641 continue; 642 } 643 644 number[0] = 0; 645 error[0] = 0; 646 msg[0] = 0; 647 nodest = 0; 648 s = Find_str_value(&job.info,PRSTATUS,Value_sep); 649 if( s == 0 ){ 650 SNPRINTF(number,sizeof(number))"%d",count+1); 651 } else { 652 SNPRINTF(number,sizeof(number))"%s",s); 653 } 654 identifier = Find_str_value(&job.info,IDENTIFIER,Value_sep); 655 if( identifier == 0 ){ 656 identifier = Find_str_value(&job.info,LOGNAME,Value_sep); 657 } 658 if( identifier == 0 ){ 659 identifier = "???"; 660 } 661 priority = Find_str_value(&job.info,PRIORITY,Value_sep); 662 class = Find_str_value(&job.info,CLASS,Value_sep); 663 jobname = Find_str_value(&job.info,JOBNAME,Value_sep); 664 filenames = Find_str_value(&job.info,FILENAMES,Value_sep); 665 jobnumber = Find_decimal_value(&job.info,NUMBER,Value_sep); 666 joberror = Find_str_value(&job.info,ERROR,Value_sep); 667 jobsize = Find_double_value(&job.info,SIZE,Value_sep); 668 job_time = Find_str_value(&job.info,JOB_TIME,Value_sep ); 669 destinations = Find_flag_value(&job.info,DESTINATIONS,Value_sep); 670 671 openname = Find_str_value(&job.info,OPENNAME,Value_sep); 672 if( !openname ){ 673 openname = Find_str_value(&job.info,TRANSFERNAME,Value_sep); 674 } 675 if( !openname ){ 676 DEBUGF(DLPQ4)("Get_queue_status: no openname or transfername"); 677 continue; 678 } 679 hf_name = Find_str_value(&job.info,HF_NAME,Value_sep); 680 if( !hf_name ){ 681 DEBUGF(DLPQ4)("Get_queue_status: no hf_name"); 682 continue; 683 } 684 685 /* we report this jobs status */ 686 687 DEBUGF(DLPQ3)("Get_queue_status: joberror '%s'", joberror ); 688 DEBUGF(DLPQ3)("Get_queue_status: class '%s', priority '%s'", 689 class, priority ); 690 691 if( (Class_in_status_DYN && class) || priority == 0 ){ 692 priority = class; 693 } 694 695 if( displayformat == REQ_DLONG ){ 696 SNPRINTF( msg, sizeof(msg)) 697 "%-*s %-*s ", RANKW-1, number, OWNERW-1, identifier ); 698 while( (len = safestrlen(msg)) > (RANKW+OWNERW) 699 && isspace(cval(msg+len-1)) && isspace(cval(msg+len-2)) ){ 700 msg[len-1] = 0; 701 } 702 SNPRINTF( buffer, sizeof(buffer)) "%-*s %*d ", 703 CLASSW-1,priority, JOBW-1,jobnumber); 704 DEBUGF(DLPQ3)("Get_queue_status: msg len %d '%s', buffer %d, '%s'", 705 safestrlen(msg),msg, safestrlen(buffer), buffer ); 706 DEBUGF(DLPQ3)("Get_queue_status: RANKW %d, OWNERW %d, CLASSW %d, JOBW %d", 707 RANKW, OWNERW, CLASSW, JOBW ); 708 s = buffer; 709 while( safestrlen(buffer) > CLASSW+JOBW && (s = safestrchr(s,' ')) ){ 710 if( cval(s+1) == ' ' ){ 711 memmove(s,s+1,safestrlen(s)+1); 712 } else { 713 ++s; 714 } 715 } 716 s = msg+safestrlen(msg)-1; 717 while( safestrlen(msg) + safestrlen(buffer) > RANKW+OWNERW+CLASSW+JOBW ){ 718 if( cval(s) == ' ' && cval(s-1) == ' ' ){ 719 *s-- = 0; 720 } else { 721 break; 722 } 723 } 724 s = buffer; 725 while( safestrlen(msg) + safestrlen(buffer) > RANKW+OWNERW+CLASSW+JOBW 726 && (s = safestrchr(s,' ')) ){ 727 if( cval(s+1) == ' ' ){ 728 memmove(s,s+1,safestrlen(s)+1); 729 } else { 730 ++s; 731 } 732 } 733 len = safestrlen(msg); 734 735 SNPRINTF(msg+len, sizeof(msg)-len)"%s",buffer); 736 if( joberror ){ 737 len = safestrlen(msg); 738 SNPRINTF(msg+len,sizeof(msg)-len) 739 "ERROR: %s", joberror ); 740 } else { 741 DEBUGF(DLPQ3)("Get_queue_status: jobname '%s'", jobname ); 742 743 len = safestrlen(msg); 744 SNPRINTF(msg+len,sizeof(msg)-len)"%-s",jobname?jobname:filenames); 745 746 DEBUGF(DLPQ3)("Get_queue_status: jobtime '%s'", job_time ); 747 job_time = Time_str(1, Convert_to_time_t(job_time)); 748 if( !Full_time_DYN && (s = safestrchr(job_time,'.')) ) *s = 0; 749 750 { 751 char jobb[32]; 752 SNPRINTF(jobb,sizeof(jobb)) "%0.0f", jobsize ); 753 SNPRINTF( sizestr, sizeof(sizestr)) "%*s %-s", 754 SIZEW-1,jobb, job_time ); 755 } 756 757 len = Max_status_line_DYN; 758 if( len >= (int)sizeof(msg)) len = sizeof(msg)-1; 759 len = len-safestrlen(sizestr); 760 if( len > 0 ){ 761 /* pad with spaces */ 762 for( nx = safestrlen(msg); nx < len; ++nx ){ 763 msg[nx] = ' '; 764 } 765 msg[nx] = 0; 766 } 767 /* remove spaces if necessary */ 768 while( safestrlen(msg) + safestrlen(sizestr) > Max_status_line_DYN ){ 769 if( isspace( cval(sizestr) ) ){ 770 memmove(sizestr, sizestr+1, safestrlen(sizestr)+1); 771 } else { 772 s = msg+safestrlen(msg)-1; 773 if( isspace(cval(s)) && isspace(cval(s-1)) ){ 774 s[0] = 0; 775 } else { 776 break; 777 } 778 } 779 } 780 if( safestrlen(msg) + safestrlen(sizestr) >= Max_status_line_DYN ){ 781 len = Max_status_line_DYN - safestrlen(sizestr); 782 msg[len-1] = ' '; 783 msg[len] = 0; 784 } 785 strcpy( msg+safestrlen(msg), sizestr ); 786 } 787 788 if( Max_status_line_DYN < (int)sizeof(msg) ) msg[Max_status_line_DYN] = 0; 789 790 DEBUGF(DLPQ3)("Get_queue_status: adding '%s'", msg ); 791 Add_line_list(&outbuf,msg,0,0,0); 792 DEBUGF(DLPQ3)("Get_queue_status: destinations '%d'", destinations ); 793 if( nodest == 0 && destinations ){ 794 for( dcount = 0; dcount < destinations; ++dcount ){ 795 if( Get_destination( &job, dcount ) ) continue; 796#ifdef ORIGINAL_DEBUG//JY@1020 797 DEBUGFC(DLPQ3)Dump_line_list("Get_queue_status: destination", 798 &job.destination); 799#endif 800 d_error = 801 Find_str_value(&job.destination,ERROR,Value_sep); 802 d_dest = 803 Find_str_value(&job.destination,DEST,Value_sep); 804 d_copies = 805 Find_flag_value(&job.destination,COPIES,Value_sep); 806 d_copy_done = 807 Find_flag_value(&job.destination,COPY_DONE,Value_sep); 808 d_identifier = 809 Find_str_value(&job.destination,IDENTIFIER,Value_sep); 810 s = Find_str_value(&job.destination, PRSTATUS,Value_sep); 811 if( !s ) s = ""; 812 SNPRINTF(number, sizeof(number))" - %-8s", s ); 813 SNPRINTF( msg, sizeof(msg)) 814 "%-*s %-*s ", RANKW, number, OWNERW, d_identifier ); 815 len = safestrlen(msg); 816 SNPRINTF(msg+len, sizeof(msg)-len) " ->%s", d_dest ); 817 if( d_copies > 1 ){ 818 len = safestrlen( msg ); 819 SNPRINTF( msg+len, sizeof(msg)-len) 820 _(" <cpy %d/%d>"), d_copy_done, d_copies ); 821 } 822 if( d_error ){ 823 len = safestrlen(msg); 824 SNPRINTF( msg+len, sizeof(msg)-len) " ERROR: %s", d_error ); 825 } 826 Add_line_list(&outbuf,msg,0,0,0); 827 } 828 } 829 DEBUGF(DLPQ3)("Get_queue_status: after dests" ); 830 } else if( displayformat == REQ_VERBOSE ){ 831 SNPRINTF( header, sizeof(header)) 832 _(" Job: %s"), identifier ); 833 SNPRINTF( msg, sizeof(msg)) _("%s status= %s"), 834 header, number ); 835 Add_line_list(&outbuf,msg,0,0,0); 836 SNPRINTF( msg, sizeof(msg)) _("%s size= %0.0f"), 837 header, jobsize ); 838 Add_line_list(&outbuf,msg,0,0,0); 839 SNPRINTF( msg, sizeof(msg)) _("%s time= %s"), 840 header, job_time ); 841 Add_line_list(&outbuf,msg,0,0,0); 842 if( joberror ){ 843 SNPRINTF( msg, sizeof(msg)) _("%s error= %s"), 844 header, joberror ); 845 Add_line_list(&outbuf,msg,0,0,0); 846 } 847 SNPRINTF( msg, sizeof(msg)) _("%s CONTROL="), header ); 848 Add_line_list(&outbuf,msg,0,0,0); 849 s = Get_file_image(openname,0); 850 Add_line_list(&outbuf,s,0,0,0); 851 if( s ) free(s); s = 0; 852 853 SNPRINTF( msg, sizeof(msg)) _("%s HOLDFILE="), header ); 854 Add_line_list(&outbuf,msg,0,0,0); 855 s = Get_file_image(hf_name,0); 856 Add_line_list(&outbuf,s,0,0,0); 857 if( s ) free(s); s = 0; 858 } else if( displayformat == REQ_DSHORT ){ 859 if( printable ){ 860 ++matches; 861 } else if( held ){ 862 ++total_held; 863 } else if( move ){ 864 ++total_move; 865 } 866 } 867 } 868 DEBUGF(DLPQ3)("Get_queue_status: matches %d", matches ); 869 /* this gives a short 1 line format with minimum info */ 870 if( displayformat == REQ_DSHORT ){ 871 len = safestrlen( header ); 872 SNPRINTF( header+len, sizeof(header)-len) _(" %d job%s"), 873 matches, (matches == 1)?"":"s" ); 874 if( total_held ){ 875 len = safestrlen( header ); 876 SNPRINTF( header+len, sizeof(header)-len) _(" (%d held)"), 877 total_held ); 878 } 879 if( total_move ){ 880 len = safestrlen( header ); 881 SNPRINTF( header+len, sizeof(header)-len) _(" (%d move)"), 882 total_move ); 883 } 884 } 885 len = safestrlen( header ); 886 887#ifdef ORIGINAL_DEBUG//JY@1020 888 DEBUGFC(DLPQ4)Dump_line_list("Get_queue_status: job status",&outbuf); 889 890 DEBUGF(DLPQ3)( 891 "Get_queue_status: RemoteHost_DYN '%s', RemotePrinter_DYN '%s', Lp '%s'", 892 RemoteHost_DYN, RemotePrinter_DYN, Lp_device_DYN ); 893#endif 894 895 if( displayformat != REQ_DSHORT ){ 896 s = 0; 897 if( (s = Comment_tag_DYN) == 0 ){ 898 if( (nx = PC_alias_line_list.count) > 1 ){ 899 s = PC_alias_line_list.list[nx-1]; 900 } 901 } 902 if( s ){ 903 s = Fix_str(s); 904 len = safestrlen( header ); 905 if( displayformat == REQ_VERBOSE ){ 906 SNPRINTF( header+len, sizeof(header)-len) _(" Comment: %s"), s ); 907 } else { 908 SNPRINTF( header+len, sizeof(header)-len) " '%s'", s ); 909 } 910 if(s) free(s); s = 0; 911 } 912 } 913 914 len = safestrlen( header ); 915 if( displayformat == REQ_VERBOSE ){ 916 SNPRINTF( header+len, sizeof(header)-len) 917 _("\n Printing: %s\n Aborted: %s\n Spooling: %s"), 918 Pr_disabled(&Spool_control)?"yes":"no", 919 Pr_aborted(&Spool_control)?"yes":"no", 920 Sp_disabled(&Spool_control)?"yes":"no"); 921 } else if( displayformat == REQ_DLONG || displayformat == REQ_DSHORT ){ 922 flag = 0; 923 if( Pr_disabled(&Spool_control) || Sp_disabled(&Spool_control) || Pr_aborted(&Spool_control) ){ 924 SNPRINTF( header+len, sizeof(header)-len) " (" ); 925 len = safestrlen( header ); 926 if( Pr_disabled(&Spool_control) ){ 927 SNPRINTF( header+len, sizeof(header)-len) "%s%s", 928 flag?", ":"", "printing disabled" ); 929 flag = 1; 930 len = safestrlen( header ); 931 } 932 if( Pr_aborted(&Spool_control) ){ 933 SNPRINTF( header+len, sizeof(header)-len) "%s%s", 934 flag?", ":"", "printing aborted" ); 935 flag = 1; 936 len = safestrlen( header ); 937 } 938 if( Sp_disabled(&Spool_control) ){ 939 SNPRINTF( header+len, sizeof(header)-len) "%s%s", 940 flag?", ":"", "spooling disabled" ); 941 len = safestrlen( header ); 942 } 943 SNPRINTF( header+len, sizeof(header)-len) ")" ); 944 len = safestrlen( header ); 945 } 946 } 947 948 /* 949 * check to see if this is a server or subserver. If it is 950 * for subserver, then you can forget starting it up unless started 951 * by the server. 952 */ 953 if( (s = Server_names_DYN) || (s = Destinations_DYN) ){ 954 Split( &info, s, File_sep, 0,0,0,0,0,0); 955 len = safestrlen( header ); 956 if( displayformat == REQ_VERBOSE ){ 957 if ( Server_names_DYN ) { 958 s = "Subservers"; 959 } else { 960 s = "Destinations"; 961 } 962 SNPRINTF( header+len, sizeof(header)-len) 963 _("\n %s: "), s ); 964 } else { 965 if ( Server_names_DYN ) { 966 s = "subservers"; 967 } else { 968 s = "destinations"; 969 } 970 SNPRINTF( header+len, sizeof(header)-len) 971 _(" (%s"), s ); 972 } 973 for( ix = 0; ix < info.count; ++ix ){ 974 len = safestrlen( header ); 975 SNPRINTF( header+len, sizeof(header)-len) 976 "%s%s", (ix > 0)?", ":" ", info.list[ix] ); 977 } 978 Free_line_list( &info ); 979 if( displayformat != REQ_VERBOSE ){ 980 safestrncat( header, ") " ); 981 } 982 } else if( (s = Frwarding(&Spool_control)) ){ 983 len = safestrlen( header ); 984 if( displayformat == REQ_VERBOSE ){ 985 SNPRINTF( header+len, sizeof(header)-len) 986 _("\n Redirected_to: %s"), s ); 987 } else { 988 SNPRINTF( header+len, sizeof(header)-len) 989 _(" (redirect %s)"), s ); 990 } 991 } else if( RemoteHost_DYN && RemotePrinter_DYN ){ 992 len = safestrlen( header ); 993 s = Frwarding(&Spool_control); 994 if( displayformat == REQ_VERBOSE ){ 995 SNPRINTF( header+len, sizeof(header)-len) 996 "\n Destination: %s@%s", RemotePrinter_DYN, RemoteHost_DYN ); 997 } else { 998 SNPRINTF( header+len, sizeof(header)-len) 999 _(" (dest %s@%s)"), RemotePrinter_DYN, RemoteHost_DYN ); 1000 } 1001 } 1002 if( Server_queue_name_DYN ){ 1003 len = safestrlen( header ); 1004 if( displayformat == REQ_VERBOSE ){ 1005 SNPRINTF( header+len, sizeof(header)-len) 1006 _("\n Serving: %s"), Server_queue_name_DYN ); 1007 } else { 1008 SNPRINTF( header+len, sizeof(header)-len) 1009 _(" (serving %s)"), Server_queue_name_DYN ); 1010 } 1011 } 1012 if( (s = Clsses(&Spool_control)) ){ 1013 len = safestrlen( header ); 1014 if( displayformat == REQ_VERBOSE ){ 1015 SNPRINTF( header+len, sizeof(header)-len) 1016 _("\n Classes: %s"), s ); 1017 } else { 1018 SNPRINTF( header+len, sizeof(header)-len) 1019 _(" (classes %s)"), s ); 1020 } 1021 } 1022 if( (Hld_all(&Spool_control)) ){ 1023 len = safestrlen( header ); 1024 if( displayformat == REQ_VERBOSE ){ 1025 SNPRINTF( header+len, sizeof(header)-len) 1026 _("\n Hold_all: on") ); 1027 } else { 1028 SNPRINTF( header+len, sizeof(header)-len) 1029 _(" (holdall)")); 1030 } 1031 } 1032 if( Auto_hold_DYN ){ 1033 len = safestrlen( header ); 1034 if( displayformat == REQ_VERBOSE ){ 1035 SNPRINTF( header+len, sizeof(header)-len) 1036 _("\n Auto_hold: on") ); 1037 } else { 1038 SNPRINTF( header+len, sizeof(header)-len) 1039 _(" (autohold)")); 1040 } 1041 } 1042 1043 if( (s = Find_str_value( &Spool_control,MSG,Value_sep )) ){ 1044 len = safestrlen( header ); 1045 if( displayformat == REQ_VERBOSE ){ 1046 SNPRINTF( header+len, sizeof(header)-len) 1047 _("\n Message: %s"), s ); 1048 } else { 1049 SNPRINTF( header+len, sizeof(header)-len) 1050 _(" (message: %s)"), s ); 1051 } 1052 } 1053 safestrncat( header, "\n" ); 1054 if( Write_fd_str( *sock, header ) < 0 ) cleanup(0); 1055 header[0] = 0; 1056 1057 if( displayformat == REQ_DSHORT ) goto remote; 1058 1059 /* now check to see if there is a server and unspooler process active */ 1060 path = Make_pathname( Spool_dir_DYN, Queue_lock_file_DYN ); 1061 server_pid = 0; 1062 if( (fd = Checkread( path, &statb ) ) >= 0 ){ 1063 server_pid = Read_pid( fd, (char *)0, 0 ); 1064 close( fd ); 1065 } 1066 DEBUGF(DLPQ3)("Get_queue_status: checking server pid %d", server_pid ); 1067 free(path); 1068 if( server_pid > 0 && kill( server_pid, 0 ) ){ 1069 DEBUGF(DLPQ3)("Get_queue_status: server %d not active", server_pid ); 1070 server_pid = 0; 1071 } 1072 1073 path = Make_pathname( Spool_dir_DYN, Queue_unspooler_file_DYN ); 1074 unspooler_pid = 0; 1075 if( (fd = Checkread( path, &statb ) ) >= 0 ){ 1076 unspooler_pid = Read_pid( fd, (char *)0, 0 ); 1077 close( fd ); 1078 } 1079 if(path) free(path); path=0; 1080 DEBUGF(DLPQ3)("Get_queue_status: checking unspooler pid %d", unspooler_pid ); 1081 if( unspooler_pid > 0 && kill( unspooler_pid, 0 ) ){ 1082 DEBUGF(DLPQ3)("Get_queue_status: unspooler %d not active", unspooler_pid ); 1083 unspooler_pid = 0; 1084 } 1085 1086 if( printable == 0 ){ 1087 safestrncpy( msg, _(" Queue: no printable jobs in queue\n") ); 1088 } else { 1089 /* check to see if there are files and no spooler */ 1090 SNPRINTF( msg, sizeof(msg)) _(" Queue: %d printable job%s\n"), 1091 printable, printable > 1 ? "s" : "" ); 1092 } 1093 if( Write_fd_str( *sock, msg ) < 0 ) cleanup(0); 1094 if( held ){ 1095 SNPRINTF( msg, sizeof(msg)) 1096 _(" Holding: %d held jobs in queue\n"), held ); 1097 if( Write_fd_str( *sock, msg ) < 0 ) cleanup(0); 1098 } 1099 1100 msg[0] = 0; 1101 if( count && server_pid == 0 ){ 1102 safestrncpy(msg, _(" Server: no server active") ); 1103 } else if( server_pid ){ 1104 len = safestrlen(msg); 1105 SNPRINTF( msg+len, sizeof(msg)-len) _(" Server: pid %d active"), 1106 server_pid ); 1107 } 1108 if( unspooler_pid ){ 1109 if( msg[0] ){ 1110 safestrncat( msg, (displayformat == REQ_VERBOSE )?", ":"\n"); 1111 } 1112 len = safestrlen(msg); 1113 SNPRINTF( msg+len, sizeof(msg)-len) _(" Unspooler: pid %d active"), 1114 unspooler_pid ); 1115 } 1116 if( msg[0] ){ 1117 safestrncat( msg, "\n" ); 1118 } 1119 if( msg[0] ){ 1120 if( Write_fd_str( *sock, msg ) < 0 ) cleanup(0); 1121 } 1122 msg[0] = 0; 1123 1124 if( displayformat == REQ_VERBOSE ){ 1125 SNPRINTF( msg, sizeof(msg)) _("%s SPOOLCONTROL=\n"), header ); 1126 if( Write_fd_str( *sock, msg ) < 0 ) cleanup(0); 1127 msg[0] = 0; 1128 for( ix = 0; ix < Spool_control.count; ++ix ){ 1129 s = safestrdup3(" ",Spool_control.list[ix],"\n",__FILE__,__LINE__); 1130 if( Write_fd_str( *sock, s ) < 0 ) cleanup(0); 1131 free(s); 1132 } 1133 } 1134 1135 /* 1136 * get the last status of the spooler 1137 */ 1138 Print_status_info( sock, Queue_status_file_DYN, 1139 _(" Status: "), status_lines, max_size ); 1140 1141 if( Status_file_DYN ){ 1142 Print_status_info( sock, Status_file_DYN, 1143 _(" Filter_status: "), status_lines, max_size ); 1144 } 1145 1146 s = Join_line_list(&outbuf,"\n"); 1147 if( s ){ 1148 if( Write_fd_str(*sock,s) < 0 ) cleanup(0); 1149 free(s); 1150 } 1151 Free_line_list(&outbuf); 1152 1153 remote: 1154 if( tempfd > 0 ){ 1155 /* we send the generated status back to the user */ 1156 *sock = savedfd; 1157 DEBUGF(DLPQ3)("Get_queue_status: reporting created status" ); 1158 if( lseek( tempfd, 0, SEEK_SET ) == -1 ){ 1159 LOGERR_DIE(LOG_INFO)"Get_queue_status: lseek of '%s' failed", 1160 tempfile ); 1161 } 1162 while( (ix = read( tempfd, buffer, sizeof(buffer)-1 )) > 0 ){ 1163 if( write( *sock, buffer, ix ) < 0 ){ 1164 break; 1165 } 1166 } 1167 close(tempfd); tempfd = -1; 1168#ifdef ORIGINAL_DEBUG//JY@1020 1169 DEBUGFC(DLPQ3)Dump_line_list("Get_queue_status- cache", &cache ); 1170 /* now we update the cached information */ 1171 DEBUGF(DLPQ3)("Get_queue_status: hash_key '%s', cache_index %d", 1172 hash_key, cache_index ); 1173#endif 1174 modified = 0; 1175 nx = -1; 1176 for( ix = 0; cache_index < 0 && ix < cache.count; ++ix ){ 1177 s = cache.list[ix]; 1178 DEBUGF(DLPQ3)("Get_queue_status: [%d] '%s'", ix, s ); 1179 Free_line_list(&cache_info); 1180 if( s && (t = strchr(s,'=')) ){ 1181 Split(&cache_info,t+1,Arg_sep,1,Value_sep,1,1,0,0); 1182 if( (file = Find_str_value(&cache_info,FILENAMES,Value_sep)) ){ 1183 /* we need to get the age of the file */ 1184 if( stat( file,&statb ) ){ 1185 /* the file is not there */ 1186 cache_index = ix; 1187 } else if( modified == 0 || statb.st_mtime < modified ){ 1188 nx = ix; 1189 modified = statb.st_mtime; 1190 } 1191 } else { 1192 cache_index = ix; 1193 } 1194 } else { 1195 DEBUGF(DLPQ3)("Get_queue_status: end of list [%d]", ix ); 1196 /* end of the list */ 1197 cache_index = ix; 1198 } 1199 } 1200 DEBUGF(DLPQ3)("Get_queue_status: cache_index %d", cache_index ); 1201 if( cache_index < 0 ) cache_index = nx; 1202 DEBUGF(DLPQ3)("Get_queue_status: using cache_index %d", cache_index ); 1203 if( cache_index < 0 ){ 1204 FATAL(LOG_INFO)"Get_queue_status: cache entry not found"); 1205 } 1206 SNPRINTF(buffer,sizeof(buffer))"%s.%d", Lpq_status_file_DYN,cache_index); 1207 1208 Free_line_list(&cache_info); 1209 Set_str_value(&cache_info,FILENAMES,buffer); 1210 1211 modified = 0; 1212 if( Queue_status_file_DYN && stat(Queue_status_file_DYN,&statb) == 0 ){ 1213 modified = statb.st_mtime; 1214 } 1215 Set_flag_value(&cache_info,QUEUE_STATUS_FILE,modified); 1216 1217 modified = 0; 1218 if( Status_file_DYN && stat(Status_file_DYN,&statb) == 0 ){ 1219 modified = statb.st_mtime; 1220 } 1221 Set_flag_value(&cache_info,PRSTATUS,modified); 1222 s = Join_line_list(&cache_info,","); 1223 1224 /* now set up the new values */ 1225 if( cache.list[cache_index] ) free( cache.list[cache_index]); cache.list[cache_index] = 0; 1226 cache.list[cache_index] = safestrdup3(hash_key,"=",s,__FILE__,__LINE__); 1227 if( s ) free(s); s = 0; 1228 1229#ifdef ORIGINAL_DEBUG//JY@1020 1230 DEBUGFC(DLPQ3)Dump_line_list("Get_queue_status- new cache", &cache ); 1231#endif 1232 if( rename( tempfile, buffer ) ){ 1233 err = errno; 1234 unlink( Lpq_status_file_DYN ); 1235 errno = err; 1236 LOGERR_DIE(LOG_INFO)"Get_queue_status: rename of '%s' to '%s' failed", 1237 tempfile, buffer ); 1238 } 1239 s = Join_line_list( &cache,"\n" ); 1240 if( lseek( lockfd, 0, SEEK_SET) == -1 ){ 1241 Errorcode = JABORT; 1242 LOGERR_DIE(LOG_INFO) "Get_queue_status: lseek failed write file '%s'", Lpq_status_file_DYN); 1243 } 1244 if( ftruncate( lockfd, 0 ) ){ 1245 Errorcode = JABORT; 1246 LOGERR_DIE(LOG_INFO) "Get_queue_status: ftruncate failed file '%s'", Lpq_status_file_DYN); 1247 } 1248 if( Write_fd_str( lockfd, s ) < 0 ){ 1249 unlink( Lpq_status_file_DYN ); 1250 Errorcode = JABORT; 1251 LOGERR_DIE(LOG_INFO) "Get_queue_status: write failed file '%s'", Lpq_status_file_DYN); 1252 } 1253 if(s) free(s); s = 0; 1254 close(lockfd); 1255 1256#if 0 1257 tempfd = Make_temp_fd( &tempfile ); 1258 if( Write_fd_str( tempfd, s ) < 0 ){ 1259 err = errno; 1260 unlink( Lpq_status_file_DYN ); 1261 LOGERR_DIE(LOG_INFO)"Get_queue_status: write to '%s' failed", 1262 tempfile ); 1263 errno = err; 1264 cleanup(0); 1265 } 1266 close(tempfd); tempfd = -1; 1267 if(s) free(s); s = 0; 1268 if( rename( tempfile, Lpq_status_file_DYN ) ){ 1269 err = errno; 1270 unlink( Lpq_status_file_DYN ); 1271 errno = err; 1272 LOGERR_DIE(LOG_INFO)"Get_queue_status: rename of '%s' to '%s' failed", 1273 tempfile, Lpq_status_file_DYN ); 1274 } 1275#endif 1276 Free_line_list(&cache_info); 1277 Free_line_list(&cache); 1278 close( lockfd ); lockfd = -1; 1279 } 1280 if( Server_names_DYN ){ 1281 Free_line_list(&info); 1282 Split(&info, Server_names_DYN, File_sep, 0,0,0,0,0,0); 1283 for( ix = 0; ix < info.count; ++ix ){ 1284 DEBUGF(DLPQ3)("Get_queue_status: getting subserver status '%s'", 1285 info.list[ix] ); 1286 Set_DYN(&Printer_DYN,info.list[ix]); 1287 Get_local_or_remote_status( tokens, sock, displayformat, 1288 status_lines, done_list, max_size, hash_key ); 1289 DEBUGF(DLPQ3)("Get_queue_status: finished subserver status '%s'", 1290 info.list[ix] ); 1291 } 1292 } else if( Destinations_DYN ){ 1293 Free_line_list(&info); 1294 Split(&info, Destinations_DYN, File_sep, 0,0,0,0,0,0); 1295 for( ix = 0; ix < info.count; ++ix ){ 1296 DEBUGF(DLPQ3)("Get_queue_status: getting destination status '%s'", 1297 info.list[ix] ); 1298 Set_DYN(&Printer_DYN,info.list[ix]); 1299 Get_local_or_remote_status( tokens, sock, displayformat, 1300 status_lines, done_list, max_size, hash_key ); 1301 DEBUGF(DLPQ3)("Get_queue_status: finished destination status '%s'", 1302 info.list[ix] ); 1303 } 1304 } else if( RemoteHost_DYN ){ 1305 /* now we look at the remote host */ 1306 if( Find_fqdn( &LookupHost_IP, RemoteHost_DYN ) 1307 && ( !Same_host(&LookupHost_IP,&Host_IP ) 1308 || !Same_host(&LookupHost_IP,&Localhost_IP )) ){ 1309 DEBUGF(DLPQ1)("Get_queue_status: doing local"); 1310 if( safestrcmp(RemotePrinter_DYN, Printer_DYN) ){ 1311 Set_DYN(&Printer_DYN,RemotePrinter_DYN); 1312 Get_queue_status( tokens, sock, displayformat, status_lines, 1313 done_list, max_size, hash_key ); 1314 } else { 1315 SNPRINTF(msg,sizeof(msg))"Error: loop in printcap- %s@%s -> %s@%s\n", 1316 Printer_DYN, FQDNHost_FQDN, RemotePrinter_DYN, RemoteHost_DYN ); 1317 Write_fd_str(*sock, msg ); 1318 } 1319 } else { 1320 DEBUGF(DLPQ1)("Get_queue_status: doing remote %s@%s", 1321 RemotePrinter_DYN, RemoteHost_DYN); 1322 if( Remote_support_DYN ) uppercase( Remote_support_DYN ); 1323 if( safestrchr( Remote_support_DYN, 'Q' ) ){ 1324#ifdef ORIGINAL_DEBUG//JY@1020 1325 fd = Send_request( 'Q', displayformat, tokens->list, Connect_timeout_DYN, 1326 Send_query_rw_timeout_DYN, *sock ); 1327#endif 1328 if( fd >= 0 ){ 1329 char *tempfile; 1330 /* shutdown( fd, 1 ); */ 1331 tempfd = Make_temp_fd( &tempfile ); 1332 while( (nx = read(fd,msg,sizeof(msg))) > 0 ){ 1333 if( Write_fd_len(tempfd,msg,nx) < 0 ) cleanup(0); 1334 } 1335 close(fd); fd = -1; 1336 Print_different_last_status_lines( sock, tempfd, status_lines, 0 ); 1337 close(tempfd); tempfd = -1; 1338 unlink( tempfile ); 1339 } 1340 } 1341 } 1342 } 1343 1344 DEBUGF(DLPQ3)("Get_queue_status: finished '%s'", Printer_DYN ); 1345 goto done; 1346 1347 error: 1348 SNPRINTF(header,sizeof(header))"Printer: %s@%s - ERROR: %s", 1349 Printer_DYN, Report_server_as_DYN?Report_server_as_DYN:ShortHost_FQDN, error ); 1350 DEBUGF(DLPQ1)("Get_queue_status: error msg '%s'", header ); 1351 if( Write_fd_str( *sock, header ) < 0 ) cleanup(0); 1352 done: 1353 if( savedfd > 0 ) *sock = savedfd; 1354 Free_line_list(&info); 1355 Free_line_list(&lineinfo); 1356 Free_line_list(&outbuf); 1357 Free_line_list(&cache); 1358 Free_line_list(&cache_info); 1359 return; 1360} 1361 1362void Print_status_info( int *sock, char *file, 1363 char *prefix, int status_lines, int max_size ) 1364{ 1365 char *image; 1366 static char *atmsg = " at "; 1367 struct line_list l; 1368 int start, i; 1369 Init_line_list(&l); 1370 1371 DEBUGF(DLPQ1)("Print_status_info: '%s', lines %d, size %d", 1372 file, status_lines, max_size ); 1373 if( status_lines > 0 ){ 1374 i = (status_lines * 100)/1024; 1375 if( i == 0 ) i = 1; 1376 image = Get_file_image(file, i); 1377 Split(&l,image,Line_ends,0,0,0,0,0,0); 1378 if( l.count < status_lines ){ 1379 if( image ) free( image ); image = 0; 1380 image = Get_file_image(file, 0); 1381 Split(&l,image,Line_ends,0,0,0,0,0,0); 1382 } 1383 } else { 1384 image = Get_file_image(file, max_size); 1385 Split(&l,image,Line_ends,0,0,0,0,0,0); 1386 } 1387 1388 DEBUGF(DLPQ1)("Print_status_info: line count %d", l.count ); 1389 1390 start = 0; 1391 if( status_lines ){ 1392 start = l.count - status_lines; 1393 if( start < 0 ) start = 0; 1394 } 1395 for( i = start; i < l.count; ++i ){ 1396 char *s, *t, *u; 1397 s = l.list[i]; 1398 if( (t = strstr( s, " ## " )) ){ 1399 *t = 0; 1400 } 1401 /* make the date format short */ 1402 if( !Full_time_DYN ){ 1403 for( u = s; (t = strstr(u,atmsg)); u = t+safestrlen(atmsg) ); 1404 if( u != s && (t = strrchr( u, '-' )) ){ 1405 memmove( u, t+1, safestrlen(t+1)+1 ); 1406 } 1407 } 1408 if( prefix && Write_fd_str(*sock,prefix) < 0 ) cleanup(0); 1409 if( Write_fd_str(*sock,s) < 0 ) cleanup(0); 1410 if( Write_fd_str(*sock,"\n") < 0 ) cleanup(0); 1411 } 1412 Free_line_list(&l); 1413 if( image) free(image); image = 0; 1414} 1415 1416void Print_different_last_status_lines( int *sock, int fd, 1417 int status_lines, int max_size ) 1418{ 1419 char header[SMALLBUFFER]; 1420 struct line_list l; 1421 int start, last_printed, i, j, same; 1422 char *s, *t; 1423 1424 Init_line_list(&l); 1425#ifdef ORIGINAL_DEBUG//JY@1020 1426 DEBUGF(DLPQ1)("Print_different_last_status_lines: status lines %d", status_lines ); 1427#endif 1428 Get_fd_image_and_split(fd,max_size,0,&l,Line_ends,0,0,0,0,0,0); 1429#ifdef ORIGINAL_DEBUG//JY@1020 1430 DEBUGFC(DLPQ1)Dump_line_list( "Print_different_last_status_lines", &l ); 1431#endif 1432 1433 header[0] = 0; 1434 last_printed = start = -1; 1435 if( status_lines > 0 ) for( i = 0; i < l.count; ++i ){ 1436 s = l.list[i]; 1437 /* find up to the first colon */ 1438 if( (t = safestrchr(s,':')) ){ 1439 *t = 0; 1440 } 1441 same = !safestrcmp( header, s ); 1442 if( !same ){ 1443 safestrncpy(header,s); 1444 } 1445 if( t ) *t = ':'; 1446 if( !same ){ 1447 /* we print from i-1-(status_lines-1) to i-1 */ 1448 start = i-status_lines; 1449 if( start <= last_printed ) start = last_printed + 1; 1450 for( j = start; j < i; ++j ){ 1451 if( Write_fd_str(*sock,l.list[j]) < 0 ) cleanup(0); 1452 if( Write_fd_str(*sock,"\n") < 0 ) cleanup(0); 1453 } 1454 last_printed = i-1; 1455 DEBUGF(DLPQ1)("Print_different_last_status_lines: start %d, last_printed %d", 1456 start, last_printed ); 1457 } 1458 } 1459 if( status_lines > 0 ){ 1460 start = l.count - status_lines; 1461 } 1462 if( start <= last_printed ) start = last_printed + 1; 1463 DEBUGF(DLPQ1)("Print_different_last_status_lines: done, start %d", start ); 1464 for( i = start; i < l.count ; ++i ){ 1465 if( Write_fd_str(*sock,l.list[i]) < 0 ) cleanup(0); 1466 if( Write_fd_str(*sock,"\n") < 0 ) cleanup(0); 1467 } 1468 Free_line_list(&l); 1469} 1470 1471 1472void Get_local_or_remote_status( struct line_list *tokens, int *sock, 1473 int displayformat, int status_lines, struct line_list *done_list, 1474 int max_size, char *hash_key ) 1475{ 1476 char msg[SMALLBUFFER]; 1477 int fd, n, tempfd; 1478 1479 /* we have to see if the host is on this machine */ 1480 1481 DEBUGF(DLPQ1)("Get_local_or_remote_status: %s", Printer_DYN ); 1482 if( !safestrchr(Printer_DYN,'@') ){ 1483 DEBUGF(DLPQ1)("Get_local_or_remote_status: doing local"); 1484 Get_queue_status( tokens, sock, displayformat, status_lines, 1485 done_list, max_size, hash_key ); 1486 return; 1487 } 1488 Fix_Rm_Rp_info(0,0); 1489 /* now we look at the remote host */ 1490 if( Find_fqdn( &LookupHost_IP, RemoteHost_DYN ) 1491 && ( !Same_host(&LookupHost_IP,&Host_IP ) 1492 || !Same_host(&LookupHost_IP,&Localhost_IP )) ){ 1493 DEBUGF(DLPQ1)("Get_local_or_remote_status: doing local"); 1494 Get_queue_status( tokens, sock, displayformat, status_lines, 1495 done_list, max_size, hash_key ); 1496 return; 1497 } 1498 uppercase( Remote_support_DYN ); 1499 if( safestrchr( Remote_support_DYN, 'Q' ) ){ 1500 DEBUGF(DLPQ1)("Get_local_or_remote_status: doing remote %s@%s", 1501 RemotePrinter_DYN, RemoteHost_DYN); 1502#ifdef ORIGINAL_DEBUG//JY@1020 1503 fd = Send_request( 'Q', displayformat, tokens->list, Connect_timeout_DYN, 1504 Send_query_rw_timeout_DYN, *sock ); 1505#endif 1506 if( fd >= 0 ){ 1507 /* shutdown( fd, 1 ); */ 1508 tempfd = Make_temp_fd( 0 ); 1509 while( (n = read(fd,msg,sizeof(msg))) > 0 ){ 1510 if( Write_fd_len(tempfd,msg,n) < 0 ) cleanup(0); 1511 } 1512 close(fd); fd = -1; 1513 Print_different_last_status_lines( sock, tempfd, status_lines, 0 ); 1514 close(tempfd); 1515 } 1516 } 1517} 1518#endif 1519