148664Sbostic /*-
2*62391Sbostic * Copyright (c) 1985, 1993
3*62391Sbostic * The Regents of the University of California. All rights reserved.
448664Sbostic *
548664Sbostic * %sccs.include.proprietary.c%
648664Sbostic */
748664Sbostic
833581Srick #ifndef lint
9*62391Sbostic static char sccsid[] = "@(#)conn.c 8.1 (Berkeley) 06/06/93";
1048664Sbostic #endif /* not lint */
1113642Ssam
1223596Sbloom #include <signal.h>
1313642Ssam #include "uucp.h"
1413642Ssam #include <setjmp.h>
1513642Ssam #include <ctype.h>
1613642Ssam #include <errno.h>
1717834Sralph #ifdef USG
1813642Ssam #include <termio.h>
1913642Ssam #include <fcntl.h>
2013642Ssam #endif
2117834Sralph #ifndef USG
2213642Ssam #include <sgtty.h>
2313642Ssam #endif
2417834Sralph #ifdef BSD4_2
2517834Sralph #include <sys/time.h>
2617834Sralph #else
2717834Sralph #include <time.h>
2817834Sralph #endif
2913642Ssam
3013642Ssam #define MAXC 1000
3113642Ssam
3213642Ssam extern jmp_buf Sjbuf;
3317834Sralph jmp_buf Cjbuf;
3418619Sralph extern int errno, onesys;
3560116Storek extern const char *const sys_errlist[];
3618619Sralph extern char MaxGrade, DefMaxGrade;
3713642Ssam
3813642Ssam /* Parity control during login procedure */
3913642Ssam #define P_ZERO 0
4013642Ssam #define P_ONE 1
4113642Ssam #define P_EVEN 2
4213642Ssam #define P_ODD 3
4317834Sralph
4417834Sralph #define ABORT -2
4517834Sralph
4617834Sralph char *AbortOn = NULL;
4713642Ssam char par_tab[128]; /* must be power of two */
4817834Sralph int linebaudrate; /* used for the sleep test in pk1.c */
4913642Ssam int next_fd = -1; /* predicted fd to close interrupted opens */
5025705Sbloom
5125705Sbloom char *PCP = "PCP"; /* PC Pursuit device type */
5225127Sbloom /*
5325127Sbloom * catch alarm routine for "expect".
5413642Ssam */
5546879Sbostic void
alarmtr()5613642Ssam alarmtr()
5713642Ssam {
5813642Ssam signal(SIGALRM, alarmtr);
5913642Ssam if (next_fd >= 0) {
6013642Ssam if (close(next_fd))
6113642Ssam logent("FAIL", "ACU LINE CLOSE");
6213642Ssam next_fd = -1;
6313642Ssam }
6413642Ssam longjmp(Sjbuf, 1);
6513642Ssam }
6613642Ssam
6725705Sbloom /* This template is for seismo to call ihnp4
6825705Sbloom * the 3 lines marked ---> will be overwritten for the appropriate city
6925705Sbloom */
7025705Sbloom #define PCP_BAUD 3
7125705Sbloom #define PCP_PHONE 4
7233562Srick #define PCP_CITY 14
7333562Srick #define PCP_PASSWORD 16
7433562Srick #define PCP_RPHONE 20
7533562Srick #define NPCFIELDS 23
7625705Sbloom
7725705Sbloom static char *PCFlds[] = {
7825705Sbloom "PC-PURSUIT",
7925705Sbloom "Any",
8025705Sbloom "ACU",
8125705Sbloom "1200",
8233562Srick CNULL,
8333562Srick CNULL,
8433562Srick "P_ZERO", /* Telenet insists on zero parity */
8525705Sbloom "ABORT",
8633562Srick "BUSY", /* Abort on Busy Signal */
8733562Srick CNULL,
8833562Srick "\\d\\d\\r\\d\\r", /* Get telenet's attention */
8933562Srick "TERMINAL=~3-\r-TERM~3-\r-TERM~5", /* Terminal type ? */
9033562Srick "\\r",
9133562Srick "@", /* telenet's prompt */
9233562Srick "D/DCWAS/21,telenetloginstring", /* overwritten later */
9333562Srick "PASSWORD",
9433562Srick CNULL, /* telenet password */
9533562Srick "CONNECTED", /* We're now talking to a Hayes in the remote city */
9633562Srick "ATZ", /* Reset it */
9733562Srick "OK",
9833562Srick "ATDT6907171", /* overwritten */
9933562Srick "CONNECT",
10033562Srick "\\d\\r", /* We're in !*/
10133562Srick CNULL,
10225705Sbloom };
10325705Sbloom
10433562Srick static char PCP_brand[25];
10534167Srick int Dcf = -1;
10634167Srick char *Flds[MAXC/10];
10734167Srick char LineType[10];
10834167Srick extern int LocalOnly;
10925705Sbloom
11018619Sralph /*
11118619Sralph * place a telephone call to system and login, etc.
11213642Ssam *
11313642Ssam * return codes:
11413642Ssam * CF_SYSTEM: don't know system
11513642Ssam * CF_TIME: wrong time to call
11613642Ssam * CF_DIAL: call failed
11713642Ssam * CF_NODEV: no devices available to place call
11813642Ssam * CF_LOGIN: login/password dialog failed
11913642Ssam *
12013642Ssam * >0 - file no. - connect ok
12113642Ssam */
conn(system)12213642Ssam conn(system)
12313642Ssam char *system;
12413642Ssam {
12525705Sbloom int nf;
12618619Sralph char info[MAXC], wkpre[NAMESIZE], file[NAMESIZE];
12713642Ssam register FILE *fsys;
12813642Ssam int fcode = 0;
12913642Ssam
13013642Ssam nf = 0;
13113642Ssam
13213642Ssam fsys = fopen(SYSFILE, "r");
13333948Srick if (fsys == NULL) {
13433948Srick syslog(LOG_ERR, "fopen(%s) failed: %m", SYSFILE);
13533948Srick cleanup(FAIL);
13633948Srick }
13713642Ssam
13817834Sralph DEBUG(4, "finds (%s) called\n", system);
13925127Sbloom keeplooking:
14017834Sralph while((nf = finds(fsys, system, info, Flds)) > 0) {
14125966Sbloom strncpy(LineType, Flds[F_LINE], 10);
14217834Sralph if (LocalOnly) {
14325966Sbloom if (strcmp("TCP", LineType)
14425966Sbloom && strcmp("DIR", LineType)
14525966Sbloom && strcmp("LOCAL", LineType) ) {
14625705Sbloom fcode = CF_TIME;
14725705Sbloom continue;
14825705Sbloom }
14917834Sralph }
15023596Sbloom sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname);
15118619Sralph if (!onesys && MaxGrade != DefMaxGrade &&
15225705Sbloom !iswrk(file, "chk", Spool, wkpre)) {
15325705Sbloom fcode = CF_TIME;
15425705Sbloom continue;
15525705Sbloom }
15625705Sbloom /* For GTE's PC Pursuit */
15725966Sbloom if (snccmp(LineType, PCP) == SAME) {
15825705Sbloom FILE *dfp;
15925705Sbloom int status;
16025705Sbloom static struct Devices dev;
16133562Srick
16225705Sbloom dfp = fopen(DEVFILE, "r");
16333948Srick if (dfp == NULL) {
16433948Srick syslog(LOG_ERR, "fopen(%s) failed: %m",
16533948Srick DEVFILE);
16633948Srick cleanup(FAIL);
16733948Srick }
16825705Sbloom while ((status=rddev(dfp, &dev)) != FAIL
16925705Sbloom && strcmp(PCP, dev.D_type) != SAME)
17025705Sbloom ;
17125705Sbloom fclose(dfp);
17225705Sbloom if (status == FAIL)
17325705Sbloom continue;
17425705Sbloom if (mlock(PCP) == FAIL) {
17525705Sbloom fcode = CF_NODEV;
17625705Sbloom logent("DEVICE", "NO");
17725705Sbloom continue;
17825705Sbloom }
17925705Sbloom PCFlds[PCP_BAUD] = dev.D_class;
18025705Sbloom PCFlds[PCP_PHONE] = dev.D_calldev;
18133562Srick sprintf(PCFlds[PCP_CITY], "c d/%s%s,%s",
18233562Srick Flds[F_CLASS],
18333562Srick index(Flds[F_CLASS], '/') == NULL ? "/12" : "",
18433562Srick dev.D_arg[D_CHAT]);
18533562Srick PCFlds[PCP_PASSWORD] = dev.D_line;
18633562Srick strncpy(&PCFlds[PCP_RPHONE][4], Flds[F_PHONE], 7);
18725705Sbloom strncpy(PCP_brand, dev.D_brand, sizeof(PCP_brand));
18833562Srick if ((fcode = getto(PCFlds)) < 0) {
18933562Srick rmlock(PCP);
19025705Sbloom continue;
19133562Srick }
19225705Sbloom Dcf = fcode;
19325705Sbloom fcode = login(NPCFIELDS, PCFlds, Dcf);
19433562Srick if (fcode == SUCCESS)
19533562Srick break;
19633562Srick fcode = CF_DIAL;
19733562Srick rmlock(PCP);
19833562Srick /* end PC Pursuit */
19933562Srick } else if ((fcode = getto(Flds)) > 0) {
20033562Srick Dcf = fcode;
20113642Ssam break;
20233562Srick }
20313642Ssam }
20413642Ssam
20525127Sbloom if (nf <= 0) {
20625127Sbloom fclose(fsys);
20717834Sralph return fcode ? fcode : nf;
20825127Sbloom }
20913642Ssam
21025705Sbloom
21125705Sbloom if (fcode >= 0) {
21225705Sbloom DEBUG(4, "login %s\n", "called");
21334167Srick setproctitle("login");
21433562Srick fcode = login(nf, Flds, Dcf); }
21525705Sbloom if (fcode < 0) {
21613642Ssam clsacu();
21725705Sbloom if (fcode == ABORT) {
21825127Sbloom fcode = CF_DIAL;
21925127Sbloom goto keeplooking;
22025127Sbloom } else {
22125127Sbloom fclose(fsys);
22223596Sbloom return CF_LOGIN;
22325127Sbloom }
22413642Ssam }
22525127Sbloom fclose(fsys);
22625705Sbloom fioclex(Dcf);
22725705Sbloom return Dcf;
22813642Ssam }
22913642Ssam
23034167Srick int nulldev();
23134167Srick int (*CU_end)() = nulldev;
23234167Srick
23325127Sbloom /*
23425127Sbloom * connect to remote machine
23513642Ssam *
23613642Ssam * return codes:
23713642Ssam * >0 - file number - ok
23813642Ssam * FAIL - failed
23913642Ssam */
getto(flds)24013642Ssam getto(flds)
24113642Ssam register char *flds[];
24213642Ssam {
24313642Ssam register struct condev *cd;
24434094Sbostic int diropn();
24525127Sbloom char *line;
24613642Ssam
24717834Sralph DEBUG(4, "getto: call no. %s ", flds[F_PHONE]);
24813642Ssam DEBUG(4, "for sys %s\n", flds[F_NAME]);
24913642Ssam
25025127Sbloom if (snccmp(flds[F_LINE], "LOCAL") == SAME)
25125127Sbloom line = "ACU";
25225127Sbloom else
25325127Sbloom line = flds[F_LINE];
25425127Sbloom #ifdef DIALINOUT
25525127Sbloom if (snccmp(line, "ACU") != SAME)
25625127Sbloom reenable();
25725127Sbloom #endif DIALINOUT
25813642Ssam CU_end = nulldev;
25925705Sbloom if (snccmp(line, PCP) == SAME) {
26025705Sbloom for(cd = condevs; cd->CU_meth != NULL; cd++) {
26125705Sbloom if (snccmp(PCP_brand, cd->CU_brand) == SAME) {
26225705Sbloom CU_end = cd->CU_clos;
26325705Sbloom return diropn(flds);
26425705Sbloom }
26513642Ssam }
26625705Sbloom logent(PCP_brand, "UNSUPPORTED ACU TYPE");
26725705Sbloom } else {
26825705Sbloom for (cd = condevs; cd->CU_meth != NULL; cd++) {
26925705Sbloom if (snccmp(cd->CU_meth, line) == SAME) {
27025705Sbloom DEBUG(4, "Using %s to call\n", cd->CU_meth);
27125705Sbloom return (*(cd->CU_gen))(flds);
27225705Sbloom }
27325705Sbloom }
27425705Sbloom DEBUG(1, "Can't find %s, assuming DIR\n", flds[F_LINE]);
27513642Ssam }
27617834Sralph return diropn(flds); /* search failed, so use direct */
27717834Sralph }
27813642Ssam
27925127Sbloom /*
28025127Sbloom * close call unit
28113642Ssam *
28213642Ssam * return codes: none
28313642Ssam */
clsacu()28413642Ssam clsacu()
28513642Ssam {
28617834Sralph /* make *sure* Dcf is no longer exclusive.
28717834Sralph * Otherwise dual call-in/call-out modems could get stuck.
28817834Sralph * Unfortunately, doing this here is not ideal, but it is the
28917834Sralph * easiest place to put the call.
29017834Sralph * Hopefully everyone honors the LCK protocol, of course
29117834Sralph */
29225705Sbloom #ifdef TIOCNXCL
29323596Sbloom if (!IsTcpIp && Dcf >= 0 && ioctl(Dcf, TIOCNXCL, STBNULL) < 0)
29423596Sbloom DEBUG(5, "clsacu ioctl %s\n", sys_errlist[errno]);
29517834Sralph #endif
29617834Sralph if (setjmp(Sjbuf))
29717834Sralph logent(Rmtname, "CLOSE TIMEOUT");
29817834Sralph else {
29917834Sralph signal(SIGALRM, alarmtr);
30017834Sralph alarm(20);
30117834Sralph (*(CU_end))(Dcf);
30217834Sralph alarm(0);
30317834Sralph }
30413642Ssam if (close(Dcf) == 0) {
30513642Ssam DEBUG(4, "fd %d NOT CLOSED by CU_clos\n", Dcf);
30613642Ssam logent("clsacu", "NOT CLOSED by CU_clos");
30713642Ssam }
30813642Ssam Dcf = -1;
30913642Ssam CU_end = nulldev;
31013642Ssam }
31113642Ssam
31225127Sbloom /*
31325127Sbloom * expand phone number for given prefix and number
31413642Ssam */
exphone(in,out)31513642Ssam exphone(in, out)
31613642Ssam register char *in, *out;
31713642Ssam {
31813642Ssam FILE *fn;
31913642Ssam char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH];
32013642Ssam char buf[BUFSIZ];
32113642Ssam register char *s1;
32213642Ssam
32317834Sralph if (!isascii(*in) || !isalpha(*in)) {
32413642Ssam strcpy(out, in);
32513642Ssam return;
32613642Ssam }
32713642Ssam
32813642Ssam s1=pre;
32917834Sralph while (isascii(*in) && isalpha(*in))
33013642Ssam *s1++ = *in++;
33113642Ssam *s1 = '\0';
33213642Ssam s1 = npart;
33313642Ssam while (*in != '\0')
33413642Ssam *s1++ = *in++;
33513642Ssam *s1 = '\0';
33613642Ssam
33713642Ssam tpre[0] = '\0';
33813642Ssam if ((fn = fopen(DIALFILE, "r")) == NULL)
33913642Ssam DEBUG(2, "CAN'T OPEN %s\n", DIALFILE);
34013642Ssam else {
34113642Ssam while (cfgets(buf, BUFSIZ, fn)) {
34217834Sralph if (sscanf(buf, "%s%s", p, tpre) != 2)
34317834Sralph continue;
34413642Ssam if (strcmp(p, pre) == SAME)
34513642Ssam goto found;
34613642Ssam tpre[0] = '\0';
34713642Ssam }
34813642Ssam DEBUG(2, "CAN'T FIND dialcodes prefix '%s'\n", pre);
34913642Ssam found:;
35013642Ssam fclose(fn);
35113642Ssam }
35213642Ssam
35313642Ssam strcpy(out, tpre);
35413642Ssam strcat(out, npart);
35513642Ssam }
35613642Ssam
35718619Sralph /*
35818619Sralph * read and decode a line from device file
35913642Ssam *
36013642Ssam * return code - FAIL at end-of file; 0 otherwise
36113642Ssam */
rddev(fp,dev)36213642Ssam rddev(fp, dev)
36313642Ssam register struct Devices *dev;
36413642Ssam FILE *fp;
36513642Ssam {
36617834Sralph register int na;
36713642Ssam
36817834Sralph if (!cfgets(dev->D_argbfr, sizeof(dev->D_argbfr), fp))
36917834Sralph return FAIL;
37017834Sralph na = getargs(dev->D_argbfr, dev->D_arg, 20);
37133948Srick if (na < 4) {
37233948Srick syslog(LOG_ERR, "%s: invalid device entry", dev->D_argbfr);
37333948Srick cleanup(FAIL);
37433948Srick }
37517834Sralph if (na == 4) {
37617834Sralph dev->D_brand = "";
37717834Sralph na++;
37817834Sralph }
37913642Ssam dev->D_speed = atoi(fdig(dev->D_class));
38017834Sralph dev->D_numargs = na;
38117834Sralph return 0;
38213642Ssam }
38313642Ssam
38418619Sralph /*
38518619Sralph * set system attribute vector
38613642Ssam *
38713642Ssam * return codes:
38813642Ssam * >0 - number of arguments in vector - succeeded
38913642Ssam * CF_SYSTEM - system name not found
39013642Ssam * CF_TIME - wrong time to call
39113642Ssam */
finds(fsys,sysnam,info,flds)39213642Ssam finds(fsys, sysnam, info, flds)
39313642Ssam char *sysnam, info[], *flds[];
39413642Ssam FILE *fsys;
39513642Ssam {
39613642Ssam int na;
39713642Ssam int fcode = 0;
39813642Ssam
39913642Ssam /* format of fields
40013642Ssam * 0 name;
40113642Ssam * 1 time
40213642Ssam * 2 acu/hardwired
40313642Ssam * 3 speed
40413642Ssam * etc
40513642Ssam */
40613642Ssam while (cfgets(info, MAXC, fsys) != NULL) {
40717834Sralph na = getargs(info, flds, MAXC/10);
40823596Sbloom if (strncmp(sysnam, flds[F_NAME], MAXBASENAME) != SAME)
40913642Ssam continue;
41018619Sralph if (ifdate(flds[F_TIME]) != FAIL)
41113642Ssam /* found a good entry */
41217834Sralph return na;
41313642Ssam DEBUG(2, "Wrong time ('%s') to call\n", flds[F_TIME]);
41413642Ssam fcode = CF_TIME;
41513642Ssam }
41617834Sralph return fcode ? fcode : CF_SYSTEM;
41713642Ssam }
41813642Ssam
41918619Sralph /*
42018619Sralph * do login conversation
42113642Ssam *
42223596Sbloom * return codes: SUCCESS | FAIL
42313642Ssam */
login(nf,flds,fn)42413642Ssam login(nf, flds, fn)
42513642Ssam register char *flds[];
42613642Ssam int nf, fn;
42713642Ssam {
42813642Ssam register char *want, *altern;
42913642Ssam int k, ok;
43013642Ssam
43133948Srick if (nf < 4) {
43233948Srick syslog(LOG_ERR, "Too few log fields: %d", nf);
43333948Srick cleanup(FAIL);
43433948Srick }
43517834Sralph if (setjmp(Cjbuf))
43617834Sralph return FAIL;
43717834Sralph AbortOn = NULL;
43813642Ssam for (k = F_LOGIN; k < nf; k += 2) {
43913642Ssam want = flds[k];
44033562Srick if (want == NULL)
44133562Srick want = "";
44213642Ssam ok = FAIL;
44317834Sralph while (ok != SUCCESS) {
44413642Ssam altern = index(want, '-');
44513642Ssam if (altern != NULL)
44613642Ssam *altern++ = '\0';
44717834Sralph if (strcmp(want, "ABORT") == 0) {
44817834Sralph AbortOn = flds[k+1];
44917834Sralph DEBUG(4, "ABORT ON: %s\n", AbortOn);
45017834Sralph goto nextfield;
45117834Sralph }
45225705Sbloom DEBUG(4, "wanted \"%s\"\n", want);
45313642Ssam ok = expect(want, fn);
45417834Sralph DEBUG(4, "got: %s\n", ok ? "?" : "that");
45517834Sralph if (ok == FAIL) {
45617834Sralph if (altern == NULL) {
45717834Sralph logent("LOGIN", _FAILED);
45817834Sralph return FAIL;
45917834Sralph }
46017834Sralph want = index(altern, '-');
46117834Sralph if (want != NULL)
46217834Sralph *want++ = '\0';
46317834Sralph sendthem(altern, fn);
46417834Sralph } else
46517834Sralph if (ok == ABORT) {
46633562Srick char sbuf[MAXFULLNAME];
46733562Srick sprintf(sbuf, "LOGIN ABORTED on \"%s\"", AbortOn);
46833562Srick logent(sbuf, _FAILED);
46923596Sbloom return ABORT;
47017834Sralph }
47113642Ssam }
47217834Sralph sleep(1);
47313642Ssam if (k+1 < nf)
47413642Ssam sendthem(flds[k+1], fn);
47517834Sralph nextfield: ;
47613642Ssam }
47717834Sralph return SUCCESS;
47813642Ssam }
47913642Ssam
48013642Ssam
48117834Sralph /* conditional table generation to support odd speeds */
48213642Ssam struct sg_spds {int sp_val, sp_name;} spds[] = {
48313642Ssam #ifdef B50
48413642Ssam { 50, B50},
48513642Ssam #endif
48613642Ssam #ifdef B75
48713642Ssam { 75, B75},
48813642Ssam #endif
48913642Ssam #ifdef B110
49013642Ssam { 110, B110},
49113642Ssam #endif
49213642Ssam #ifdef B150
49313642Ssam { 150, B150},
49413642Ssam #endif
49513642Ssam #ifdef B200
49613642Ssam { 200, B200},
49713642Ssam #endif
49813642Ssam #ifdef B300
49913642Ssam { 300, B300},
50013642Ssam #endif
50113642Ssam #ifdef B600
50213642Ssam {600, B600},
50313642Ssam #endif
50413642Ssam #ifdef B1200
50513642Ssam {1200, B1200},
50613642Ssam #endif
50713642Ssam #ifdef B1800
50813642Ssam {1800, B1800},
50913642Ssam #endif
51013642Ssam #ifdef B2000
51113642Ssam {2000, B2000},
51213642Ssam #endif
51313642Ssam #ifdef B2400
51413642Ssam {2400, B2400},
51513642Ssam #endif
51613642Ssam #ifdef B3600
51713642Ssam {3600, B3600},
51813642Ssam #endif
51913642Ssam #ifdef B4800
52013642Ssam {4800, B4800},
52113642Ssam #endif
52213642Ssam #ifdef B7200
52313642Ssam {7200, B7200},
52413642Ssam #endif
52513642Ssam #ifdef B9600
52613642Ssam {9600, B9600},
52713642Ssam #endif
52813642Ssam #ifdef B19200
52917834Sralph {19200, B19200},
53013642Ssam #endif
53117834Sralph #ifdef EXTA
53217834Sralph {19200, EXTA},
53317834Sralph #endif
53413642Ssam {0, 0}
53513642Ssam };
53613642Ssam
53718619Sralph /*
53818619Sralph * set speed/echo/mode...
53913642Ssam *
54013642Ssam * return codes: none
54113642Ssam */
fixline(tty,spwant)54213642Ssam fixline(tty, spwant)
54313642Ssam int tty, spwant;
54413642Ssam {
54517834Sralph #ifdef USG
54613642Ssam struct termio ttbuf;
54717834Sralph #else !USG
54813642Ssam struct sgttyb ttbuf;
54917834Sralph #endif !USG
55013642Ssam register struct sg_spds *ps;
55113642Ssam int speed = -1;
55213642Ssam
55313642Ssam for (ps = spds; ps->sp_val; ps++)
55413642Ssam if (ps->sp_val == spwant)
55513642Ssam speed = ps->sp_name;
55633948Srick if (speed < 0) {
55733948Srick syslog(LOG_ERR, "unrecognized speed: %d", speed);
55833948Srick cleanup(FAIL);
55933948Srick }
56017834Sralph #ifdef USG
56123596Sbloom if (ioctl(tty, TCGETA, &ttbuf) < 0)
56223596Sbloom return FAIL;
56313642Ssam /* ttbuf.sg_flags = (ANYP|RAW);
56413642Ssam ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; */
56513642Ssam ttbuf.c_iflag = (ushort)0;
56613642Ssam ttbuf.c_oflag = (ushort)0;
56713642Ssam ttbuf.c_cflag = (speed|CS8|HUPCL|CREAD);
56813642Ssam ttbuf.c_lflag = (ushort)0;
56913642Ssam ttbuf.c_cc[VMIN] = 6;
57013642Ssam ttbuf.c_cc[VTIME] = 1;
57123596Sbloom if (ioctl(tty, TCSETA, &ttbuf) < 0)
57223596Sbloom return FAIL;
57317834Sralph #else !USG
57423596Sbloom if (ioctl(tty, TIOCGETP, &ttbuf) < 0)
57523596Sbloom return FAIL;
57613642Ssam ttbuf.sg_flags = (ANYP|RAW);
57713642Ssam ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed;
57823596Sbloom if (ioctl(tty, TIOCSETP, &ttbuf) < 0)
57923596Sbloom return FAIL;
58013642Ssam #endif
58117834Sralph #ifndef USG
58223596Sbloom if (ioctl(tty, TIOCHPCL, STBNULL) < 0)
58323596Sbloom return FAIL;
58423596Sbloom if (ioctl(tty, TIOCEXCL, STBNULL) < 0)
58523596Sbloom return FAIL;
58613642Ssam #endif
58717834Sralph linebaudrate = spwant;
58823596Sbloom return SUCCESS;
58913642Ssam }
59013642Ssam
59117834Sralph #define MR 100
59213642Ssam
59318619Sralph /*
59418619Sralph * look for expected string
59513642Ssam *
59613642Ssam * return codes:
59713642Ssam * 0 - found
59813642Ssam * FAIL - lost line or too many characters read
59913642Ssam * some character - timed out
60013642Ssam */
expect(str,fn)60113642Ssam expect(str, fn)
60213642Ssam register char *str;
60313642Ssam int fn;
60413642Ssam {
60514592Skarels char rdvec[MR];
60617834Sralph register char *rp = rdvec, *strptr;
60717834Sralph int kr, cnt_char;
60813642Ssam char nextch;
60925127Sbloom int timo = MAXMSGTIME;
61013642Ssam
61117834Sralph if (*str == '\0' || strcmp(str, "\"\"") == SAME)
61217834Sralph return SUCCESS;
61317834Sralph /* Cleanup str, convert \0xx strings to one char */
61417834Sralph for (strptr = str; *strptr; strptr++) {
61517834Sralph if (*strptr == '\\')
61617834Sralph switch(*++strptr) {
61717834Sralph case 's':
61817834Sralph DEBUG(5, "BLANK\n", CNULL);
61934167Srick strptr--;
62017834Sralph *strptr = ' ';
62134167Srick strcpy(&strptr[1], &strptr[4]);
62217834Sralph break;
62317834Sralph default:
62417834Sralph strptr--; /* back up to backslash */
62517834Sralph sscanf(strptr + 1,"%o", &cnt_char);
62617834Sralph DEBUG(6, "BACKSLASHED %02xH\n", cnt_char);
62717834Sralph *strptr = (char) (cnt_char);
62817834Sralph strcpy(&strptr[1], &strptr[4]);
62917834Sralph }
63017834Sralph }
63117834Sralph
63225127Sbloom strptr = index(str, '~');
63325127Sbloom if (strptr != NULL) {
63425127Sbloom *strptr++ = '\0';
63525127Sbloom timo = atoi(strptr);
63625127Sbloom if (timo <= 0)
63725127Sbloom timo = MAXMSGTIME;
63825127Sbloom }
63925127Sbloom
64017834Sralph if (setjmp(Sjbuf))
64117834Sralph return FAIL;
64213642Ssam signal(SIGALRM, alarmtr);
64325127Sbloom alarm(timo);
64425127Sbloom *rp = 0;
64513642Ssam while (notin(str, rdvec)) {
64625705Sbloom int c;
64717834Sralph if(AbortOn != NULL && !notin(AbortOn, rdvec)) {
64817834Sralph DEBUG(1, "Call aborted on '%s'\n", AbortOn);
64917834Sralph alarm(0);
65017834Sralph return ABORT;
65117834Sralph }
65213642Ssam kr = read(fn, &nextch, 1);
65313642Ssam if (kr <= 0) {
65413642Ssam alarm(0);
65513642Ssam DEBUG(4, "lost line kr - %d\n, ", kr);
65613642Ssam logent("LOGIN", "LOST LINE");
65717834Sralph return FAIL;
65813642Ssam }
65913642Ssam c = nextch & 0177;
66025705Sbloom if (c == '\0')
66125705Sbloom continue;
66225705Sbloom DEBUG(4, (isprint(c) || isspace(c)) ? "%c" : "\\%03o", c);
66325705Sbloom *rp++ = c;
66413642Ssam if (rp >= rdvec + MR) {
66517834Sralph register char *p;
66617834Sralph for (p = rdvec+MR/2; p < rp; p++)
66717834Sralph *(p-MR/2) = *p;
66817834Sralph rp -= MR/2;
66913642Ssam }
67013642Ssam *rp = '\0';
67113642Ssam }
67213642Ssam alarm(0);
67317834Sralph return SUCCESS;
67413642Ssam }
67513642Ssam
67613642Ssam
67713642Ssam /*
67813642Ssam * Determine next file descriptor that would be allocated.
67913642Ssam * This permits later closing of a file whose open was interrupted.
68013642Ssam * It is a UNIX kernel problem, but it has to be handled.
68113642Ssam * unc!smb (Steve Bellovin) probably first discovered it.
68213642Ssam */
getnextfd()68313642Ssam getnextfd()
68413642Ssam {
68513642Ssam close(next_fd = open("/", 0));
68613642Ssam }
68713642Ssam
68817834Sralph /*
68917834Sralph * send line of login sequence
69013642Ssam *
69113642Ssam * return codes: none
69213642Ssam */
sendthem(str,fn)69313642Ssam sendthem(str, fn)
69413642Ssam register char *str;
69513642Ssam int fn;
69613642Ssam {
69713642Ssam register char *strptr;
69813642Ssam int i, n, cr = 1;
69917834Sralph register char c;
70013642Ssam static int p_init = 0;
70113642Ssam
70225705Sbloom DEBUG(5, "send \"%s\"\n", str);
70313642Ssam
70413642Ssam if (!p_init) {
70513642Ssam p_init++;
70633948Srick bld_partab(P_ZERO);
70713642Ssam }
70813642Ssam
70913642Ssam if (prefix("BREAK", str)) {
71013642Ssam sscanf(&str[5], "%1d", &i);
71113642Ssam if (i <= 0 || i > 10)
71213642Ssam i = 3;
71313642Ssam /* send break */
71413642Ssam genbrk(fn, i);
71513642Ssam return;
71613642Ssam }
71713642Ssam
71813642Ssam if (prefix("PAUSE", str)) {
71913642Ssam sscanf(&str[5], "%1d", &i);
72013642Ssam if (i <= 0 || i > 10)
72113642Ssam i = 3;
72213642Ssam /* pause for a while */
72313642Ssam sleep((unsigned)i);
72413642Ssam return;
72513642Ssam }
72613642Ssam
72713642Ssam if (strcmp(str, "EOT") == SAME) {
72813642Ssam p_chwrite(fn, '\04');
72913642Ssam return;
73013642Ssam }
73113642Ssam
73213642Ssam /* Send a '\n' */
73325705Sbloom if (strcmp(str, "LF") == SAME) {
73425705Sbloom p_chwrite(fn, '\n');
73525705Sbloom return;
73625705Sbloom }
73713642Ssam
73813642Ssam /* Send a '\r' */
73925705Sbloom if (strcmp(str, "CR") == SAME) {
74025705Sbloom p_chwrite(fn, '\r');
74125705Sbloom return;
74225705Sbloom }
74313642Ssam
74413642Ssam /* Set parity as needed */
74513642Ssam if (strcmp(str, "P_ZERO") == SAME) {
74613642Ssam bld_partab(P_ZERO);
74713642Ssam return;
74813642Ssam }
74913642Ssam if (strcmp(str, "P_ONE") == SAME) {
75013642Ssam bld_partab(P_ONE);
75113642Ssam return;
75213642Ssam }
75313642Ssam if (strcmp(str, "P_EVEN") == SAME) {
75413642Ssam bld_partab(P_EVEN);
75513642Ssam return;
75613642Ssam }
75713642Ssam if (strcmp(str, "P_ODD") == SAME) {
75813642Ssam bld_partab(P_ODD);
75913642Ssam return;
76013642Ssam }
76113642Ssam
76213642Ssam /* If "", just send '\r' */
76317834Sralph if (strcmp(str, "\"\"") == SAME) {
76417834Sralph p_chwrite(fn, '\r');
76517834Sralph return;
76617834Sralph }
76717834Sralph
76825705Sbloom strptr = str;
76925705Sbloom while ((c = *strptr++) != '\0') {
77017834Sralph if (c == '\\') {
77117834Sralph switch(*strptr++) {
77225705Sbloom case '\0':
77325705Sbloom DEBUG(5, "TRAILING BACKSLASH IGNORED\n", CNULL);
77425705Sbloom --strptr;
77525705Sbloom continue;
77617834Sralph case 's':
77717834Sralph DEBUG(5, "BLANK\n", CNULL);
77825705Sbloom c = ' ';
77917834Sralph break;
78017834Sralph case 'd':
78117834Sralph DEBUG(5, "DELAY\n", CNULL);
78217834Sralph sleep(1);
78317834Sralph continue;
78425705Sbloom case 'n':
78525705Sbloom DEBUG(5, "NEW LINE\n", CNULL);
78625705Sbloom c = '\n';
78725705Sbloom break;
78817834Sralph case 'r':
78917834Sralph DEBUG(5, "RETURN\n", CNULL);
79025705Sbloom c = '\r';
79117834Sralph break;
79217834Sralph case 'b':
79317834Sralph if (isdigit(*strptr)) {
79417834Sralph i = (*strptr++ - '0');
79517834Sralph if (i <= 0 || i > 10)
79617834Sralph i = 3;
79717834Sralph } else
79813642Ssam i = 3;
79917834Sralph /* send break */
80017834Sralph genbrk(fn, i);
80117834Sralph if (*strptr == '\0')
80217834Sralph cr = 0;
80313642Ssam continue;
80417834Sralph case 'c':
80517834Sralph if (*strptr == '\0') {
80617834Sralph DEBUG(5, "NO CR\n", CNULL);
80717834Sralph cr = 0;
80825705Sbloom } else
80925705Sbloom DEBUG(5, "NO CR - IGNORED NOT EOL\n", CNULL);
81013642Ssam continue;
81125705Sbloom #define isoctal(x) ((x >= '0') && (x <= '7'))
81217834Sralph default:
81325705Sbloom if (isoctal(strptr[-1])) {
81417834Sralph i = 0;
81517834Sralph n = 0;
81625705Sbloom --strptr;
81725705Sbloom while (isoctal(*strptr) && ++n <= 3)
81825705Sbloom i = i * 8 + (*strptr++ - '0');
81925705Sbloom DEBUG(5, "\\%o\n", i);
82017834Sralph p_chwrite(fn, (char)i);
82117834Sralph continue;
82217834Sralph }
82313642Ssam }
82425705Sbloom }
82525705Sbloom p_chwrite(fn, c);
82613642Ssam }
82713642Ssam
82813642Ssam if (cr)
82913642Ssam p_chwrite(fn, '\r');
83013642Ssam return;
83113642Ssam }
83213642Ssam
p_chwrite(fd,c)83313642Ssam p_chwrite(fd, c)
83413642Ssam int fd;
83517834Sralph char c;
83613642Ssam {
83717834Sralph c = par_tab[c&0177];
83817834Sralph if (write(fd, &c, 1) != 1) {
83917834Sralph logent(sys_errlist[errno], "BAD WRITE");
84017834Sralph longjmp(Cjbuf, 2);
84117834Sralph }
84213642Ssam }
84313642Ssam
84413642Ssam /*
84513642Ssam * generate parity table for use by p_chwrite.
84613642Ssam */
bld_partab(type)84713642Ssam bld_partab(type)
84813642Ssam int type;
84913642Ssam {
85013642Ssam register int i, j, n;
85113642Ssam
85213642Ssam for (i = 0; i < sizeof(par_tab); i++) {
85313642Ssam n = 0;
85413642Ssam for (j = i&(sizeof(par_tab)-1); j; j = (j-1)&j)
85513642Ssam n++;
85613642Ssam par_tab[i] = i;
85713642Ssam if (type == P_ONE
85813642Ssam || (type == P_EVEN && (n&01) != 0)
85913642Ssam || (type == P_ODD && (n&01) == 0))
86013642Ssam par_tab[i] |= sizeof(par_tab);
86113642Ssam }
86213642Ssam }
86313642Ssam
86418619Sralph /*
86518619Sralph * check for occurrence of substring "sh"
86613642Ssam *
86713642Ssam * return codes:
86813642Ssam * 0 - found the string
86913642Ssam * 1 - not in the string
87013642Ssam */
notin(sh,lg)87113642Ssam notin(sh, lg)
87213642Ssam register char *sh, *lg;
87313642Ssam {
87413642Ssam while (*lg != '\0') {
87513642Ssam if (wprefix(sh, lg))
87618619Sralph return 0;
87713642Ssam else
87813642Ssam lg++;
87913642Ssam }
88018619Sralph return 1;
88113642Ssam }
88213642Ssam
88318619Sralph /*
88423596Sbloom * Allow multiple date specifications separated by ','.
88513642Ssam */
ifdate(p)88618619Sralph ifdate(p)
88718619Sralph register char *p;
88813642Ssam {
88925705Sbloom register char *np;
89018619Sralph register int ret, g;
89123596Sbloom int rtime, i;
89213642Ssam
89323596Sbloom /* pick up retry time for failures */
89423596Sbloom /* global variable Retrytime is set here */
89523596Sbloom if ((np = index(p, ';')) == NULL) {
89623596Sbloom Retrytime = RETRYTIME;
89723596Sbloom } else {
89823596Sbloom i = sscanf(np+1, "%d", &rtime);
89923596Sbloom if (i < 1 || rtime < 0)
90023596Sbloom rtime = 5;
90123596Sbloom Retrytime = rtime * 60;
90223596Sbloom }
90323596Sbloom
90418619Sralph ret = FAIL;
90518619Sralph MaxGrade = '\0';
90618619Sralph do {
90723596Sbloom np = strpbrk(p, ",|"); /* prefer , but allow | for compat */
90823596Sbloom if (np)
90923596Sbloom *np = '\0';
91018619Sralph g = ifadate(p);
91118619Sralph DEBUG(11,"ifadate returns %o\n", g);
91218619Sralph if (g != FAIL) {
91318619Sralph ret = SUCCESS;
91418619Sralph if (g > MaxGrade)
91518619Sralph MaxGrade = g;
91618619Sralph }
91723596Sbloom if (np)
91823596Sbloom *np = ',';
91923596Sbloom p = np + 1;
92023596Sbloom } while (np);
92123596Sbloom if (MaxGrade == '\0')
92223596Sbloom MaxGrade = DefMaxGrade;
92318619Sralph return ret;
92413642Ssam }
92513642Ssam
92618619Sralph /*
92718619Sralph * this routine will check a string (string)
92813642Ssam * like "MoTu0800-1730" to see if the present
92913642Ssam * time is within the given limits.
93013642Ssam * SIDE EFFECT - Retrytime is set
93113642Ssam *
93213642Ssam * return codes:
93313642Ssam * 0 - not within limits
93413642Ssam * 1 - within limits
93513642Ssam */
93613642Ssam
ifadate(string)93718619Sralph ifadate(string)
93818619Sralph char *string;
93913642Ssam {
94013642Ssam static char *days[]={
94113642Ssam "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0
94213642Ssam };
94313642Ssam time_t clock;
94418619Sralph register char *s = string;
94517834Sralph int i, tl, th, tn, dayok=0;
94613642Ssam struct tm *localtime();
94713642Ssam struct tm *tp;
94818619Sralph char *p, MGrade;
94913642Ssam
95023596Sbloom if ((p = index(s, '/')) == NULL)
95118619Sralph MGrade = DefMaxGrade;
95218619Sralph else
95318619Sralph MGrade = p[1];
95418619Sralph
95513642Ssam time(&clock);
95613642Ssam tp = localtime(&clock);
95717834Sralph while (isascii(*s) && isalpha(*s)) {
95813642Ssam for (i = 0; days[i]; i++) {
95913642Ssam if (prefix(days[i], s))
96013642Ssam if (tp->tm_wday == i)
96113642Ssam dayok = 1;
96213642Ssam }
96313642Ssam
96413642Ssam if (prefix("Wk", s))
96513642Ssam if (tp->tm_wday >= 1 && tp->tm_wday <= 5)
96613642Ssam dayok = 1;
96713642Ssam if (prefix("Any", s))
96813642Ssam dayok = 1;
96917834Sralph if (prefix("Evening", s)) {
97017834Sralph /* Sat or Sun */
97117834Sralph if (tp->tm_wday == 6 || tp->tm_wday == 0
97217834Sralph || tp->tm_hour >= 17 || tp->tm_hour < 8)
97317834Sralph dayok = 1;
97417834Sralph }
97517834Sralph if (prefix("Night", s)) {
97617834Sralph if (tp->tm_wday == 6 /* Sat */
97718619Sralph || tp->tm_hour >= 23 || tp->tm_hour < 8
97818619Sralph /* Sunday before 5pm */
97918619Sralph || (tp->tm_wday == 0 && tp->tm_hour < 17))
98017834Sralph dayok = 1;
98117834Sralph }
98225705Sbloom if (prefix("NonPeak", s)) { /* For Tymnet and PC Pursuit */
98325705Sbloom /* Sat or Sun */
98425705Sbloom if (tp->tm_wday == 6 || tp->tm_wday == 0
98525705Sbloom || tp->tm_hour >= 18 || tp->tm_hour < 7)
98625705Sbloom dayok = 1;
98725705Sbloom }
98813642Ssam s++;
98913642Ssam }
99013642Ssam
99118619Sralph if (dayok == 0 && s != string)
99218619Sralph return FAIL;
99313642Ssam i = sscanf(s, "%d-%d", &tl, &th);
99418619Sralph if (i < 2)
99518619Sralph return MGrade;
99618619Sralph tn = tp->tm_hour * 100 + tp->tm_min;
99718619Sralph if (th < tl) { /* crosses midnight */
99818619Sralph if (tl <= tn || tn < th)
99918619Sralph return MGrade;
100025966Sbloom } else {
100117834Sralph if (tl <= tn && tn < th)
100218619Sralph return MGrade;
100325966Sbloom }
100418619Sralph return FAIL;
100513642Ssam }
100613642Ssam
100718619Sralph /*
100818619Sralph * find first digit in string
100913642Ssam *
101013642Ssam * return - pointer to first digit in string or end of string
101113642Ssam */
101213642Ssam char *
fdig(cp)101313642Ssam fdig(cp)
101413642Ssam register char *cp;
101513642Ssam {
101613642Ssam register char *c;
101713642Ssam
101813642Ssam for (c = cp; *c; c++)
101913642Ssam if (*c >= '0' && *c <= '9')
102013642Ssam break;
102117834Sralph return c;
102213642Ssam }
102313642Ssam
102413642Ssam /*
102513642Ssam * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0
102613642Ssam * Strings are compared as if they contain all capital letters.
102713642Ssam */
snccmp(s1,s2)102813642Ssam snccmp(s1, s2)
102913642Ssam register char *s1, *s2;
103013642Ssam {
103113642Ssam char c1, c2;
103213642Ssam
103325127Sbloom if (islower(*s1))
103425127Sbloom c1 = toupper(*s1);
103525127Sbloom else
103625127Sbloom c1 = *s1;
103725127Sbloom if (islower(*s2))
103825127Sbloom c2 = toupper(*s2);
103925127Sbloom else
104025127Sbloom c2 = *s2;
104113642Ssam
104213642Ssam while (c1 == c2) {
104325127Sbloom if (*s1++ == '\0')
104417834Sralph return 0;
104513642Ssam s2++;
104625127Sbloom if (islower(*s1))
104725127Sbloom c1 = toupper(*s1);
104825127Sbloom else
104925127Sbloom c1 = *s1;
105025127Sbloom if (islower(*s2))
105125127Sbloom c2 = toupper(*s2);
105225127Sbloom else
105325127Sbloom c2 = *s2;
105413642Ssam }
105517834Sralph return c1 - c2;
105613642Ssam }
105725127Sbloom
105817834Sralph /*
105925127Sbloom * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0
106025127Sbloom * Strings are compared as if they contain all capital letters.
106125127Sbloom */
sncncmp(s1,s2,n)106225127Sbloom sncncmp(s1, s2, n)
106325127Sbloom register char *s1, *s2;
106425127Sbloom register int n;
106525127Sbloom {
106625127Sbloom char c1, c2;
106725127Sbloom
106825127Sbloom if (islower(*s1))
106925127Sbloom c1 = toupper(*s1);
107025127Sbloom else
107125127Sbloom c1 = *s1;
107225127Sbloom if (islower(*s2))
107325127Sbloom c2 = toupper(*s2);
107425127Sbloom else
107525127Sbloom c2 = *s2;
107625127Sbloom
107725127Sbloom while ( --n >= 0 && c1 == c2) {
107825127Sbloom if (*s1++ == '\0')
107925127Sbloom return 0;
108025127Sbloom s2++;
108125127Sbloom if (islower(*s1))
108225127Sbloom c1 = toupper(*s1);
108325127Sbloom else
108425127Sbloom c1 = *s1;
108525127Sbloom if (islower(*s2))
108625127Sbloom c2 = toupper(*s2);
108725127Sbloom else
108825127Sbloom c2 = *s2;
108925127Sbloom }
109025127Sbloom return n<0 ? 0 : (c1 - c2);
109125127Sbloom }
109225127Sbloom /*
109317834Sralph * do chat script
109417834Sralph * occurs after local port is opened,
109517834Sralph * before 'dialing' the other machine.
109617834Sralph */
dochat(dev,flds,fd)109717834Sralph dochat(dev, flds, fd)
109817834Sralph register struct Devices *dev;
109917834Sralph char *flds[];
110017834Sralph int fd;
110117834Sralph {
110217834Sralph register int i;
110317834Sralph register char *p;
110417834Sralph char bfr[sizeof(dev->D_argbfr)];
110517834Sralph
110617834Sralph if (dev->D_numargs <= 5)
110717834Sralph return(0);
110817834Sralph DEBUG(4, "dochat called %d\n", dev->D_numargs);
110917834Sralph for (i = 0; i < dev->D_numargs-5; i++) {
111017834Sralph sprintf(bfr, dev->D_arg[D_CHAT+i], flds[F_PHONE]);
111117834Sralph if (strcmp(bfr, dev->D_arg[D_CHAT+i])) {
111217834Sralph p = malloc((unsigned)strlen(bfr)+1);
111317834Sralph if (p != NULL) {
111417834Sralph strcpy(p, bfr);
111517834Sralph dev->D_arg[D_CHAT+i] = p;
111617834Sralph }
111717834Sralph }
111817834Sralph }
111917834Sralph /* following is a kludge because login() arglist is a kludge */
112017834Sralph i = login(dev->D_numargs, &dev->D_arg[D_CHAT-5], fd);
112117834Sralph /*
112217834Sralph * If login() last did a sendthem(), must pause so things can settle.
112317834Sralph * But don't bother if chat failed.
112417834Sralph */
112517834Sralph if (i == 0 && (dev->D_numargs&01))
112617834Sralph sleep(2);
112717834Sralph return(i);
112817834Sralph }
112925705Sbloom
113025705Sbloom /*
113125705Sbloom * fix kill/echo/raw on line
113225705Sbloom *
113325705Sbloom * return codes: none
113425705Sbloom */
fixmode(tty)113525705Sbloom fixmode(tty)
113625705Sbloom register int tty;
113725705Sbloom {
113825705Sbloom #ifdef USG
113925705Sbloom struct termio ttbuf;
114025705Sbloom #else !USG
114125705Sbloom struct sgttyb ttbuf;
114225705Sbloom #endif !USG
114325705Sbloom register struct sg_spds *ps;
114425705Sbloom int speed;
114525705Sbloom
114625705Sbloom if (IsTcpIp)
114725705Sbloom return;
114825705Sbloom #ifdef USG
114925705Sbloom ioctl(tty, TCGETA, &ttbuf);
115025705Sbloom ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0;
115125705Sbloom speed = ttbuf.c_cflag &= (CBAUD);
115225705Sbloom ttbuf.c_cflag |= (CS8|CREAD);
115325705Sbloom ttbuf.c_cc[VMIN] = 6;
115425705Sbloom ttbuf.c_cc[VTIME] = 1;
115525705Sbloom ioctl(tty, TCSETA, &ttbuf);
115625705Sbloom #else !USG
115725705Sbloom ioctl(tty, TIOCGETP, &ttbuf);
115825705Sbloom ttbuf.sg_flags = (ANYP | RAW);
115925705Sbloom ioctl(tty, TIOCSETP, &ttbuf);
116025705Sbloom speed = ttbuf.sg_ispeed;
116125705Sbloom ioctl(tty, TIOCEXCL, STBNULL);
116225705Sbloom #endif !USG
116325705Sbloom
116425705Sbloom for (ps = spds; ps->sp_val; ps++)
116525705Sbloom if (ps->sp_name == speed) {
116625705Sbloom linebaudrate = ps->sp_val;
116725705Sbloom DEBUG(9,"Incoming baudrate is %d\n", linebaudrate);
116825705Sbloom return;
116925705Sbloom }
117033948Srick if (linebaudrate < 0) {
117133948Srick syslog(LOG_ERR, "unrecognized speed: %d", linebaudrate);
117233948Srick cleanup(FAIL);
117333948Srick }
117425705Sbloom }
1175