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_rcvjob.c,v 1.1.1.1 2008/10/15 03:28:27 james26_jang Exp $"; 28 29 30#include "lp.h" 31 32#include "child.h" 33#include "errorcodes.h" 34#include "fileopen.h" 35#include "gethostinfo.h" 36#include "getopt.h" 37#include "getqueue.h" 38#include "linksupport.h" 39#include "lockfile.h" 40#include "permission.h" 41#include "proctitle.h" 42 43#include "lpd_remove.h" 44#include "lpd_rcvjob.h" 45#include "lpd_jobs.h" 46#ifdef JYDEBUG//JYWeng 47FILE *aaaaaa; 48#endif 49/**** ENDINCLUDE ****/ 50 51/*************************************************************************** 52 * Commentary: 53 * Patrick Powell Mon Apr 17 05:43:48 PDT 1995 54 * 55 * The protocol used to send a job to a remote host consists of the 56 * following: 57 * 58 * Client Server 59 * \2printername\n - receive a job 60 * \0 (ack) 61 * \2count controlfilename\n 62 * <count bytes> 63 * \0 64 * \0 65 * \3count datafilename\n 66 * <count bytes> 67 * \0 68 * \0 69 * \3count datafilename\n 70 * <count bytes> 71 * \0 72 * \0 73 * <close connection> 74 * 75 * 1. Read the control file from the other end. 76 * 2. Check to see if the printer exists, and if has a printcap entry 77 * 3. If it does, check the permissions for the user. 78 * 4. Read the job to the queue. 79 * 80 * Control file processing 81 * 1. The control file at this end might exist already, and be in use. 82 * If this is the case, we will try and allocate another control 83 * file name if the option is allowed. 84 * 2. After we lock the control file, we will then try and read the 85 * data files. Again, there might be a collision. If this is 86 * the case, then we will again try to generate a new number. 87 * 88 * The control file is first read into a file and then read into memory, 89 * where it is parsed. 90 * 91 * Duplicate Control/Data files: 92 * When copying jobs over, you might get to a point where you 93 * discover that a control and/or data file already exists. 94 * 95 * if file already exists: 96 * 1. if the existing file length is 0, then you can clobber the file. 97 * This is reasonable given file locking is working 98 * and games are not being played with NFS file systems. 99 * Most likely you have found an abandonded file. 100 * 2. If you have the control file and it is locked, 101 * then you might as well clobber the data files 102 * as they are probably left over from another job. 103 * If you do not have the control file, then you give up 104 * 3. If the first file file is the control file, 105 * and you cannot lock it or it is locked and has a non-zero length, 106 * then you should rename the file and try again. 107 * rename the data files/control files 108 * This can be done if the first file is a control file 109 * and you cannot lock it, or you lock it and it is 110 * non-zero in length. 111 * 112 * Job Size: 113 * when the total received job size exceeds limits, then abort job 114 * when the available file space falls below limit, then abort job 115 * 116 ***************************************************************************/ 117 118int Receive_job( int *sock, char *input ) 119{ 120 char line[SMALLBUFFER]; /* line buffer for input */ 121 char error[SMALLBUFFER]; /* line buffer for input */ 122 char buffer[SMALLBUFFER]; /* line buffer for input */ 123 int errlen = sizeof(error); 124 char *tempfile; /* name of temp file */ 125 double file_len; /* length of file */ 126 double read_len; /* amount to read from sock */ 127 double jobsize = 0; /* size of job */ 128 int ack = 0; /* ack to send */ 129 int status = 0; /* status of the last command */ 130 double len; /* length of last read */ 131 char *s, *filename; /* name of control or data file */ 132 int temp_fd = -1; /* used for file opening and locking */ 133 int filetype; /* type of file - control or data */ 134 int fd; /* for log file */ 135 int hold_fd = -1; /* hold file */ 136 int db, dbf, rlen; 137 int fifo_fd = -1; /* fifo lock file */ 138 struct line_list files, info, l; 139 struct job job; 140 struct stat statb; 141 142#ifdef REMOVE 143#ifdef WINDOW_1//JYWeng 144//aaaaaa=fopen("/tmp/pp", "a"); 145//fprintf(aaaaaa, "lpd_rcvjobs.c\n"); 146//fclose(aaaaaa); 147#endif 148#ifdef JYDEBUG//JYWeng 149aaaaaa=fopen("/tmp/qqqqq", "a"); 150fprintf(aaaaaa, "Receive_job: check point 1\n"); 151fclose(aaaaaa); 152#endif 153#endif 154 Init_line_list(&l); 155 Init_line_list(&files); 156 Init_line_list(&info); 157 Init_job(&job); 158 159 Name = "RECV"; 160 161 if( input && *input ) ++input; 162 Clean_meta(input); 163 Split(&info,input,Whitespace,0,0,0,0,0,0); 164 165//printf("Receive_job!\n");//JY1107 166/*JY1113: test QueueName*/ 167 if(get_queue_name(input)) 168 { 169 //printf("QueueName is not LPRServer\n"); 170 send_ack_packet(sock, ACK_FAIL);//JY1120 171 return(0); 172 } 173 //else printf("QueueName is LPRServer\n"); 174/**/ 175 176#ifdef ORIGINAL_DEBUG//JY@1020 177 DEBUGFC(DRECV1)Dump_line_list("Receive_job: input", &info ); 178#endif 179 if( info.count != 1 ){ 180 SNPRINTF( error, errlen) _("bad command line") ); 181 goto error; 182 } 183 if( Is_clean_name( info.list[0] ) ){ 184 SNPRINTF( error, errlen) _("bad printer name") ); 185 goto error; 186 } 187 188#ifdef REMOVE 189 setproctitle( "lpd RECV '%s'", info.list[0] ); 190 191#ifdef JYDEBUG//JYWeng 192aaaaaa=fopen("/tmp/qqqqq", "a"); 193fprintf(aaaaaa, "Receive_job: check point 2\n"); 194fclose(aaaaaa); 195#endif 196 if( Setup_printer( info.list[0], error, errlen, 0 ) ){ 197 if( error[0] == 0 ){ 198 SNPRINTF( error, errlen) _("%s: cannot set up print queue"), Printer_DYN ); 199 } 200 goto error; 201 } 202 203 204 db = Debug; 205 dbf = DbgFlag; 206 s = Find_str_value(&Spool_control,DEBUG,Value_sep); 207 if(!s) s = New_debug_DYN; 208 Parse_debug( s, 0 ); 209 210 if( !(DRECVMASK & DbgFlag) ){ 211 Debug = db; 212 DbgFlag = dbf; 213 } else { 214 int i, j; 215 i = Debug; 216 j = DbgFlag; 217 Debug = db; 218 DbgFlag = dbf; 219 if( Log_file_DYN ){ 220 fd = Checkwrite( Log_file_DYN, &statb,0,0,0); 221 if( fd > 0 && fd != 2 ){ 222 dup2(fd,2); 223 close(fd); 224 } 225 } 226 Debug = i; 227 DbgFlag = j; 228 } 229 230#ifdef JYDEBUG//JYWeng 231aaaaaa=fopen("/tmp/qqqqq", "a"); 232fprintf(aaaaaa, "Receive_job: check point 3\n"); 233fclose(aaaaaa); 234#endif 235 DEBUGF(DRECV1)("Receive_job: spooling_disabled %d", 236 Sp_disabled(&Spool_control) ); 237 if( Sp_disabled(&Spool_control) ){ 238 SNPRINTF( error, errlen) 239 _("%s: spooling disabled"), Printer_DYN ); 240 ack = ACK_RETRY; /* retry */ 241 goto error; 242 } 243#endif 244 245 /* send an ACK */ 246 DEBUGF(DRECV1)("Receive_job: sending 0 ACK for job transfer request" ); 247 printf("Send ACK\n"); 248 249#ifdef JYDEBUG//JYWeng 250aaaaaa=fopen("/tmp/qqqqq", "a"); 251fprintf(aaaaaa, "Receive_job: check point 4\n"); 252fclose(aaaaaa); 253#endif 254 status = Link_send( ShortRemote_FQDN, sock, Send_job_rw_timeout_DYN, "", 1, 0 ); 255 256 if( status ) 257 { 258 259 SNPRINTF( error, errlen) 260 _("%s: Receive_job: sending ACK 0 failed"), Printer_DYN ); 261 goto error; 262 } 263 264#ifdef REMOVE 265 /* fifo order enforcement */ 266 if( Fifo_DYN ){ 267 char * path = Make_pathname( Spool_dir_DYN, Fifo_lock_file_DYN ); 268 path = safestrappend4( path,"." , RemoteHost_IP.fqdn, 0 ); 269 DEBUG1( "Receive_job: checking fifo_lock file '%s'", path ); 270 fifo_fd = Checkwrite( path, &statb, O_RDWR, 1, 0 ); 271 if( fifo_fd < 0 ){ 272 Errorcode = JABORT; 273 LOGERR_DIE(LOG_ERR) _("Receive_job: cannot open lockfile '%s'"), 274 path ); 275 } 276 if( Do_lock( fifo_fd, 1 ) < 0 ){ 277 Errorcode = JABORT; 278 LOGERR_DIE(LOG_ERR) _("Receive_job: cannot lock lockfile '%s'"), 279 path ); 280 } 281 if(path) free(path); path = 0; 282 } 283 284#ifdef JYDEBUG//JYWeng 285aaaaaa=fopen("/tmp/qqqqq", "a"); 286fprintf(aaaaaa, "Receive_job: check point 5\n"); 287fclose(aaaaaa); 288#endif 289#endif 290 291 while( status == 0 ){ 292 DEBUGF(DRECV1)("Receive_job: from %s- getting file transfer line", FQDNRemote_FQDN ); 293 rlen = sizeof(line)-1; 294 line[0] = 0; 295 status = Link_line_read( ShortRemote_FQDN, sock, Send_job_rw_timeout_DYN, line, &rlen ); 296#ifdef JYDEBUG//JYWeng 297aaaaaa=fopen("/tmp/pp", "a"); 298fprintf(aaaaaa, "Receive_job: line=%0x\n", &line[0]); 299fclose(aaaaaa); 300#endif 301 302 DEBUGF(DRECV1)( "Receive_job: read from %s- status %d read %d bytes '%s'", 303 FQDNRemote_FQDN, status, rlen, line ); 304#if 0 305 LOGMSG(LOG_INFO) "Receive_job: read from %s- status %d read %d bytes '%s'", 306 FQDNRemote_FQDN, status, rlen, line ); 307#endif 308 309 310 if( rlen == 0 || status ){ 311 DEBUGF(DRECV1)( "Receive_job: ending reading from remote" ); 312 /* treat like normal closing of connection */ 313 line[0] = 0; 314 status = 0; 315 break; 316 } 317 318 filetype = line[0]; 319 Clean_meta(line+1); 320 321 /* make sure we have a data file transfer */ 322 if( filetype != DATA_FILE && filetype != CONTROL_FILE ){ 323 /* we may have another type of command */ 324 status = 0; 325 break; 326 } 327 /* make sure we have length and filename */ 328 329 filename = 0; 330 file_len = strtod(line+1,&filename); 331 if ((line+1) == filename){ 332 /* Recover from Apple Desktop Printing stupidity. 333 It occasionally resends the queue selection cmd. 334 Darian Davis DD 03JUL2000 */ 335 status = 0; 336 LOGERR(LOG_ERR)"Recovering from incorrect job submission"); 337 continue; 338 } 339 340 if( filename ){ 341 while( isspace(cval(filename)) ) ++filename; 342 Clean_meta(filename); 343 s = filename; 344 while( (s = strpbrk(s," \t")) ) *s++ = '_'; 345 } 346 if( file_len < 0 347 || filename == 0 || *filename == 0 348 || (file_len == 0 && filetype != DATA_FILE) ){ 349 ack = ACK_STOP_Q; 350 SNPRINTF( error, errlen) 351 _("%s: Receive_job - bad control line '%s', len %0.0f, name '%s'"), 352 Printer_DYN, line, file_len, filename ); 353 goto error; 354 } 355 356 357 /************************************************ 358 * check for job size and available space 359 * This is done here so that we can neatly clean up 360 * if we need to. Note we do this after we truncate... 361 ************************************************/ 362 jobsize += file_len; 363 read_len = file_len; 364 365 366 if( read_len == 0 ) read_len = Max_job_size_DYN*1024; 367 if( Max_job_size_DYN > 0 && (jobsize/1024) > (0.0+Max_job_size_DYN) ){ 368 SNPRINTF( error, errlen) 369 _("%s: job size %0.3fK is larger than %d K"), 370 Printer_DYN, jobsize/1024, Max_job_size_DYN ); 371 ack = ACK_RETRY; 372 goto error; 373 } else if( !Check_space( read_len, Minfree_DYN, Spool_dir_DYN ) ){ 374 SNPRINTF( error, errlen) 375 _("%s: insufficient file space"), Printer_DYN ); 376 ack = ACK_RETRY; 377 goto error; 378 } 379 380 381 /* 382 * we are ready to read the file; send 0 ack saying so 383 */ 384 385 DEBUGF(DRECV2)("Receive_job: sending 0 ACK to transfer '%s'", filename ); 386 status = Link_send( ShortRemote_FQDN, sock, Send_job_rw_timeout_DYN, "", 1, 0 ); 387 if( status ){ 388 SNPRINTF( error, errlen) 389 _("%s: sending ACK 0 for '%s' failed"), Printer_DYN, filename ); 390 ack = ACK_RETRY; 391 goto error; 392 } 393 394 395 temp_fd = Make_temp_fd(&tempfile); 396 397 /* 398 * If the file length is 0, then we transfer only as much as we have 399 * space available. Note that this will be the last file in a job 400 */ 401 402 DEBUGF(DRECV4)("Receive_job: receiving '%s' %d bytes ", filename, read_len ); 403 len = read_len; 404#if TEST_WRITE//JYWeng 405 if(filetype != DATA_FILE){ 406#if 1//JY1110 407 status = Link_file_read( ShortRemote_FQDN, sock, 408 Send_job_rw_timeout_DYN, 0, temp_fd, &read_len, &ack ); 409#else 410 status = Link_file_read_test( ShortRemote_FQDN, sock, 411 Send_job_rw_timeout_DYN, 0, temp_fd, &read_len, &ack ); 412#endif 413 } 414 else { 415 status = Link_file_read_test( ShortRemote_FQDN, sock, 416 Send_job_rw_timeout_DYN, 0, temp_fd, &read_len, &ack ); 417 } 418#else 419 status = Link_file_read( ShortRemote_FQDN, sock, 420 Send_job_rw_timeout_DYN, 0, temp_fd, &read_len, &ack ); 421#endif 422 423 DEBUGF(DRECV4)("Receive_job: status %d, read_len %0.0f, file_len %0.0f", 424 status, read_len, file_len ); 425 426 /* close the file */ 427 close(temp_fd); 428 temp_fd = -1; 429 430 if( status 431 || (file_len == 0 && read_len == 0) 432 || (file_len != 0 && file_len != read_len) ) 433 { 434 printf("Why error %lf %lf %d\n", file_len, read_len, status); 435 SNPRINTF( error, errlen) 436 _("%s: transfer of '%s' from '%s' failed"), Printer_DYN, 437 filename, ShortRemote_FQDN ); 438 ack = ACK_RETRY; 439 goto error; 440 } 441 442 /* 443 * we process the control file and make sure we can print it 444 */ 445 printf(" Control file\n"); 446 447#if defined(JYWENG20031104CONTROL) 448 if( filetype == CONTROL_FILE ){ 449 DEBUGF(DRECV2)("Receive_job: receiving new control file, old job.info.count %d, old files.count %d", 450 job.info.count, files.count ); 451 if( job.info.count ){ 452 /* we received another control file */ 453 if( Check_for_missing_files(&job, &files, error, errlen, 0, &hold_fd) ){ 454 goto error; 455 } 456 hold_fd = -1; 457 Free_line_list(&files); 458 jobsize = 0; 459 } 460 Free_job(&job); 461 Set_str_value(&job.info,OPENNAME,tempfile); 462 Set_str_value(&job.info,TRANSFERNAME,filename); 463 hold_fd = Set_up_temporary_hold_file( &job, error, errlen ); 464 if( files.count ){ 465 /* we have datafiles, FOLLOWED by a control file, 466 followed (possibly) by another control file */ 467 /* we receive another control file */ 468 if( Check_for_missing_files(&job, &files, error, errlen, 0, &hold_fd) ){ 469 goto error; 470 } 471 hold_fd = -1; 472 Free_line_list(&files); 473 jobsize = 0; 474 Free_job(&job); 475 } 476 } else { 477 Set_casekey_str_value(&files,filename,tempfile); 478 } 479#endif 480 DEBUGF(DRECV2)("Receive_job: sending 0 ACK transfer done" ); 481 status = Link_send( ShortRemote_FQDN, sock, Send_job_rw_timeout_DYN, "",1, 0 ); 482 } 483 484 DEBUGF(DRECV2)("Receive_job: eof on transfer, job.info.count %d, files.count %d", 485 job.info.count, files.count ); 486 487#if defined(JYWENG20031104Check_for_missing_files) 488 if( job.info.count ){ 489 /* we receive another control file */ 490 if( Check_for_missing_files(&job, &files, error, errlen, 0, &hold_fd) ){ 491 goto error; 492 } 493 hold_fd = -1; 494 Free_line_list(&files); 495 jobsize = 0; 496 Free_job(&job); 497 } 498#endif 499 500/*JY1110*/ 501 502 503 error: 504 505#if 0//JY1111 506 if( temp_fd > 0 ) close(temp_fd); temp_fd = -1; 507 if( fifo_fd > 0 ){ 508 Do_unlock( fifo_fd ); 509 close(fifo_fd); fifo_fd = -1; 510 } 511 512 Remove_tempfiles(); 513 if( error[0] ){ 514#ifdef ORIGINAL_DEBUG//JY@1020 515 DEBUGF(DRECV1)("Receive_job: error, removing job" ); 516 DEBUGFC(DRECV4)Dump_job("Receive_job - error", &job ); 517#endif 518 s = Find_str_value(&job.info,HF_NAME,Value_sep); 519 if( !ISNULL(s) ) unlink(s); 520 if( ack == 0 ) ack = ACK_FAIL; 521 buffer[0] = ack; 522 SNPRINTF(buffer+1,sizeof(buffer)-1)"%s\n",error); 523 /* LOG( LOG_INFO) "Receive_job: error '%s'", error ); */ 524 DEBUGF(DRECV1)("Receive_job: sending ACK %d, msg '%s'", ack, error ); 525 (void)Link_send( ShortRemote_FQDN, sock, 526 Send_job_rw_timeout_DYN, buffer, safestrlen(buffer), 0 ); 527 Link_close( sock ); 528 if( hold_fd >= 0 ){ 529 close(hold_fd); hold_fd = -1; 530 } 531 } else { 532 Link_close( sock ); 533 /* update the spool queue */ 534 Get_spool_control( Queue_control_file_DYN, &Spool_control ); 535 Set_flag_value(&Spool_control,CHANGE,1); 536 Set_spool_control( 0, Queue_control_file_DYN, &Spool_control ); 537 if( Lpq_status_file_DYN ){ 538 unlink( Lpq_status_file_DYN ); 539 } 540 s = Server_queue_name_DYN; 541 if( !s ) s = Printer_DYN; 542 543 SNPRINTF( line, sizeof(line)) "%s\n", s ); 544 DEBUGF(DRECV1)("Receive_jobs: Lpd_request fd %d, starting '%s'", Lpd_request, line ); 545 if( Write_fd_str( Lpd_request, line ) < 0 ){ 546 LOGERR_DIE(LOG_ERR) _("Receive_jobs: write to fd '%d' failed"), 547 Lpd_request ); 548 } 549 Free_line_list(&info); 550 Free_line_list(&files); 551 Free_job(&job); 552 Free_line_list(&l); 553 554 /* Do_queue_jobs( s, 0 ); */ 555 } 556 Free_line_list(&info); 557 Free_line_list(&files); 558 Free_job(&job); 559 Free_line_list(&l); 560 561 cleanup( 0 ); 562#endif//JY1111 563 564/*JY1111*/ 565 check_prn_status(ONLINE, ""); 566 return(0); 567} 568 569#ifdef ORIGINAL_DEBUG//JY@1020 570/*************************************************************************** 571 * Block Job Transfer 572 * \RCV_BLOCKprinter size 573 * The actual file transferred has the format: 574 * \CONTROL_FILElen name 575 * [control file contents] 576 * \DATA_FILElen name 577 * [data file contents] 578 * 579 * We receive the entire file, placing it into the control file. 580 * We then split the job up as usual 581 ***************************************************************************/ 582 583#define MAX_INPUT_TOKENS 10 584 585int Receive_block_job( int *sock, char *input ) 586{ 587 int temp_fd = -1, fd; /* fd for received file */ 588 double read_len; /* file read length */ 589 char error[SMALLBUFFER]; 590 int errlen = sizeof(error); 591 char buffer[SMALLBUFFER]; 592 int ack = 0, status = 0; 593 double file_len; 594 char *tempfile, *s; 595 struct stat statb; 596 struct line_list l; 597 int db, dbf; 598 599 600 error[0] = 0; 601 Init_line_list(&l); 602 603 Name = "RECVB"; 604 605 if( *input ) ++input; 606 Clean_meta(input); 607 Split(&l,input,Whitespace,0,0,0,0,0,0); 608#ifdef ORIGINAL_DEBUG//JY@1020 609 DEBUGFC(DRECV1)Dump_line_list("Receive_block_job: input", &l ); 610#endif 611 612 if( l.count != 2 ){ 613 SNPRINTF( error, errlen-4) _("bad command line") ); 614 goto error; 615 } 616 if( Is_clean_name( l.list[0] ) ){ 617 SNPRINTF( error, errlen-4) _("bad printer name") ); 618 goto error; 619 } 620 setproctitle( "lpd RECVB '%s'", l.list[0] ); 621 622 if( Setup_printer( l.list[0], error, errlen-4, 0 ) ){ 623 if( error[0] == 0 ){ 624 SNPRINTF( error, errlen-4) _("%s: cannot set up printer"), Printer_DYN ); 625 } 626 goto error; 627 } 628 629 630 db = Debug; 631 dbf =DbgFlag; 632 s = Find_str_value(&Spool_control,DEBUG,Value_sep); 633 if(!s) s = New_debug_DYN; 634 Parse_debug( s, 0 ); 635 636 if( !(DRECVMASK & DbgFlag) ){ 637 Debug = db; 638 DbgFlag = dbf; 639 } else { 640 dbf = Debug; 641 Debug = db; 642 if( Log_file_DYN ){ 643 fd = Checkwrite( Log_file_DYN, &statb,0,0,0); 644 if( fd > 0 && fd != 2 ){ 645 dup2(fd,2); 646 close(fd); 647 } 648 } 649 Debug = dbf; 650 } 651 652#ifndef NODEBUG 653 DEBUGF(DRECV1)("Receive_block_job: debug '%s', Debug %d, DbgFlag 0x%x", s, Debug, DbgFlag ); 654#endif 655 656 657 DEBUGF(DRECV1)("Receive_block_job: spooling_disabled %d", Sp_disabled(&Spool_control) ); 658 if( Sp_disabled(&Spool_control) ){ 659 SNPRINTF( error, errlen-4) 660 _("%s: spooling disabled"), Printer_DYN ); 661 ack = ACK_RETRY; /* retry */ 662 goto error; 663 } 664 665 /* check for space */ 666 667 file_len = strtod( l.list[1], 0 ); 668 read_len = file_len; 669 670 if( Max_job_size_DYN > 0 && (read_len+1023)/1024 > Max_job_size_DYN ){ 671 SNPRINTF( error, errlen) 672 _("%s: job size %0.3f is larger than %dK"), 673 Printer_DYN, file_len/1024, Max_job_size_DYN ); 674 ack = ACK_RETRY; 675 goto error; 676 } else if( !Check_space( read_len, Minfree_DYN, Spool_dir_DYN ) ){ 677 SNPRINTF( error, errlen-4) 678 _("%s: insufficient file space"), Printer_DYN ); 679 ack = ACK_RETRY; 680 goto error; 681 } 682 683 /* 684 * we are ready to read the file; send 0 ack saying so 685 */ 686 687 DEBUGF(DRECV1)("Receive_block_job: sending 0 ACK for job transfer request" ); 688 689 status = Link_send( ShortRemote_FQDN, sock, Send_job_rw_timeout_DYN, "",1, 0 ); 690 if( status ){ 691 SNPRINTF( error, errlen-4) 692 _("%s: Receive_block_job: sending ACK 0 failed"), Printer_DYN ); 693 goto error; 694 } 695 696 temp_fd = Make_temp_fd( &tempfile ); 697 DEBUGF(DRECV4)("Receive_block_job: receiving '%s' %0.0f bytes ", tempfile, file_len ); 698 status = Link_file_read( ShortRemote_FQDN, sock, 699 Send_job_rw_timeout_DYN, 0, temp_fd, &read_len, &ack ); 700 DEBUGF(DRECV4)("Receive_block_job: received %d bytes ", read_len ); 701 if( status ){ 702 SNPRINTF( error, errlen-4) 703 _("%s: transfer of '%s' from '%s' failed"), Printer_DYN, 704 tempfile, ShortRemote_FQDN ); 705 ack = ACK_FAIL; 706 goto error; 707 } 708 709 /* extract jobs */ 710 711 if( lseek( temp_fd, 0, SEEK_SET ) == -1 ){ 712#ifdef ORIGINAL_DEBUG//JY@1020 713 SNPRINTF( error, errlen-4) 714 _("Receive_block_job: lseek failed '%s'"), Errormsg(errno) ); 715#endif 716 ack = ACK_FAIL; 717 goto error; 718 } 719 720 if( Scan_block_file( temp_fd, error, errlen-4, 0 ) ){ 721 ack = ACK_FAIL; 722 goto error; 723 } 724 725 close( temp_fd ); 726 temp_fd = -1; 727 728 DEBUGF(DRECV2)("Receive_block_job: sending 0 ACK" ); 729 status = Link_send( ShortRemote_FQDN, sock, Send_job_rw_timeout_DYN, "",1, 0 ); 730 if( status ){ 731 SNPRINTF( error, errlen-4) 732 _("%s: sending ACK 0 for '%s' failed"), Printer_DYN, tempfile ); 733 ack = ACK_RETRY; 734 goto error; 735 } 736 error[0] = 0; 737 738 error: 739 Free_line_list(&l); 740 if( temp_fd > 0 ){ 741 close(temp_fd ); 742 } 743 if( error[0] ){ 744 if( ack != 0 ) ack = ACK_FAIL; 745 buffer[0] = ack; 746 SNPRINTF(buffer+1,sizeof(buffer)-1)"%s\n",error); 747 /* LOG( LOG_INFO) "Receive_block_job: error '%s'", error ); */ 748 DEBUGF(DRECV1)("Receive_block_job: sending ACK %d, msg '%s'", ack, error ); 749 (void)Link_send( ShortRemote_FQDN, sock, 750 Send_job_rw_timeout_DYN, buffer, safestrlen(buffer), 0 ); 751 Link_close( sock ); 752 } else { 753 Link_close( sock ); 754 Remove_tempfiles(); 755 756 s = Server_queue_name_DYN; 757 if( !s ) s = Printer_DYN; 758 759 SNPRINTF( buffer, sizeof(buffer)) "%s\n", s ); 760 DEBUGF(DRECV1)("Receive_block_jobs: Lpd_request fd %d, starting '%s'", Lpd_request, buffer ); 761 if( Write_fd_str( Lpd_request, buffer ) < 0 ){ 762 LOGERR_DIE(LOG_ERR) _("Receive_block_jobs: write to fd '%d' failed"), 763 Lpd_request ); 764 } 765 } 766 return( error[0] != 0 ); 767} 768#endif 769 770 771#ifdef ORIGINAL_DEBUG//JY@1020 772/*************************************************************************** 773 * Scan_block_file( int fd, struct control_file *cfp ) 774 * we scan the block file, getting the various portions 775 * 776 * Generate the compressed data files - this has the format 777 * \3count cfname\n 778 * [count control file bytes] 779 * \4count dfname\n 780 * [count data file bytes] 781 * 782 * We extract the various sections and find the offsets. 783 * Note that the various name fields will be the original 784 * values; the ones we actually use will be the transfer values 785 * RETURNS: nonzero on error, error set 786 * 0 on success 787 ***************************************************************************/ 788 789int Scan_block_file( int fd, char *error, int errlen, struct line_list *header_info ) 790{ 791 char line[LINEBUFFER]; 792 char buffer[LARGEBUFFER]; 793 int startpos; 794 int read_len, filetype, tempfd = -1; /* type and length fields */ 795 char *filename; /* name field */ 796 char *tempfile; /* name field */ 797 int status; 798 int len, count, n; 799 int hold_fd = -1; 800 struct line_list l, info, files; 801 struct job job; 802 struct stat statb; 803 804 if( fstat( fd, &statb) < 0 ){ 805 Errorcode = JABORT; 806 LOGERR_DIE(LOG_INFO)"Scan_block_file: fstat failed"); 807 } 808 DEBUGF(DRECV2)("Scan_block_file: starting, file size '%0.0f'", 809 (double)(statb.st_size) ); 810 Init_line_list(&l); 811 Init_line_list(&info); 812 Init_line_list(&files); 813 Init_job(&job); 814 815 /* first we find the file position */ 816 817 startpos = lseek( fd, 0, SEEK_CUR ); 818 DEBUGF(DRECV2)("Scan_block_file: starting at %d", startpos ); 819 while( (status = Read_one_line( fd, line, sizeof(line) )) > 0 ){ 820 /* the next position is the start of data */ 821 Free_line_list(&l); 822 Free_line_list(&info); 823 startpos = lseek( fd, 0, SEEK_CUR ); 824 if( startpos == -1 ){ 825#ifdef ORIGINAL_DEBUG//JY@1020 826 SNPRINTF( error, errlen) 827 _("Scan_block_file: lseek failed '%s'"), Errormsg(errno) ); 828#endif 829 status = 1; 830 goto error; 831 } 832 DEBUGF(DRECV2)("Scan_block_file: '%s', end position %d", 833 line, startpos ); 834 filetype = line[0]; 835 if( filetype != CONTROL_FILE && filetype != DATA_FILE ){ 836 /* get the next line */ 837 continue; 838 } 839 Clean_meta(line+1); 840 Split(&info,line+1,Whitespace,0,0,0,0,0,0); 841 if( info.count != 2 ){ 842 SNPRINTF( error, errlen) 843 _("bad length information '%s'"), line+1 ); 844 status = 1; 845 goto error; 846 } 847#ifdef ORIGINAL_DEBUG//JY@1020 848 DEBUGFC(DRECV2)Dump_line_list("Scan_block_file- input", &info ); 849#endif 850 read_len = atoi( info.list[0] ); 851 filename = info.list[1]; 852 tempfd = Make_temp_fd( &tempfile ); 853 DEBUGF(DRECV2)("Scan_block_file: tempfd %d, read_len %d", read_len, tempfd ); 854 for( len = read_len; len > 0; len -= count ){ 855 n = sizeof(buffer); 856 if( n > len ) n = len; 857 count = read(fd,buffer,n); 858 DEBUGF(DRECV2)("Scan_block_file: len %d, reading %d, got count %d", 859 len, n, count ); 860 if( count < 0 ){ 861#ifdef ORIGINAL_DEBUG//JY@1020 862 SNPRINTF( error, errlen) 863 _("Scan_block_file: read failed '%s'"), Errormsg(errno) ); 864#endif 865 status = 1; 866 goto error; 867 } else if( count == 0 ){ 868 SNPRINTF( error, errlen) 869 _("Scan_block_file: read unexecpted EOF") ); 870 status = 1; 871 goto error; 872 } 873 n = write(tempfd,buffer,count); 874 if( n != count ){ 875#ifdef ORIGINAL_DEBUG//JY@1020 876 SNPRINTF( error, errlen) 877 _("Scan_block_file: lseek failed '%s'"), Errormsg(errno) ); 878#endif 879 status = 1; 880 goto error; 881 } 882 } 883 close( tempfd); 884 tempfd = -1; 885 886 if( filetype == CONTROL_FILE ){ 887 DEBUGF(DRECV2)("Scan_block_file: control file '%s'", filename ); 888 DEBUGF(DRECV2)("Scan_block_file: received control file, job.info.count %d, files.count %d", 889 job.info.count, files.count ); 890 891#if defined(JYWENG20031104Config_value_conversion) 892 if( job.info.count ){ 893 if( Check_for_missing_files(&job, &files, error, errlen, 0, &hold_fd) ){ 894 goto error; 895 } 896 hold_fd = -1; 897 Free_line_list(&files); 898 Free_job(&job); 899 } 900#endif 901 Set_str_value(&job.info,OPENNAME,tempfile); 902 Set_str_value(&job.info,TRANSFERNAME,filename); 903 hold_fd = Set_up_temporary_hold_file( &job, error, errlen ); 904 if( hold_fd < 0 ) goto error; 905#if defined(JYWENG20031104Config_value_conversion) 906 if( files.count ){ 907 /* we have datafiles, FOLLOWED by a control file, 908 followed (possibly) by another control file */ 909 /* we receive another control file */ 910 if( Check_for_missing_files(&job, &files, error, errlen, 0, &hold_fd) ){ 911 goto error; 912 } 913 hold_fd = -1; 914 Free_line_list(&files); 915 Free_job(&job); 916 } 917#endif 918 } else { 919 Set_str_value(&files,filename,tempfile); 920 } 921 } 922 923#if defined(JYWENG20031104Config_value_conversion) 924 if( files.count ){ 925 /* we receive another control file */ 926 if( Check_for_missing_files(&job, &files, error, errlen, header_info, &hold_fd) ){ 927 goto error; 928 } 929 hold_fd = -1; 930 Free_line_list(&files); 931 Free_job(&job); 932 } 933#endif 934 935 error: 936 if( hold_fd >= 0 ){ 937 Remove_job( &job ); 938 close(hold_fd); hold_fd = -1; 939 } 940 if( tempfd >= 0 ) close(tempfd); tempfd = -1; 941 Free_line_list(&l); 942 Free_line_list(&info); 943 Free_line_list(&files); 944 Free_job(&job); 945 return( status ); 946} 947#endif 948 949/*************************************************************************** 950 * static int read_one_line(int fd, char *buffer, int maxlen ); 951 * reads one line (terminated by \n) into the buffer 952 *RETURNS: 0 if EOF characters read 953 * n = # chars read 954 * Note: buffer terminated by 0 955 ***************************************************************************/ 956int Read_one_line( int fd, char *buffer, int maxlen ) 957{ 958 int len, status; 959 len = status = 0; 960 961 while( len < maxlen-1 && (status = read( fd, &buffer[len], 1)) > 0 ){ 962 if( buffer[len] == '\n' ){ 963 break; 964 } 965 ++len; 966 } 967 buffer[len] = 0; 968 return( status ); 969} 970 971int Check_space( double jobsize, int min_space, char *pathname ) 972{ 973 double space = Space_avail(pathname); 974 int ok; 975 976 jobsize = ((jobsize+1023)/1024); 977 978 ok = ((jobsize + min_space) < space); 979#ifdef RETURNOK 980aaaaaa=fopen("/tmp/qqqqq", "a"); 981fprintf(aaaaaa, "PATH=%s\n", pathname); 982fprintf(aaaaaa, "*********************************************************\n"); 983fprintf(aaaaaa, "min_space=%d\n", min_space); 984fprintf(aaaaaa, "jobsize=%f\n", jobsize); 985fprintf(aaaaaa, "availspace=%f\n", space); 986fprintf(aaaaaa, "ok=%d\n", ok); 987fprintf(aaaaaa, "*********************************************************\n"); 988fclose(aaaaaa); 989#endif 990 991 DEBUGF(DRECV1)("Check_space: path '%s', space %0.0f, jobsize %0.0fK, ok %d", 992 pathname, space, jobsize, ok ); 993 994#ifdef RETURNOK 995 return( ok );//JYWeng 996#else 997 return( 1 ); 998#endif 999} 1000 1001#if defined(JYWENG20031104Do_perm_check) 1002int Do_perm_check( struct job *job, char *error, int errlen ) 1003{ 1004 int permission = 0; /* permission */ 1005 char *s; 1006 1007#ifdef ORIGINAL_DEBUG//JY@1020 1008 DEBUGFC(DRECV1)Dump_job("Do_perm_check", job ); 1009#endif 1010 Perm_check.service = 'R'; 1011 Perm_check.printer = Printer_DYN; 1012 s = Find_str_value(&job->info,LOGNAME,Value_sep); 1013 Perm_check.user = s; 1014 Perm_check.remoteuser = s; 1015 Perm_check.host = 0; 1016 s = Find_str_value(&job->info,FROMHOST,Value_sep); 1017 if( s && Find_fqdn( &PermHost_IP, s ) ){ 1018 Perm_check.host = &PermHost_IP; 1019 } 1020 Perm_check.remotehost = &RemoteHost_IP; 1021 1022 /* check for permission */ 1023 1024 if( Perm_filters_line_list.count ){ 1025 Free_line_list(&Perm_line_list); 1026 Merge_line_list(&Perm_line_list,&RawPerm_line_list,0,0,0); 1027 Filterprintcap( &Perm_line_list, &Perm_filters_line_list, ""); 1028 } 1029 1030 if( (permission = Perms_check( &Perm_line_list, &Perm_check, job, 1 )) 1031 == P_REJECT ){ 1032 SNPRINTF( error, errlen) 1033 _("%s: no permission to print"), Printer_DYN ); 1034 } 1035 Perm_check.user = 0; 1036 Perm_check.remoteuser = 0; 1037 DEBUGF(DRECV1)("Do_perm_check: permission '%s'", perm_str(permission) ); 1038 return( permission ); 1039} 1040#endif 1041 1042/* 1043 * Process the list of control and data files, and make a job from them 1044 * job - the job structure 1045 * files - list of files that we received and need to check. 1046 * if this is a copy of a job from another queue, files == 0 1047 * spool_control - the spool control values for this queue 1048 * spool_dir - the spool directory for this queue 1049 * xlate_incoming_format - only valid for received files 1050 * error, errlen - the error message information 1051 * header_info - authentication ID to put in the job 1052 * - if 0, do not update, this preserves copy 1053 * returns: 0 - successful 1054 * != 0 - error 1055 */ 1056 1057#if defined(JYWENG20031104Check_for_missing_files) 1058int Check_for_missing_files( struct job *job, struct line_list *files, 1059 char *error, int errlen, struct line_list *header_info, int *holdfile_fd ) 1060{ 1061 int count; 1062 struct line_list *lp = 0, datafiles; 1063 int status = 0; 1064 char *openname, *transfername; 1065 double jobsize; 1066 int copies; 1067 struct stat statb; 1068 struct timeval start_time; 1069 1070 if( gettimeofday( &start_time, 0 ) ){ 1071 Errorcode = JABORT; 1072 LOGERR_DIE(LOG_INFO) "Check_for_missing_files: gettimeofday failed"); 1073 } 1074#ifdef ORIGINAL_DEBUG//JY@1020 1075 DEBUG1("Check_for_missing_files: holdfile_fd %d, start time 0x%x usec 0x%x", 1076 *holdfile_fd, 1077 (int)start_time.tv_sec, (int)start_time.tv_usec ); 1078 if(DEBUGL1)Dump_job("Check_for_missing_files - start", job ); 1079 if(DEBUGL1)Dump_line_list("Check_for_missing_files- files", files ); 1080 if(DEBUGL1)Dump_line_list("Check_for_missing_files- header_info", header_info ); 1081#endif 1082 1083 Set_flag_value(&job->info,JOB_TIME,(int)start_time.tv_sec); 1084 Set_flag_value(&job->info,JOB_TIME_USEC,(int)start_time.tv_usec); 1085 1086 Init_line_list(&datafiles); 1087 1088 /* we can get this as a new job or as a copy. 1089 * if we get a copy, we do not need to check this stuff 1090 */ 1091 if( !Find_str_value(&job->info,REMOTEHOST,Value_sep) ){ 1092 Set_str_value(&job->info,REMOTEHOST,RemoteHost_IP.fqdn); 1093 Set_flag_value(&job->info,UNIXSOCKET,Perm_check.unix_socket); 1094 Set_flag_value(&job->info,REMOTEPORT,Perm_check.port); 1095 } 1096 if( files ){ 1097 if( Do_perm_check( job, error, errlen ) == P_REJECT ){ 1098 status = 1; 1099 goto error; 1100 } 1101 1102 jobsize = 0; 1103 error[0] = 0; 1104 /* RedHat Linux 6.1 - sends a control file with NO data files */ 1105 if( job->datafiles.count == 0 && files->count > 0 ){ 1106 Check_max(&job->datafiles,files->count+1); 1107 for( count = 0; count < files->count; ++count ){ 1108 lp = malloc_or_die(sizeof(lp[0]),__FILE__,__LINE__); 1109 memset(lp,0,sizeof(lp[0])); 1110 job->datafiles.list[job->datafiles.count++] = (void *)lp; 1111 /* 1112 * now we add the information needed 1113 * the files list has 'transfername=openname' 1114 */ 1115 transfername = files->list[count]; 1116 if( (openname = strchr(transfername,'=')) ) *openname++ = 0; 1117 Set_str_value(lp,TRANSFERNAME,transfername); 1118 Set_str_value(lp,FORMAT,"f"); 1119 Set_flag_value(lp,COPIES,1); 1120 if( openname ) openname[-1] = '='; 1121 } 1122#ifdef ORIGINAL_DEBUG//JY@1020 1123 if(DEBUGL1)Dump_job("RedHat Linux fix", job ); 1124#endif 1125 } 1126 for( count = 0; count < job->datafiles.count; ++count ){ 1127 lp = (void *)job->datafiles.list[count]; 1128 transfername = Find_str_value(lp,OTRANSFERNAME,Value_sep); 1129 if( ISNULL(transfername) ) transfername = Find_str_value(lp,TRANSFERNAME,Value_sep); 1130 /* find the open name and replace it in the information */ 1131 if( (openname = Find_casekey_str_value(files,transfername,Value_sep)) ){ 1132 Set_str_value(lp,OPENNAME,openname); 1133 Set_casekey_str_value(&datafiles,transfername,openname); 1134 } else { 1135 SNPRINTF(error,errlen)"missing data file '%s'",transfername); 1136 status = 1; 1137 goto error; 1138 } 1139 if( (status = stat( openname, &statb )) ){ 1140#ifdef ORIGINAL_DEBUG//JY@1020 1141 SNPRINTF( error, errlen) "stat() '%s' error - %s", 1142 openname, Errormsg(errno) ); 1143#endif 1144 goto error; 1145 } 1146 copies = Find_flag_value(lp,COPIES,Value_sep); 1147 if( copies == 0 ) copies = 1; 1148 jobsize += copies * statb.st_size; 1149 } 1150 Set_double_value(&job->info,SIZE,jobsize); 1151 1152#ifdef ORIGINAL_DEBUG//JY@1020 1153 if(DEBUGL1)Dump_line_list("Check_for_missing_files- found", &datafiles ); 1154#endif 1155 if( files->count != datafiles.count ){ 1156 SNPRINTF(error,errlen)"too many data files"); 1157 status = 1; 1158 goto error; 1159 } 1160 Free_line_list(&datafiles); 1161 } 1162 1163 /* now we need to assign a control file number */ 1164 if( *holdfile_fd <= 0 && (*holdfile_fd = Find_non_colliding_job_number( job )) < 0 ){ 1165 SNPRINTF(error,errlen) 1166 "cannot allocate hold file"); 1167 status = 1; 1168 goto error; 1169 } 1170 DEBUG1("Check_for_missing_files: holdfile_fd now '%d'", *holdfile_fd ); 1171 1172 if( header_info && User_is_authuser_DYN ){ 1173 char *s = Find_str_value(header_info,AUTHUSER,Value_sep); 1174 if( !ISNULL(s) ){ 1175 Set_str_value( &job->info,LOGNAME,s); 1176 DEBUG1("Check_for_missing_files: setting user to authuser '%s'", s ); 1177 } 1178 } 1179#if defined(JYWENG20031104Create_control) 1180 if( Create_control( job, error, errlen, Xlate_incoming_format_DYN ) ){ 1181 DEBUG1("Check_for_missing_files: Create_control error '%s'", error ); 1182 status = 1; 1183 goto error; 1184 } 1185#endif 1186 Set_str_value(&job->info,HPFORMAT,0); 1187 Set_str_value(&job->info,INCOMING_TIME,0); 1188 1189 if( header_info ){ 1190 char *authfrom, *authuser, *authtype, *authca; 1191 authfrom = Find_str_value(header_info,AUTHFROM,Value_sep); 1192 authuser = Find_str_value(header_info,AUTHUSER,Value_sep); 1193 authtype = Find_str_value(header_info,AUTHTYPE,Value_sep); 1194 authca = Find_str_value(header_info,AUTHCA,Value_sep); 1195 if( ISNULL(authuser) ) authuser = authfrom; 1196 Set_str_value(&job->info,AUTHUSER,authuser); 1197 Set_str_value(&job->info,AUTHFROM,authfrom); 1198 Set_str_value(&job->info,AUTHTYPE,authtype); 1199 Set_str_value(&job->info,AUTHCA,authca); 1200 } 1201 /* now we do the renaming */ 1202 status = 0; 1203 for( count = 0; status == 0 && count < job->datafiles.count; ++count ){ 1204 lp = (void *)job->datafiles.list[count]; 1205 openname = Find_str_value(lp,OPENNAME,Value_sep); 1206 if( stat(openname,&statb) ) continue; 1207 transfername = Find_str_value(lp,TRANSFERNAME,Value_sep); 1208 DEBUG1("Check_for_missing_files: renaming '%s' to '%s'", 1209 openname, transfername ); 1210 if( (status = rename(openname,transfername)) ){ 1211#ifdef ORIGINAL_DEBUG//JY@1020 1212 SNPRINTF( error,errlen) 1213 "error renaming '%s' to '%s' - %s", 1214 openname, transfername, Errormsg( errno ) ); 1215#endif 1216 } 1217 } 1218 if( status ) goto error; 1219 if( (status = Get_route( job, error, errlen )) ){ 1220 DEBUG1("Check_for_missing_files: Routing_filter error '%s'", error ); 1221 goto error; 1222 } 1223 openname = Find_str_value(&job->info,OPENNAME,Value_sep); 1224 transfername = Find_str_value(&job->info,TRANSFERNAME,Value_sep); 1225 DEBUG1("Check_for_missing_files: renaming '%s' to '%s'", 1226 openname, transfername ); 1227 if( (status = rename(openname,transfername)) ){ 1228#ifdef ORIGINAL_DEBUG//JY@1020 1229 SNPRINTF( error,errlen) 1230 "error renaming '%s' to '%s' - %s", 1231 openname, transfername, Errormsg( errno ) ); 1232#endif 1233 goto error; 1234 } 1235 if( (status = Set_hold_file( job, 0, *holdfile_fd )) ){ 1236#ifdef ORIGINAL_DEBUG//JY@1020 1237 SNPRINTF( error,errlen) 1238 "error setting up hold file - %s", 1239 Errormsg( errno ) ); 1240#endif 1241 goto error; 1242 } 1243#ifdef ORIGINAL_DEBUG//JY@1020 1244 if(DEBUGL1)Dump_job("Check_for_missing_files - ending", job ); 1245#endif 1246 1247 error: 1248 transfername = Find_str_value(&job->info,TRANSFERNAME,Value_sep); 1249 if( status ){ 1250 LOGMSG(LOG_INFO) "Check_for_missing_files: FAIL '%s' %s", transfername, error); 1251 /* we need to unlink the data files */ 1252 openname = Find_str_value(&job->info,OPENNAME,Value_sep); 1253 transfername = Find_str_value(&job->info,TRANSFERNAME,Value_sep); 1254 if( openname ) unlink( openname ); 1255 if( transfername) unlink( transfername ); 1256 for( count = 0; count < job->datafiles.count; ++count ){ 1257 lp = (void *)job->datafiles.list[count]; 1258 transfername = Find_str_value(lp,TRANSFERNAME,Value_sep); 1259 openname = Find_str_value(lp,OPENNAME,Value_sep); 1260 unlink(openname); 1261 unlink(transfername); 1262 } 1263 openname = Find_str_value(&job->info,HF_NAME,Value_sep); 1264 if( openname ) unlink(openname); 1265 } else { 1266 /* 1267 LOGMSG(LOG_INFO) "Check_for_missing_files: SUCCESS '%s'", transfername); 1268 */ 1269#ifdef ORIGINAL_DEBUG//JY@1020 1270 setmessage( job, "STATE", "CREATE" ); 1271#endif 1272 } 1273 1274 if( *holdfile_fd >= 0 ) close(*holdfile_fd); *holdfile_fd = -1; 1275 Free_line_list(&datafiles); 1276 return( status ); 1277} 1278#endif 1279 1280#if defined(JYWENG200301104Set_up_temporary_hold_file) 1281/*************************************************************************** 1282 * int Set_up_temporary_hold_file( struct job *job, 1283 * char *error, int errlen ) 1284 * sets up a hold file and control file 1285 ***************************************************************************/ 1286 1287int Set_up_temporary_hold_file( struct job *job, 1288 char *error, int errlen ) 1289{ 1290 int fd = -1; 1291 /* now we need to assign a control file number */ 1292 DEBUG1("Set_up_temporary_hold_file: starting" ); 1293 1294 /* sets identifier and hold information */ 1295 Setup_job( job, &Spool_control, 0, 0, 0); 1296 /* now we get collision resolution */ 1297 if( (fd = Find_non_colliding_job_number( job )) < 0 ){ 1298 SNPRINTF(error,errlen) 1299 "cannot allocate hold file"); 1300 goto error; 1301 } 1302 DEBUG1("Set_up_temporary_hold_file: hold file fd '%d'", fd ); 1303 1304 /* mark as incoming */ 1305 Set_flag_value(&job->info,INCOMING_TIME,time((void *)0) ); 1306 /* write status */ 1307 if( Set_hold_file( job, 0, fd ) ){ 1308#ifdef ORIGINAL_DEBUG//JY@1020 1309 SNPRINTF( error,errlen) 1310 "error setting up hold file - %s", 1311 Errormsg( errno ) ); 1312#endif 1313 close(fd); fd = -1; 1314 goto error; 1315 } 1316 error: 1317 return( fd ); 1318} 1319#endif 1320 1321/*************************************************************************** 1322 * int Find_non_colliding_job_number( struct job *job ) 1323 * Find a non-colliding job number for the new job 1324 * RETURNS: 0 if successful 1325 * ack value if unsuccessful 1326 * Side effects: sets up control file fields; 1327 ***************************************************************************/ 1328 1329int Find_non_colliding_job_number( struct job *job ) 1330{ 1331 int hold_fd = -1; /* job hold file fd */ 1332 struct stat statb; /* for status */ 1333 char hold_file[SMALLBUFFER], *number; 1334 int max, n, start; 1335 1336 /* we set the job number to a reasonable range */ 1337 hold_fd = -1; 1338 number = Fix_job_number(job,0); 1339 start = n = strtol(number,0,10); 1340 max = 1000; 1341 if( Long_number_DYN ) max = 1000000; 1342 while( hold_fd < 0 ){ 1343 number = Fix_job_number(job,n); 1344 SNPRINTF(hold_file,sizeof(hold_file))"hfA%s",number); 1345 DEBUGF(DRECV1)("Find_non_colliding_job_number: trying %s", hold_file ); 1346 hold_fd = Checkwrite(hold_file, &statb, 1347 O_RDWR|O_CREAT, 0, 0 ); 1348 /* if the hold file locked or is non-zero, we skip to a new one */ 1349 if( hold_fd < 0 || Do_lock( hold_fd, 0 ) < 0 || statb.st_size ){ 1350 close( hold_fd ); 1351 hold_fd = -1; 1352 hold_file[0] = 0; 1353 ++n; 1354 if( n > max ) n = 0; 1355 if( n == start ){ 1356 break; 1357 } 1358 } else { 1359 Set_str_value(&job->info,HF_NAME,hold_file); 1360 } 1361 } 1362 DEBUGF(DRECV1)("Find_non_colliding_job_number: using %s", hold_file ); 1363 return( hold_fd ); 1364} 1365 1366int Get_route( struct job *job, char *error, int errlen ) 1367#ifdef ORIGINAL_DEBUG//JY@1020 1368{ 1369#else 1370{} 1371#endif 1372#ifdef ORIGINAL_DEBUG//JY@1020 1373 int i, fd, tempfd, count, c; 1374 char *tempfile, *openname, *s, *t, *id; 1375 char buffer[SMALLBUFFER]; 1376 int errorcode = 0; 1377 struct line_list info, dest, env, *lp, cf_line_list; 1378 1379 DEBUG1("Get_route: routing filter '%s', control filter '%s'", 1380 Routing_filter_DYN, Incoming_control_filter_DYN ); 1381 if( Routing_filter_DYN == 0 && Incoming_control_filter_DYN == 0 ){ 1382 return(errorcode); 1383 } 1384 1385 Init_line_list(&info); 1386 Init_line_list(&dest); 1387 Init_line_list(&env); 1388 Init_line_list(&cf_line_list); 1389 1390 /* build up the list of files and initialize the DATAFILES 1391 * environment variable 1392 */ 1393 1394 for( i = 0; i < job->datafiles.count; ++i ){ 1395 lp = (void *)job->datafiles.list[i]; 1396 openname = Find_str_value(lp,TRANSFERNAME,Value_sep); 1397 Add_line_list(&env,openname,Value_sep,1,1); 1398 } 1399 s = Join_line_list_with_sep(&env," "); 1400 Free_line_list( &env ); 1401 Set_str_value(&env,DATAFILES,s); 1402 free(s); s = 0; 1403 1404 openname = Find_str_value(&job->info,OPENNAME,Value_sep); 1405 if( (fd = open(openname,O_RDONLY,0)) < 0 ){ 1406#ifdef ORIGINAL_DEBUG//JY@1020 1407 SNPRINTF(error,errlen)"Get_route: open '%s' failed '%s'", 1408 openname, Errormsg(errno) ); 1409#endif 1410 errorcode = 1; 1411 goto error; 1412 } 1413 Max_open(fd); 1414 tempfd = Make_temp_fd(&tempfile); 1415 1416 /* we pass the control file through the incoming control filter */ 1417 if( Incoming_control_filter_DYN ){ 1418 DEBUG1("Get_route: running '%s'", 1419 Incoming_control_filter_DYN ); 1420 errorcode = Filter_file( fd, tempfd, "INCOMING_CONTROL_FILTER", 1421 Incoming_control_filter_DYN, Filter_options_DYN, job, &env, 0); 1422 switch(errorcode){ 1423 case 0: break; 1424 case JHOLD: 1425 Set_flag_value(&job->info,HOLD_TIME,time((void *)0) ); 1426 errorcode = 0; 1427 break; 1428 case JREMOVE: break; 1429 default: 1430 SNPRINTF(error,errlen)"Get_route: incoming control filter '%s' failed '%s'", 1431 Incoming_control_filter_DYN, Server_status(errorcode) ); 1432 errorcode = JFAIL; 1433 goto error; 1434 } 1435 close(fd); close(tempfd); fd = -1; tempfd = -1; 1436 if( rename( tempfile, openname ) == -1 ){ 1437#ifdef ORIGINAL_DEBUG//JY@1020 1438 SNPRINTF(error,errlen)"Get_route: rename '%s' to '%s' failed - %s", 1439 tempfile, openname, Errormsg(errno) ); 1440#endif 1441 errorcode = 1; 1442 goto error; 1443 } 1444 if( (fd = open(openname,O_RDONLY,0)) < 0 ){ 1445#ifdef ORIGINAL_DEBUG//JY@1020 1446 SNPRINTF(error,errlen)"Get_route: open '%s' failed '%s'", 1447 openname, Errormsg(errno) ); 1448#endif 1449 errorcode = 1; 1450 goto error; 1451 } 1452 Max_open(fd); 1453 if( Get_file_image_and_split(openname,0,0, &cf_line_list, Line_ends,0,0,0,0,0,0) ){ 1454#ifdef ORIGINAL_DEBUG//JY@1020 1455 SNPRINTF(error,errlen) 1456 "Get_route: open failed - modified control file %s - %s", openname, Errormsg(errno) ); 1457#endif 1458 goto error; 1459 } 1460 for( i = 'A'; i <= 'Z'; ++i ){ 1461 buffer[1] = 0; 1462 buffer[0] = i; 1463 Set_str_value(&job->info,buffer,0); 1464 } 1465 for( i = 0; i < cf_line_list.count; ++i ){ 1466 s = cf_line_list.list[i]; 1467 Clean_meta(s); 1468 c = cval(s); 1469 DEBUG3("Get_route: doing line '%s'", s ); 1470 if( isupper(c) && c != 'U' && c != 'N' ){ 1471 buffer[0] = c; buffer[1] = 0; 1472 DEBUG3("Get_route: control '%s'='%s'", buffer, s+1 ); 1473 Set_str_value(&job->info,buffer,s+1); 1474 } 1475 } 1476 tempfd = Make_temp_fd(&tempfile); 1477 } 1478 1479 if( Routing_filter_DYN == 0 ) goto error; 1480 1481 errorcode = Filter_file( fd, tempfd, "ROUTING_FILTER", 1482 Routing_filter_DYN, Filter_options_DYN, job, &env, 0); 1483 if(errorcode)switch(errorcode){ 1484 case 0: break; 1485 case JHOLD: 1486 Set_flag_value(&job->info,HOLD_TIME,time((void *)0) ); 1487 errorcode = 0; 1488 break; 1489 case JREMOVE: break; 1490 default: 1491 SNPRINTF(error,errlen)"Get_route: incoming control filter '%s' failed '%s'", 1492 Incoming_control_filter_DYN, Server_status(errorcode) ); 1493 errorcode = JFAIL; 1494 goto error; 1495 } 1496 if( tempfd > 0 ) close(tempfd); tempfd = -1; 1497 1498 Free_line_list( &env ); 1499 Get_file_image_and_split(tempfile,0,1,&env,Line_ends,0,0,0,1,0,0); 1500 Free_line_list(&job->destination); 1501 1502 id = Find_str_value(&job->info,IDENTIFIER,Value_sep); 1503 if(!id){ 1504 FATAL(LOG_ERR) 1505 _("Get_route: no identifier for '%s'"), 1506 Find_str_value(&job->info,HF_NAME,Value_sep) ); 1507 } 1508 count = 0; 1509 for(i = 0; i < env.count; ++i ){ 1510 s = env.list[i]; 1511 if( safestrcasecmp(END,s) ){ 1512 if( !isupper(cval(s)) 1513 && (t = safestrpbrk(s,Value_sep)) ){ 1514 *t = '='; 1515 } 1516 Add_line_list(&job->destination,s,Value_sep,1,1); 1517 } else { 1518 if( (s = Find_str_value(&job->destination, DEST,Value_sep)) ){ 1519 int n; 1520 DEBUG1("Get_route: destination '%s'", s ); 1521 Set_flag_value(&job->destination,DESTINATION,count); 1522 n = Find_flag_value(&job->destination,COPIES,Value_sep); 1523 if( n < 0 ){ 1524 Set_flag_value(&job->destination,COPIES,0); 1525 } 1526 SNPRINTF(buffer,sizeof(buffer))".%d",count+1); 1527 s = safestrdup2(id,buffer,__FILE__,__LINE__); 1528 Set_str_value(&job->destination,IDENTIFIER,s); 1529 if(s) free(s); 1530 Update_destination(job); 1531 ++count; 1532 } 1533 Free_line_list(&job->destination); 1534 } 1535 } 1536 if( (s = Find_str_value(&job->destination, DEST,Value_sep)) ){ 1537 int n; 1538 DEBUG1("Get_route: destination '%s'", s ); 1539 Set_flag_value(&job->destination,DESTINATION,count); 1540 n = Find_flag_value(&job->destination,COPIES,Value_sep); 1541 if( n < 0 ){ 1542 Set_flag_value(&job->destination,COPIES,0); 1543 } 1544 SNPRINTF(buffer,sizeof(buffer))".%d",count+1); 1545 s = safestrdup2(id,buffer,__FILE__,__LINE__); 1546 Set_str_value(&job->destination,IDENTIFIER,s); 1547 if(s) free(s); 1548 Update_destination(job); 1549 ++count; 1550 } 1551 Free_line_list(&job->destination); 1552 Set_flag_value(&job->info,DESTINATIONS,count); 1553#ifdef ORIGINAL_DEBUG//JY@1020 1554 if(DEBUGL1)Dump_job("Get_route: final", job ); 1555#endif 1556 1557 error: 1558 Free_line_list(&info); 1559 Free_line_list(&dest); 1560 Free_line_list(&env); 1561 Free_line_list(&cf_line_list); 1562 return( errorcode ); 1563} 1564#endif 1565