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