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