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: lpd_remove.c,v 1.1.1.1 2008/10/15 03:28:27 james26_jang Exp $"; 12 13 14#include "lp.h" 15#include "lpd_remove.h" 16#include "getqueue.h" 17#include "getprinter.h" 18#include "gethostinfo.h" 19#include "getopt.h" 20#include "permission.h" 21#include "child.h" 22#include "proctitle.h" 23#include "fileopen.h" 24#include "sendreq.h" 25/**** ENDINCLUDE ****/ 26 27/*************************************************************************** 28 * Commentary: 29 * Patrick Powell Tue May 2 09:32:50 PDT 1995 30 * 31 * Remove a Job. 32 * This is very similar to the status program. 33 * 34 * 1. We check for permissions first 35 * - first we check to see if the remote host has permissions 36 * - next we check to see if the user has permissions 37 * Note: 38 * if we have control permissions, then we can remove any job. 39 * Normally, the options passed are 'user jobnumber' and we 40 * use the user name and/or job number to select them. When we have 41 * control permissions, we are not restricted to our own jobs. 42 * so: if we have control permissions, AND pass an option, we 43 * do not check for our name. 44 * if we have control permissions AND we do not pass an option, 45 * we check for our name. 46 * 47 * we have \006printer user key key key 48 * 0 1 2 ... index 49 ***************************************************************************/ 50 51int Job_remove( int *sock, char *input ) 52{ 53printf("Job_remove\n");//JY 54#if !defined(JYWENG20031106remove) 55 if( input && *input ) ++input;//JY1114 56 57 if(get_queue_name(input)) 58 { 59 printf("QueueName is not LPRServer\n"); 60 send_ack_packet(sock, ACK_FAIL);//JY1120 61 return(0); 62 } 63 else 64 printf("QueueName is LPRServer\n"); 65 66 if(lptstatus.pid != 0){ 67 check_prn_status(ONLINE, ""); 68 kill(lptstatus.pid, SIGKILL); 69 } 70 else 71 return(0); 72#endif 73 74#ifdef REMOVE 75 char error[LINEBUFFER]; 76 int i; 77 char *name, *s, *user = 0; 78 struct line_list tokens, done_list; 79 80 Init_line_list(&tokens); 81 Init_line_list(&done_list); 82 Name = "Job_remove"; 83 84 /* get the options */ 85 ++input; 86 DEBUGF(DLPRM1)("Job_remove: input '%s'", input ); 87 Split(&tokens,input,Whitespace,0,0,0,0,0,0); 88#ifdef ORIGINAL_DEBUG//JY@1020 89 DEBUGFC(DLPRM2)Dump_line_list("Job_remove: input", &tokens ); 90#endif 91 92 /* check printername for characters, underscore, digits */ 93 94 if( tokens.count < 2 ){ 95 SNPRINTF( error, sizeof(error)) 96 _("missing user or printer name")); 97 goto error; 98 } 99 name = tokens.list[0]; 100 101 DEBUGF(DLPRM1)("Job_remove: checking '%s'", name ); 102 if( (s = Is_clean_name( name )) ){ 103 SNPRINTF( error, sizeof(error)) 104 _("printer '%s' has illegal character at '%s' in name"), name, s ); 105 goto error; 106 } 107 DEBUGF(DLPRM1)("Job_remove: result '%s'", name ); 108 Set_DYN(&Printer_DYN,name); 109 110 user = safestrdup(tokens.list[1],__FILE__,__LINE__); 111 Perm_check.remoteuser = user; 112 113 /* remove the first two tokens */ 114 Remove_line_list(&tokens,1); 115 Remove_line_list(&tokens,0); 116 Check_max(&tokens,1); 117 tokens.list[tokens.count] = 0; 118 119 if( safestrcmp( Printer_DYN, ALL ) ){ 120 DEBUGF(DLPRM2)( "Job_remove: checking printcap entry '%s'", Printer_DYN ); 121 Set_DYN(&Printer_DYN, Printer_DYN ); 122 Get_queue_remove( user, sock, &tokens, &done_list ); 123 } else { 124/*1103 125 Get_all_printcap_entries(); 126 for( i = 0; i < All_line_list.count; ++i ){ 127 Set_DYN(&Printer_DYN, All_line_list.list[i]); 128 Get_queue_remove( user, sock, &tokens, &done_list ); 129 } 130*/ 131 } 132 goto done; 133 134 error: 135 LOGMSG( LOG_INFO) _("Job_remove: error '%s'"), error ); 136 DEBUGF(DLPRM2)("Job_remove: error msg '%s'", error ); 137 safestrncat(error,"\n"); 138 if( Write_fd_str( *sock, error ) < 0 ) cleanup(0); 139 done: 140 DEBUGF(DLPRM2)( "Job_remove: done" ); 141 if( user ) free(user); user = 0; 142 Free_line_list(&done_list); 143 Free_line_list(&tokens); 144#endif 145 return( 0 ); 146} 147 148#ifdef REMOVE 149/*************************************************************************** 150 * void Get_queue_remove 151 * - find and remove the spool queue entries 152 ***************************************************************************/ 153 154void Get_queue_remove( char *user, int *sock, struct line_list *tokens, 155 struct line_list *done_list ) 156{ 157 char msg[SMALLBUFFER], header[SMALLBUFFER]; 158 int control_perm, permission, count, removed, status, 159 i, c = 0, pid, fd; 160 char *s, *identifier; 161 struct stat statb; 162 struct line_list info, active_pid; 163 struct job job; 164 165 Init_line_list(&info); 166 Init_line_list(&active_pid); 167 Init_job(&job); 168 169 /* set printer name and printcap variables */ 170 171#ifdef ORIGINAL_DEBUG//JY@1020 172 DEBUGFC(DLPRM2)Dump_line_list("Get_queue_remove - tokens", tokens ); 173 DEBUGF(DLPRM2)( "Get_queue_remove: user '%s', printer '%s'", 174 user, Printer_DYN ); 175#endif 176 177 Errorcode = 0; 178 179 setproctitle( "lpd LPRM '%s'", Printer_DYN ); 180 /* first check to see if you have control permissions */ 181 182 msg[0] = 0; 183 status = Setup_printer( Printer_DYN, msg, sizeof(msg), 0 ); 184 if( status ){ 185 if( msg[0] == 0 ){ 186 DEBUGF(DLPRM2)("Get_queue_remove: cannot set up printer '%s'", Printer_DYN); 187 } 188 goto error; 189 } 190 191 c = Debug; 192 i = DbgFlag; 193 s = Find_str_value(&Spool_control,DEBUG,Value_sep); 194 if( !s ) s = New_debug_DYN; 195 Parse_debug( s, 0 ); 196 197 if( !(DbgFlag & DLPRMMASK) ){ 198 Debug = c; 199 DbgFlag = i; 200 } else { 201 i = Debug; 202 Debug = c; 203 if( Log_file_DYN ){ 204 fd = Trim_status_file( -1, Log_file_DYN, Max_log_file_size_DYN, 205 Min_log_file_size_DYN ); 206 if( fd > 0 && fd != 2 ){ 207 dup2(fd,2); 208 close(fd); 209 } 210 } 211 Debug = i; 212 } 213 214 /* set up status */ 215 if( Find_exists_value(done_list,Printer_DYN,Value_sep ) ){ 216 return; 217 } 218 Add_line_list(done_list,Printer_DYN,Value_sep,1,1); 219 220 /* check for permissions */ 221 222 Perm_check.service = 'C'; 223 Perm_check.printer = Printer_DYN; 224 Perm_check.host = 0; 225 Perm_check.user = 0; 226 227 control_perm = Perms_check( &Perm_line_list, &Perm_check, 0, 0 ); 228 DEBUGF(DLPRM2)("Job_status: permission '%s'", perm_str(control_perm)); 229 230 if( control_perm != P_ACCEPT ) control_perm = 0; 231 232 SNPRINTF( msg, sizeof(msg)) _("Printer %s@%s:\n"), 233 Printer_DYN, ShortHost_FQDN ); 234 Write_fd_str( *sock, msg ); 235 236 Free_line_list( &Sort_order ); 237 Scan_queue( &Spool_control, &Sort_order,0,0,0,0,0,0,0,0 ); 238 DEBUGF(DLPRM2)("Get_queue_remove: total files %d", Sort_order.count ); 239 240 /* scan the files to see if there is one which matches */ 241 removed = 0; 242#ifdef ORIGINAL_DEBUG//JY@1020 243 DEBUGFC(DLPRM3)Dump_line_list("Get_queue_remove - tokens", tokens ); 244#endif 245 for( count = 0; count < Sort_order.count; ++count ){ 246 Free_job(&job); 247 Get_hold_file(&job, Sort_order.list[count] ); 248 249#ifdef ORIGINAL_DEBUG//JY@1020 250 DEBUGFC(DLPRM3)Dump_job("Get_queue_remove - info",&job); 251#endif 252 if( tokens->count && Patselect( tokens, &job.info, 0) ){ 253 continue; 254 } 255 256 /* get everything for the job now */ 257 Setup_cf_info( &job, 0 ); 258 identifier = Find_str_value(&job.info,IDENTIFIER,Value_sep); 259 if( !identifier ) identifier 260 = Find_str_value(&job.info,TRANSFERNAME,Value_sep); 261 262 DEBUGF(DLPRM3)("Get_queue_remove: matched '%s'", identifier ); 263 SNPRINTF( msg, sizeof(msg)) _(" checking perms '%s'\n"), 264 identifier ); 265 Write_fd_str( *sock, msg ); 266 267 268 /* we check to see if we can remove this one if we are the user */ 269 if( control_perm == 0 ){ 270 /* now we get the user name and IP address */ 271 Perm_check.user = Find_str_value(&job.info,LOGNAME,Value_sep); 272 Perm_check.host = 0; 273 if( (s = Find_str_value(&job.info,FROMHOST,Value_sep)) 274 && Find_fqdn( &PermHost_IP, s ) ){ 275 Perm_check.host = &PermHost_IP; 276 } 277 Perm_check.service = 'M'; 278 permission = Perms_check( &Perm_line_list, &Perm_check, &job, 1 ); 279 if( permission == P_REJECT ){ 280 SNPRINTF( msg, sizeof(msg)) _(" no permissions '%s'\n"), 281 identifier ); 282 Write_fd_str( *sock, msg ); 283 continue; 284 } 285 } 286 287 /* log this to the world */ 288 DEBUGF(DLPRM4)("Get_queue_remove: removing '%s'", identifier ); 289 SNPRINTF( msg, sizeof(msg)) _(" dequeued '%s'\n"), identifier ); 290 Write_fd_str( *sock, msg ); 291 292#ifdef ORIGINAL_DEBUG//JY@1020 293 setmessage( &job, "LPRM", "start" ); 294#endif 295 if( Remove_job( &job ) ){ 296#ifdef ORIGINAL_DEBUG//JY@1020 297 setmessage( &job, "LPRM", "fail" ); 298#endif 299 SNPRINTF( msg, sizeof(msg)) 300 _("error: could not remove '%s'"), identifier ); 301 Write_fd_str( *sock, msg ); 302 goto error; 303 } 304#ifdef ORIGINAL_DEBUG//JY@1020 305 setmessage( &job, "LPRM", "success" ); 306#endif 307 if( (pid = Find_flag_value(&job.info,SERVER,Value_sep)) ){ 308 DEBUGF(DLPRM4)("Get_queue_remove: active_pid %d", pid ); 309 if( kill( pid, 0 ) == 0 ){ 310 Check_max(&active_pid,1); 311 active_pid.list[active_pid.count++] = Cast_int_to_voidstar(pid); 312 } 313 } 314 ++removed; 315 if( tokens->count == 0 ) break; 316 } 317 Free_line_list(&info); 318 Free_job(&job); 319 Free_line_list( &Sort_order ); 320 if( removed ){ 321 for( i = 0; i < active_pid.count; ++i ){ 322 pid = Cast_ptr_to_int(active_pid.list[i]); 323 active_pid.list[i] = 0; 324 DEBUGF(DLPRM2)("Get_queue_remove: killing pid '%d' SIGHUP/SIGINT/SIGQUIT/SIGCONT", pid ); 325 killpg( pid, SIGHUP ); 326 kill( pid, SIGHUP ); 327 killpg( pid, SIGINT ); 328 kill( pid, SIGINT ); 329 killpg( pid, SIGQUIT ); 330 kill( pid, SIGQUIT ); 331 killpg( pid, SIGCONT ); 332 kill( pid, SIGCONT ); 333 } 334 /* kill spooler process */ 335 336 pid = 0; 337#if 0//1103 338 if( (fd = Checkread( Queue_lock_file_DYN, &statb )) >= 0 ){ 339 pid = Read_pid( fd, (char *)0, 0 ); 340 close( fd ); 341 } 342#else 343#endif 344 DEBUGF(DLPRM2)("Get_queue_status: checking server pid %d", pid ); 345 /* kill active spooler */ 346 if( pid > 0 ){ 347 kill( pid, SIGUSR2 ); 348 } 349 } 350 351 if( Server_names_DYN ){ 352 Free_line_list(&info); 353 Split(&info, Server_names_DYN, File_sep, 0,0,0,0,0,0); 354 for( i = 0; i < info.count; ++i ){ 355 DEBUGF(DLPRM2)("Get_queue_status: getting subserver status '%s'", 356 info.list[i] ); 357 Set_DYN(&Printer_DYN,info.list[i]); 358 Get_local_or_remote_remove( user, sock, tokens, done_list ); 359 DEBUGF(DLPRM2)("Get_queue_status: finished subserver status '%s'", 360 info.list[i] ); 361 } 362 } else if( Destinations_DYN ){ 363 Free_line_list(&info); 364 Split(&info, Destinations_DYN, File_sep, 0,0,0,0,0,0); 365 for( i = 0; i < info.count; ++i ){ 366 DEBUGF(DLPRM2)("Get_queue_status: getting destination status '%s'", 367 info.list[i] ); 368 Set_DYN(&Printer_DYN,info.list[i]); 369 Get_local_or_remote_remove( user, sock, tokens, done_list ); 370 DEBUGF(DLPRM2)("Get_queue_status: finished destination status '%s'", 371 info.list[i] ); 372 } 373 } else if( RemoteHost_DYN ){ 374 if( Find_fqdn( &LookupHost_IP, RemoteHost_DYN ) 375 && ( !Same_host(&LookupHost_IP,&Host_IP ) 376 || !Same_host(&LookupHost_IP,&Localhost_IP )) ){ 377 DEBUGF(DLPQ1)("Get_local_or_remote_status: doing local"); 378 if( safestrcmp(RemotePrinter_DYN, Printer_DYN) ){ 379 Set_DYN(&Printer_DYN,RemotePrinter_DYN); 380 Get_queue_remove( user, sock, tokens, done_list ); 381 } else { 382 SNPRINTF(msg,sizeof(msg))"Error: loop in printcap- %s@%s -> %s@%s\n", 383 Printer_DYN, FQDNHost_FQDN, RemotePrinter_DYN, RemoteHost_DYN ); 384 Write_fd_str(*sock, msg ); 385 } 386 } else { 387 /* put user name at start of list */ 388 Check_max(tokens,2); 389 for( i = tokens->count; i > 0; --i ){ 390 tokens->list[i] = tokens->list[i-1]; 391 } 392 tokens->list[0] = user; 393 ++tokens->count; 394 tokens->list[tokens->count] = 0; 395#ifdef ORIGINAL_DEBUG//JY@1020 396 fd = Send_request( 'M', REQ_REMOVE, tokens->list, Connect_timeout_DYN, 397 Send_query_rw_timeout_DYN, *sock ); 398#endif 399 if( fd >= 0 ){ 400 shutdown( fd, 1 ); 401 while( (c = read(fd,msg,sizeof(msg))) > 0 ){ 402 Write_fd_len(*sock,msg,c); 403 } 404 close(fd); fd = -1; 405 } 406 for( i = 0; i < tokens->count; ++i ){ 407 tokens->list[i] = tokens->list[i+1]; 408 } 409 --tokens->count; 410 } 411 } 412 413 DEBUGF(DLPRM2)("Get_queue_remove: finished '%s'", Printer_DYN ); 414 goto done; 415 416 error: 417 DEBUGF(DLPRM2)("Get_queue_remove: error msg '%s'", msg ); 418 SNPRINTF(header, sizeof(header)) "Printer: %s", Printer_DYN ); 419 safestrncpy( header, _(" ERROR: ") ); 420 safestrncat( header, msg ); 421 safestrncat( header, "\n" ); 422 Write_fd_str( *sock, header ); 423 done: 424 active_pid.count = 0; 425 Free_line_list(&info); 426 Free_line_list(&active_pid); 427 Free_job(&job); 428 return; 429} 430 431void Get_local_or_remote_remove( char *user, int *sock, 432 struct line_list *tokens, struct line_list *done_list ) 433{ 434 char msg[LARGEBUFFER]; 435 int fd, n, i; 436 437 /* we have to see if the host is on this machine */ 438 439 if( !safestrchr(Printer_DYN,'@') ){ 440 Get_queue_remove( user, sock, tokens, done_list ); 441 return; 442 } 443/*1103 444 Fix_Rm_Rp_info(0,0); 445*/ 446 /* now we look at the remote host */ 447 if( Find_fqdn( &LookupHost_IP, RemoteHost_DYN ) 448 && ( !Same_host(&LookupHost_IP,&Host_IP ) 449 || !Same_host(&LookupHost_IP,&Localhost_IP )) ){ 450 Get_queue_remove( user, sock, tokens, done_list ); 451 return; 452 } 453 /* put user name at start of list */ 454 Check_max(tokens,2); 455 for( i = tokens->count; i > 0; --i ){ 456 tokens->list[i] = tokens->list[i-1]; 457 } 458 tokens->list[0] = user; 459 ++tokens->count; 460 tokens->list[tokens->count] = 0; 461#ifdef ORIGINAL_DEBUG//JY@1020 462 fd = Send_request( 'M', REQ_REMOVE, tokens->list, Connect_timeout_DYN, 463 Send_query_rw_timeout_DYN, *sock ); 464#endif 465 if( fd >= 0 ){ 466 shutdown( fd, 1 ); 467 while( (n = read(fd,msg,sizeof(msg))) > 0 ){ 468 Write_fd_len(*sock,msg,n); 469 } 470 close(fd); fd = -1; 471 } 472 for( i = 0; i < tokens->count; ++i ){ 473 tokens->list[i] = tokens->list[i+1]; 474 } 475 --tokens->count; 476} 477 478int Remove_file( char *openname ) 479{ 480 int fail = 0; 481 struct stat statb; 482 483 if( openname && stat( openname, &statb ) == 0 ){ 484 DEBUGF(DLPRM3)("Remove_file: removing '%s'", openname ); 485 if( unlink( openname ) || stat( openname, &statb ) == 0 ){ 486 LOGERR(LOG_INFO) "Remove_file: unlink did not remove '%s'", 487 openname); 488 fail |= 1; 489 } 490 } 491 return( fail ); 492} 493 494int Remove_job( struct job *job ) 495{ 496 int i; 497 int fail = 0; 498 char *identifier, *openname; 499 struct line_list *datafile; 500 501#ifdef ORIGINAL_DEBUG//JY@1020 502 DEBUGFC(DLPRM1)Dump_job("Remove_job",job); 503#endif 504#ifdef ORIGINAL_DEBUG//JY@1020 505 setmessage(job,STATE,"REMOVE"); 506#endif 507 identifier = Find_str_value(&job->info,IDENTIFIER,Value_sep); 508#ifdef ORIGINAL_DEBUG//JY@1020 509 setmessage( job, TRACE, "remove START" ); 510#endif 511 if( !identifier ){ 512 identifier = Find_str_value(&job->info,TRANSFERNAME,Value_sep); 513 } 514 515 DEBUGF(DLPRM1)("Remove_job: identifier '%s'",identifier); 516 fail = 0; 517 for( i = 0; i < job->datafiles.count; ++i ){ 518 datafile = (void *)job->datafiles.list[i]; 519 openname = Find_str_value(datafile,OPENNAME,Value_sep); 520 fail |= Remove_file( openname ); 521 openname = Find_str_value(datafile,TRANSFERNAME,Value_sep); 522 fail |= Remove_file( openname ); 523 } 524 openname = Find_str_value(&job->info,OPENNAME,Value_sep); 525 fail |= Remove_file( openname ); 526 openname = Find_str_value(&job->info,TRANSFERNAME,Value_sep); 527 fail |= Remove_file( openname ); 528 openname = Find_str_value(&job->info,HF_NAME,Value_sep); 529 fail |= Remove_file( openname ); 530 531 if( fail == 0 ){ 532#ifdef ORIGINAL_DEBUG//JY@1020 533 setmessage( job, TRACE, "remove SUCCESS" ); 534#endif 535 } else { 536#ifdef ORIGINAL_DEBUG//JY@1020 537 setmessage( job, TRACE, "remove FAILED" ); 538#endif 539 } 540 if( Lpq_status_file_DYN ){ 541 unlink(Lpq_status_file_DYN); 542 } 543 return( fail ); 544} 545#endif 546 547 548