1*ffe34450Schristos /* $NetBSD: biz31.c,v 1.12 2006/12/14 17:09:43 christos Exp $ */
239801cccSjtc
361f28255Scgd /*
439801cccSjtc * Copyright (c) 1983, 1993
539801cccSjtc * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * Redistribution and use in source and binary forms, with or without
861f28255Scgd * modification, are permitted provided that the following conditions
961f28255Scgd * are met:
1061f28255Scgd * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd * notice, this list of conditions and the following disclaimer.
1261f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd * notice, this list of conditions and the following disclaimer in the
1461f28255Scgd * documentation and/or other materials provided with the distribution.
1589aaa1bbSagc * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd * may be used to endorse or promote products derived from this software
1761f28255Scgd * without specific prior written permission.
1861f28255Scgd *
1961f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd * SUCH DAMAGE.
3061f28255Scgd */
3161f28255Scgd
32e37283e1Slukem #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3439801cccSjtc #if 0
3539801cccSjtc static char sccsid[] = "@(#)biz31.c 8.1 (Berkeley) 6/6/93";
3639801cccSjtc #endif
37*ffe34450Schristos __RCSID("$NetBSD: biz31.c,v 1.12 2006/12/14 17:09:43 christos Exp $");
3861f28255Scgd #endif /* not lint */
3961f28255Scgd
4061f28255Scgd #include "tip.h"
4161f28255Scgd
4261f28255Scgd #define MAXRETRY 3 /* sync up retry count */
4361f28255Scgd #define DISCONNECT_CMD "\21\25\11\24" /* disconnection string */
4461f28255Scgd
45*ffe34450Schristos static void sigALRM(int);
4661f28255Scgd static int timeout = 0;
4761f28255Scgd static jmp_buf timeoutbuf;
4861f28255Scgd
49*ffe34450Schristos static void echo(const char *);
50*ffe34450Schristos static int detect(const char *);
51*ffe34450Schristos static void flush(const char *);
52*ffe34450Schristos static int bizsync(int);
53*ffe34450Schristos
5461f28255Scgd /*
5561f28255Scgd * Dial up on a BIZCOMP Model 1031 with either
5661f28255Scgd * tone dialing (mod = "f")
5761f28255Scgd * pulse dialing (mod = "w")
5861f28255Scgd */
5961f28255Scgd static int
biz_dialer(char * num,const char * mod)60*ffe34450Schristos biz_dialer(char *num, const char *mod)
6161f28255Scgd {
62e37283e1Slukem int connected = 0;
6361f28255Scgd
6461f28255Scgd if (!bizsync(FD)) {
6561f28255Scgd logent(value(HOST), "", "biz", "out of sync");
66*ffe34450Schristos (void)printf("bizcomp out of sync\n");
6761f28255Scgd exit(0);
6861f28255Scgd }
6961f28255Scgd if (boolean(value(VERBOSE)))
70*ffe34450Schristos (void)printf("\nstarting call...");
7161f28255Scgd echo("#\rk$\r$\n"); /* disable auto-answer */
7261f28255Scgd echo("$>$.$ #\r"); /* tone/pulse dialing */
7361f28255Scgd echo(mod);
7461f28255Scgd echo("$\r$\n");
7561f28255Scgd echo("$>$.$ #\re$ "); /* disconnection sequence */
7661f28255Scgd echo(DISCONNECT_CMD);
7761f28255Scgd echo("\r$\n$\r$\n");
7861f28255Scgd echo("$>$.$ #\rr$ "); /* repeat dial */
7961f28255Scgd echo(num);
8061f28255Scgd echo("\r$\n");
8161f28255Scgd if (boolean(value(VERBOSE)))
82*ffe34450Schristos (void)printf("ringing...");
8361f28255Scgd /*
8461f28255Scgd * The reply from the BIZCOMP should be:
8561f28255Scgd * `^G NO CONNECTION\r\n^G\r\n' failure
8661f28255Scgd * ` CONNECTION\r\n^G' success
8761f28255Scgd */
8861f28255Scgd connected = detect(" ");
8961f28255Scgd if (!connected)
9061f28255Scgd flush(" NO CONNECTION\r\n\07\r\n");
9161f28255Scgd else
9261f28255Scgd flush("CONNECTION\r\n\07");
9361f28255Scgd if (timeout)
9461f28255Scgd biz31_disconnect(); /* insurance */
9561f28255Scgd return (connected);
9661f28255Scgd }
9761f28255Scgd
98*ffe34450Schristos int
99*ffe34450Schristos /*ARGSUSED*/
biz31w_dialer(char * num,char * acu __unused)100*ffe34450Schristos biz31w_dialer(char *num, char *acu __unused)
10161f28255Scgd {
10261f28255Scgd
10361f28255Scgd return (biz_dialer(num, "w"));
10461f28255Scgd }
10561f28255Scgd
106*ffe34450Schristos int
107*ffe34450Schristos /*ARGSUSED*/
biz31f_dialer(char * num,char * acu __unused)108*ffe34450Schristos biz31f_dialer(char *num, char *acu __unused)
10961f28255Scgd {
11061f28255Scgd
11161f28255Scgd return (biz_dialer(num, "f"));
11261f28255Scgd }
11361f28255Scgd
114*ffe34450Schristos void
biz31_disconnect(void)11558c2151fSperry biz31_disconnect(void)
11661f28255Scgd {
11761f28255Scgd
118*ffe34450Schristos (void)write(FD, DISCONNECT_CMD, 4);
119*ffe34450Schristos (void)sleep(2);
120*ffe34450Schristos (void)tcflush(FD, TCIOFLUSH);
12161f28255Scgd }
12261f28255Scgd
123*ffe34450Schristos void
biz31_abort(void)12458c2151fSperry biz31_abort(void)
12561f28255Scgd {
12661f28255Scgd
127*ffe34450Schristos (void)write(FD, "\33", 1);
12861f28255Scgd }
12961f28255Scgd
130*ffe34450Schristos static void
echo(const char * s)131*ffe34450Schristos echo(const char *s)
13261f28255Scgd {
13361f28255Scgd char c;
13461f28255Scgd
135*ffe34450Schristos while ((c = *s++) != '\0')
136*ffe34450Schristos switch (c) {
13761f28255Scgd case '$':
138*ffe34450Schristos (void)read(FD, &c, 1);
13961f28255Scgd s++;
14061f28255Scgd break;
14161f28255Scgd
14261f28255Scgd case '#':
14361f28255Scgd c = *s++;
144*ffe34450Schristos (void)write(FD, &c, 1);
14561f28255Scgd break;
14661f28255Scgd
14761f28255Scgd default:
148*ffe34450Schristos (void)write(FD, &c, 1);
149*ffe34450Schristos (void)read(FD, &c, 1);
15061f28255Scgd }
15161f28255Scgd }
15261f28255Scgd
15361f28255Scgd static void
154*ffe34450Schristos /*ARGSUSED*/
sigALRM(int signo __unused)155*ffe34450Schristos sigALRM(int signo __unused)
15661f28255Scgd {
15761f28255Scgd
15861f28255Scgd timeout = 1;
15961f28255Scgd longjmp(timeoutbuf, 1);
16061f28255Scgd }
16161f28255Scgd
16261f28255Scgd static int
detect(const char * s)163*ffe34450Schristos detect(const char *s)
16461f28255Scgd {
16561f28255Scgd sig_t f;
16661f28255Scgd char c;
16761f28255Scgd
16861f28255Scgd f = signal(SIGALRM, sigALRM);
16961f28255Scgd timeout = 0;
17061f28255Scgd while (*s) {
17161f28255Scgd if (setjmp(timeoutbuf)) {
172*ffe34450Schristos (void)printf("\07timeout waiting for reply\n");
17361f28255Scgd biz31_abort();
17461f28255Scgd break;
17561f28255Scgd }
176*ffe34450Schristos (void)alarm((unsigned)number(value(DIALTIMEOUT)));
177*ffe34450Schristos (void)read(FD, &c, 1);
178*ffe34450Schristos (void)alarm(0);
17961f28255Scgd if (c != *s++)
18061f28255Scgd break;
18161f28255Scgd }
182*ffe34450Schristos (void)signal(SIGALRM, f);
18361f28255Scgd return (timeout == 0);
18461f28255Scgd }
18561f28255Scgd
186*ffe34450Schristos static void
flush(const char * s)187*ffe34450Schristos flush(const char *s)
18861f28255Scgd {
18961f28255Scgd sig_t f;
19061f28255Scgd char c;
19161f28255Scgd
19261f28255Scgd f = signal(SIGALRM, sigALRM);
19361f28255Scgd while (*s++) {
19461f28255Scgd if (setjmp(timeoutbuf))
19561f28255Scgd break;
196*ffe34450Schristos (void)alarm(10);
197*ffe34450Schristos (void)read(FD, &c, 1);
198*ffe34450Schristos (void)alarm(0);
19961f28255Scgd }
200*ffe34450Schristos (void)signal(SIGALRM, f);
20161f28255Scgd timeout = 0; /* guard against disconnection */
20261f28255Scgd }
20361f28255Scgd
20461f28255Scgd /*
20561f28255Scgd * This convoluted piece of code attempts to get
20661f28255Scgd * the bizcomp in sync. If you don't have the capacity or nread
20761f28255Scgd * call there are gory ways to simulate this.
20861f28255Scgd */
20961f28255Scgd static int
bizsync(int fd)21058c2151fSperry bizsync(int fd)
21161f28255Scgd {
21261f28255Scgd #ifdef FIOCAPACITY
21361f28255Scgd struct capacity b;
21461f28255Scgd # define chars(b) ((b).cp_nbytes)
21561f28255Scgd # define IOCTL FIOCAPACITY
21661f28255Scgd #endif
21761f28255Scgd #ifdef FIONREAD
21861f28255Scgd long b;
21961f28255Scgd # define chars(b) (b)
22061f28255Scgd # define IOCTL FIONREAD
22161f28255Scgd #endif
222e37283e1Slukem int already = 0;
22361f28255Scgd char buf[10];
22461f28255Scgd
22561f28255Scgd retry:
226*ffe34450Schristos if (ioctl(fd, IOCTL, &b) >= 0 && chars(b) > 0)
227*ffe34450Schristos (void)tcflush(FD, TCIOFLUSH);
228*ffe34450Schristos (void)write(fd, "\rp>\r", 4);
229*ffe34450Schristos (void)sleep(1);
230*ffe34450Schristos if (ioctl(fd, IOCTL, &b) >= 0) {
23161f28255Scgd if (chars(b) != 10) {
23261f28255Scgd nono:
23361f28255Scgd if (already > MAXRETRY)
23461f28255Scgd return (0);
235*ffe34450Schristos (void)write(fd, DISCONNECT_CMD, 4);
236*ffe34450Schristos (void)sleep(2);
23761f28255Scgd already++;
23861f28255Scgd goto retry;
23961f28255Scgd } else {
240*ffe34450Schristos (void)read(fd, buf, 10);
24161f28255Scgd if (strncmp(buf, "p >\r\n\r\n>", 8))
24261f28255Scgd goto nono;
24361f28255Scgd }
24461f28255Scgd }
24561f28255Scgd return (1);
24661f28255Scgd }
247