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
conn(char * system)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
getto(char * flds[])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
classmatch(char * flds[],char * dev[])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
rddev(char * type,char * dev[],char * buf,int devcount)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
finds(char * sysnam,char * flds[],int fldcount)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
getProto(char * save,char * str)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
chat(int nf,char * flds[],int fn,char * phstr1,char * phstr2)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
expect(char * str,int fn)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
expect_str(char * str,int fn)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
alarmtr(int sig)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
wait_for_hangup(int dcf)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
sendthem(char * str,int fn,char * phstr1,char * phstr2)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
wrstr(int fn,char * buf,int len,int echocheck)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
wrchr(int fn,char * buf,int len)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
notin(char * sh,char * lg)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
ifdate(char * s)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 *
fdig(char * cp)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
nap(unsigned int n)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