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