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 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 * 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 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 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 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 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 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 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 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 682 unetcall(flds, dev) 683 char *flds[], *dev[]; 684 { 685 Uerror = SS_NO_DEVICE; 686 return(FAIL); 687 } 688 #else /* UNET */ 689 GLOBAL int 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 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