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 2005 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 struct servent *sp; 586 struct hostent *hp; 587 struct sockaddr_in sin; 588 589 if (EQUALS(flds[F_CLASS], "-")) { 590 /* 591 * Use standard UUCP port number. 592 */ 593 sp = getservbyname("uucp", "tcp"); 594 endservent(); 595 ASSERT(sp != NULL, "No uucp service number", 0, 0); 596 port = sp->s_port; 597 } else { 598 /* 599 * Systems file specifies a port number. 600 */ 601 sp = getservbyname(flds[F_CLASS], "tcp"); 602 endservent(); 603 if (sp == NULL) { 604 port = htons(atoi(flds[F_CLASS])); 605 if (port == 0) { 606 logent("tcpopen", "unknown port number"); 607 Uerror = SS_NO_DEVICE; 608 return(FAIL); 609 } 610 } else 611 port = sp->s_port; 612 } 613 if (EQUALS(flds[F_PHONE], "-")) { 614 /* 615 * Use UUCP name as host name. 616 */ 617 hp = gethostbyname(flds[F_NAME]); 618 } else { 619 /* 620 * Systems file specifies a host name different from the UUCP 621 * host name. 622 */ 623 hp = gethostbyname(flds[F_PHONE]); 624 } 625 endhostent(); 626 if (hp == NULL) { 627 logent("tcpopen", "no such host"); 628 Uerror = SS_NO_DEVICE; 629 return(FAIL); 630 } 631 DEBUG(4, "tcpdial host %s, ", hp->h_name); 632 DEBUG(4, "port %d\n", ntohs(port)); 633 634 ret = socket(AF_INET, SOCK_STREAM, 0); 635 if (ret < 0) { 636 DEBUG(5, "no socket: %s\n", strerror(errno)); 637 logent("no socket", strerror(errno)); 638 Uerror = SS_NO_DEVICE; 639 return(FAIL); 640 } 641 sin.sin_family = hp->h_addrtype; 642 #ifdef BSD4_2 643 bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 644 #else 645 memcpy((caddr_t)&sin.sin_addr, hp->h_addr, hp->h_length); 646 #endif 647 sin.sin_port = port; 648 if (setjmp(Sjbuf)) { 649 DEBUG(4, "timeout tcpopen\n%s", ""); 650 logent("tcpopen", "TIMEOUT"); 651 Uerror = SS_NO_DEVICE; 652 return(FAIL); 653 } 654 (void) signal(SIGALRM, alarmtr); 655 (void) alarm(connecttime); 656 DEBUG(7, "family: %d\n", sin.sin_family); 657 DEBUG(7, "port: %d\n", sin.sin_port); 658 DEBUG(7, "addr: %08x\n",*((int *) &sin.sin_addr)); 659 if (connect(ret, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 660 (void) alarm(0); 661 (void) close(ret); 662 DEBUG(5, "connect failed: %s\n", strerror(errno)); 663 logent("connect failed", strerror(errno)); 664 Uerror = SS_NO_DEVICE; 665 return(FAIL); 666 } 667 (void) signal(SIGPIPE, SIG_IGN); /* watch out for broken ipc link...*/ 668 (void) alarm(0); 669 (void) strcpy(Dc, "IPC"); 670 return(ret); 671 } 672 673 #endif /* BSD4_2 */ 674 675 /* 676 * unetcall(flds, dev) make ethernet connection 677 * 678 * return codes: 679 * >0 - file number - ok 680 * FAIL - failed 681 */ 682 683 #ifndef UNET 684 /*ARGSUSED*/ 685 GLOBAL int 686 unetcall(flds, dev) 687 char *flds[], *dev[]; 688 { 689 Uerror = SS_NO_DEVICE; 690 return(FAIL); 691 } 692 #else /* UNET */ 693 GLOBAL int 694 unetcall(flds, dev) 695 char *flds[], *dev[]; 696 { 697 int ret; 698 int port; 699 700 port = atoi(dev[D_ARG]); 701 DEBUG(4, "unetdial host %s, ", flds[F_PHONE]); 702 DEBUG(4, "port %d\n", port); 703 (void) alarm(connecttime); 704 ret = tcpopen(flds[F_PHONE], port, 0, TO_ACTIVE, "rw"); 705 (void) alarm(0); 706 endhnent(); 707 if (ret < 0) { 708 DEBUG(5, "tcpopen failed: errno %d\n", errno); 709 Uerror = SS_DIAL_FAILED; 710 return(FAIL); 711 } 712 (void) strcpy(Dc, "UNET"); 713 return(ret); 714 } 715 #endif /* UNET */ 716 717 #endif /* TCP */ 718 719 #ifdef SYTEK 720 721 /* 722 * sytcall(flds, dev) make a sytek connection 723 * 724 * return codes: 725 * >0 - file number - ok 726 * FAIL - failed 727 */ 728 729 /*ARGSUSED*/ 730 GLOBAL int 731 sytcall(flds, dev) 732 char *flds[], *dev[]; 733 { 734 int dcr, dcr2, nullfd, ret; 735 char dcname[20], command[BUFSIZ]; 736 737 (void) sprintf(dcname, "/dev/%s", dev[D_LINE]); 738 DEBUG(4, "dc - %s, ", dcname); 739 dcr = open(dcname, O_WRONLY|O_NDELAY); 740 if (dcr < 0) { 741 Uerror = SS_DIAL_FAILED; 742 DEBUG(4, "OPEN FAILED %s\n", dcname); 743 return(FAIL); 744 } 745 if ( fd_mklock(dcr) != SUCCESS ) { 746 (void)close(dcr); 747 DEBUG(1, "failed to lock device %s\n", dcname); 748 Uerror = SS_LOCKED_DEVICE; 749 return(FAIL); 750 } 751 752 sytfixline(dcr, atoi(fdig(dev[D_CLASS])), D_DIRECT); 753 (void) sleep(2); 754 DEBUG(4, "Calling Sytek unit %s\n", dev[D_ARG]); 755 (void) sprintf(command,"\r\rcall %s\r", dev[D_ARG]); 756 ret = (*Write)(dcr, command, strlen(command)); 757 (void) sleep(1); 758 DEBUG(4, "COM1 return = %d\n", ret); 759 sytfix2line(dcr); 760 (void) close(nullfd = open("/", O_RDONLY)); 761 (void) signal(SIGALRM, alarmtr); 762 if (setjmp(Sjbuf)) { 763 DEBUG(4, "timeout sytek open\n%s", ""); 764 (void) close(nullfd); 765 (void) close(dcr2); 766 fd_rmlock(dcr); 767 (void) close(dcr); 768 Uerror = SS_DIAL_FAILED; 769 return(FAIL); 770 } 771 (void) alarm(10); 772 dcr2 = open(dcname,O_RDWR); 773 (void) alarm(0); 774 fd_rmlock(dcr); 775 (void) close(dcr); 776 if (dcr2 < 0) { 777 DEBUG(4, "OPEN 2 FAILED %s\n", dcname); 778 Uerror = SS_DIAL_FAILED; 779 (void) close(nullfd); /* kernel might think dc2 is open */ 780 return(FAIL); 781 } 782 if ( fd_mklock(dcr2) != SUCCESS ) { 783 (void)close(dcr2); 784 DEBUG(1, "failed to lock device %s\n", dcname); 785 Uerror = SS_LOCKED_DEVICE; 786 return(FAIL); 787 return(dcr2); 788 } 789 790 #endif /* SYTEK */ 791 792 #ifdef DIAL801 793 794 /* 795 * dial801(flds, dev) dial remote machine on 801/801 796 * char *flds[], *dev[]; 797 * 798 * return codes: 799 * file descriptor - succeeded 800 * FAIL - failed 801 * 802 * unfortunately, open801() is different for usg and non-usg 803 */ 804 805 /*ARGSUSED*/ 806 GLOBAL int 807 dial801(flds, dev) 808 char *flds[], *dev[]; 809 { 810 char dcname[20], dnname[20], phone[MAXPH+2]; 811 int dcf = -1, speed; 812 813 (void) sprintf(dnname, "/dev/%s", dev[D_CALLDEV]); 814 (void) sprintf(phone, "%s%s", dev[D_ARG] , ACULAST); 815 (void) sprintf(dcname, "/dev/%s", dev[D_LINE]); 816 CDEBUG(1, "Use Port %s, ", dcname); 817 DEBUG(4, "acu - %s, ", dnname); 818 VERBOSE("Trying modem - %s, ", dcname); /* for cu */ 819 VERBOSE("acu - %s, ", dnname); /* for cu */ 820 if(getuid()==0 || GRPCHK(getgid())) { 821 CDEBUG(1, "Phone Number %s\n", phone); 822 /* In cu, only give out the phone number to trusted people. */ 823 VERBOSE("calling %s: ", phone); /* for cu */ 824 } 825 speed = atoi(fdig(dev[D_CLASS])); 826 dcf = open801(dcname, dnname, phone, speed); 827 if (dcf >= 0) { 828 if ( fd_mklock(dcf) != SUCCESS ) { 829 (void) close(dcf); 830 DEBUG(5, "fd_mklock line %s failed\n", dev[D_LINE]); 831 Uerror = SS_LOCKED_DEVICE; 832 return(FAIL); 833 } 834 fixline(dcf, speed, D_ACU); 835 (void) strcpy(Dc, dev[D_LINE]); /* for later unlock() */ 836 VERBOSE("SUCCEEDED\n%s", ""); 837 } else { 838 VERBOSE("FAILED\n%s", ""); 839 } 840 return(dcf); 841 } 842 843 844 #ifndef ATTSV 845 /*ARGSUSED*/ 846 GLOBAL int 847 open801(dcname, dnname, phone, speed) 848 char *dcname, *dnname, *phone; 849 { 850 int nw, lt, dcf = -1, nullfd, dnf = -1; 851 pid_t w_ret, pid = -1; 852 unsigned timelim; 853 854 if ((dnf = open(dnname, O_WRONLY)) < 0) { 855 DEBUG(5, "can't open %s\n", dnname); 856 Uerror = SS_CANT_ACCESS_DEVICE; 857 return(FAIL); 858 } 859 DEBUG(5, "%s is open\n", dnname); 860 861 (void) close(nullfd = open("/dev/null", O_RDONLY));/* partial open hack */ 862 if (setjmp(Sjbuf)) { 863 DEBUG(4, "timeout modem open\n%s", ""); 864 (void) close(nullfd); 865 (void) close(dcf); 866 (void) close(dnf); 867 logent("801 open", "TIMEOUT"); 868 if (pid > 0) { 869 kill(pid, 9); 870 wait((int *) 0); 871 } 872 Uerror = SS_DIAL_FAILED; 873 return(FAIL); 874 } 875 (void) signal(SIGALRM, alarmtr); 876 timelim = 5 * strlen(phone); 877 (void) alarm(timelim < connecttime ? connecttime : timelim); 878 if ((pid = fork()) == 0) { 879 sleep(2); 880 nw = (*Write)(dnf, phone, lt = strlen(phone)); 881 if (nw != lt) { 882 DEBUG(4, "ACU write error %d\n", errno); 883 logent("ACU write", "FAILED"); 884 exit(1); 885 } 886 DEBUG(4, "ACU write ok\n%s", ""); 887 exit(0); 888 } 889 /* open line - will return on carrier */ 890 dcf = open(dcname, O_RDWR); 891 892 DEBUG(4, "dcf is %d\n", dcf); 893 if (dcf < 0) { /* handle like a timeout */ 894 (void) alarm(0); 895 longjmp(Sjbuf, 1); 896 } 897 898 /* modem is open */ 899 while ((w_ret = wait(<)) != pid) 900 if (w_ret == -1 && errno != EINTR) { 901 DEBUG(4, "Wait failed errno=%d\n", errno); 902 (void) close(dcf); 903 (void) close(dnf); 904 Uerror = SS_DIAL_FAILED; 905 return(FAIL); 906 } 907 (void) alarm(0); 908 909 (void) close(dnf); /* no reason to keep the 801 open */ 910 if (lt != 0) { 911 DEBUG(4, "Fork Stat %o\n", lt); 912 (void) close(dcf); 913 Uerror = SS_DIAL_FAILED; 914 return(FAIL); 915 } 916 return(dcf); 917 } 918 919 #else /* ATTSV */ 920 921 GLOBAL int 922 open801(dcname, dnname, phone, speed) 923 char *dcname, *dnname, *phone; 924 { 925 int nw, lt, dcf = -1, nullfd, dnf = -1, ret; 926 unsigned timelim; 927 928 (void) close(nullfd = open("/", O_RDONLY)); /* partial open hack */ 929 if (setjmp(Sjbuf)) { 930 DEBUG(4, "DN write %s\n", "timeout"); 931 (void) close(dnf); 932 (void) close(dcf); 933 (void) close(nullfd); 934 Uerror = SS_DIAL_FAILED; 935 return(FAIL); 936 } 937 (void) signal(SIGALRM, alarmtr); 938 timelim = 5 * strlen(phone); 939 (void) alarm(timelim < connecttime ? connecttime : timelim); 940 941 if ((dnf = open(dnname, O_WRONLY)) < 0 ) { 942 DEBUG(5, "can't open %s\n", dnname); 943 Uerror = SS_CANT_ACCESS_DEVICE; 944 return(FAIL); 945 } 946 DEBUG(5, "%s is open\n", dnname); 947 if ( fd_mklock(dnf) != SUCCESS ) { 948 (void)close(dnf); 949 DEBUG(1, "failed to lock device %s\n", dnname); 950 Uerror = SS_LOCKED_DEVICE; 951 } 952 if ( (dcf = open(dcname, O_RDWR | O_NDELAY)) < 0 ) { 953 DEBUG(5, "can't open %s\n", dcname); 954 Uerror = SS_CANT_ACCESS_DEVICE; 955 return(FAIL); 956 } 957 if ( fd_mklock(dcf) != SUCCESS ) { 958 (void)close(dcf); 959 DEBUG(1, "failed to lock device %s\n", dcname); 960 Uerror = SS_LOCKED_DEVICE; 961 return(FAIL); 962 } 963 964 DEBUG(4, "dcf is %d\n", dcf); 965 fixline(dcf, speed, D_ACU); 966 nw = (*Write)(dnf, phone, lt = strlen(phone)); 967 if (nw != lt) { 968 (void) alarm(0); 969 DEBUG(4, "ACU write error %d\n", errno); 970 (void) close(dnf); 971 (void) close(dcf); 972 Uerror = SS_DIAL_FAILED; 973 return(FAIL); 974 } else 975 DEBUG(4, "ACU write ok\n%s", ""); 976 977 (void) close(dnf); 978 (void) close(nullfd = open("/", O_RDONLY)); /* partial open hack */ 979 ret = open(dcname, O_RDWR); /* wait for carrier */ 980 (void) alarm(0); 981 (void) close(ret); /* close 2nd modem open() */ 982 if (ret < 0) { /* open() interrupted by alarm */ 983 DEBUG(4, "Line open %s\n", "failed"); 984 Uerror = SS_DIAL_FAILED; 985 (void) close(nullfd); /* close partially opened modem */ 986 return(FAIL); 987 } 988 (void) fcntl(dcf,F_SETFL, fcntl(dcf, F_GETFL, 0) & ~O_NDELAY); 989 return(dcf); 990 } 991 #endif /* ATTSV */ 992 993 #endif /* DIAL801 */ 994 995 #ifdef V8 996 GLOBAL int 997 Dialout(flds) 998 char *flds[]; 999 { 1000 int fd; 1001 char phone[MAXPH+2]; 1002 1003 exphone(flds[F_PHONE], phone); 1004 1005 DEBUG(4, "call dialout(%s", phone); 1006 DEBUG(4, ", %s)\n", dev[D_CLASS]); 1007 fd = dialout(phone, dev[D_CLASS]); 1008 if (fd == -1) 1009 Uerror = SS_NO_DEVICE; 1010 if (fd == -3) 1011 Uerror = SS_DIAL_FAILED; 1012 if (fd == -9) 1013 Uerror = SS_DEVICE_FAILED; 1014 1015 (void) strcpy(Dc, "Dialout"); 1016 1017 return(fd); 1018 } 1019 #endif /* V8 */ 1020 1021 #ifdef TLI 1022 /* 1023 * 1024 * AT&T Transport Layer Interface 1025 * 1026 * expected in Devices 1027 * TLI line1 - - TLI 1028 * or 1029 * TLIS line1 - - TLIS 1030 * 1031 */ 1032 1033 #include <sys/tiuser.h> 1034 1035 EXTERN void tfaillog(); 1036 1037 char *t_alloc(); 1038 int t_bind(), t_close(), t_connect(), t_free(), t_look(), t_open(), t_rcvdis(); 1039 1040 #define CONNECT_ATTEMPTS 3 1041 #define TFREE(p, type) if ((p)) t_free((char *)(p), (type)) 1042 1043 /* 1044 * returns fd to remote uucp daemon 1045 */ 1046 /*ARGSUSED*/ 1047 GLOBAL int 1048 tlicall(flds, dev) 1049 char *flds[]; 1050 char *dev[]; 1051 { 1052 char addrbuf[ BUFSIZ ]; 1053 char devname[MAXNAMESIZE]; 1054 int fd; 1055 register int i, j; 1056 struct t_bind *bind_ret = 0; 1057 struct t_info tinfo; 1058 struct t_call *sndcall = 0, *rcvcall = 0; 1059 extern int t_errno; 1060 1061 EXTERN struct netbuf *stoa(); 1062 1063 if ( dev[D_LINE][0] != '/' ) { 1064 /* dev holds device name relative to /dev */ 1065 sprintf(devname, "/dev/%s", dev[D_LINE]); 1066 } else { 1067 /* dev holds full path name of device */ 1068 strcpy(devname, dev[D_LINE]); 1069 } 1070 /* gimme local transport endpoint */ 1071 errno = t_errno = 0; 1072 if (setjmp(Sjbuf)) { 1073 DEBUG(1, "t_open timeout\n%s", ""); 1074 logent("t_open", "TIMEOUT"); 1075 Uerror = SS_NO_DEVICE; 1076 return(FAIL); 1077 } 1078 (void) signal(SIGALRM, alarmtr); 1079 (void) alarm(5); 1080 fd = t_open(devname, O_RDWR, &tinfo); 1081 (void) alarm(0); 1082 if (fd < 0) { 1083 tfaillog(fd, "t_open" ); 1084 Uerror = SS_NO_DEVICE; 1085 return(FAIL); 1086 } 1087 if ( fd_mklock(fd) != SUCCESS ) { 1088 (void)t_close(fd); 1089 DEBUG(1, "tlicall: failed to lock device %s\n", devname); 1090 Uerror = SS_LOCKED_DEVICE; 1091 return(FAIL); 1092 } 1093 1094 /* allocate tli structures */ 1095 errno = t_errno = 0; 1096 if ( (bind_ret = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL)) == 1097 (struct t_bind *)NULL 1098 || (sndcall = (struct t_call *)t_alloc(fd, T_CALL, T_ALL)) == 1099 (struct t_call *)NULL 1100 || (rcvcall = (struct t_call *)t_alloc(fd, T_CALL, T_ALL)) == 1101 (struct t_call *)NULL ) { 1102 tfaillog(fd, "t_alloc" ); 1103 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL); 1104 TFREE(rcvcall, T_CALL); 1105 Uerror = SS_NO_DEVICE; 1106 return(FAIL); 1107 } 1108 1109 /* bind */ 1110 errno = t_errno = 0; 1111 if (t_bind(fd, (struct t_bind *) 0, bind_ret ) < 0) { 1112 tfaillog(fd, "t_bind" ); 1113 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL); 1114 TFREE(rcvcall, T_CALL); 1115 Uerror = SS_NO_DEVICE; 1116 fd_rmlock(fd); 1117 (void) t_close(fd); 1118 return(FAIL); 1119 } 1120 DEBUG(5, "tlicall: bound to %s\n", bind_ret->addr.buf); 1121 1122 /* 1123 * Prepare to connect. 1124 * 1125 * If address begins with "\x", "\X", "\o", or "\O", 1126 * assume is hexadecimal or octal address and use stoa() 1127 * to convert it. 1128 * 1129 * Else is usual uucico address -- only \N's left to process. 1130 * Walk thru connection address, changing \N's to NULLCHARs. 1131 * Note: If a NULLCHAR must be part of the connection address, 1132 * it must be overtly included in the address. One recommended 1133 * way is to do it in the Devices file, thusly: 1134 * Netname /dev/netport - - TLI \D\000 1135 * bsfix() turns \000 into \N and then the loop below makes it a 1136 * real, included-in-the-length null-byte. 1137 * 1138 * The DEBUG must print the strecpy'd address (so that 1139 * non-printables will have been replaced with C escapes). 1140 */ 1141 1142 DEBUG(5, "t_connect to addr \"%s\"\n", 1143 strecpy( addrbuf, dev[D_ARG], "\\" ) ); 1144 1145 if ( dev[D_ARG][0] == '\\' && 1146 ( dev[D_ARG][1] == 'x' || dev[D_ARG][1] == 'X' 1147 || dev[D_ARG][1] == 'o' || dev[D_ARG][1] == 'O' ) ) { 1148 if ( stoa(dev[D_ARG], &(sndcall->addr)) == (struct netbuf *)NULL ) { 1149 DEBUG(5, "tlicall: stoa failed\n%s", ""); 1150 logent("tlicall", "string-to-address failed"); 1151 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL); 1152 TFREE(rcvcall, T_CALL); 1153 Uerror = SS_NO_DEVICE; 1154 fd_rmlock(fd); 1155 (void) t_close(fd); 1156 return(FAIL); 1157 } 1158 } else { 1159 for( i = j = 0; i < BUFSIZ && dev[D_ARG][i] != NULLCHAR; 1160 ++i, ++j ) { 1161 if( dev[D_ARG][i] == '\\' && dev[D_ARG][i+1] == 'N' ) { 1162 addrbuf[j] = NULLCHAR; 1163 ++i; 1164 } 1165 else { 1166 addrbuf[j] = dev[D_ARG][i]; 1167 } 1168 } 1169 sndcall->addr.buf = addrbuf; 1170 sndcall->addr.len = j; 1171 } 1172 1173 if (setjmp(Sjbuf)) { 1174 DEBUG(4, "timeout tlicall\n%s", ""); 1175 logent("tlicall", "TIMEOUT"); 1176 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL); 1177 TFREE(rcvcall, T_CALL); 1178 Uerror = SS_NO_DEVICE; 1179 fd_rmlock(fd); 1180 (void) t_close(fd); 1181 return(FAIL); 1182 } 1183 (void) signal(SIGALRM, alarmtr); 1184 (void) alarm(connecttime); 1185 1186 /* connect to the service -- some listeners can't handle */ 1187 /* multiple connect requests, so try it a few times */ 1188 errno = t_errno = 0; 1189 for ( i = 0; i < CONNECT_ATTEMPTS; ++i ) { 1190 if (t_connect(fd, sndcall, rcvcall) == 0) 1191 break; 1192 if ( (t_errno == TLOOK) && (t_look(fd) == T_DISCONNECT)) { 1193 t_rcvdis(fd,NULL); 1194 (void) alarm(0); 1195 } else { 1196 (void) alarm(0); 1197 tfaillog(fd, "t_connect"); 1198 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL); 1199 TFREE(rcvcall, T_CALL); 1200 Uerror = SS_DIAL_FAILED; 1201 fd_rmlock(fd); 1202 (void) t_close(fd); 1203 return(FAIL); 1204 } 1205 } 1206 (void) alarm(0); 1207 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL); 1208 TFREE(rcvcall, T_CALL); 1209 if ( i == CONNECT_ATTEMPTS ) { 1210 tfaillog(fd, "t_connect"); 1211 Uerror = SS_DIAL_FAILED; 1212 fd_rmlock(fd); 1213 (void) t_close(fd); 1214 return(FAIL); 1215 } 1216 errno = t_errno = 0; 1217 (void) strcpy(Dc, dev[D_CALLER]); 1218 return(fd); 1219 } 1220 #endif /* TLI */ 1221