xref: /plan9-contrib/sys/src/cmd/fax/fax2send.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 
5 #include "modem.h"
6 
7 int
8 faxsend(Modem *m, int argc, char *argv[])
9 {
10 	int c, count, r;
11 	char buf[128];
12 
13 	verbose("faxsend");
14 	if((r = initfaxmodem(m)) != Eok)
15 		return r;
16 
17 	/* telco just does the dialing */
18 	r = response(m, 120);
19 	switch(r){
20 	case Rok:
21 		break;
22 	default:
23 		r = seterror(m, Enoanswer);
24 		return r;
25 
26 	}
27 
28 	m->pageno = 1;
29 	while(argc--){
30 		if(m->pageno != 1)
31 			sleep(1000);	/* let the paper catch up */
32 
33 		m->valid &= ~(Vfhng|Vfet|Vfpts|Vftsi|Vfdcs);
34 		if((r = openfaxfile(m, *argv)) != Eok)
35 			return r;
36 
37 		sprint(buf, "AT+FDT=%d,%d,%d,%d", m->df, m->vr, m->wd, m->ln);
38 		if(command(m, buf) != Eok)
39 			goto buggery;
40 		if(response(m, 20) != Rconnect){
41 			r = seterror(m, Eincompatible);
42 			goto buggery;
43 		}
44 
45 		/* wait for first ^S */
46 		getmchar(m, buf, 5);
47 
48 		/*
49 		 * Write the data, stuffing DLE's.
50 		 * After each bufferfull check if the remote
51 		 * sent us anything, e.g. CAN to abort.
52 		 * This also flushes out the ^S/^Q characters
53 		 * which the driver insists on sending us.
54 		 * (Could fix the driver, of course...).
55 		 */
56 		for(;;){
57 			count = 0;
58 			c = 0;
59 			while(count < sizeof(buf)-1){
60 				if((c = BGETC(m->bp)) < 0)
61 					break;
62 				buf[count++] = c;
63 				if(c == '\020')
64 					buf[count++] = c;
65 			}
66 			if(count && write(m->fd, buf, count) < 0){
67 				r = seterror(m, Esys);
68 				goto buggery;
69 			}
70 			if(c < 0)
71 				break;
72 
73 			while((r = rawmchar(m, buf)) == Eok){
74 				if(buf[0] == '\030'){
75 					verbose("%c", buf[0]);
76 					if(write(m->fd, "\020\003", 2) < 0){
77 						r = seterror(m, Esys);
78 						goto buggery;
79 					}
80 					goto okexit;
81 				}
82 				if(buf[0] != '\021' && buf[0] != '\023' && buf[0] != '\n'){
83 					verbose("%c", buf[0]);
84 					r = seterror(m, Eproto);
85 					goto buggery;
86 				}
87 			}
88 		}
89 
90 		/*
91 		 * End of page, send DLE+ETX,
92 		 * get OK in response.
93 		 */
94 		if(write(m->fd, "\020\003", 2) < 0){
95 			r = seterror(m, Esys);
96 			goto buggery;
97 		}
98 		if(response(m, 20) != Rok){
99 			r = seterror(m, Enoresponse);
100 			goto buggery;
101 		}
102 
103 		/*
104 		 * Did you hear me? - IT'S THE END OF THE PAGE.
105 		 * Argument is 0 if more pages to follow.
106 		 * Should get back an FPTS with an indication
107 		 * as to whether the page was successfully
108 		 * transmitted or not.
109 		 */
110 		sprint(buf, "AT+FET=%d", argc == 0? 2: 0);
111 		if(command(m, buf) != Eok)
112 			goto buggery;
113 		switch(response(m, 20)){
114 		case Rok:
115 			break;
116 		case Rhangup:
117 			if(m->fhng == 0 && argc == 0)
118 				break;
119 			r = seterror(m, Eproto);
120 			goto buggery;
121 		default:
122 			r = seterror(m, Enoresponse);
123 			goto buggery;
124 		}
125 
126 		if((m->valid & Vfpts) == 0 || m->fpts[0] != 1){
127 			r = seterror(m, Eproto);
128 			goto buggery;
129 		}
130 
131 		Bterm(m->bp);
132 		m->pageno++;
133 		argv++;
134 	}
135 okexit:
136 	return Eok;
137 
138 buggery:
139 	Bterm(m->bp);
140 	command(m, "AT+FK");
141 	response(m, 5);
142 	return r;
143 }
144