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