1 #ifndef lint 2 static char sccsid[] = "@(#)conn.c 5.5 (Berkeley) 04/10/85"; 3 #endif 4 5 #include "uucp.h" 6 #include <signal.h> 7 #include <setjmp.h> 8 #include <ctype.h> 9 #include <errno.h> 10 #ifdef USG 11 #include <termio.h> 12 #include <fcntl.h> 13 #endif 14 #ifndef USG 15 #include <sgtty.h> 16 #endif 17 #ifdef BSD4_2 18 #include <sys/time.h> 19 #else 20 #include <time.h> 21 #endif 22 23 #define MAXC 1000 24 25 extern jmp_buf Sjbuf; 26 jmp_buf Cjbuf; 27 extern int errno, onesys; 28 extern char *sys_errlist[]; 29 extern char MaxGrade, DefMaxGrade; 30 31 /* Parity control during login procedure */ 32 #define P_ZERO 0 33 #define P_ONE 1 34 #define P_EVEN 2 35 #define P_ODD 3 36 37 #define ABORT -2 38 39 char *AbortOn = NULL; 40 char par_tab[128]; /* must be power of two */ 41 int linebaudrate; /* used for the sleep test in pk1.c */ 42 int next_fd = -1; /* predicted fd to close interrupted opens */ 43 /* rti!trt, courtesy unc!smb */ 44 /*** 45 * alarmtr() - catch alarm routine for "expect". 46 */ 47 alarmtr() 48 { 49 signal(SIGALRM, alarmtr); 50 if (next_fd >= 0) { 51 if (close(next_fd)) 52 logent("FAIL", "ACU LINE CLOSE"); 53 next_fd = -1; 54 } 55 longjmp(Sjbuf, 1); 56 } 57 58 /* 59 * place a telephone call to system and login, etc. 60 * 61 * return codes: 62 * CF_SYSTEM: don't know system 63 * CF_TIME: wrong time to call 64 * CF_DIAL: call failed 65 * CF_NODEV: no devices available to place call 66 * CF_LOGIN: login/password dialog failed 67 * 68 * >0 - file no. - connect ok 69 */ 70 71 int Dcf = -1; 72 char *Flds[MAXC/10]; 73 extern int LocalOnly; 74 75 conn(system) 76 char *system; 77 { 78 int ret, nf; 79 register int fn = 0; 80 char info[MAXC], wkpre[NAMESIZE], file[NAMESIZE]; 81 register FILE *fsys; 82 int fcode = 0; 83 84 nf = 0; 85 86 fsys = fopen(SYSFILE, "r"); 87 ASSERT(fsys != NULL, "CAN'T OPEN", SYSFILE, 0); 88 89 DEBUG(4, "finds (%s) called\n", system); 90 while((nf = finds(fsys, system, info, Flds)) > 0) { 91 if (LocalOnly) { 92 if (strcmp("TCP", Flds[F_LINE]) 93 && strcmp("DIR", Flds[F_LINE]) 94 && strcmp("LOCAL", Flds[F_LINE]) ) 95 fn = CF_TIME; 96 } 97 sprintf(wkpre, "%c.%.7s", CMDPRE, Rmtname); 98 if (!onesys && MaxGrade != DefMaxGrade && 99 !iswrk(file, "chk", Spool, wkpre)) 100 fn = CF_TIME; 101 if (fn != CF_TIME && (fn = getto(Flds)) > 0) { 102 Dcf = fn; 103 break; 104 } 105 fcode = (fn == FAIL ? CF_DIAL : fn); 106 } 107 fclose(fsys); 108 109 if (nf <= 0) 110 return fcode ? fcode : nf; 111 112 DEBUG(4, "login %s\n", "called"); 113 ret = login(nf, Flds, fn); 114 if (ret == FAIL) { 115 clsacu(); 116 return CF_LOGIN; 117 } 118 /* rti!trt: avoid passing file to children */ 119 fioclex(fn); 120 return fn; 121 } 122 123 /*** 124 * getto(flds) connect to remote machine 125 * char *flds[]; 126 * 127 * return codes: 128 * >0 - file number - ok 129 * FAIL - failed 130 */ 131 132 getto(flds) 133 register char *flds[]; 134 { 135 register struct condev *cd; 136 int nulldev(), diropn(); 137 138 DEBUG(4, "getto: call no. %s ", flds[F_PHONE]); 139 DEBUG(4, "for sys %s\n", flds[F_NAME]); 140 141 CU_end = nulldev; 142 for (cd = condevs; cd->CU_meth != NULL; cd++) { 143 if (snccmp(cd->CU_meth, flds[F_LINE]) == SAME) { 144 DEBUG(4, "Using %s to call\n", cd->CU_meth); 145 return (*(cd->CU_gen))(flds); 146 } 147 } 148 DEBUG(1, "Can't find %s, assuming DIR", flds[F_LINE]); 149 return diropn(flds); /* search failed, so use direct */ 150 } 151 152 /*** 153 * clsacu() close call unit 154 * 155 * return codes: none 156 */ 157 158 int (*CU_end)() = nulldev; 159 clsacu() 160 { 161 /* make *sure* Dcf is no longer exclusive. 162 * Otherwise dual call-in/call-out modems could get stuck. 163 * Unfortunately, doing this here is not ideal, but it is the 164 * easiest place to put the call. 165 * Hopefully everyone honors the LCK protocol, of course 166 */ 167 #ifndef USG 168 ioctl(Dcf, TIOCNXCL, STBNULL); 169 #endif 170 if (setjmp(Sjbuf)) 171 logent(Rmtname, "CLOSE TIMEOUT"); 172 else { 173 signal(SIGALRM, alarmtr); 174 alarm(20); 175 (*(CU_end))(Dcf); 176 alarm(0); 177 } 178 if (close(Dcf) == 0) { 179 DEBUG(4, "fd %d NOT CLOSED by CU_clos\n", Dcf); 180 logent("clsacu", "NOT CLOSED by CU_clos"); 181 } 182 Dcf = -1; 183 CU_end = nulldev; 184 } 185 186 /*** 187 * exphone - expand phone number for given prefix and number 188 * 189 * return code - none 190 */ 191 192 exphone(in, out) 193 register char *in, *out; 194 { 195 FILE *fn; 196 char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH]; 197 char buf[BUFSIZ]; 198 register char *s1; 199 200 if (!isascii(*in) || !isalpha(*in)) { 201 strcpy(out, in); 202 return; 203 } 204 205 s1=pre; 206 while (isascii(*in) && isalpha(*in)) 207 *s1++ = *in++; 208 *s1 = '\0'; 209 s1 = npart; 210 while (*in != '\0') 211 *s1++ = *in++; 212 *s1 = '\0'; 213 214 tpre[0] = '\0'; 215 if ((fn = fopen(DIALFILE, "r")) == NULL) 216 DEBUG(2, "CAN'T OPEN %s\n", DIALFILE); 217 else { 218 while (cfgets(buf, BUFSIZ, fn)) { 219 if (sscanf(buf, "%s%s", p, tpre) != 2) 220 continue; 221 if (strcmp(p, pre) == SAME) 222 goto found; 223 tpre[0] = '\0'; 224 } 225 DEBUG(2, "CAN'T FIND dialcodes prefix '%s'\n", pre); 226 found:; 227 fclose(fn); 228 } 229 230 strcpy(out, tpre); 231 strcat(out, npart); 232 } 233 234 /* 235 * read and decode a line from device file 236 * 237 * return code - FAIL at end-of file; 0 otherwise 238 */ 239 240 rddev(fp, dev) 241 register struct Devices *dev; 242 FILE *fp; 243 { 244 register int na; 245 246 if (!cfgets(dev->D_argbfr, sizeof(dev->D_argbfr), fp)) 247 return FAIL; 248 na = getargs(dev->D_argbfr, dev->D_arg, 20); 249 ASSERT(na >= 4, "BAD DEVICE ENTRY", dev->D_argbfr, 0); 250 if (na == 4) { 251 dev->D_brand = ""; 252 na++; 253 } 254 dev->D_speed = atoi(fdig(dev->D_class)); 255 dev->D_numargs = na; 256 return 0; 257 } 258 259 /* 260 * set system attribute vector 261 * 262 * return codes: 263 * >0 - number of arguments in vector - succeeded 264 * CF_SYSTEM - system name not found 265 * CF_TIME - wrong time to call 266 */ 267 268 finds(fsys, sysnam, info, flds) 269 char *sysnam, info[], *flds[]; 270 FILE *fsys; 271 { 272 int na; 273 int fcode = 0; 274 275 /* format of fields 276 * 0 name; 277 * 1 time 278 * 2 acu/hardwired 279 * 3 speed 280 * etc 281 */ 282 while (cfgets(info, MAXC, fsys) != NULL) { 283 na = getargs(info, flds, MAXC/10); 284 if (strncmp(sysnam, flds[F_NAME], 7) != SAME) 285 continue; 286 if (ifdate(flds[F_TIME]) != FAIL) 287 /* found a good entry */ 288 return na; 289 DEBUG(2, "Wrong time ('%s') to call\n", flds[F_TIME]); 290 fcode = CF_TIME; 291 } 292 return fcode ? fcode : CF_SYSTEM; 293 } 294 295 /* 296 * do login conversation 297 * 298 * return codes: 0 | FAIL 299 */ 300 301 login(nf, flds, fn) 302 register char *flds[]; 303 int nf, fn; 304 { 305 register char *want, *altern; 306 extern char *index(); 307 int k, ok; 308 309 ASSERT(nf > 4, "TOO FEW LOG FIELDS", CNULL, nf); 310 if (setjmp(Cjbuf)) 311 return FAIL; 312 AbortOn = NULL; 313 for (k = F_LOGIN; k < nf; k += 2) { 314 want = flds[k]; 315 ok = FAIL; 316 while (ok != SUCCESS) { 317 altern = index(want, '-'); 318 if (altern != NULL) 319 *altern++ = '\0'; 320 if (strcmp(want, "ABORT") == 0) { 321 AbortOn = flds[k+1]; 322 DEBUG(4, "ABORT ON: %s\n", AbortOn); 323 goto nextfield; 324 } 325 DEBUG(4, "wanted: %s\n", want); 326 ok = expect(want, fn); 327 DEBUG(4, "got: %s\n", ok ? "?" : "that"); 328 if (ok == FAIL) { 329 if (altern == NULL) { 330 logent("LOGIN", _FAILED); 331 return FAIL; 332 } 333 want = index(altern, '-'); 334 if (want != NULL) 335 *want++ = '\0'; 336 sendthem(altern, fn); 337 } else 338 if (ok == ABORT) { 339 logent("LOGIN ABORTED", _FAILED); 340 return FAIL; 341 } 342 } 343 sleep(1); 344 if (k+1 < nf) 345 sendthem(flds[k+1], fn); 346 nextfield: ; 347 } 348 return SUCCESS; 349 } 350 351 352 /* conditional table generation to support odd speeds */ 353 struct sg_spds {int sp_val, sp_name;} spds[] = { 354 #ifdef B50 355 { 50, B50}, 356 #endif 357 #ifdef B75 358 { 75, B75}, 359 #endif 360 #ifdef B110 361 { 110, B110}, 362 #endif 363 #ifdef B150 364 { 150, B150}, 365 #endif 366 #ifdef B200 367 { 200, B200}, 368 #endif 369 #ifdef B300 370 { 300, B300}, 371 #endif 372 #ifdef B600 373 {600, B600}, 374 #endif 375 #ifdef B1200 376 {1200, B1200}, 377 #endif 378 #ifdef B1800 379 {1800, B1800}, 380 #endif 381 #ifdef B2000 382 {2000, B2000}, 383 #endif 384 #ifdef B2400 385 {2400, B2400}, 386 #endif 387 #ifdef B3600 388 {3600, B3600}, 389 #endif 390 #ifdef B4800 391 {4800, B4800}, 392 #endif 393 #ifdef B7200 394 {7200, B7200}, 395 #endif 396 #ifdef B9600 397 {9600, B9600}, 398 #endif 399 #ifdef B19200 400 {19200, B19200}, 401 #endif 402 #ifdef EXTA 403 {19200, EXTA}, 404 #endif 405 {0, 0} 406 }; 407 408 /* 409 * set speed/echo/mode... 410 * 411 * return codes: none 412 */ 413 414 fixline(tty, spwant) 415 int tty, spwant; 416 { 417 #ifdef USG 418 struct termio ttbuf; 419 #else !USG 420 struct sgttyb ttbuf; 421 #endif !USG 422 register struct sg_spds *ps; 423 int speed = -1; 424 int ret; 425 426 for (ps = spds; ps->sp_val; ps++) 427 if (ps->sp_val == spwant) 428 speed = ps->sp_name; 429 ASSERT(speed >= 0, "BAD SPEED", CNULL, speed); 430 #ifdef USG 431 ioctl(tty, TCGETA, &ttbuf); 432 /* ttbuf.sg_flags = (ANYP|RAW); 433 ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; */ 434 ttbuf.c_iflag = (ushort)0; 435 ttbuf.c_oflag = (ushort)0; 436 ttbuf.c_cflag = (speed|CS8|HUPCL|CREAD); 437 ttbuf.c_lflag = (ushort)0; 438 ttbuf.c_cc[VMIN] = 6; 439 ttbuf.c_cc[VTIME] = 1; 440 ret = ioctl(tty, TCSETA, &ttbuf); 441 #else !USG 442 ioctl(tty, TIOCGETP, &ttbuf); 443 ttbuf.sg_flags = (ANYP|RAW); 444 ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; 445 ret = ioctl(tty, TIOCSETP, &ttbuf); 446 #endif 447 ASSERT(ret >= 0, "RETURN FROM STTY", CNULL, ret); 448 #ifndef USG 449 ioctl(tty, TIOCHPCL, STBNULL); 450 ioctl(tty, TIOCEXCL, STBNULL); 451 #endif 452 linebaudrate = spwant; 453 return; 454 } 455 456 #define MR 100 457 458 /* 459 * look for expected string 460 * 461 * return codes: 462 * 0 - found 463 * FAIL - lost line or too many characters read 464 * some character - timed out 465 */ 466 467 expect(str, fn) 468 register char *str; 469 int fn; 470 { 471 char rdvec[MR]; 472 register char *rp = rdvec, *strptr; 473 int kr, cnt_char; 474 char nextch; 475 476 if (*str == '\0' || strcmp(str, "\"\"") == SAME) 477 return SUCCESS; 478 /* Cleanup str, convert \0xx strings to one char */ 479 for (strptr = str; *strptr; strptr++) { 480 if (*strptr == '\\') 481 switch(*++strptr) { 482 case 's': 483 DEBUG(5, "BLANK\n", CNULL); 484 *strptr = ' '; 485 break; 486 default: 487 strptr--; /* back up to backslash */ 488 sscanf(strptr + 1,"%o", &cnt_char); 489 DEBUG(6, "BACKSLASHED %02xH\n", cnt_char); 490 *strptr = (char) (cnt_char); 491 strcpy(&strptr[1], &strptr[4]); 492 } 493 } 494 495 *rp = 0; 496 if (setjmp(Sjbuf)) 497 return FAIL; 498 signal(SIGALRM, alarmtr); 499 alarm(MAXMSGTIME); 500 while (notin(str, rdvec)) { 501 if(AbortOn != NULL && !notin(AbortOn, rdvec)) { 502 DEBUG(1, "Call aborted on '%s'\n", AbortOn); 503 alarm(0); 504 return ABORT; 505 } 506 kr = read(fn, &nextch, 1); 507 if (kr <= 0) { 508 alarm(0); 509 DEBUG(4, "lost line kr - %d\n, ", kr); 510 logent("LOGIN", "LOST LINE"); 511 return FAIL; 512 } 513 { 514 int c; 515 c = nextch & 0177; 516 DEBUG(4, c >= 040 ? "%c" : "\\%03o", c); 517 if (c == '\n') 518 DEBUG(4,"\n", CNULL); 519 } 520 if ((*rp = nextch & 0177) != '\0') 521 rp++; 522 if (rp >= rdvec + MR) { 523 register char *p; 524 for (p = rdvec+MR/2; p < rp; p++) 525 *(p-MR/2) = *p; 526 rp -= MR/2; 527 } 528 *rp = '\0'; 529 } 530 alarm(0); 531 return SUCCESS; 532 } 533 534 535 /* 536 * Determine next file descriptor that would be allocated. 537 * This permits later closing of a file whose open was interrupted. 538 * It is a UNIX kernel problem, but it has to be handled. 539 * unc!smb (Steve Bellovin) probably first discovered it. 540 */ 541 getnextfd() 542 { 543 close(next_fd = open("/", 0)); 544 } 545 546 /* 547 * send line of login sequence 548 * 549 * return codes: none 550 */ 551 sendthem(str, fn) 552 register char *str; 553 int fn; 554 { 555 register char *strptr; 556 int i, n, cr = 1; 557 register char c; 558 static int p_init = 0; 559 560 DEBUG(5, "send %s\n", str); 561 562 if (!p_init) { 563 p_init++; 564 bld_partab(P_EVEN); 565 } 566 567 if (prefix("BREAK", str)) { 568 sscanf(&str[5], "%1d", &i); 569 if (i <= 0 || i > 10) 570 i = 3; 571 /* send break */ 572 genbrk(fn, i); 573 return; 574 } 575 576 if (prefix("PAUSE", str)) { 577 sscanf(&str[5], "%1d", &i); 578 if (i <= 0 || i > 10) 579 i = 3; 580 /* pause for a while */ 581 sleep((unsigned)i); 582 return; 583 } 584 585 if (strcmp(str, "EOT") == SAME) { 586 p_chwrite(fn, '\04'); 587 return; 588 } 589 590 /* Send a '\n' */ 591 if (strcmp(str, "LF") == SAME) 592 str = "\\n\\c"; 593 594 /* Send a '\r' */ 595 if (strcmp(str, "CR") == SAME) 596 str = "\\r\\c"; 597 598 /* Set parity as needed */ 599 if (strcmp(str, "P_ZERO") == SAME) { 600 bld_partab(P_ZERO); 601 return; 602 } 603 if (strcmp(str, "P_ONE") == SAME) { 604 bld_partab(P_ONE); 605 return; 606 } 607 if (strcmp(str, "P_EVEN") == SAME) { 608 bld_partab(P_EVEN); 609 return; 610 } 611 if (strcmp(str, "P_ODD") == SAME) { 612 bld_partab(P_ODD); 613 return; 614 } 615 616 /* If "", just send '\r' */ 617 if (strcmp(str, "\"\"") == SAME) { 618 p_chwrite(fn, '\r'); 619 return; 620 } 621 622 for (strptr = str; c = *strptr++;) { 623 if (c == '\\') { 624 switch(*strptr++) { 625 case 's': 626 DEBUG(5, "BLANK\n", CNULL); 627 p_chwrite(fn, ' '); 628 break; 629 case 'd': 630 DEBUG(5, "DELAY\n", CNULL); 631 sleep(1); 632 continue; 633 case 'r': 634 DEBUG(5, "RETURN\n", CNULL); 635 p_chwrite(fn, '\r'); 636 break; 637 case 'b': 638 if (isdigit(*strptr)) { 639 i = (*strptr++ - '0'); 640 if (i <= 0 || i > 10) 641 i = 3; 642 } else 643 i = 3; 644 /* send break */ 645 genbrk(fn, i); 646 if (*strptr == '\0') 647 cr = 0; 648 continue; 649 case 'c': 650 if (*strptr == '\0') { 651 DEBUG(5, "NO CR\n", CNULL); 652 cr = 0; 653 continue; 654 } 655 DEBUG(5, "NO CR - MIDDLE IGNORED\n", CNULL); 656 continue; 657 default: 658 if (isdigit(*strptr)) { 659 i = 0; 660 n = 0; 661 while (isdigit(*strptr) && ++n <= 3) 662 i = i*8 + (*strptr++ - '0'); 663 p_chwrite(fn, (char)i); 664 continue; 665 } 666 DEBUG(5, "BACKSLASH\n", CNULL); 667 --strptr; 668 } 669 } else 670 p_chwrite(fn, c); 671 } 672 673 if (cr) 674 p_chwrite(fn, '\r'); 675 return; 676 } 677 678 p_chwrite(fd, c) 679 int fd; 680 char c; 681 { 682 c = par_tab[c&0177]; 683 if (write(fd, &c, 1) != 1) { 684 logent(sys_errlist[errno], "BAD WRITE"); 685 longjmp(Cjbuf, 2); 686 } 687 } 688 689 /* 690 * generate parity table for use by p_chwrite. 691 */ 692 bld_partab(type) 693 int type; 694 { 695 register int i, j, n; 696 697 for (i = 0; i < sizeof(par_tab); i++) { 698 n = 0; 699 for (j = i&(sizeof(par_tab)-1); j; j = (j-1)&j) 700 n++; 701 par_tab[i] = i; 702 if (type == P_ONE 703 || (type == P_EVEN && (n&01) != 0) 704 || (type == P_ODD && (n&01) == 0)) 705 par_tab[i] |= sizeof(par_tab); 706 } 707 } 708 709 #define BSPEED B150 710 711 /* 712 * send a break 713 * 714 * return codes; none 715 */ 716 717 genbrk(fn, bnulls) 718 register int fn, bnulls; 719 { 720 register int ret; 721 #ifdef USG 722 ret = ioctl(fn, TCSBRK, STBNULL); 723 DEBUG(5, "break ioctl ret %d\n", ret); 724 #else !USG 725 #ifdef TIOCSBRK 726 ret = ioctl(fn, TIOCSBRK, STBNULL); 727 DEBUG(5, "break ioctl ret %d\n", ret); 728 #ifdef TIOCCBRK 729 sleep(1); 730 ret = ioctl(fn, TIOCCBRK, STBNULL); 731 DEBUG(5, "break ioctl ret %d\n", ret); 732 #endif TIOCCBRK 733 DEBUG(4, "ioctl %d second break\n", bnulls ); 734 #else !TIOCSBRK 735 struct sgttyb ttbuf; 736 register int sospeed; 737 738 ret = ioctl(fn, TIOCGETP, &ttbuf); 739 sospeed = ttbuf.sg_ospeed; 740 ttbuf.sg_ospeed = BSPEED; 741 ret = ioctl(fn, TIOCSETP, &ttbuf); 742 ret = write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", bnulls); 743 if (ret != bnulls) { 744 badbreak: 745 logent(sys_errlist[errno], "BAD WRITE genbrk"); 746 alarm(0); 747 longjmp(Sjbuf, 3); 748 } 749 ttbuf.sg_ospeed = sospeed; 750 ret = ioctl(fn, TIOCSETP, &ttbuf); 751 ret = write(fn, "@", 1); 752 if (ret != 1) 753 goto badbreak; 754 DEBUG(4, "sent BREAK nulls - %d\n", bnulls); 755 #endif !TIOCSBRK 756 #endif !USG 757 } 758 759 /* 760 * check for occurrence of substring "sh" 761 * 762 * return codes: 763 * 0 - found the string 764 * 1 - not in the string 765 */ 766 notin(sh, lg) 767 register char *sh, *lg; 768 { 769 while (*lg != '\0') { 770 if (wprefix(sh, lg)) 771 return 0; 772 else 773 lg++; 774 } 775 return 1; 776 } 777 778 /* 779 * Allow multiple date specifications separated by '|'. 780 */ 781 ifdate(p) 782 register char *p; 783 { 784 register int ret, g; 785 786 ret = FAIL; 787 MaxGrade = '\0'; 788 do { 789 g = ifadate(p); 790 DEBUG(11,"ifadate returns %o\n", g); 791 if (g != FAIL) { 792 ret = SUCCESS; 793 if (g > MaxGrade) 794 MaxGrade = g; 795 } 796 p = index(p, '|'); 797 } while (p++ && *p); 798 return ret; 799 } 800 801 /* 802 * this routine will check a string (string) 803 * like "MoTu0800-1730" to see if the present 804 * time is within the given limits. 805 * SIDE EFFECT - Retrytime is set 806 * 807 * return codes: 808 * 0 - not within limits 809 * 1 - within limits 810 */ 811 812 ifadate(string) 813 char *string; 814 { 815 static char *days[]={ 816 "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0 817 }; 818 time_t clock; 819 register char *s = string; 820 int rtime; 821 int i, tl, th, tn, dayok=0; 822 struct tm *localtime(); 823 struct tm *tp; 824 char *p, MGrade; 825 826 /* pick up retry time for failures */ 827 /* global variable Retrytime is set here */ 828 if ((p = index(s, ',')) == NULL) { 829 Retrytime = RETRYTIME; 830 } else { 831 i = sscanf(p+1, "%d", &rtime); 832 if (i < 1 || rtime < 0) 833 rtime = 5; 834 Retrytime = rtime * 60; 835 } 836 837 if ((p = index(s, '@')) == NULL) 838 MGrade = DefMaxGrade; 839 else 840 MGrade = p[1]; 841 842 time(&clock); 843 tp = localtime(&clock); 844 while (isascii(*s) && isalpha(*s)) { 845 for (i = 0; days[i]; i++) { 846 if (prefix(days[i], s)) 847 if (tp->tm_wday == i) 848 dayok = 1; 849 } 850 851 if (prefix("Wk", s)) 852 if (tp->tm_wday >= 1 && tp->tm_wday <= 5) 853 dayok = 1; 854 if (prefix("Any", s)) 855 dayok = 1; 856 if (prefix("Evening", s)) { 857 /* Sat or Sun */ 858 if (tp->tm_wday == 6 || tp->tm_wday == 0 859 || tp->tm_hour >= 17 || tp->tm_hour < 8) 860 dayok = 1; 861 } 862 if (prefix("Night", s)) { 863 if (tp->tm_wday == 6 /* Sat */ 864 || tp->tm_hour >= 23 || tp->tm_hour < 8 865 /* Sunday before 5pm */ 866 || (tp->tm_wday == 0 && tp->tm_hour < 17)) 867 dayok = 1; 868 } 869 s++; 870 } 871 872 if (dayok == 0 && s != string) 873 return FAIL; 874 i = sscanf(s, "%d-%d", &tl, &th); 875 if (i < 2) 876 return MGrade; 877 tn = tp->tm_hour * 100 + tp->tm_min; 878 if (th < tl) { /* crosses midnight */ 879 if (tl <= tn || tn < th) 880 return MGrade; 881 } else 882 883 if (i < 2) 884 return MGrade; 885 if (th < tl) { /* crosses midnight */ 886 if (tl <= tn || tn < th) 887 return MGrade; 888 } else 889 if (tl <= tn && tn < th) 890 return MGrade; 891 return FAIL; 892 } 893 894 /* 895 * find first digit in string 896 * 897 * return - pointer to first digit in string or end of string 898 */ 899 char * 900 fdig(cp) 901 register char *cp; 902 { 903 register char *c; 904 905 for (c = cp; *c; c++) 906 if (*c >= '0' && *c <= '9') 907 break; 908 return c; 909 } 910 911 /* 912 * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0 913 * Strings are compared as if they contain all capital letters. 914 */ 915 snccmp(s1, s2) 916 register char *s1, *s2; 917 { 918 char c1, c2; 919 920 if (islower(*s1)) c1 = toupper(*s1); 921 else c1 = *s1; 922 if (islower(*s2)) c2 = toupper(*s2); 923 else c2 = *s2; 924 925 while (c1 == c2) { 926 if (*s1++=='\0') 927 return 0; 928 s2++; 929 if (islower(*s1)) c1 = toupper(*s1); 930 else c1 = *s1; 931 if (islower(*s2)) c2 = toupper(*s2); 932 else c2 = *s2; 933 } 934 return c1 - c2; 935 } 936 /* 937 * do chat script 938 * occurs after local port is opened, 939 * before 'dialing' the other machine. 940 */ 941 dochat(dev, flds, fd) 942 register struct Devices *dev; 943 char *flds[]; 944 int fd; 945 { 946 register int i; 947 register char *p; 948 char bfr[sizeof(dev->D_argbfr)]; 949 950 if (dev->D_numargs <= 5) 951 return(0); 952 DEBUG(4, "dochat called %d\n", dev->D_numargs); 953 for (i = 0; i < dev->D_numargs-5; i++) { 954 sprintf(bfr, dev->D_arg[D_CHAT+i], flds[F_PHONE]); 955 if (strcmp(bfr, dev->D_arg[D_CHAT+i])) { 956 p = malloc((unsigned)strlen(bfr)+1); 957 if (p != NULL) { 958 strcpy(p, bfr); 959 dev->D_arg[D_CHAT+i] = p; 960 } 961 } 962 } 963 /* following is a kludge because login() arglist is a kludge */ 964 i = login(dev->D_numargs, &dev->D_arg[D_CHAT-5], fd); 965 /* 966 * If login() last did a sendthem(), must pause so things can settle. 967 * But don't bother if chat failed. 968 */ 969 if (i == 0 && (dev->D_numargs&01)) 970 sleep(2); 971 return(i); 972 } 973