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