1 #ident "$Id: faxsend.c,v 4.9 2007/06/15 06:44:58 gert Exp $ Copyright (c) 1994 Gert Doering"
2
3 /* faxsend.c
4 *
5 * Send single fax pages using a class 2 or class 2.0 faxmodem.
6 * Called by faxrec.c (poll server) and sendfax.c (sending faxes).
7 *
8 * Depends on "modem_type" being set to Mt_class2_0 for 2.0 support.
9 *
10 * Eventually add headers to each page.
11 *
12 * The code is still quite rough, but it works.
13 *
14 * $Log: faxsend.c,v $
15 * Revision 4.9 2007/06/15 06:44:58 gert
16 * add CVS Log tag
17 *
18 */
19
20 #include <stdio.h>
21 #include <strings.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include "syslibs.h"
25
26 #ifndef sunos4
27 #include <sys/ioctl.h>
28 #endif
29 #include <signal.h>
30
31 #include "mgetty.h"
32 #include "tio.h"
33 #include "policy.h"
34 #include "fax_lib.h"
35
36 static boolean fax_sendpg_timeout = FALSE;
37
fax_send_timeout(SIG_HDLR_ARGS)38 static RETSIGTYPE fax_send_timeout(SIG_HDLR_ARGS)
39 {
40 signal( SIGALRM, fax_send_timeout ); /* reactivate handler */
41
42 lprintf( L_WARN, "fax_send: timeout" );
43 fax_sendpg_timeout = TRUE;
44 }
45
46 /* DLE ETX: send at end of all fax data to terminate page */
47
48 static char fax_end_of_page[] = { DLE, ETX };
49
50 static void fax_send_panic_exit _P1( (fd), int fd )
51 {
52 lprintf( L_FATAL, "PANIC: timeout sending fax page data, trying force modem reset\n" );
53
54 /* by all means, reset modem */
55
56 /* heavily use alarm(), to make sure nothing blocks */
57
58 /* flush output queue */
59 alarm( 5 ); tio_flush_queue( fd, TIO_Q_OUT );
60
61 /* restart possibly suspended output */
62 alarm( 5 ); tio_flow( fd, TRUE );
63
64 /* tell modem that the page is finished. Try twice */
65 alarm( 5 ); write( fd, fax_end_of_page, sizeof( fax_end_of_page ) );
66
67 alarm( 5 ); write( fd, fax_end_of_page, sizeof( fax_end_of_page ) );
68
69 /* Hang up. Various methods */
70 alarm( 5 ); write( fd, "AT+FK\r\n", 7 );
71 alarm( 5 ); write( fd, "ATH0\r\n", 6 );
72
73 /* Now, try to reset it by lowering DTR */
74 alarm( 10 );
75 tio_toggle_dtr( fd, 500 );
76 delay(500);
77 tio_toggle_dtr( fd, 500 );
78 delay(500);
79
80 /* try again to hang up + reset it */
81 alarm( 5 ); write( fd, "ATH0Z\r\n", 7 );
82 delay(500);
83
84 /* if the modem is *still* off-hook, there's nothing we can do. */
85 /* Hope that mgetty will be able to reinitialize it */
86
87 alarm( 0 );
88 rmlocks();
89 exit(15);
90 }
91
92 /* fax_send_page - send one complete fax-G3-file to the modem
93 *
94 * modem has to be in sync, waiting for at+fdt
95 * page punctuation is transmitted according to "ppm"
96 * number of bytes transmitted is added to "*bytes_sent" (for statistics)
97 */
98 int fax_send_page _P5( (g3_file, bytes_sent, tio, ppm, fd),
99 char * g3_file, int * bytes_sent, TIO * tio,
100 Post_page_messages ppm, int fd )
101 {
102 int g3fd;
103 char ch;
104 char buf[256]; /* read chunk */
105 char wbuf[ sizeof(buf) * 2 ]; /* worst case: size doubles */
106
107 int w_total = 0; /* total bytes written */
108
109 int rc; /* return code */
110
111 #ifdef CLASS1
112 if ( modem_type == Mt_class1 || modem_type == Mt_class1_0 )
113 return fax1_send_page( g3_file, bytes_sent, tio, ppm, fd );
114 #endif
115
116 lprintf( L_NOISE, "fax_send_page(\"%s\") started...", g3_file );
117
118 /* disable software output flow control! It would eat the XON otherwise! */
119 tio_set_flow_control( fd, tio, (FAXSEND_FLOW) & FLOW_HARD );
120 tio_set( fd, tio );
121
122 /* tell modem that we're ready to send - modem will answer
123 * with a couple of "+F..." messages and finally CONNECT and XON
124 */
125
126 if ( fax_command( "AT+FDT", "CONNECT", fd ) == ERROR ||
127 fax_hangup != 0 )
128 {
129 lprintf( L_WARN, "AT+FDT -> some error (%d), abort fax send!",
130 fax_hangup_code );
131 return ERROR;
132 }
133
134 /* alarm handler */
135 signal( SIGALRM, fax_send_timeout );
136
137 /* when modem is ready to receive data, it will send us an XON
138 * (20 seconds timeout)
139 *
140 * Not all issues of the class 2 draft require this Xon, and, further,
141 * the class 2.0 and 2.1 standard do *not* have it, so it's optional.
142 */
143 if ( modem_type == Mt_class2 &&
144 ( modem_quirks & MQ_NO_XON ) == 0 )
145 {
146 lprintf( L_NOISE, "waiting for XON, got:" );
147
148 alarm( 20 );
149 do
150 {
151 if ( mdm_read_byte( fd, &ch ) != 1 )
152 {
153 lprintf( L_ERROR, "timeout waiting for XON" );
154 fprintf( stderr, "error waiting for XON!\n" );
155 close( fd );
156 exit(11); /*! FIXME! should be done farther up */
157 }
158 lputc( L_NOISE, ch );
159 }
160 while ( ch != XON );
161 alarm(0);
162 } /* end if ( mt == class 2 ) */
163
164 /* Now enable software flow control, if desired, we've got the Xon
165 */
166 tio_set_flow_control( fd, tio, (FAXSEND_FLOW) & (FLOW_HARD|FLOW_XON_OUT));
167 tio_set( fd, tio );
168
169 /* send one page */
170 lprintf( L_MESG, "sending %s...", g3_file );
171
172 g3fd = open( g3_file, O_RDONLY );
173 if ( g3fd == -1 )
174 {
175 lprintf( L_ERROR, "cannot open %s", g3_file );
176 lprintf( L_WARN, "have to send empty page instead" );
177 }
178 else
179 {
180 int r, i, w;
181 int w_refresh = 0;
182 boolean first = TRUE;
183
184 /* timing at start of page is a bit critical - some modems can't
185 * get this reliably right, so we have the option to send a few ms
186 * of 0-bytes, before the 001 EOL, thus relaxing the timing a bit
187 */
188 if ( modem_quirks & MQ_NEED_SP_PAD )
189 {
190 char nbuf[100];
191
192 lprintf( L_MESG, "send %d 0-bytes (pad before first EOL)...", sizeof(nbuf) );
193 bzero( nbuf, sizeof(nbuf) );
194 write( fd, nbuf, sizeof(nbuf) );
195 }
196
197 alarm( 40 ); /* timeout if we get stuck in flow control */
198
199 while ( ( r = read( g3fd, buf, 64 ) ) > 0 )
200 {
201 /* refresh alarm counter every 1000 bytes */
202 if ( w_refresh > 1000 )
203 {
204 w_refresh -= 1000;
205 alarm( 30 );
206 }
207
208 i = 0;
209 /* skip over GhostScript / digifaxhigh header */
210
211 if ( first )
212 {
213 first = FALSE;
214 if ( r >= 64 && strcmp( buf+1,
215 "PC Research, Inc" ) == 0 )
216 {
217 lprintf( L_MESG, "skipping over GhostScript header" );
218 i = 64;
219 /* for dfax files, we can check if the resolutions match
220 */
221 if ( ( fax_par_d.vr != 0 ) != ( buf[29] != 0 ) )
222 {
223 fprintf( stderr, "WARNING: sending in %s mode, fax data is %s mode\n",
224 fax_par_d.vr? "fine" : "normal",
225 buf[29] ? "fine" : "normal" );
226 lprintf( L_WARN, "resolution mismatch" );
227 }
228 }
229 else
230 /* it's incredible how stupid users are - check for */
231 /* "tiffg3" files and issue a warning if the file is */
232 /* suspect */
233 if ( r >= 2 && ( ( buf[0] == 0x49 && buf[1] == 0x49 ) ||
234 ( buf[0] == 0x4d && buf[1] == 0x4d ) ) )
235 {
236 lprintf( L_WARN, "file may be 'tiffg3' - TIFF is *not* a valid input format" );
237 fprintf( stderr, "WARNING: file may be 'tiffg3' - TIFF file format is *not* supported!\n" );
238 fprintf( stderr, " Thus, fax transmission will most propably fail\n" );
239 }
240 else
241 if ( r < 10 || buf[0] != 0 )
242 {
243 lprintf( L_WARN, "file looks 'suspicious', buf=%02x %02x %02x %02x...", buf[0] &0xff, buf[1] &0xff, buf[2] &0xff, buf[3] &0xff );
244 fprintf( stderr, "WARNING: are you sure that this is a G3 fax file? Doesn't seem to be...\n" );
245 }
246 }
247
248 /* escape DLE characters. If necessary (+FBO=0), swap bits */
249
250 for ( w = 0; i < r; i++ )
251 {
252 wbuf[ w ] = fax_send_swaptable[ (unsigned char) buf[i] ];
253 if ( wbuf[ w++ ] == DLE ) wbuf[ w++ ] = DLE;
254 }
255
256 lprintf( L_JUNK, "read %d, write %d", r, w );
257
258 if ( write( fd, wbuf, w ) != w )
259 {
260 lprintf( L_ERROR, "could not write all %d bytes", w );
261 }
262
263 /* check for timeout */
264
265 if ( fax_sendpg_timeout )
266 {
267 fax_send_panic_exit( fd );
268 }
269
270 w_total += w;
271 w_refresh += w;
272
273 /* look if there's something to read
274 *
275 * normally there shouldn't be anything, but I have
276 * seen very old ZyXEL releases sending junk and then
277 * failing completely... so this may help when debugging
278 *
279 * Also, if you don't use FLOW_SOFT for sendfax, and
280 * your modem insists on xon/xoff flow control, you'll
281 * see these characters [0x11/0x13] here.
282 */
283
284 if ( check_for_input( fd ) )
285 {
286 lprintf( L_NOISE, "input: got " );
287 do
288 {
289 /* intentionally don't use mdm_read_byte here */
290 if ( read( fd, &ch, 1 ) != 1 )
291 {
292 lprintf( L_ERROR, "read failed" );
293 break;
294 }
295 else
296 lputc( L_NOISE, ch );
297 }
298 while ( check_for_input( fd ) );
299 }
300 } /* end while (more g3 data to read) */
301 close(g3fd);
302 } /* end if (open file succeeded) */
303
304 lprintf( L_MESG, "page complete, %d bytes sent", w_total );
305
306 if ( bytes_sent != NULL )
307 *bytes_sent += w_total;
308
309 /* send end-of-page characters and post-page-message */
310 rc = fax_send_ppm( fd, tio, ppm );
311
312 alarm(0);
313
314 return rc;
315 }
316
317 /* send end-of-page code, set fax_page_transmit_status
318 *
319 * class 2 : send <DLE> <ETX>, then send AT+FET=... according to "type"
320 * class 2.0: send <DLE>{<mps>|<eop>|<eom>}, then send AT+FPS?
321 */
322 int fax_send_ppm _P3( (fd, tio, ppm),
323 int fd, TIO * tio, Post_page_messages ppm )
324 {
325 int rc;
326
327 /* set alarm clock to a time long enough to handle *very* slow links
328 * on modems with *very* large buffers (2400 / ZyXEL...)
329 */
330 alarm( FAX_RESPONSE_TIMEOUT );
331
332 if ( modem_type == Mt_class2_0 )
333 {
334 /* in class 2.0, end-of-page *and* page punctuation are
335 * transmitted in one. The modem will return OK or ERROR,
336 * depending on the remote page transmit status
337 */
338 /* EIA 592, 8.3.3.7 */
339 char ppm_char, ppm_buf[2], *ppm_r;
340
341 switch( ppm )
342 {
343 case pp_mps: /* another page next */
344 ppm_char = 0x2c; break;
345 case pp_eom: /* last page, another document next */
346 ppm_char = 0x3b; break;
347 case pp_eop: /* no more pages or documents */
348 /* stop being sensitive to DCD drops */
349 #ifdef sun
350 /* On SUNs, HW handshake has to be off while carrier is low */
351 /* -> to avoid underruns, drain buffers first (Nils Jonsson) */
352 tio_drain_output( fd );
353 tio_set_flow_control(fd, tio, (FAXSEND_FLOW) & FLOW_XON_OUT);
354 #endif
355 tio_carrier( tio, FALSE );
356 tio_set( fd, tio );
357
358 ppm_char = 0x2e; break;
359 default:
360 lprintf( L_WARN, "ppm type %d not implemented", ppm );
361 return ERROR;
362 }
363
364 lprintf( L_MESG, "sending DLE '" );
365 lputc( L_MESG, ppm_char ); lputc( L_MESG, '\'' );
366
367 ppm_buf[0] = DLE; ppm_buf[1] = ppm_char;
368 if ( write( fd, ppm_buf, 2 ) != 2 )
369 {
370 lprintf( L_ERROR, "cannot write PPM" );
371 return ERROR;
372 }
373
374 /* FIXME: I think this should be done with fax_wait_for()! */
375 do
376 {
377 ppm_r = mdm_get_line( fd );
378 if ( ppm_r == NULL ) return ERROR;
379
380 /* hangup code. See fax_wait_for() for comments */
381 if ( strncmp( ppm_r, "+FHS:", 5 ) == 0 )
382 {
383 fax_hangup = 1;
384 signal( SIGHUP, SIG_IGN );
385 sscanf( &ppm_r[5], "%d", &fax_hangup_code );
386 lprintf( L_MESG, "connection hangup: '%s'", ppm_r );
387 lprintf( L_NOISE,"(%s)", fax_strerror( fax_hangup_code ));
388 }
389 }
390 while ( strcmp( ppm_r, "OK" ) != 0 &&
391 strcmp( ppm_r, "ERROR" ) != 0 );
392 lprintf( L_MESG, "got response: '%s'", ppm_r );
393
394 /* fax page status is encoded here! */
395 /* FIXME: query page tx status from modem */
396 fax_page_tx_status = ( strcmp( ppm_r, "OK" ) == 0 ) ? 1: 2;
397
398 /* FIXME: this way? */
399 /* fax_command( "AT+FPS?", "OK", fd ); */
400
401 return NOERROR;
402 }
403 else
404 {
405 /* transmit end of page (<DLE><ETX> -> OK) */
406
407 lprintf( L_MESG, "sending DLE ETX..." );
408 write( fd, fax_end_of_page, sizeof( fax_end_of_page ));
409
410 if ( fax_wait_for( "OK", fd ) == ERROR ) return ERROR;
411
412 /* transmit page punctuation */
413
414 switch ( ppm )
415 {
416 case pp_mps: /* another page next */
417 rc = fax_command( "AT+FET=0", "OK", fd );
418 break;
419 case pp_eom: /* last page, another document next */
420 rc = fax_command( "AT+FET=1", "OK", fd );
421 break;
422 case pp_eop: /* no more pages or documents, over & out */
423
424 /* take care of modems pulling DCD low before the final
425 * result code has reached the host
426 */
427 tio_carrier( tio, FALSE );
428 #ifdef sun
429 /* HW handshake has to be off while carrier is low */
430 tio_set_flow_control(fd, tio, (FAXSEND_FLOW) & FLOW_XON_OUT);
431 #endif
432 tio_set( fd, tio );
433
434 rc = fax_command( "AT+FET=2", "OK", fd );
435 break;
436 default: /* pri-xxx codes */
437 lprintf( L_WARN, "ppm type %d not implemented", ppm );
438 rc = ERROR;
439 }
440
441 return rc;
442 } /* end if ( ! modem == 2.0 ) */
443 }
444