]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/tip/aculib/courier.c
BSD 4.4 Lite Usr.bin Sources
[FreeBSD/FreeBSD.git] / usr.bin / tip / aculib / courier.c
1 /*
2  * Copyright (c) 1986, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #ifndef lint
35 static char sccsid[] = "@(#)courier.c   8.1 (Berkeley) 6/6/93";
36 #endif /* not lint */
37
38 /*
39  * Routines for calling up on a Courier modem.
40  * Derived from Hayes driver.
41  */
42 #include "tip.h"
43 #include <stdio.h>
44
45 #define MAXRETRY        5
46
47 static  void sigALRM();
48 static  int timeout = 0;
49 static  int connected = 0;
50 static  jmp_buf timeoutbuf, intbuf;
51 static  int coursync();
52
53 cour_dialer(num, acu)
54         register char *num;
55         char *acu;
56 {
57         register char *cp;
58 #ifdef ACULOG
59         char line[80];
60 #endif
61         static int cour_connect(), cour_swallow();
62
63         if (boolean(value(VERBOSE)))
64                 printf("Using \"%s\"\n", acu);
65
66         ioctl(FD, TIOCHPCL, 0);
67         /*
68          * Get in synch.
69          */
70         if (!coursync()) {
71 badsynch:
72                 printf("can't synchronize with courier\n");
73 #ifdef ACULOG
74                 logent(value(HOST), num, "courier", "can't synch up");
75 #endif
76                 return (0);
77         }
78         cour_write(FD, "AT E0\r", 6);   /* turn off echoing */
79         sleep(1);
80 #ifdef DEBUG
81         if (boolean(value(VERBOSE)))
82                 cour_verbose_read();
83 #endif
84         ioctl(FD, TIOCFLUSH, 0);        /* flush any clutter */
85         cour_write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21);
86         if (!cour_swallow("\r\nOK\r\n"))
87                 goto badsynch;
88         fflush(stdout);
89         cour_write(FD, "AT D", 4);
90         for (cp = num; *cp; cp++)
91                 if (*cp == '=')
92                         *cp = ',';
93         cour_write(FD, num, strlen(num));
94         cour_write(FD, "\r", 1);
95         connected = cour_connect();
96 #ifdef ACULOG
97         if (timeout) {
98                 sprintf(line, "%d second dial timeout",
99                         number(value(DIALTIMEOUT)));
100                 logent(value(HOST), num, "cour", line);
101         }
102 #endif
103         if (timeout)
104                 cour_disconnect();
105         return (connected);
106 }
107
108 cour_disconnect()
109 {
110          /* first hang up the modem*/
111         ioctl(FD, TIOCCDTR, 0);
112         sleep(1);
113         ioctl(FD, TIOCSDTR, 0);
114         coursync();                             /* reset */
115         close(FD);
116 }
117
118 cour_abort()
119 {
120         cour_write(FD, "\r", 1);        /* send anything to abort the call */
121         cour_disconnect();
122 }
123
124 static void
125 sigALRM()
126 {
127         printf("\07timeout waiting for reply\n");
128         timeout = 1;
129         longjmp(timeoutbuf, 1);
130 }
131
132 static int
133 cour_swallow(match)
134   register char *match;
135   {
136         sig_t f;
137         char c;
138
139         f = signal(SIGALRM, sigALRM);
140         timeout = 0;
141         do {
142                 if (*match =='\0') {
143                         signal(SIGALRM, f);
144                         return (1);
145                 }
146                 if (setjmp(timeoutbuf)) {
147                         signal(SIGALRM, f);
148                         return (0);
149                 }
150                 alarm(number(value(DIALTIMEOUT)));
151                 read(FD, &c, 1);
152                 alarm(0);
153                 c &= 0177;
154 #ifdef DEBUG
155                 if (boolean(value(VERBOSE)))
156                         putchar(c);
157 #endif
158         } while (c == *match++);
159 #ifdef DEBUG
160         if (boolean(value(VERBOSE)))
161                 fflush(stdout);
162 #endif
163         signal(SIGALRM, SIG_DFL);
164         return (0);
165 }
166
167 struct baud_msg {
168         char *msg;
169         int baud;
170 } baud_msg[] = {
171         "",             B300,
172         " 1200",        B1200,
173         " 2400",        B2400,
174         " 9600",        B9600,
175         " 9600/ARQ",    B9600,
176         0,              0,
177 };
178
179 static int
180 cour_connect()
181 {
182         char c;
183         int nc, nl, n;
184         struct sgttyb sb;
185         char dialer_buf[64];
186         struct baud_msg *bm;
187         sig_t f;
188
189         if (cour_swallow("\r\n") == 0)
190                 return (0);
191         f = signal(SIGALRM, sigALRM);
192 again:
193         nc = 0; nl = sizeof(dialer_buf)-1;
194         bzero(dialer_buf, sizeof(dialer_buf));
195         timeout = 0;
196         for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
197                 if (setjmp(timeoutbuf))
198                         break;
199                 alarm(number(value(DIALTIMEOUT)));
200                 n = read(FD, &c, 1);
201                 alarm(0);
202                 if (n <= 0)
203                         break;
204                 c &= 0x7f;
205                 if (c == '\r') {
206                         if (cour_swallow("\n") == 0)
207                                 break;
208                         if (!dialer_buf[0])
209                                 goto again;
210                         if (strcmp(dialer_buf, "RINGING") == 0 &&
211                             boolean(value(VERBOSE))) {
212 #ifdef DEBUG
213                                 printf("%s\r\n", dialer_buf);
214 #endif
215                                 goto again;
216                         }
217                         if (strncmp(dialer_buf, "CONNECT",
218                                     sizeof("CONNECT")-1) != 0)
219                                 break;
220                         for (bm = baud_msg ; bm->msg ; bm++)
221                                 if (strcmp(bm->msg,
222                                     dialer_buf+sizeof("CONNECT")-1) == 0) {
223                                         if (ioctl(FD, TIOCGETP, &sb) < 0) {
224                                                 perror("TIOCGETP");
225                                                 goto error;
226                                         }
227                                         sb.sg_ispeed = sb.sg_ospeed = bm->baud;
228                                         if (ioctl(FD, TIOCSETP, &sb) < 0) {
229                                                 perror("TIOCSETP");
230                                                 goto error;
231                                         }
232                                         signal(SIGALRM, f);
233 #ifdef DEBUG
234                                         if (boolean(value(VERBOSE)))
235                                                 printf("%s\r\n", dialer_buf);
236 #endif
237                                         return (1);
238                                 }
239                         break;
240                 }
241                 dialer_buf[nc] = c;
242 #ifdef notdef
243                 if (boolean(value(VERBOSE)))
244                         putchar(c);
245 #endif
246         }
247 error1:
248         printf("%s\r\n", dialer_buf);
249 error:
250         signal(SIGALRM, f);
251         return (0);
252 }
253
254 /*
255  * This convoluted piece of code attempts to get
256  * the courier in sync.
257  */
258 static int
259 coursync()
260 {
261         int already = 0;
262         int len;
263         char buf[40];
264
265         while (already++ < MAXRETRY) {
266                 ioctl(FD, TIOCFLUSH, 0);        /* flush any clutter */
267                 cour_write(FD, "\rAT Z\r", 6);  /* reset modem */
268                 bzero(buf, sizeof(buf));
269                 sleep(1);
270                 ioctl(FD, FIONREAD, &len);
271                 if (len) {
272                         len = read(FD, buf, sizeof(buf));
273 #ifdef DEBUG
274                         buf[len] = '\0';
275                         printf("coursync: (\"%s\")\n\r", buf);
276 #endif
277                         if (index(buf, '0') || 
278                            (index(buf, 'O') && index(buf, 'K')))
279                                 return(1);
280                 }
281                 /*
282                  * If not strapped for DTR control,
283                  * try to get command mode.
284                  */
285                 sleep(1);
286                 cour_write(FD, "+++", 3);
287                 sleep(1);
288                 /*
289                  * Toggle DTR to force anyone off that might have left
290                  * the modem connected.
291                  */
292                 ioctl(FD, TIOCCDTR, 0);
293                 sleep(1);
294                 ioctl(FD, TIOCSDTR, 0);
295         }
296         cour_write(FD, "\rAT Z\r", 6);
297         return (0);
298 }
299
300 cour_write(fd, cp, n)
301 int fd;
302 char *cp;
303 int n;
304 {
305         struct sgttyb sb;
306 #ifdef notdef
307         if (boolean(value(VERBOSE)))
308                 write(1, cp, n);
309 #endif
310         ioctl(fd, TIOCGETP, &sb);
311         ioctl(fd, TIOCSETP, &sb);
312         cour_nap();
313         for ( ; n-- ; cp++) {
314                 write(fd, cp, 1);
315                 ioctl(fd, TIOCGETP, &sb);
316                 ioctl(fd, TIOCSETP, &sb);
317                 cour_nap();
318         }
319 }
320
321 #ifdef DEBUG
322 cour_verbose_read()
323 {
324         int n = 0;
325         char buf[BUFSIZ];
326
327         if (ioctl(FD, FIONREAD, &n) < 0)
328                 return;
329         if (n <= 0)
330                 return;
331         if (read(FD, buf, n) != n)
332                 return;
333         write(1, buf, n);
334 }
335 #endif
336
337 /*
338  * Code stolen from /usr/src/lib/libc/gen/sleep.c
339  */
340 #define mask(s) (1<<((s)-1))
341 #define setvec(vec, a) \
342         vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
343
344 static napms = 50; /* Give the courier 50 milliseconds between characters */
345
346 static int ringring;
347
348 cour_nap()
349 {
350         
351         static void cour_napx();
352         int omask;
353         struct itimerval itv, oitv;
354         register struct itimerval *itp = &itv;
355         struct sigvec vec, ovec;
356
357         timerclear(&itp->it_interval);
358         timerclear(&itp->it_value);
359         if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
360                 return;
361         setvec(ovec, SIG_DFL);
362         omask = sigblock(mask(SIGALRM));
363         itp->it_value.tv_sec = napms/1000;
364         itp->it_value.tv_usec = ((napms%1000)*1000);
365         setvec(vec, cour_napx);
366         ringring = 0;
367         (void) sigvec(SIGALRM, &vec, &ovec);
368         (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
369         while (!ringring)
370                 sigpause(omask &~ mask(SIGALRM));
371         (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
372         (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
373         (void) sigsetmask(omask);
374 }
375
376 static void
377 cour_napx()
378 {
379         ringring = 1;
380 }