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 (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 /* 26 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 #include "mt.h" 31 #include "uucp.h" 32 static char _ProtoSys[40]; /* protocol string from Systems file entry */ 33 static char _ProtoDev[40]; /* protocol string from Devices file entry */ 34 static char _ProtoCfg[]; /* protocol string from Config file entry */ 35 36 static jmp_buf Sjbuf; 37 static unsigned expecttime; 38 39 static int Modemctrl; 40 41 static void alarmtr(int); 42 static void getProto(char *, char *); 43 static int finds(char *, char *[], int); 44 static int getto(char *[]); /* make this static when ct uses altconn() */ 45 static int chat(int, char *[], int, char *, char *); 46 static int rddev(char *, char *[], char *, int); 47 static int expect(char *, int); 48 static int wrstr(int, char *, int, int); 49 static int wrchr(int, char *, int); 50 static int processdev(char *[], char *[]); 51 static int getdevline(char *, int); 52 static int getsysline(char *, int); 53 static int sysaccess(int); 54 static int clear_hup(int); 55 #ifndef SMALL 56 static char *currsys(void); 57 static char *currdev(void); 58 #endif 59 static int wait_for_hangup(int); 60 static int expect_str(char *, int); 61 62 static void sendthem(char *, int, char *, char *); 63 static void nap(unsigned int); 64 static int notin(char *, char *); 65 static int ifdate(char *); 66 static int classmatch(char *[], char *[]); 67 68 static char *Myline = CNULL; /* to force which line will be used */ 69 static char *Mytype = CNULL; /* to force selection of specific device type */ 70 71 /* 72 * conn - place a telephone call to system and login, etc. 73 * 74 * return codes: 75 * FAIL - connection failed 76 * >0 - file no. - connect ok 77 * When a failure occurs, Uerror is set. 78 */ 79 80 static void sysreset(void); 81 static int 82 conn(char *system) 83 { 84 int nf, fn = FAIL; 85 char *flds[F_MAX+1]; 86 87 CDEBUG(4, "conn(%s)\n", system); 88 Uerror = 0; 89 while ((nf = finds(system, flds, F_MAX)) > 0) { 90 fn = getto(flds); 91 CDEBUG(4, "getto ret %d\n", fn); 92 if (fn < 0) 93 continue; 94 if (EQUALS(Progname, "uucico")) { 95 if (chat(nf - F_LOGIN, flds + F_LOGIN, fn, "", "") == 96 SUCCESS) { 97 sysreset(); 98 return (fn); /* successful return */ 99 } 100 101 /* login failed */ 102 DEBUG(6, "close caller (%d)\n", fn); 103 fd_rmlock(fn); 104 (void) close(fn); 105 if (Dc[0] != NULLCHAR) { 106 /*EMPTY*/ 107 DEBUG(6, "delock line (%s)\n", Dc); 108 } 109 } else { 110 sysreset(); 111 return (fn); 112 } 113 } 114 115 /* finds or getto failed */ 116 sysreset(); 117 CDEBUG(1, "Call Failed: %s\n", UERRORTEXT); 118 return (FAIL); 119 } 120 121 static void devreset(void); 122 123 /* 124 * getto - connect to remote machine 125 * 126 * return codes: 127 * >0 - file number - ok 128 * FAIL - failed 129 */ 130 131 static int 132 getto(char *flds[]) 133 { 134 char *dev[D_MAX+2], devbuf[BUFSIZ]; 135 int status; 136 int dcf = -1; 137 int reread = 0; 138 int tries = 0; /* count of call attempts - for limit purposes */ 139 140 CDEBUG(1, "Device Type %s wanted\n", flds[F_TYPE]); 141 Uerror = 0; 142 while (tries < TRYCALLS) { 143 if ((status = rddev(flds[F_TYPE], dev, devbuf, D_MAX)) == 144 FAIL) { 145 if (tries == 0 || ++reread >= TRYCALLS) 146 break; 147 devreset(); 148 continue; 149 } 150 /* check class, check (and possibly set) speed */ 151 if (classmatch(flds, dev) != SUCCESS) { 152 DEBUG(7, "Skipping entry in '%s'", currdev()); 153 DEBUG(7, " - class (%s) not wanted.\n", dev[D_CLASS]); 154 continue; 155 } 156 DEBUG(5, "Trying device entry from '%s'.\n", currdev()); 157 if ((dcf = processdev(flds, dev)) >= 0) 158 break; 159 160 switch (Uerror) { 161 case SS_CANT_ACCESS_DEVICE: 162 case SS_DEVICE_FAILED: 163 case SS_LOCKED_DEVICE: 164 break; 165 default: 166 tries++; 167 break; 168 } 169 } 170 devreset(); /* reset devices file(s) */ 171 if (status == FAIL && !Uerror) { 172 CDEBUG(1, "Requested Device Type Not Found\n%s", ""); 173 Uerror = SS_NO_DEVICE; 174 } 175 return (dcf); 176 } 177 178 /* 179 * classmatch - process 'Any' in Devices and Systems and 180 * determine the correct speed, or match for == 181 */ 182 183 static int 184 classmatch(char *flds[], char *dev[]) 185 { 186 /* check class, check (and possibly set) speed */ 187 if (EQUALS(flds[F_CLASS], "Any") && EQUALS(dev[D_CLASS], "Any")) { 188 dev[D_CLASS] = DEFAULT_BAUDRATE; 189 return (SUCCESS); 190 } else if (EQUALS(dev[D_CLASS], "Any")) { 191 dev[D_CLASS] = flds[F_CLASS]; 192 return (SUCCESS); 193 } else if (EQUALS(flds[F_CLASS], "Any") || 194 EQUALS(flds[F_CLASS], dev[D_CLASS])) 195 return (SUCCESS); 196 else 197 return (FAIL); 198 } 199 200 201 /* 202 * rddev - find and unpack a line from device file for this caller type 203 * lines starting with whitespace of '#' are comments 204 * 205 * return codes: 206 * >0 - number of arguments in vector - succeeded 207 * FAIL - EOF 208 */ 209 210 static int 211 rddev(char *type, char *dev[], char *buf, int devcount) 212 { 213 char *commap, d_type[BUFSIZ]; 214 int na; 215 216 while (getdevline(buf, BUFSIZ)) { 217 if (buf[0] == ' ' || buf[0] == '\t' || buf[0] == '\n' || 218 buf[0] == '\0' || buf[0] == '#') 219 continue; 220 na = getargs(buf, dev, devcount); 221 ASSERT(na >= D_CALLER, "BAD LINE", buf, na); 222 223 if (strncmp(dev[D_LINE], "/dev/", 5) == 0) { 224 /* since cu (altconn()) strips off leading */ 225 /* "/dev/", do the same here. */ 226 (void) strcpy(dev[D_LINE], &(dev[D_LINE][5])); 227 } 228 229 /* may have ",M" subfield in D_LINE */ 230 Modemctrl = FALSE; 231 if ((commap = strchr(dev[D_LINE], ',')) != NULL) { 232 if (strcmp(commap, ",M") == SAME) 233 Modemctrl = TRUE; 234 *commap = '\0'; 235 } 236 237 /* 238 * D_TYPE field may have protocol subfield, which 239 * must be pulled off before comparing to desired type. 240 */ 241 (void) strcpy(d_type, dev[D_TYPE]); 242 if ((commap = strchr(d_type, ',')) != NULL) 243 *commap = '\0'; 244 245 /* to force the requested device type to be used. */ 246 if ((Mytype != NULL) && (!EQUALS(Mytype, d_type))) 247 continue; 248 /* to force the requested line to be used */ 249 if ((Myline != NULL) && (!EQUALS(Myline, dev[D_LINE]))) 250 continue; 251 252 bsfix(dev); /* replace \X fields */ 253 254 if (EQUALS(d_type, type)) { 255 getProto(_ProtoDev, dev[D_TYPE]); 256 return (na); 257 } 258 } 259 return (FAIL); 260 } 261 262 263 /* 264 * finds - set system attribute vector 265 * 266 * input: 267 * fsys - open Systems file descriptor 268 * sysnam - system name to find 269 * output: 270 * flds - attibute vector from Systems file 271 * fldcount - number of fields in flds 272 * return codes: 273 * >0 - number of arguments in vector - succeeded 274 * FAIL - failed 275 * Uerror set: 276 * 0 - found a line in Systems file 277 * SS_BADSYSTEM - no line found in Systems file 278 * SS_TIME_WRONG - wrong time to call 279 */ 280 281 static int 282 finds(char *sysnam, char *flds[], int fldcount) 283 { 284 static char *info; /* dynamically allocated BUFSIZ */ 285 int na; 286 287 /* 288 * format of fields 289 * 0 name; 290 * 1 time 291 * 2 acu/hardwired 292 * 3 speed 293 * etc 294 */ 295 296 if (sysnam == 0 || *sysnam == 0) { 297 Uerror = SS_BADSYSTEM; 298 return (FAIL); 299 } 300 301 if (info == NULL) { 302 info = malloc(BUFSIZ); 303 if (info == NULL) { 304 DEBUG(1, "malloc failed for info in finds\n", 0); 305 return (0); 306 } 307 } 308 while (getsysline(info, BUFSIZ)) { 309 na = getargs(info, flds, fldcount); 310 bsfix(flds); /* replace \X fields */ 311 if (!EQUALSN(sysnam, flds[F_NAME], MAXBASENAME)) 312 continue; 313 /* check if requested Mytype device type */ 314 if ((Mytype != CNULL) && 315 (!EQUALSN(flds[F_TYPE], Mytype, strlen(Mytype)))) { 316 DEBUG(7, "Skipping entry in '%s'", currsys()); 317 DEBUG(7, " - type (%s) not wanted.\n", flds[F_TYPE]); 318 continue; 319 } else { 320 /*EMPTY*/ 321 DEBUG(5, "Trying entry from '%s'", currsys()); 322 DEBUG(5, " - device type %s.\n", flds[F_TYPE]); 323 } 324 /* OK if not uucico (ie. ct or cu) or the time is right */ 325 if (!EQUALS(Progname, "uucico") || ifdate(flds[F_TIME])) { 326 /* found a good entry */ 327 getProto(_ProtoSys, flds[F_TYPE]); 328 Uerror = 0; 329 return (na); /* FOUND OK LINE */ 330 } 331 CDEBUG(1, "Wrong Time To Call: %s\n", flds[F_TIME]); 332 Uerror = SS_TIME_WRONG; 333 } 334 if (!Uerror) 335 Uerror = SS_BADSYSTEM; 336 return (FAIL); 337 } 338 339 /* 340 * getProto - get the protocol letters from the input string. 341 * input: 342 * str - string from Systems/Devices/Config file, 343 * a ',' delimits the protocol string 344 * e.g. ACU,g or DK,d 345 * output: 346 * str - the , (if present) will be replaced with NULLCHAR 347 * 348 * return: none 349 */ 350 351 static void 352 getProto(char *save, char *str) 353 { 354 char *p; 355 356 *save = NULLCHAR; 357 if ((p = strchr(str, ',')) != NULL) { 358 *p = NULLCHAR; 359 (void) strcpy(save, p+1); 360 DEBUG(7, "Protocol = %s\n", save); 361 } 362 } 363 364 /* 365 * chat - do conversation 366 * input: 367 * nf - number of fields in flds array 368 * flds - fields from Systems file 369 * fn - write file number 370 * phstr1 - phone number to replace \D 371 * phstr2 - phone number to replace \T 372 * 373 * return codes: 0 | FAIL 374 */ 375 376 static int 377 chat(int nf, char *flds[], int fn, char *phstr1, char *phstr2) 378 { 379 char *want, *altern; 380 int k, ok; 381 382 for (k = 0; k < nf; k += 2) { 383 want = flds[k]; 384 ok = FAIL; 385 while (ok != 0) { 386 altern = index(want, '-'); 387 if (altern != NULL) 388 *altern++ = NULLCHAR; 389 ok = expect(want, fn); 390 if (ok == 0) 391 break; 392 if (altern == NULL) { 393 Uerror = SS_LOGIN_FAILED; 394 logent(UERRORTEXT, "FAILED"); 395 return (FAIL); 396 } 397 want = index(altern, '-'); 398 if (want != NULL) 399 *want++ = NULLCHAR; 400 sendthem(altern, fn, phstr1, phstr2); 401 } 402 (void) sleep(2); 403 if (flds[k+1]) 404 sendthem(flds[k+1], fn, phstr1, phstr2); 405 } 406 return (0); 407 } 408 409 #define MR 1000 410 411 /* 412 * expect(str, fn) look for expected string w/ possible special chars 413 * char *str; 414 * 415 * return codes: 416 * 0 - found 417 * FAIL - lost line or too many characters read 418 * some character - timed out 419 */ 420 421 static int 422 expect(char *str, int fn) 423 { 424 char *bptr, *sptr; 425 char buf[BUFSIZ]; 426 427 bptr = buf; 428 429 for (sptr = str; *sptr; sptr++) { 430 if (*sptr == '\\') { 431 switch (*++sptr) { 432 case 'H': 433 *bptr++ = '\0'; 434 if (expect_str(buf, fn) == FAIL) { 435 return (FAIL); 436 } 437 if (wait_for_hangup(fn) == FAIL) { 438 return (FAIL); 439 } 440 bptr = buf; 441 continue; 442 case '\\': 443 *bptr++ = '\\'; 444 continue; 445 default: 446 *bptr++ = '\\'; 447 *bptr++ = *sptr; 448 continue; 449 } 450 } else 451 *bptr++ = *sptr; 452 } 453 *bptr = '\0'; 454 if (expect_str(buf, fn) == FAIL) { 455 return (FAIL); 456 } 457 return (0); 458 } 459 460 /* 461 * expect_str(str, fn) look for expected string, w/ no special chars 462 * 463 * return codes: 464 * 0 - found 465 * FAIL - too many characters read 466 * some character - timed out 467 */ 468 469 static int 470 expect_str(char *str, int fn) 471 { 472 static char rdvec[MR]; 473 char *rp = rdvec; 474 int kr, c; 475 char nextch; 476 477 *rp = 0; 478 479 CDEBUG(4, "expect: (%s", ""); 480 for (c = 0; (kr = str[c]) != 0; c++) 481 if (kr < 040) { 482 /*EMPTY*/ 483 CDEBUG(4, "^%c", kr | 0100); 484 } else { 485 /*EMPTY*/ 486 CDEBUG(4, "%c", kr); 487 } 488 CDEBUG(4, ")\n%s", ""); 489 490 if (EQUALS(str, "\"\"")) { 491 CDEBUG(4, "got it\n%s", ""); 492 return (0); 493 } 494 if (*str == '\0') 495 return (0); 496 if (setjmp(Sjbuf)) 497 return (FAIL); 498 (void) signal(SIGALRM, alarmtr); 499 (void) alarm(expecttime); 500 while (notin(str, rdvec)) { 501 errno = 0; 502 kr = (*Read)(fn, &nextch, 1); 503 if (kr <= 0) { 504 (void) alarm(0); 505 CDEBUG(4, "lost line errno - %d\n", errno); 506 logent("LOGIN", "LOST LINE"); 507 return (FAIL); 508 } 509 c = nextch & 0177; 510 CDEBUG(4, "%s", c < 040 ? "^" : ""); 511 CDEBUG(4, "%c", c < 040 ? c | 0100 : c); 512 if ((*rp = nextch & 0177) != NULLCHAR) 513 rp++; 514 if (rp >= rdvec + MR) { 515 CDEBUG(4, "enough already\n%s", ""); 516 (void) alarm(0); 517 return (FAIL); 518 } 519 *rp = NULLCHAR; 520 } 521 (void) alarm(0); 522 CDEBUG(4, "got it\n%s", ""); 523 return (0); 524 } 525 526 527 /* 528 * alarmtr() - catch alarm routine for "expect". 529 */ 530 /*ARGSUSED*/ 531 static void 532 alarmtr(int sig) 533 { 534 CDEBUG(6, "timed out\n%s", ""); 535 longjmp(Sjbuf, 1); 536 } 537 538 /* 539 * wait_for_hangup() - wait for a hangup to occur on the given device 540 */ 541 int 542 wait_for_hangup(int dcf) 543 { 544 int rval; 545 char buff[BUFSIZ]; 546 547 CDEBUG(4, "Waiting for hangup\n%s", ""); 548 while ((rval = read(dcf, buff, BUFSIZ)) > 0) 549 ; 550 551 if (rval < 0) 552 return (FAIL); 553 CDEBUG(4, "Received hangup\n%s", ""); 554 555 if (clear_hup(dcf) != SUCCESS) { 556 CDEBUG(4, "Unable to clear hup on device\n%s", ""); 557 return (FAIL); 558 } 559 return (SUCCESS); 560 } 561 562 /* 563 * sendthem(str, fn, phstr1, phstr2) send line of chat sequence 564 * char *str, *phstr; 565 * 566 * return codes: none 567 */ 568 569 #define FLUSH() { \ 570 if ((bptr - buf) > 0) \ 571 if (wrstr(fn, buf, bptr - buf, echocheck) != SUCCESS) \ 572 goto err; \ 573 bptr = buf; \ 574 } 575 576 static void 577 sendthem(char *str, int fn, char *phstr1, char *phstr2) 578 { 579 int sendcr = 1, echocheck = 0; 580 char *sptr, *bptr; 581 char buf[BUFSIZ]; 582 struct termio ttybuf; 583 584 /* should be EQUALS, but previous versions had BREAK n for integer n */ 585 586 if (PREFIX("BREAK", str)) { 587 /* send break */ 588 CDEBUG(5, "BREAK\n%s", ""); 589 (*genbrk)(fn); 590 return; 591 } 592 593 if (EQUALS(str, "EOT")) { 594 CDEBUG(5, "EOT\n%s", ""); 595 (void) (*Write)(fn, EOTMSG, strlen(EOTMSG)); 596 return; 597 } 598 599 if (EQUALS(str, "\"\"")) { 600 CDEBUG(5, "\"\"\n%s", ""); 601 str += 2; 602 } 603 604 bptr = buf; 605 CDEBUG(5, "sendthem (%s", ""); 606 for (sptr = str; *sptr; sptr++) { 607 if (*sptr == '\\') { 608 switch (*++sptr) { 609 610 /* adjust switches */ 611 case 'c': /* no CR after string */ 612 FLUSH(); 613 if (sptr[1] == NULLCHAR) { 614 CDEBUG(5, "<NO CR>%s", ""); 615 sendcr = 0; 616 } else { 617 /*EMPTY*/ 618 CDEBUG(5, "<NO CR IGNORED>\n%s", ""); 619 } 620 continue; 621 } 622 623 /* stash in buf and continue */ 624 switch (*sptr) { 625 case 'D': /* raw phnum */ 626 (void) strcpy(bptr, phstr1); 627 bptr += strlen(bptr); 628 continue; 629 case 'T': /* translated phnum */ 630 (void) strcpy(bptr, phstr2); 631 bptr += strlen(bptr); 632 continue; 633 case 'N': /* null */ 634 *bptr++ = 0; 635 continue; 636 case 's': /* space */ 637 *bptr++ = ' '; 638 continue; 639 case '\\': /* backslash escapes itself */ 640 *bptr++ = *sptr; 641 continue; 642 default: /* send the backslash */ 643 *bptr++ = '\\'; 644 *bptr++ = *sptr; 645 continue; 646 647 /* flush buf, perform action, and continue */ 648 case 'E': /* echo check on */ 649 FLUSH(); 650 CDEBUG(5, "ECHO CHECK ON\n%s", ""); 651 echocheck = 1; 652 continue; 653 case 'e': /* echo check off */ 654 FLUSH(); 655 CDEBUG(5, "ECHO CHECK OFF\n%s", ""); 656 echocheck = 0; 657 continue; 658 case 'd': /* sleep briefly */ 659 FLUSH(); 660 CDEBUG(5, "DELAY\n%s", ""); 661 (void) sleep(2); 662 continue; 663 case 'p': /* pause momentarily */ 664 FLUSH(); 665 CDEBUG(5, "PAUSE\n%s", ""); 666 nap(HZ/4); /* approximately 1/4 second */ 667 continue; 668 case 'K': /* inline break */ 669 FLUSH(); 670 CDEBUG(5, "BREAK\n%s", ""); 671 (*genbrk)(fn); 672 continue; 673 case 'M': /* modem control - set CLOCAL */ 674 case 'm': /* no modem control - clear CLOCAL */ 675 FLUSH(); 676 CDEBUG(5, ")\n%s CLOCAL ", 677 (*sptr == 'M' ? "set" : "clear")); 678 if ((*Ioctl)(fn, TCGETA, &ttybuf) != 0) { 679 /*EMPTY*/ 680 CDEBUG(5, 681 "ignored. TCGETA failed, errno %d", 682 errno); 683 } else { 684 if (*sptr == 'M') 685 ttybuf.c_cflag |= CLOCAL; 686 else 687 ttybuf.c_cflag &= ~CLOCAL; 688 if ((*Ioctl)(fn, TCSETAW, &ttybuf) != 0) 689 /*EMPTY*/ 690 CDEBUG(5, 691 "failed. TCSETAW failed, errno %d", 692 errno); 693 } 694 CDEBUG(5, "\n%s", ""); 695 continue; 696 } 697 } else 698 *bptr++ = *sptr; 699 } 700 if (sendcr) 701 *bptr++ = '\r'; 702 if ((bptr - buf) > 0) 703 (void) wrstr(fn, buf, bptr - buf, echocheck); 704 705 err: 706 CDEBUG(5, ")\n%s", ""); 707 } 708 709 #undef FLUSH 710 711 static int 712 wrstr(int fn, char *buf, int len, int echocheck) 713 { 714 int i; 715 char dbuf[BUFSIZ], *dbptr = dbuf; 716 717 buf[len] = 0; 718 719 if (echocheck) 720 return (wrchr(fn, buf, len)); 721 722 if (Debug >= 5) { 723 if (sysaccess(ACCESS_SYSTEMS) == 0) { 724 /* Systems file access ok */ 725 for (i = 0; i < len; i++) { 726 *dbptr = buf[i]; 727 if (*dbptr < 040) { 728 *dbptr++ = '^'; 729 *dbptr = buf[i] | 0100; 730 } 731 dbptr++; 732 } 733 *dbptr = 0; 734 } else 735 (void) strcpy(dbuf, "????????"); 736 CDEBUG(5, "%s", dbuf); 737 } 738 if ((*Write)(fn, buf, len) != len) 739 return (FAIL); 740 return (SUCCESS); 741 } 742 743 static int 744 wrchr(int fn, char *buf, int len) 745 { 746 int i, saccess; 747 char cin, cout; 748 749 saccess = (sysaccess(ACCESS_SYSTEMS) == 0); /* protect Systems file */ 750 if (setjmp(Sjbuf)) 751 return (FAIL); 752 (void) signal(SIGALRM, alarmtr); 753 754 for (i = 0; i < len; i++) { 755 cout = buf[i]; 756 if (saccess) { 757 /*EMPTY*/ 758 CDEBUG(5, "%s", cout < 040 ? "^" : ""); 759 CDEBUG(5, "%c", cout < 040 ? cout | 0100 : cout); 760 } else { 761 /*EMPTY*/ 762 CDEBUG(5, "?%s", ""); 763 } 764 if (((*Write)(fn, &cout, 1)) != 1) 765 return (FAIL); 766 do { 767 (void) alarm(expecttime); 768 if ((*Read)(fn, &cin, 1) != 1) 769 return (FAIL); 770 (void) alarm(0); 771 cin &= 0177; 772 if (saccess) { 773 /*EMPTY*/ 774 CDEBUG(5, "%s", cin < 040 ? "^" : ""); 775 CDEBUG(5, "%c", cin < 040 ? cin | 0100 : cin); 776 } else { 777 /*EMPTY*/ 778 CDEBUG(5, "?%s", ""); 779 } 780 } while (cout != (cin & 0177)); 781 } 782 return (SUCCESS); 783 } 784 785 786 /* 787 * notin(sh, lg) check for occurrence of substring "sh" 788 * char *sh, *lg; 789 * 790 * return codes: 791 * 0 - found the string 792 * 1 - not in the string 793 */ 794 795 static int 796 notin(char *sh, char *lg) 797 { 798 while (*lg != NULLCHAR) { 799 if (PREFIX(sh, lg)) 800 return (0); 801 else 802 lg++; 803 } 804 return (1); 805 } 806 807 808 /* 809 * ifdate(s) 810 * char *s; 811 * 812 * ifdate - this routine will check a string (s) 813 * like "MoTu0800-1730" to see if the present 814 * time is within the given limits. 815 * SIDE EFFECT - Retrytime is set to number following ";" 816 * 817 * String alternatives: 818 * Wk - Mo thru Fr 819 * zero or one time means all day 820 * Any - any day 821 * 822 * return codes: 823 * 0 - not within limits 824 * 1 - within limits 825 */ 826 827 static int 828 ifdate(char *s) 829 { 830 static char *days[] = { 831 "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0 832 }; 833 time_t clock; 834 int t__now; 835 char *p; 836 struct tm *tp; 837 838 (void) time(&clock); 839 tp = localtime(&clock); 840 t__now = tp->tm_hour * 100 + tp->tm_min; /* "navy" time */ 841 842 /* 843 * pick up retry time for failures 844 * global variable Retrytime is set here 845 */ 846 if ((p = rindex(s, ';')) != NULL) 847 if (isdigit(p[1])) { 848 if (sscanf(p+1, "%ld", &Retrytime) < 1) 849 Retrytime = 5; /* 5 minutes is error default */ 850 Retrytime *= 60; 851 *p = NULLCHAR; 852 } 853 854 while (*s) { 855 int i, dayok; 856 857 for (dayok = 0; (!dayok) && isalpha(*s); s++) { 858 if (PREFIX("Any", s)) 859 dayok = 1; 860 else if (PREFIX("Wk", s)) { 861 if (tp->tm_wday >= 1 && tp->tm_wday <= 5) 862 dayok = 1; 863 } else 864 for (i = 0; days[i]; i++) 865 if (PREFIX(days[i], s)) 866 if (tp->tm_wday == i) 867 dayok = 1; 868 } 869 870 if (dayok) { 871 int t__low, t__high; 872 873 while (isalpha(*s)) /* flush remaining day stuff */ 874 s++; 875 876 if ((sscanf(s, "%d-%d", &t__low, &t__high) < 2) || 877 (t__low == t__high)) 878 return (1); 879 880 /* 0000 crossover? */ 881 if (t__low < t__high) { 882 if (t__low <= t__now && t__now <= t__high) 883 return (1); 884 } else if (t__low <= t__now || t__now <= t__high) 885 return (1); 886 887 /* aim at next time slot */ 888 if ((s = index(s, ',')) == NULL) 889 break; 890 } 891 if (*s) 892 s++; 893 } 894 return (0); 895 } 896 897 /* 898 * char * 899 * fdig(cp) find first digit in string 900 * 901 * return - pointer to first digit in string or end of string 902 */ 903 904 static char * 905 fdig(char *cp) 906 { 907 char *c; 908 909 for (c = cp; *c; c++) 910 if (*c >= '0' && *c <= '9') 911 break; 912 return (c); 913 } 914 915 /* nap(n) -- sleep for 'n' ticks of 1/60th sec each. */ 916 /* This version uses the select system call */ 917 918 919 static void 920 nap(unsigned int n) 921 { 922 struct timeval tv; 923 924 if (n == 0) 925 return; 926 tv.tv_sec = n/60; 927 tv.tv_usec = ((n%60)*1000000L)/60; 928 (void) select(32, 0, 0, 0, &tv); 929 } 930