1 /***************************************************************************
2 * LPRng - An Extended Print Spooler System
3 *
4 * Copyright 1988-2003, Patrick Powell, San Diego, CA
5 * papowell@lprng.com
6 * See LICENSE for conditions of use.
7 *
8 ***************************************************************************/
9
10 #include "lp.h"
11
12 #include "accounting.h"
13 #include "errorcodes.h"
14 #include "fileopen.h"
15 #include "getqueue.h"
16 #include "user_auth.h"
17 #include "linksupport.h"
18 #include "sendjob.h"
19 #include "sendauth.h"
20
21 /**** ENDINCLUDE ****/
22
23
24 /***************************************************************************
25 * Commentary:
26 * The protocol used to send a job to a remote RemoteHost_DYN consists of the
27 * following:
28 *
29 * Client Server
30 * \2RemotePrinter_DYNname\n - receive a job
31 * \0 (ack)
32 * \2count controlfilename\n
33 * <count bytes>
34 * \0
35 * \0
36 * \3count datafilename\n
37 * <count bytes>
38 * \0
39 * \0
40 * \3count datafilename\n
41 * <count bytes>
42 * \0
43 * \0
44 * <close connection>
45 *
46 * 1. In order to abort the job transfer, client sends \1
47 * 2. Anything but a 0 ACK is an error indication
48 *
49 * NB: some spoolers require that the data files be sent first.
50 * The same transfer protocol is followed, but the data files are
51 * send first, followed by the control file.
52 *
53 * The Send_job() routine will try to transfer a control file
54 * to the remote RemoteHost_DYN. It does so using the following algorithm.
55 *
56 * 1. makes a connection (connection timeout)
57 * 2. sends the \2RemotePrinter_DYN and gets ACK (transfer timeout)
58 * 3. sends the control file (transfer timeout)
59 * 4. sends the data files (transfer timeout)
60 *
61 * int Send_job(
62 * struct jobfile *job, - control file
63 * int connect_timeout_len, - timeout on making connection
64 * int connect_interval, - interval between retries
65 * int max_connect_interval - maximum connection interval
66 * int transfer_timeout - maximum time to send
67 *
68 * RETURNS: 0 if successful, non-zero if not
69 **************************************************************************/
70
71 static int Send_control( int *sock, struct job *job, struct job *logjob, int transfer_timeout,
72 int block_fd );
73 static int Send_data_files( int *sock, struct job *job, struct job *logjob,
74 int transfer_timeout, int block_fd, char *final_filter );
75
Send_job(struct job * job,struct job * logjob,int connect_timeout_len,int connect_interval,int max_connect_interval,int transfer_timeout,char * final_filter)76 int Send_job( struct job *job, struct job *logjob,
77 int connect_timeout_len, int connect_interval, int max_connect_interval,
78 int transfer_timeout, char *final_filter )
79 {
80 int sock = -1; /* socket to use */
81 char *id = 0, *s;
82 char *real_host = 0, *save_host = 0;
83 int status = 0, err, errcount = 0, n, len;
84 char msg[SMALLBUFFER];
85 char error[LARGEBUFFER], errmsg[SMALLBUFFER];
86 const struct security *security = 0;
87 struct line_list info;
88
89 /* fix up the control file */
90 Init_line_list(&info);
91 if(DEBUGL1)Dump_job("Send_job- starting",job);
92 Errorcode = 0;
93 error[0] = 0;
94
95
96 Set_str_value(&job->info,ERROR,0);
97 Set_flag_value(&job->info,ERROR_TIME,0);
98 /* send job to the LPD server for the RemotePrinter_DYN */
99
100 id = Find_str_value( &job->info,IDENTIFIER);
101 if( id == 0 ) id = Find_str_value( &job->info,XXCFTRANSFERNAME);
102 DEBUG3("Send_job: '%s'->%s@%s,connect(timeout %d,interval %d)",
103 id, RemotePrinter_DYN, RemoteHost_DYN,
104 connect_timeout_len, connect_interval );
105
106 /* determine authentication type to use */
107 security = Fix_send_auth(0,&info,job, error, sizeof(error) );
108 if( error[0] ){
109 status = JFAIL;
110 Set_str_value(&job->info,ERROR,error);
111 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
112 error[0] = 0;
113 goto error;
114 }
115 if( final_filter && (security || Send_block_format_DYN) ){
116 status = JABORT;
117 Set_str_value(&job->info,ERROR,
118 "Cannot have user filter with secure or block format transfer");
119 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
120 goto error;
121 }
122
123 setstatus(logjob,
124 "sending job '%s' to %s@%s",
125 id, RemotePrinter_DYN, RemoteHost_DYN );
126
127 retry_connect:
128 error[0] = 0;
129 Set_str_value(&job->info,ERROR,0);
130 Set_flag_value(&job->info,ERROR_TIME,0);
131 setstatus(logjob, "connecting to '%s', attempt %d",
132 RemoteHost_DYN, errcount+1 );
133 if( (Is_server || errcount) && Network_connect_grace_DYN > 0 ){
134 plp_sleep( Network_connect_grace_DYN );
135 }
136
137 errno = 0;
138
139 errmsg[0] = 0;
140 sock = Link_open_list( RemoteHost_DYN,
141 &real_host, connect_timeout_len, 0, Unix_socket_path_DYN, errmsg, sizeof(errmsg) );
142 err = errno;
143
144 DEBUG4("Send_job: socket %d", sock );
145 if( sock < 0 ){
146 ++errcount;
147 status = LINK_OPEN_FAIL;
148 msg[0] = 0;
149 if( !Is_server ){
150 plp_snprintf( msg, sizeof(msg),
151 "\nMake sure the remote host supports the LPD protocol");
152 if( geteuid() && getuid() ){
153 int v = safestrlen(msg);
154 plp_snprintf( msg+v, sizeof(msg)-v,
155 "\nand accepts connections from this host and from non-privileged (>1023) ports");
156 }
157 }
158 plp_snprintf( error, sizeof(error)-2,
159 "cannot open connection to %s - %s%s", RemoteHost_DYN,
160 errmsg[0]?errmsg:(err?Errormsg(err):"bad or missing hostname?"), msg );
161 if( Is_server && Retry_NOLINK_DYN ){
162 if( connect_interval > 0 ){
163 n = (connect_interval * (1 << (errcount - 1)));
164 if( max_connect_interval && n > max_connect_interval ){
165 n = max_connect_interval;
166 }
167 if( n > 0 ){
168 setstatus(logjob,
169 _("sleeping %d secs before retry, starting sleep"),n );
170 plp_sleep( n );
171 }
172 }
173 goto retry_connect;
174 }
175 setstatus(logjob, "%s", error);
176 goto error;
177 }
178 save_host = safestrdup(RemoteHost_DYN,__FILE__,__LINE__);
179 Set_DYN(&RemoteHost_DYN, real_host );
180 if( real_host ) free( real_host );
181 setstatus(logjob, "connected to '%s'", RemoteHost_DYN );
182
183 if( security && security->client_connect ){
184 status = security->client_connect( job, &sock,
185 transfer_timeout,
186 error, sizeof(error),
187 security, &info );
188 if( status ) goto error;
189 }
190 if( security && security->client_send ){
191 status = Send_auth_transfer( &sock, transfer_timeout,
192 job, logjob, error, sizeof(error)-1, 0, security, &info );
193 } else if( Send_block_format_DYN ){
194 status = Send_block( &sock, job, logjob, transfer_timeout );
195 } else {
196 status = Send_normal( &sock, job, logjob, transfer_timeout, 0, final_filter );
197 }
198 DEBUG2("Send_job: after sending, status %d, error '%s'",
199 status, error );
200 if( status ) goto error;
201
202 setstatus(logjob, "done job '%s' transfer to %s@%s",
203 id, RemotePrinter_DYN, RemoteHost_DYN );
204
205 error:
206
207 if( sock >= 0 ) sock = Shutdown_or_close(sock);
208 if( status ){
209 if( (s = Find_str_value(&job->info,ERROR )) ){
210 setstatus(logjob, "job '%s' transfer to %s@%s failed\n %s",
211 id, RemotePrinter_DYN, RemoteHost_DYN, s );
212 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
213 }
214 DEBUG2("Send_job: sock is %d", sock);
215 if( sock >= 0 ){
216 len = 0;
217 msg[0] = 0;
218 n = 0;
219 while( len < (int)sizeof(msg)-1
220 && (n = Read_fd_len_timeout(Send_job_rw_timeout_DYN,
221 sock,msg+len,sizeof(msg)-len-1)) > 0 ){
222 msg[len+n] = 0;
223 DEBUG2("Send_job: read %d, '%s'", n, msg);
224 while( (s = safestrchr(msg,'\n')) ){
225 *s++ = 0;
226 setstatus(logjob, "error msg: '%s'", msg );
227 memmove(msg,s,safestrlen(s)+1);
228 }
229 len = safestrlen(msg);
230 }
231 DEBUG2("Send_job: read %d, '%s'", n, msg);
232 if( len ) setstatus(logjob, "error msg: '%s'", msg );
233 }
234 }
235 if( sock >= 0 ) close(sock); sock = -1;
236 if( save_host ){
237 Set_DYN(&RemoteHost_DYN,save_host);
238 free(save_host); save_host = 0;
239 }
240 Free_line_list(&info);
241 return( status );
242 }
243
244 /***************************************************************************
245 * int Send_normal(
246 * int sock, - socket to use
247 * struct job *job, struct job *logjob, - control file
248 * int transfer_timeout, - transfer timeout
249 * ) - acknowlegement status
250 *
251 * 1. send the \2RemotePrinter_DYN\n string to the remote RemoteHost_DYN, wait for an ACK
252 *
253 * 2. if control file first, send the control file:
254 * send \3count cfname\n
255 * get back <0> ack
256 * send 'count' file bytes
257 * send <0> term
258 * get back <0> ack
259 * 3. for each data file
260 * send the \4count dfname\n
261 * Note: count is 0 if file is filter
262 * get back <0> ack
263 * send 'count' file bytes
264 * Close socket and finish if filter
265 * send <0> term
266 * get back <0> ack
267 * 4. If control file last, send the control file as in step 2.
268 *
269 *
270 * If the block_fd parameter is non-zero, we write out the
271 * control and data information to a file instead.
272 *
273 ***************************************************************************/
274
Send_normal(int * sock,struct job * job,struct job * logjob,int transfer_timeout,int block_fd,char * final_filter)275 int Send_normal( int *sock, struct job *job, struct job *logjob,
276 int transfer_timeout, int block_fd, char *final_filter )
277 {
278 char status = 0, *id, *transfername;
279 char line[SMALLBUFFER];
280 char error[SMALLBUFFER];
281 int ack;
282
283 DEBUG3("Send_normal: send_data_first %d, sock %d, block_fd %d",
284 Send_data_first_DYN, *sock, block_fd );
285
286 id = Find_str_value(&job->info,IDENTIFIER);
287 transfername = Find_str_value(&job->info,XXCFTRANSFERNAME);
288
289 if( !block_fd ){
290 setstatus(logjob, "requesting printer %s@%s",
291 RemotePrinter_DYN, RemoteHost_DYN );
292 plp_snprintf( line, sizeof(line), "%c%s\n",
293 REQ_RECV, RemotePrinter_DYN );
294 ack = 0;
295 if( (status = Link_send( RemoteHost_DYN, sock, transfer_timeout,
296 line, safestrlen(line), &ack ) )){
297 char *v;
298 if( (v = safestrchr(line,'\n')) ) *v = 0;
299 if( ack ){
300 plp_snprintf(error,sizeof(error),
301 "error '%s' with ack '%s'\n sending str '%s' to %s@%s",
302 Link_err_str(status), Ack_err_str(ack), line,
303 RemotePrinter_DYN, RemoteHost_DYN );
304 } else {
305 plp_snprintf(error,sizeof(error),
306 "error '%s'\n sending str '%s' to %s@%s",
307 Link_err_str(status), line,
308 RemotePrinter_DYN, RemoteHost_DYN );
309 }
310 Set_str_value(&job->info,ERROR,error);
311 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
312 return(status);
313 }
314 }
315
316 if( !block_fd && Send_data_first_DYN ){
317 status = Send_data_files( sock, job, logjob, transfer_timeout, block_fd, final_filter );
318 if( !status ) status = Send_control(
319 sock, job, logjob, transfer_timeout, block_fd );
320 } else {
321 status = Send_control( sock, job, logjob, transfer_timeout, block_fd );
322 if( !status ) status = Send_data_files(
323 sock, job, logjob, transfer_timeout, block_fd, final_filter );
324 }
325 return(status);
326 }
327
Send_control(int * sock,struct job * job,struct job * logjob,int transfer_timeout,int block_fd)328 static int Send_control( int *sock, struct job *job, struct job *logjob, int transfer_timeout,
329 int block_fd )
330 {
331 char msg[SMALLBUFFER];
332 char error[SMALLBUFFER];
333 int status = 0, size, ack, err;
334 char *cf = 0, *transfername = 0, *s;
335 /*
336 * get the total length of the control file
337 */
338
339 if( !(cf = Find_str_value(&job->info,CF_OUT_IMAGE)) ){
340 Errorcode = JABORT;
341 fatal(LOG_ERR, "Send_control: LOGIC ERROR! missing CF_OUT_IMAGE");
342 }
343 size = safestrlen(cf);
344 transfername = Find_str_value(&job->info,XXCFTRANSFERNAME);
345
346 DEBUG3( "Send_control: '%s' is %d bytes, sock %d, block_fd %d, cf '%s'",
347 transfername, size, *sock, block_fd, cf );
348 if( !block_fd ){
349 setstatus(logjob, "sending control file '%s' to %s@%s",
350 transfername, RemotePrinter_DYN, RemoteHost_DYN );
351 }
352
353 ack = 0;
354 errno = 0;
355 error[0] = 0;
356 plp_snprintf( msg, sizeof(msg), "%c%d %s\n",
357 CONTROL_FILE, size, transfername);
358 if( !block_fd ){
359 if( (status = Link_send( RemoteHost_DYN, sock, transfer_timeout,
360 msg, safestrlen(msg), &ack )) ){
361 if( (s = safestrchr(msg,'\n')) ) *s = 0;
362 if( ack ){
363 plp_snprintf(error,sizeof(error),
364 "error '%s' with ack '%s'\n sending str '%s' to %s@%s",
365 Link_err_str(status), Ack_err_str(ack), msg,
366 RemotePrinter_DYN, RemoteHost_DYN );
367 } else {
368 plp_snprintf(error,sizeof(error),
369 "error '%s'\n sending str '%s' to %s@%s",
370 Link_err_str(status), msg, RemotePrinter_DYN, RemoteHost_DYN );
371 }
372 Set_str_value(&job->info,ERROR,error);
373 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
374 status = JFAIL;
375 goto error;
376 }
377 } else {
378 if( Write_fd_str( block_fd, msg ) < 0 ){
379 goto write_error;
380 }
381 }
382
383 /*
384 * send the control file
385 */
386 errno = 0;
387 if( block_fd == 0 ){
388 /* we include the 0 at the end */
389 ack = 0;
390 if( (status = Link_send( RemoteHost_DYN, sock, transfer_timeout,
391 cf,size+1,&ack )) ){
392 if( ack ){
393 plp_snprintf(error,sizeof(error),
394 "error '%s' with ack '%s'\n sending control file '%s' to %s@%s",
395 Link_err_str(status), Ack_err_str(ack), transfername,
396 RemotePrinter_DYN, RemoteHost_DYN );
397 } else {
398 plp_snprintf(error,sizeof(error),
399 "error '%s'\n sending control file '%s' to %s@%s",
400 Link_err_str(status), transfername,
401 RemotePrinter_DYN, RemoteHost_DYN );
402 }
403 Set_str_value(&job->info,ERROR,error);
404 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
405 status = JFAIL;
406 goto error;
407 }
408 DEBUG3( "Send_control: control file '%s' sent", transfername );
409 setstatus(logjob, "completed sending '%s' to %s@%s",
410 transfername, RemotePrinter_DYN, RemoteHost_DYN );
411 } else {
412 if( Write_fd_str( block_fd, cf ) < 0 ){
413 goto write_error;
414 }
415 }
416 status = 0;
417 goto error;
418
419 write_error:
420 err = errno;
421 plp_snprintf(error,sizeof(error),
422 "job '%s' write to temporary file failed '%s'",
423 transfername, Errormsg( err ) );
424 Set_str_value(&job->info,ERROR,error);
425 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
426 status = JFAIL;
427 error:
428 return(status);
429 }
430
431
Send_data_files(int * sock,struct job * job,struct job * logjob,int transfer_timeout,int block_fd,char * final_filter)432 static int Send_data_files( int *sock, struct job *job, struct job *logjob,
433 int transfer_timeout, int block_fd, char *final_filter )
434 {
435 int count, fd, err, status = 0, ack;
436 double size;
437 struct line_list *lp;
438 const char *openname, *transfername, *id;
439 char *s;
440 char msg[SMALLBUFFER];
441 char error[SMALLBUFFER];
442 struct stat statb;
443
444 DEBUG3( "Send_data_files: data file count '%d'", job->datafiles.count );
445 id = Find_str_value(&job->info,IDENTIFIER);
446 if( id == 0 ) id = Find_str_value(&job->info,XXCFTRANSFERNAME);
447 for( count = 0; count < job->datafiles.count; ++count ){
448 lp = (void *)job->datafiles.list[count];
449 if(DEBUGL3)Dump_line_list("Send_data_files - entries",lp);
450 transfername = Find_str_value(lp,DFTRANSFERNAME);
451 openname = Find_str_value(lp,OPENNAME);
452 if( !openname ) openname = transfername;
453 DEBUG3("Send_data_files: opening file '%s', transfername '%s'",
454 openname, transfername );
455
456 /*
457 * open file as user; we should be running as user
458 */
459 size = 0;
460 if( !strcmp(openname,"-") ){
461 openname = "(STDIN)";
462 fd = 0;
463 size = 0;
464 } else {
465 fd = Checkread( openname, &statb );
466 if( fd < 0 ){
467 status = JFAILNORETRY;
468 plp_snprintf(error,sizeof(error),
469 "cannot open '%s' - '%s'", openname, Errormsg(errno) );
470 Set_str_value(&job->info,ERROR,error);
471 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
472 goto error;
473 }
474 if( statb.st_size == 0 ){
475 plp_snprintf(error,sizeof(error),
476 "zero length file '%s'", transfername );
477 status = JABORT;
478 Set_str_value(&job->info,ERROR,error);
479 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
480 goto error;
481 }
482 size = statb.st_size;
483 }
484 if( count == job->datafiles.count -1 && final_filter ){
485 size = 0;
486 }
487
488 DEBUG3( "Send_data_files: openname '%s', fd %d, size %0.0f",
489 openname, fd, size );
490 /*
491 * send the data file name line
492 */
493 plp_snprintf( msg, sizeof(msg), "%c%0.0f %s\n",
494 DATA_FILE, size, transfername );
495 if( block_fd == 0 ){
496 setstatus(logjob, "sending data file '%s' to %s@%s", transfername,
497 RemotePrinter_DYN, RemoteHost_DYN );
498 DEBUG3("Send_data_files: data file msg '%s'", msg );
499 errno = 0;
500 if( (status = Link_send( RemoteHost_DYN, sock, transfer_timeout,
501 msg, safestrlen(msg), &ack )) ){
502 if( (s = safestrchr(msg,'\n')) ) *s = 0;
503 if( ack ){
504 plp_snprintf(error,sizeof(error),
505 "error '%s' with ack '%s'\n sending str '%s' to %s@%s",
506 Link_err_str(status), Ack_err_str(ack), msg,
507 RemotePrinter_DYN, RemoteHost_DYN );
508 } else {
509 plp_snprintf(error,sizeof(error),
510 "error '%s'\n sending str '%s' to %s@%s",
511 Link_err_str(status), msg, RemotePrinter_DYN, RemoteHost_DYN );
512 }
513 Set_str_value(&job->info,ERROR,error);
514 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
515 goto error;
516 }
517
518 /*
519 * send the data files content
520 */
521 DEBUG3("Send_data_files: transfering '%s', fd %d", openname, fd );
522 ack = 0;
523 if( count == job->datafiles.count-1 && final_filter ){
524 status = Filter_file( transfer_timeout, fd, *sock, "UserFilter",
525 final_filter, Filter_options_DYN, job, 0, 1 );
526 DEBUG3("Send_data_files: final_filter '%s' status %d", final_filter, status );
527 close(fd); fd = 0;
528 } else {
529 status = Link_copy( RemoteHost_DYN, sock, 0, transfer_timeout,
530 openname, fd, size );
531 }
532 /* special case - cannot read error code from other end */
533 if( fd == 0 ){
534 close(*sock);
535 *sock = -1;
536 }
537 if( status
538 || ( fd !=0 && (status = Link_send( RemoteHost_DYN,sock,
539 transfer_timeout,"",1,&ack )) ) ){
540 if( ack ){
541 plp_snprintf(error,sizeof(error),
542 "error '%s' with ack '%s'\n sending data file '%s' to %s@%s",
543 Link_err_str(status), Ack_err_str(ack), transfername,
544 RemotePrinter_DYN, RemoteHost_DYN );
545 } else {
546 plp_snprintf(error,sizeof(error),
547 "error '%s'\n sending data file '%s' to %s@%s",
548 Link_err_str(status), transfername,
549 RemotePrinter_DYN, RemoteHost_DYN );
550 }
551 Set_str_value(&job->info,ERROR,error);
552 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
553 goto error;
554 }
555 setstatus(logjob, "completed sending '%s' to %s@%s",
556 transfername, RemotePrinter_DYN, RemoteHost_DYN );
557 } else {
558 double total;
559 int len;
560
561 if( Write_fd_str( block_fd, msg ) < 0 ){
562 goto write_error;
563 }
564 /* now we need to read the file and transfer it */
565 total = 0;
566 while( total < size && (len = Read_fd_len_timeout(Send_job_rw_timeout_DYN,
567 fd, msg, sizeof(msg))) > 0 ){
568 if( write( block_fd, msg, len ) < 0 ){
569 goto write_error;
570 }
571 total += len;
572 }
573 if( total != size ){
574 plp_snprintf(error,sizeof(error),
575 "job '%s' did not copy all of '%s'",
576 id, transfername );
577 status = JFAIL;
578 Set_str_value(&job->info,ERROR,error);
579 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
580 goto error;
581 }
582 }
583 close(fd); fd = -1;
584 }
585 goto error;
586
587 write_error:
588 err = errno;
589 plp_snprintf(error,sizeof(error),
590 "job '%s' write to temporary file failed '%s'",
591 id, Errormsg( err ) );
592 Set_str_value(&job->info,ERROR,error);
593 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
594 status = JFAIL;
595
596 error:
597 return(status);
598 }
599
600 /***************************************************************************
601 * int Send_block(
602 * char *RemoteHost_DYN, - RemoteHost_DYN name
603 * char *RemotePrinter_DYN, - RemotePrinter_DYN name
604 * char *dpathname *dpath - spool directory pathname
605 * int *sock, - socket to use
606 * struct job *job, struct job *logjob, - control file
607 * int transfer_timeout, - transfer timeout
608 * ) - acknowlegement status
609 *
610 * 1. Get a temporary file
611 * 2. Generate the compressed data files - this has the format
612 * \3count cfname\n
613 * [count control file bytes]
614 * \4count dfname\n
615 * [count data file bytes]
616 *
617 * 3. send the \6RemotePrinter_DYN size\n
618 * string to the remote RemoteHost_DYN, wait for an ACK
619 *
620 * 4. send the compressed data files
621 * wait for an ACK
622 *
623 ***************************************************************************/
624
Send_block(int * sock,struct job * job,struct job * logjob,int transfer_timeout)625 int Send_block( int *sock, struct job *job, struct job *logjob, int transfer_timeout )
626 {
627 int tempfd; /* temp file for data transfer */
628 char msg[SMALLBUFFER]; /* buffer */
629 char error[SMALLBUFFER]; /* buffer */
630 struct stat statb;
631 double size; /* ACME! The best... */
632 int status = 0; /* job status */
633 int ack;
634 char *id, *transfername, *tempfile;
635
636 error[0] = 0;
637 id = Find_str_value(&job->info,IDENTIFIER);
638 transfername = Find_str_value(&job->info,XXCFTRANSFERNAME);
639 if( id == 0 ) id = transfername;
640
641 tempfd = Make_temp_fd( &tempfile );
642 DEBUG1("Send_block: sending '%s' to '%s'", id, tempfile );
643
644 status = Send_normal( &tempfd, job, logjob, transfer_timeout, tempfd, 0 );
645
646 DEBUG1("Send_block: sendnormal of '%s' returned '%s'", id, Server_status(status) );
647 if( status ) return( status );
648
649 /* rewind the file */
650 if( lseek( tempfd, 0, SEEK_SET ) == -1 ){
651 Errorcode = JFAIL;
652 logerr_die(LOG_INFO, "Send_files: lseek tempfd failed" );
653 }
654 /* now we have the copy, we need to send the control message */
655 if( fstat( tempfd, &statb ) ){
656 Errorcode = JFAIL;
657 logerr_die(LOG_INFO, "Send_files: fstat tempfd failed" );
658 }
659 size = statb.st_size;
660
661 /* now we know the size */
662 DEBUG3("Send_block: size %0.0f", size );
663 setstatus(logjob, "sending job '%s' to %s@%s, block transfer",
664 id, RemotePrinter_DYN, RemoteHost_DYN );
665 plp_snprintf( msg, sizeof(msg), "%c%s %0.0f\n",
666 REQ_BLOCK, RemotePrinter_DYN, size );
667 DEBUG3("Send_block: sending '%s'", msg );
668 status = Link_send( RemoteHost_DYN, sock, transfer_timeout,
669 msg, safestrlen(msg), &ack );
670 DEBUG3("Send_block: status '%s'", Link_err_str(status) );
671 if( status ){
672 char *v;
673 if( (v = safestrchr(msg,'\n')) ) *v = 0;
674 if( ack ){
675 plp_snprintf(error,sizeof(error),
676 "error '%s' with ack '%s'\n sending str '%s' to %s@%s",
677 Link_err_str(status), Ack_err_str(ack), msg,
678 RemotePrinter_DYN, RemoteHost_DYN );
679 } else {
680 plp_snprintf(error,sizeof(error),
681 "error '%s'\n sending str '%s' to %s@%s",
682 Link_err_str(status), msg, RemotePrinter_DYN, RemoteHost_DYN );
683 }
684 Set_str_value(&job->info,ERROR,error);
685 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
686 return(status);
687 }
688
689 /* now we send the data file, followed by a 0 */
690 DEBUG3("Send_block: sending data" );
691 ack = 0;
692 status = Link_copy( RemoteHost_DYN, sock, 0, transfer_timeout,
693 transfername, tempfd, size );
694 DEBUG3("Send_block: status '%s'", Link_err_str(status) );
695 if( status == 0 ){
696 status = Link_send( RemoteHost_DYN,sock,transfer_timeout,"",1,&ack );
697 DEBUG3("Send_block: ack status '%s'", Link_err_str(status) );
698 }
699 if( status ){
700 char *v;
701 if( (v = safestrchr(msg,'\n')) ) *v = 0;
702 if( ack ){
703 plp_snprintf(error,sizeof(error),
704 "error '%s' with ack '%s'\n sending block file '%s' to %s@%s",
705 Link_err_str(status), Ack_err_str(ack), id,
706 RemotePrinter_DYN, RemoteHost_DYN );
707 } else {
708 plp_snprintf(error,sizeof(error),
709 "error '%s'\n sending block file '%s' to %s@%s",
710 Link_err_str(status), id, RemotePrinter_DYN, RemoteHost_DYN );
711 }
712 Set_str_value(&job->info,ERROR,error);
713 Set_nz_flag_value(&job->info,ERROR_TIME,time(0));
714 return(status);
715 } else {
716 setstatus(logjob, "completed sending '%s' to %s@%s",
717 id, RemotePrinter_DYN, RemoteHost_DYN );
718 }
719 close( tempfd ); tempfd = -1;
720 return( status );
721 }
722
723