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