1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29 #include "uucp.h"
30
31 #if defined(BSD4_2) || defined(ATTSVR4)
32 #include <netdb.h>
33 #include <netinet/in.h>
34 #include <sys/socket.h>
35 #endif
36 #ifdef UNET
37 #include "UNET/unetio.h"
38 #include "UNET/tcp.h"
39 #endif
40
41 #include <libgen.h>
42
43 EXTERN void alarmtr();
44 EXTERN jmp_buf Sjbuf;
45 EXTERN char *fdig();
46 EXTERN int interface();
47 EXTERN int fd_mklock(), fd_cklock(), chat(), getdialline();
48 EXTERN void fixline(), fd_rmlock();
49 static void translate();
50 static int gdial();
51 EXTERN int Modemctrl;
52 EXTERN unsigned connecttime;
53 EXTERN int (*Setup)();
54
55 /*
56 * to add a new caller:
57 * declare the function that knows how to call on the device,
58 * add a line to the callers table giving the name of the device
59 * (from Devices file) and the name of the function
60 * add the function to the end of this file
61 */
62
63 #ifdef DIAL801
64 EXTERN int dial801();
65 EXTERN int open801();
66 #endif
67
68 #ifdef DATAKIT
69 EXTERN int dkcall();
70 #endif /* DATAKIT */
71
72 #ifdef V8
73 int Dialout();
74 #endif
75
76 #ifdef TCP
77 int unetcall();
78 int tcpcall();
79 #endif /* TCP */
80
81 #ifdef SYTEK
82 int sytcall();
83 #endif /* SYTEK */
84
85 #ifdef TLI
86 EXTERN int tlicall();
87 #endif /* TLI */
88
89 static struct caller Caller[] = {
90
91 #ifdef DIAL801
92 {"801", dial801},
93 {"212", dial801},
94 #endif /* DIAL801 */
95
96 #ifdef V8
97 {"Dialout", Dialout}, /* ditto but using dialout(III) */
98 #endif
99
100 #ifdef TCP
101 #if defined(BSD4_2) || defined(ATTSVR4)
102 {"TCP", tcpcall}, /* 4.2BSD sockets */
103 #else /* !BSD4_2 */
104 #ifdef UNET
105 {"TCP", unetcall}, /* 3com implementation of tcp */
106 {"Unetserver", unetcall},
107 #endif /* UNET */
108 #endif /* BSD4_2 || ATTSVR4 */
109 #endif /* TCP */
110
111 #ifdef DATAKIT
112 {"DK", dkcall}, /* standard AT&T DATAKIT VCS caller */
113 #endif /* DATAKIT */
114
115 #ifdef SYTEK
116 {"Sytek", sytcall}, /* untested but should work */
117 #endif /* SYTEK */
118
119 #ifdef TLI
120 {"TLI", tlicall}, /* AT&T Transport Layer Interface */
121 #ifdef TLIS
122 {"TLIS", tlicall}, /* AT&T Transport Layer Interface */
123 #endif /* TLIS */
124 #endif /* TLI */
125
126 {NULL, NULL} /* this line must be last */
127 };
128
129 /*
130 * exphone - expand phone number for given prefix and number
131 *
132 * return code - none
133 */
134
135 static void
exphone(in,out)136 exphone(in, out)
137 char *in, *out;
138 {
139 FILE *fn;
140 char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH];
141 char buf[BUFSIZ];
142 char *s1;
143
144 if (!isalpha(*in)) {
145 (void) strcpy(out, in);
146 return;
147 }
148
149 s1=pre;
150 while (isalpha(*in))
151 *s1++ = *in++;
152 *s1 = NULLCHAR;
153 s1 = npart;
154 while (*in != NULLCHAR)
155 *s1++ = *in++;
156 *s1 = NULLCHAR;
157
158 tpre[0] = NULLCHAR;
159 fn = fopen(DIALCODES, "r");
160 if (fn != NULL) {
161 while (fgets(buf, BUFSIZ, fn)) {
162 if ( sscanf(buf, "%s%s", p, tpre) < 1)
163 continue;
164 if (EQUALS(p, pre))
165 break;
166 tpre[0] = NULLCHAR;
167 }
168 fclose(fn);
169 }
170
171 (void) strcpy(out, tpre);
172 (void) strcat(out, npart);
173 return;
174 }
175
176 /*
177 * repphone - Replace \D and \T sequences in arg with phone
178 * expanding and translating as appropriate.
179 */
180 static char *
repphone(arg,phone,trstr)181 repphone(arg, phone, trstr)
182 char *arg, *phone, *trstr;
183 {
184 static char pbuf[2*(MAXPH+2)];
185 char *fp, *tp;
186
187 for (tp=pbuf; *arg; arg++) {
188 if (*arg != '\\') {
189 *tp++ = *arg;
190 continue;
191 } else {
192 switch (*(arg+1)) {
193 case 'T':
194 exphone(phone, tp);
195 translate(trstr, tp);
196 for(; *tp; tp++)
197 ;
198 arg++;
199 break;
200 case 'D':
201 for(fp=phone; *tp = *fp++; tp++)
202 ;
203 arg++;
204 break;
205 default:
206 *tp++ = *arg;
207 break;
208 }
209 }
210 }
211 *tp = '\0';
212 return(pbuf);
213 }
214
215 static u_int saved_mode;
216 static char saved_dcname[20];
217
218 /*
219 * processdev - Process a line from the Devices file
220 *
221 * return codes:
222 * file descriptor - succeeded
223 * FAIL - failed
224 */
225 GLOBAL int
processdev(flds,dev)226 processdev(flds, dev)
227 char *flds[], *dev[];
228 {
229 int dcf = -1;
230 struct caller *ca;
231 char *args[D_MAX+1], dcname[20];
232 char **sdev;
233 EXTERN int pop_push();
234 EXTERN void setdevcfg();
235 int nullfd;
236 char *phonecl; /* clear phone string */
237 char phoneex[2*(MAXPH+2)]; /* expanded phone string */
238 EXTERN void ttygenbrk();
239 struct termio tty_orig;
240 int ret_orig = -1;
241
242 sdev = dev;
243 /* set up default "break" routine */
244 genbrk = ttygenbrk;
245
246 /* initialize Devconfig info */
247 DEBUG(5, "processdev: calling setdevcfg(%s, ", Progname);
248 DEBUG(5, "%s)\n", flds[F_TYPE]);
249 setdevcfg(Progname, flds[F_TYPE]);
250
251 for (ca = Caller; ca->CA_type != NULL; ca++) {
252 /* This will find built-in caller functions */
253 if (EQUALS(ca->CA_type, dev[D_CALLER])) {
254 DEBUG(5, "Internal caller type %s\n", dev[D_CALLER]);
255 if (dev[D_ARG] == NULL) {
256 /* if NULL - assume translate */
257 dev[D_ARG+1] = NULL; /* needed for for loop later to mark the end */
258 dev[D_ARG] = "\\T";
259 }
260 dev[D_ARG] = repphone(dev[D_ARG], flds[F_PHONE], "");
261 if ((dcf = (*(ca->CA_caller))(flds, dev)) < 0)
262 return(dcf) ;
263 if ( interface( ca->CA_type ) ) {
264 DEBUG(5, "interface(%s) failed", ca->CA_type);
265 Uerror = SS_DEVICE_FAILED;
266 /* restore vanilla unix interface */
267 (void)interface("UNIX");
268 return(FAIL);
269 }
270 dev += 2; /* Skip to next CALLER and ARG */
271 break;
272 }
273 }
274 if (dcf == -1) {
275 /* Here if not a built-in caller function */
276
277 /* We do locking (file and advisory) after open */
278
279 /*
280 * Open the line
281 */
282 if ( *dev[D_LINE] != '/' ) {
283 (void) sprintf(dcname, "/dev/%s", dev[D_LINE]);
284 } else {
285 (void) strcpy(dcname, dev[D_LINE] );
286 }
287 /* take care of the possible partial open fd */
288 (void) close(nullfd = open("/", O_RDONLY));
289 if (setjmp(Sjbuf)) {
290 (void) close(nullfd);
291 DEBUG(1, "generic open timeout\n%s", "");
292 logent("generic open", "TIMEOUT");
293 Uerror = SS_CANT_ACCESS_DEVICE;
294 goto bad;
295 }
296 (void) signal(SIGALRM, alarmtr);
297 (void) alarm(10);
298 if ( Modemctrl ) {
299 DEBUG(7, "opening with O_NDELAY set\n%s", "");
300 dcf = open(dcname, (O_RDWR | O_NDELAY) );
301 saved_mode = O_RDWR | O_NDELAY;
302 } else {
303 dcf = open(dcname, O_RDWR );
304 saved_mode = O_RDWR;
305 }
306 strcpy(saved_dcname, dcname);
307 (void) alarm(0);
308 if (dcf < 0) {
309 DEBUG(1, "generic open failed, errno = %d\n", errno);
310 (void) close(nullfd);
311 logent("generic open", "FAILED");
312 Uerror = SS_CANT_ACCESS_DEVICE;
313 goto bad;
314 }
315
316 /* check locks BEFORE modifying the stream */
317
318 if ( fd_mklock(dcf) != SUCCESS ) {
319 DEBUG(1, "failed to lock device %s\n", dcname);
320 Uerror = SS_LOCKED_DEVICE;
321 goto bad;
322 }
323
324 if ( Modemctrl ) {
325 DEBUG(7, "clear O_NDELAY\n%s", "");
326 if ( fcntl(dcf, F_SETFL,
327 (fcntl(dcf, F_GETFL, 0) & ~O_NDELAY)) < 0 ) {
328 DEBUG( 7, "clear O_NDELAY failed, errno %d\n", errno);
329 Uerror = SS_DEVICE_FAILED;
330 goto bad;
331 }
332 }
333 }
334
335 if ( (*Setup)( MASTER, &dcf, &dcf ) ) {
336 /* any device|system lock files we should remove? */
337 DEBUG(5, "MASTER Setup failed%s", "");
338 Uerror = SS_DEVICE_FAILED;
339 goto bad;
340 }
341
342 /* configure any requested streams modules */
343 if ( !pop_push(dcf) ) {
344 DEBUG(5, "STREAMS module configuration failed%s\n","");
345 Uerror = SS_DEVICE_FAILED;
346 goto bad;
347 }
348
349 /* save initial state of line in case script fails */
350 ret_orig = ioctl(dcf, TCGETA, &tty_orig);
351
352 /* use sdev[] since dev[] is incremented for internal callers */
353 fixline(dcf, atoi(fdig(sdev[D_CLASS])), D_DIRECT);
354
355 /*
356 * Now loop through the remaining callers and chat
357 * according to scripts in dialers file.
358 */
359 for (; dev[D_CALLER] != NULL; dev += 2) {
360 int w;
361 /*
362 * Scan Dialers file to find an entry
363 */
364 if ((w = gdial(dev[D_CALLER], args, D_MAX)) < 1) {
365 logent("generic call to gdial", "FAILED");
366 Uerror = SS_CANT_ACCESS_DEVICE;
367 goto bad;
368 }
369 if (w <= 2) /* do nothing - no chat */
370 break;
371 /*
372 * Translate the phone number
373 */
374 if (dev[D_ARG] == NULL) {
375 /* if NULL - assume no translation */
376 dev[D_ARG+1] = NULL; /* needed for for loop to mark the end */
377 dev[D_ARG] = "\\D";
378 }
379
380 phonecl = repphone(dev[D_ARG], flds[F_PHONE], args[1]);
381 exphone(phonecl, phoneex);
382 translate(args[1], phoneex);
383 /*
384 * Chat
385 */
386 if (chat(w-2, &args[2], dcf, phonecl, phoneex) != SUCCESS) {
387 CDEBUG(5, "\nCHAT gdial(%s) FAILED\n", dev[D_CALLER]);
388 Uerror = SS_CHAT_FAILED;
389 goto bad;
390 }
391 }
392 /*
393 * Success at last!
394 */
395 strcpy(Dc, sdev[D_LINE]);
396 return(dcf);
397 bad:
398 if ( dcf >= 0 ) {
399 /* reset line settings if we got them in the beginning */
400 if ( ret_orig == 0 )
401 (void) ioctl(dcf, TCSETAW, &tty_orig);
402 fd_rmlock(dcf);
403 (void)close(dcf);
404 }
405 /* restore vanilla unix interface */
406 (void)interface("UNIX");
407 return(FAIL);
408 }
409
410 /*
411 * clear_hup() clear the hangup state of the given device
412 */
413 GLOBAL int
clear_hup(dcf)414 clear_hup(dcf)
415 int dcf;
416 {
417 int ndcf;
418 if ((ndcf = open(saved_dcname, saved_mode)) < 0) {
419 return (FAIL);
420 }
421 if (ndcf != dcf) {
422 close(ndcf);
423 }
424 return (SUCCESS);
425 }
426
427
428 /*
429 * translate the pairs of characters present in the first
430 * string whenever the first of the pair appears in the second
431 * string.
432 */
433 static void
translate(ttab,str)434 translate(ttab, str)
435 char *ttab, *str;
436 {
437 char *s;
438
439 for(;*ttab && *(ttab+1); ttab += 2)
440 for(s=str;*s;s++)
441 if(*ttab == *s)
442 *s = *(ttab+1);
443 return;
444 }
445
446 #define MAXLINE 512
447 /*
448 * Get the information about the dialer.
449 * gdial(type, arps, narps)
450 * type -> type of dialer (e.g., penril)
451 * arps -> array of pointers returned by gdial
452 * narps -> number of elements in array returned by gdial
453 * Return value:
454 * -1 -> Can't open DIALERFILE
455 * 0 -> requested type not found
456 * >0 -> success - number of fields filled in
457 */
458 static int
gdial(type,arps,narps)459 gdial(type, arps, narps)
460 char *type, *arps[];
461 int narps;
462 {
463 static char info[MAXLINE];
464 int na;
465 EXTERN void dialreset();
466 EXTERN char * currdial();
467
468 DEBUG(2, "gdial(%s) called\n", type);
469 while (getdialline(info, sizeof(info))) {
470 if ((info[0] == '#') || (info[0] == ' ') ||
471 (info[0] == '\t') || (info[0] == '\n'))
472 continue;
473 if ((na = getargs(info, arps, narps)) == 0)
474 continue;
475 if (EQUALS(arps[0], type)) {
476 DEBUG(5, "Trying caller script '%s'", type);
477 DEBUG(5, " from '%s'.\n", currdial());
478 dialreset();
479 bsfix(arps);
480 return(na);
481 }
482 }
483 DEBUG(1, "%s not found in Dialers file\n", type);
484 dialreset();
485 return(0);
486 }
487
488
489 #ifdef DATAKIT
490
491 /*
492 * dkcall(flds, dev) make a DATAKIT VCS connection
493 * DATAKIT VCS is a trademark of AT&T
494 *
495 * return codes:
496 * >0 - file number - ok
497 * FAIL - failed
498 */
499
500 #include "dk.h"
501 EXTERN int dkdial();
502
503 /*ARGSUSED*/
504 GLOBAL int
dkcall(flds,dev)505 dkcall(flds, dev)
506 char *flds[], *dev[];
507 {
508 int fd;
509 #ifdef V8
510 extern int cdkp_ld;
511 #endif
512
513 char dialstring[64];
514 EXTERN void dkbreak();
515
516 strcpy(dialstring, dev[D_ARG]);
517 DEBUG(4, "dkcall(%s)\n", dialstring);
518
519
520 #ifdef V8
521 if (setjmp(Sjbuf)) {
522 Uerror = SS_DIAL_FAILED;
523 return(FAIL);
524 }
525
526 (void) signal(SIGALRM, alarmtr);
527 (void) alarm(connecttime);
528 DEBUG(4, "tdkdial(%s", flds[F_PHONE]);
529 DEBUG(4, ", %d)\n", atoi(dev[D_CLASS]));
530 if ((fd = tdkdial(flds[F_PHONE], atoi(dev[D_CLASS]))) >= 0)
531 if (dkproto(fd, cdkp_ld) < 0)
532 {
533 close(fd);
534 fd = -1;
535 }
536 (void) alarm(0);
537 #else
538 fd = dkdial(dialstring);
539 #endif
540
541 (void) strcpy(Dc, "DK");
542 if (fd < 0) {
543 Uerror = SS_DIAL_FAILED;
544 return(FAIL);
545 }
546 else {
547 genbrk = dkbreak;
548 return(fd);
549 }
550 }
551
552 #endif /* DATAKIT */
553
554 #ifdef TCP
555
556 /*
557 * tcpcall(flds, dev) make ethernet/socket connection
558 *
559 * return codes:
560 * >0 - file number - ok
561 * FAIL - failed
562 */
563
564 #if !(defined(BSD4_2) || defined(ATTSVR4))
565 /*ARGSUSED*/
566 GLOBAL int
tcpcall(flds,dev)567 tcpcall(flds, dev)
568 char *flds[], *dev[];
569 {
570 Uerror = SS_NO_DEVICE;
571 return(FAIL);
572 }
573 #else /* BSD4_2 */
574 /*ARGSUSED*/
575 GLOBAL int
tcpcall(flds,dev)576 tcpcall(flds, dev)
577 char *flds[], *dev[];
578 {
579 int ret;
580 short port;
581 struct servent *sp;
582 struct hostent *hp;
583 struct sockaddr_in sin;
584
585 if (EQUALS(flds[F_CLASS], "-")) {
586 /*
587 * Use standard UUCP port number.
588 */
589 sp = getservbyname("uucp", "tcp");
590 endservent();
591 ASSERT(sp != NULL, "No uucp service number", 0, 0);
592 port = sp->s_port;
593 } else {
594 /*
595 * Systems file specifies a port number.
596 */
597 sp = getservbyname(flds[F_CLASS], "tcp");
598 endservent();
599 if (sp == NULL) {
600 port = htons(atoi(flds[F_CLASS]));
601 if (port == 0) {
602 logent("tcpopen", "unknown port number");
603 Uerror = SS_NO_DEVICE;
604 return(FAIL);
605 }
606 } else
607 port = sp->s_port;
608 }
609 if (EQUALS(flds[F_PHONE], "-")) {
610 /*
611 * Use UUCP name as host name.
612 */
613 hp = gethostbyname(flds[F_NAME]);
614 } else {
615 /*
616 * Systems file specifies a host name different from the UUCP
617 * host name.
618 */
619 hp = gethostbyname(flds[F_PHONE]);
620 }
621 endhostent();
622 if (hp == NULL) {
623 logent("tcpopen", "no such host");
624 Uerror = SS_NO_DEVICE;
625 return(FAIL);
626 }
627 DEBUG(4, "tcpdial host %s, ", hp->h_name);
628 DEBUG(4, "port %d\n", ntohs(port));
629
630 ret = socket(AF_INET, SOCK_STREAM, 0);
631 if (ret < 0) {
632 DEBUG(5, "no socket: %s\n", strerror(errno));
633 logent("no socket", strerror(errno));
634 Uerror = SS_NO_DEVICE;
635 return(FAIL);
636 }
637 sin.sin_family = hp->h_addrtype;
638 #ifdef BSD4_2
639 bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
640 #else
641 memcpy((caddr_t)&sin.sin_addr, hp->h_addr, hp->h_length);
642 #endif
643 sin.sin_port = port;
644 if (setjmp(Sjbuf)) {
645 DEBUG(4, "timeout tcpopen\n%s", "");
646 logent("tcpopen", "TIMEOUT");
647 Uerror = SS_NO_DEVICE;
648 return(FAIL);
649 }
650 (void) signal(SIGALRM, alarmtr);
651 (void) alarm(connecttime);
652 DEBUG(7, "family: %d\n", sin.sin_family);
653 DEBUG(7, "port: %d\n", sin.sin_port);
654 DEBUG(7, "addr: %08x\n",*((int *) &sin.sin_addr));
655 if (connect(ret, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
656 (void) alarm(0);
657 (void) close(ret);
658 DEBUG(5, "connect failed: %s\n", strerror(errno));
659 logent("connect failed", strerror(errno));
660 Uerror = SS_NO_DEVICE;
661 return(FAIL);
662 }
663 (void) signal(SIGPIPE, SIG_IGN); /* watch out for broken ipc link...*/
664 (void) alarm(0);
665 (void) strcpy(Dc, "IPC");
666 return(ret);
667 }
668
669 #endif /* BSD4_2 */
670
671 /*
672 * unetcall(flds, dev) make ethernet connection
673 *
674 * return codes:
675 * >0 - file number - ok
676 * FAIL - failed
677 */
678
679 #ifndef UNET
680 /*ARGSUSED*/
681 GLOBAL int
unetcall(flds,dev)682 unetcall(flds, dev)
683 char *flds[], *dev[];
684 {
685 Uerror = SS_NO_DEVICE;
686 return(FAIL);
687 }
688 #else /* UNET */
689 GLOBAL int
unetcall(flds,dev)690 unetcall(flds, dev)
691 char *flds[], *dev[];
692 {
693 int ret;
694 int port;
695
696 port = atoi(dev[D_ARG]);
697 DEBUG(4, "unetdial host %s, ", flds[F_PHONE]);
698 DEBUG(4, "port %d\n", port);
699 (void) alarm(connecttime);
700 ret = tcpopen(flds[F_PHONE], port, 0, TO_ACTIVE, "rw");
701 (void) alarm(0);
702 endhnent();
703 if (ret < 0) {
704 DEBUG(5, "tcpopen failed: errno %d\n", errno);
705 Uerror = SS_DIAL_FAILED;
706 return(FAIL);
707 }
708 (void) strcpy(Dc, "UNET");
709 return(ret);
710 }
711 #endif /* UNET */
712
713 #endif /* TCP */
714
715 #ifdef SYTEK
716
717 /*
718 * sytcall(flds, dev) make a sytek connection
719 *
720 * return codes:
721 * >0 - file number - ok
722 * FAIL - failed
723 */
724
725 /*ARGSUSED*/
726 GLOBAL int
sytcall(flds,dev)727 sytcall(flds, dev)
728 char *flds[], *dev[];
729 {
730 int dcr, dcr2, nullfd, ret;
731 char dcname[20], command[BUFSIZ];
732
733 (void) sprintf(dcname, "/dev/%s", dev[D_LINE]);
734 DEBUG(4, "dc - %s, ", dcname);
735 dcr = open(dcname, O_WRONLY|O_NDELAY);
736 if (dcr < 0) {
737 Uerror = SS_DIAL_FAILED;
738 DEBUG(4, "OPEN FAILED %s\n", dcname);
739 return(FAIL);
740 }
741 if ( fd_mklock(dcr) != SUCCESS ) {
742 (void)close(dcr);
743 DEBUG(1, "failed to lock device %s\n", dcname);
744 Uerror = SS_LOCKED_DEVICE;
745 return(FAIL);
746 }
747
748 sytfixline(dcr, atoi(fdig(dev[D_CLASS])), D_DIRECT);
749 (void) sleep(2);
750 DEBUG(4, "Calling Sytek unit %s\n", dev[D_ARG]);
751 (void) sprintf(command,"\r\rcall %s\r", dev[D_ARG]);
752 ret = (*Write)(dcr, command, strlen(command));
753 (void) sleep(1);
754 DEBUG(4, "COM1 return = %d\n", ret);
755 sytfix2line(dcr);
756 (void) close(nullfd = open("/", O_RDONLY));
757 (void) signal(SIGALRM, alarmtr);
758 if (setjmp(Sjbuf)) {
759 DEBUG(4, "timeout sytek open\n%s", "");
760 (void) close(nullfd);
761 (void) close(dcr2);
762 fd_rmlock(dcr);
763 (void) close(dcr);
764 Uerror = SS_DIAL_FAILED;
765 return(FAIL);
766 }
767 (void) alarm(10);
768 dcr2 = open(dcname,O_RDWR);
769 (void) alarm(0);
770 fd_rmlock(dcr);
771 (void) close(dcr);
772 if (dcr2 < 0) {
773 DEBUG(4, "OPEN 2 FAILED %s\n", dcname);
774 Uerror = SS_DIAL_FAILED;
775 (void) close(nullfd); /* kernel might think dc2 is open */
776 return(FAIL);
777 }
778 if ( fd_mklock(dcr2) != SUCCESS ) {
779 (void)close(dcr2);
780 DEBUG(1, "failed to lock device %s\n", dcname);
781 Uerror = SS_LOCKED_DEVICE;
782 return(FAIL);
783 return(dcr2);
784 }
785
786 #endif /* SYTEK */
787
788 #ifdef DIAL801
789
790 /*
791 * dial801(flds, dev) dial remote machine on 801/801
792 * char *flds[], *dev[];
793 *
794 * return codes:
795 * file descriptor - succeeded
796 * FAIL - failed
797 *
798 * unfortunately, open801() is different for usg and non-usg
799 */
800
801 /*ARGSUSED*/
802 GLOBAL int
803 dial801(flds, dev)
804 char *flds[], *dev[];
805 {
806 char dcname[20], dnname[20], phone[MAXPH+2];
807 int dcf = -1, speed;
808
809 (void) sprintf(dnname, "/dev/%s", dev[D_CALLDEV]);
810 (void) sprintf(phone, "%s%s", dev[D_ARG] , ACULAST);
811 (void) sprintf(dcname, "/dev/%s", dev[D_LINE]);
812 CDEBUG(1, "Use Port %s, ", dcname);
813 DEBUG(4, "acu - %s, ", dnname);
814 VERBOSE("Trying modem - %s, ", dcname); /* for cu */
815 VERBOSE("acu - %s, ", dnname); /* for cu */
816 if(getuid()==0 || GRPCHK(getgid())) {
817 CDEBUG(1, "Phone Number %s\n", phone);
818 /* In cu, only give out the phone number to trusted people. */
819 VERBOSE("calling %s: ", phone); /* for cu */
820 }
821 speed = atoi(fdig(dev[D_CLASS]));
822 dcf = open801(dcname, dnname, phone, speed);
823 if (dcf >= 0) {
824 if ( fd_mklock(dcf) != SUCCESS ) {
825 (void) close(dcf);
826 DEBUG(5, "fd_mklock line %s failed\n", dev[D_LINE]);
827 Uerror = SS_LOCKED_DEVICE;
828 return(FAIL);
829 }
830 fixline(dcf, speed, D_ACU);
831 (void) strcpy(Dc, dev[D_LINE]); /* for later unlock() */
832 VERBOSE("SUCCEEDED\n%s", "");
833 } else {
834 VERBOSE("FAILED\n%s", "");
835 }
836 return(dcf);
837 }
838
839
840 #ifndef ATTSV
841 /*ARGSUSED*/
842 GLOBAL int
843 open801(dcname, dnname, phone, speed)
844 char *dcname, *dnname, *phone;
845 {
846 int nw, lt, dcf = -1, nullfd, dnf = -1;
847 pid_t w_ret, pid = -1;
848 unsigned timelim;
849
850 if ((dnf = open(dnname, O_WRONLY)) < 0) {
851 DEBUG(5, "can't open %s\n", dnname);
852 Uerror = SS_CANT_ACCESS_DEVICE;
853 return(FAIL);
854 }
855 DEBUG(5, "%s is open\n", dnname);
856
857 (void) close(nullfd = open("/dev/null", O_RDONLY));/* partial open hack */
858 if (setjmp(Sjbuf)) {
859 DEBUG(4, "timeout modem open\n%s", "");
860 (void) close(nullfd);
861 (void) close(dcf);
862 (void) close(dnf);
863 logent("801 open", "TIMEOUT");
864 if (pid > 0) {
865 kill(pid, 9);
866 wait((int *) 0);
867 }
868 Uerror = SS_DIAL_FAILED;
869 return(FAIL);
870 }
871 (void) signal(SIGALRM, alarmtr);
872 timelim = 5 * strlen(phone);
873 (void) alarm(timelim < connecttime ? connecttime : timelim);
874 if ((pid = fork()) == 0) {
875 sleep(2);
876 nw = (*Write)(dnf, phone, lt = strlen(phone));
877 if (nw != lt) {
878 DEBUG(4, "ACU write error %d\n", errno);
879 logent("ACU write", "FAILED");
880 exit(1);
881 }
882 DEBUG(4, "ACU write ok\n%s", "");
883 exit(0);
884 }
885 /* open line - will return on carrier */
886 dcf = open(dcname, O_RDWR);
887
888 DEBUG(4, "dcf is %d\n", dcf);
889 if (dcf < 0) { /* handle like a timeout */
890 (void) alarm(0);
891 longjmp(Sjbuf, 1);
892 }
893
894 /* modem is open */
895 while ((w_ret = wait(<)) != pid)
896 if (w_ret == -1 && errno != EINTR) {
897 DEBUG(4, "Wait failed errno=%d\n", errno);
898 (void) close(dcf);
899 (void) close(dnf);
900 Uerror = SS_DIAL_FAILED;
901 return(FAIL);
902 }
903 (void) alarm(0);
904
905 (void) close(dnf); /* no reason to keep the 801 open */
906 if (lt != 0) {
907 DEBUG(4, "Fork Stat %o\n", lt);
908 (void) close(dcf);
909 Uerror = SS_DIAL_FAILED;
910 return(FAIL);
911 }
912 return(dcf);
913 }
914
915 #else /* ATTSV */
916
917 GLOBAL int
918 open801(dcname, dnname, phone, speed)
919 char *dcname, *dnname, *phone;
920 {
921 int nw, lt, dcf = -1, nullfd, dnf = -1, ret;
922 unsigned timelim;
923
924 (void) close(nullfd = open("/", O_RDONLY)); /* partial open hack */
925 if (setjmp(Sjbuf)) {
926 DEBUG(4, "DN write %s\n", "timeout");
927 (void) close(dnf);
928 (void) close(dcf);
929 (void) close(nullfd);
930 Uerror = SS_DIAL_FAILED;
931 return(FAIL);
932 }
933 (void) signal(SIGALRM, alarmtr);
934 timelim = 5 * strlen(phone);
935 (void) alarm(timelim < connecttime ? connecttime : timelim);
936
937 if ((dnf = open(dnname, O_WRONLY)) < 0 ) {
938 DEBUG(5, "can't open %s\n", dnname);
939 Uerror = SS_CANT_ACCESS_DEVICE;
940 return(FAIL);
941 }
942 DEBUG(5, "%s is open\n", dnname);
943 if ( fd_mklock(dnf) != SUCCESS ) {
944 (void)close(dnf);
945 DEBUG(1, "failed to lock device %s\n", dnname);
946 Uerror = SS_LOCKED_DEVICE;
947 }
948 if ( (dcf = open(dcname, O_RDWR | O_NDELAY)) < 0 ) {
949 DEBUG(5, "can't open %s\n", dcname);
950 Uerror = SS_CANT_ACCESS_DEVICE;
951 return(FAIL);
952 }
953 if ( fd_mklock(dcf) != SUCCESS ) {
954 (void)close(dcf);
955 DEBUG(1, "failed to lock device %s\n", dcname);
956 Uerror = SS_LOCKED_DEVICE;
957 return(FAIL);
958 }
959
960 DEBUG(4, "dcf is %d\n", dcf);
961 fixline(dcf, speed, D_ACU);
962 nw = (*Write)(dnf, phone, lt = strlen(phone));
963 if (nw != lt) {
964 (void) alarm(0);
965 DEBUG(4, "ACU write error %d\n", errno);
966 (void) close(dnf);
967 (void) close(dcf);
968 Uerror = SS_DIAL_FAILED;
969 return(FAIL);
970 } else
971 DEBUG(4, "ACU write ok\n%s", "");
972
973 (void) close(dnf);
974 (void) close(nullfd = open("/", O_RDONLY)); /* partial open hack */
975 ret = open(dcname, O_RDWR); /* wait for carrier */
976 (void) alarm(0);
977 (void) close(ret); /* close 2nd modem open() */
978 if (ret < 0) { /* open() interrupted by alarm */
979 DEBUG(4, "Line open %s\n", "failed");
980 Uerror = SS_DIAL_FAILED;
981 (void) close(nullfd); /* close partially opened modem */
982 return(FAIL);
983 }
984 (void) fcntl(dcf,F_SETFL, fcntl(dcf, F_GETFL, 0) & ~O_NDELAY);
985 return(dcf);
986 }
987 #endif /* ATTSV */
988
989 #endif /* DIAL801 */
990
991 #ifdef V8
992 GLOBAL int
993 Dialout(flds)
994 char *flds[];
995 {
996 int fd;
997 char phone[MAXPH+2];
998
999 exphone(flds[F_PHONE], phone);
1000
1001 DEBUG(4, "call dialout(%s", phone);
1002 DEBUG(4, ", %s)\n", dev[D_CLASS]);
1003 fd = dialout(phone, dev[D_CLASS]);
1004 if (fd == -1)
1005 Uerror = SS_NO_DEVICE;
1006 if (fd == -3)
1007 Uerror = SS_DIAL_FAILED;
1008 if (fd == -9)
1009 Uerror = SS_DEVICE_FAILED;
1010
1011 (void) strcpy(Dc, "Dialout");
1012
1013 return(fd);
1014 }
1015 #endif /* V8 */
1016
1017 #ifdef TLI
1018 /*
1019 *
1020 * AT&T Transport Layer Interface
1021 *
1022 * expected in Devices
1023 * TLI line1 - - TLI
1024 * or
1025 * TLIS line1 - - TLIS
1026 *
1027 */
1028
1029 #include <sys/tiuser.h>
1030
1031 EXTERN void tfaillog();
1032
1033 char *t_alloc();
1034 int t_bind(), t_close(), t_connect(), t_free(), t_look(), t_open(), t_rcvdis();
1035
1036 #define CONNECT_ATTEMPTS 3
1037 #define TFREE(p, type) if ((p)) t_free((char *)(p), (type))
1038
1039 /*
1040 * returns fd to remote uucp daemon
1041 */
1042 /*ARGSUSED*/
1043 GLOBAL int
1044 tlicall(flds, dev)
1045 char *flds[];
1046 char *dev[];
1047 {
1048 char addrbuf[ BUFSIZ ];
1049 char devname[MAXNAMESIZE];
1050 int fd;
1051 int i, j;
1052 struct t_bind *bind_ret = 0;
1053 struct t_info tinfo;
1054 struct t_call *sndcall = 0, *rcvcall = 0;
1055 extern int t_errno;
1056
1057 EXTERN struct netbuf *stoa();
1058
1059 if ( dev[D_LINE][0] != '/' ) {
1060 /* dev holds device name relative to /dev */
1061 sprintf(devname, "/dev/%s", dev[D_LINE]);
1062 } else {
1063 /* dev holds full path name of device */
1064 strcpy(devname, dev[D_LINE]);
1065 }
1066 /* gimme local transport endpoint */
1067 errno = t_errno = 0;
1068 if (setjmp(Sjbuf)) {
1069 DEBUG(1, "t_open timeout\n%s", "");
1070 logent("t_open", "TIMEOUT");
1071 Uerror = SS_NO_DEVICE;
1072 return(FAIL);
1073 }
1074 (void) signal(SIGALRM, alarmtr);
1075 (void) alarm(5);
1076 fd = t_open(devname, O_RDWR, &tinfo);
1077 (void) alarm(0);
1078 if (fd < 0) {
1079 tfaillog(fd, "t_open" );
1080 Uerror = SS_NO_DEVICE;
1081 return(FAIL);
1082 }
1083 if ( fd_mklock(fd) != SUCCESS ) {
1084 (void)t_close(fd);
1085 DEBUG(1, "tlicall: failed to lock device %s\n", devname);
1086 Uerror = SS_LOCKED_DEVICE;
1087 return(FAIL);
1088 }
1089
1090 /* allocate tli structures */
1091 errno = t_errno = 0;
1092 if ( (bind_ret = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL)) ==
1093 (struct t_bind *)NULL
1094 || (sndcall = (struct t_call *)t_alloc(fd, T_CALL, T_ALL)) ==
1095 (struct t_call *)NULL
1096 || (rcvcall = (struct t_call *)t_alloc(fd, T_CALL, T_ALL)) ==
1097 (struct t_call *)NULL ) {
1098 tfaillog(fd, "t_alloc" );
1099 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1100 TFREE(rcvcall, T_CALL);
1101 Uerror = SS_NO_DEVICE;
1102 return(FAIL);
1103 }
1104
1105 /* bind */
1106 errno = t_errno = 0;
1107 if (t_bind(fd, (struct t_bind *) 0, bind_ret ) < 0) {
1108 tfaillog(fd, "t_bind" );
1109 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1110 TFREE(rcvcall, T_CALL);
1111 Uerror = SS_NO_DEVICE;
1112 fd_rmlock(fd);
1113 (void) t_close(fd);
1114 return(FAIL);
1115 }
1116 DEBUG(5, "tlicall: bound to %s\n", bind_ret->addr.buf);
1117
1118 /*
1119 * Prepare to connect.
1120 *
1121 * If address begins with "\x", "\X", "\o", or "\O",
1122 * assume is hexadecimal or octal address and use stoa()
1123 * to convert it.
1124 *
1125 * Else is usual uucico address -- only \N's left to process.
1126 * Walk thru connection address, changing \N's to NULLCHARs.
1127 * Note: If a NULLCHAR must be part of the connection address,
1128 * it must be overtly included in the address. One recommended
1129 * way is to do it in the Devices file, thusly:
1130 * Netname /dev/netport - - TLI \D\000
1131 * bsfix() turns \000 into \N and then the loop below makes it a
1132 * real, included-in-the-length null-byte.
1133 *
1134 * The DEBUG must print the strecpy'd address (so that
1135 * non-printables will have been replaced with C escapes).
1136 */
1137
1138 DEBUG(5, "t_connect to addr \"%s\"\n",
1139 strecpy( addrbuf, dev[D_ARG], "\\" ) );
1140
1141 if ( dev[D_ARG][0] == '\\' &&
1142 ( dev[D_ARG][1] == 'x' || dev[D_ARG][1] == 'X'
1143 || dev[D_ARG][1] == 'o' || dev[D_ARG][1] == 'O' ) ) {
1144 if ( stoa(dev[D_ARG], &(sndcall->addr)) == (struct netbuf *)NULL ) {
1145 DEBUG(5, "tlicall: stoa failed\n%s", "");
1146 logent("tlicall", "string-to-address failed");
1147 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1148 TFREE(rcvcall, T_CALL);
1149 Uerror = SS_NO_DEVICE;
1150 fd_rmlock(fd);
1151 (void) t_close(fd);
1152 return(FAIL);
1153 }
1154 } else {
1155 for( i = j = 0; i < BUFSIZ && dev[D_ARG][i] != NULLCHAR;
1156 ++i, ++j ) {
1157 if( dev[D_ARG][i] == '\\' && dev[D_ARG][i+1] == 'N' ) {
1158 addrbuf[j] = NULLCHAR;
1159 ++i;
1160 }
1161 else {
1162 addrbuf[j] = dev[D_ARG][i];
1163 }
1164 }
1165 sndcall->addr.buf = addrbuf;
1166 sndcall->addr.len = j;
1167 }
1168
1169 if (setjmp(Sjbuf)) {
1170 DEBUG(4, "timeout tlicall\n%s", "");
1171 logent("tlicall", "TIMEOUT");
1172 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1173 TFREE(rcvcall, T_CALL);
1174 Uerror = SS_NO_DEVICE;
1175 fd_rmlock(fd);
1176 (void) t_close(fd);
1177 return(FAIL);
1178 }
1179 (void) signal(SIGALRM, alarmtr);
1180 (void) alarm(connecttime);
1181
1182 /* connect to the service -- some listeners can't handle */
1183 /* multiple connect requests, so try it a few times */
1184 errno = t_errno = 0;
1185 for ( i = 0; i < CONNECT_ATTEMPTS; ++i ) {
1186 if (t_connect(fd, sndcall, rcvcall) == 0)
1187 break;
1188 if ( (t_errno == TLOOK) && (t_look(fd) == T_DISCONNECT)) {
1189 t_rcvdis(fd,NULL);
1190 (void) alarm(0);
1191 } else {
1192 (void) alarm(0);
1193 tfaillog(fd, "t_connect");
1194 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1195 TFREE(rcvcall, T_CALL);
1196 Uerror = SS_DIAL_FAILED;
1197 fd_rmlock(fd);
1198 (void) t_close(fd);
1199 return(FAIL);
1200 }
1201 }
1202 (void) alarm(0);
1203 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1204 TFREE(rcvcall, T_CALL);
1205 if ( i == CONNECT_ATTEMPTS ) {
1206 tfaillog(fd, "t_connect");
1207 Uerror = SS_DIAL_FAILED;
1208 fd_rmlock(fd);
1209 (void) t_close(fd);
1210 return(FAIL);
1211 }
1212 errno = t_errno = 0;
1213 (void) strcpy(Dc, dev[D_CALLER]);
1214 return(fd);
1215 }
1216 #endif /* TLI */
1217