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