upgrade looped-back message from debug statement to syslog warning
[mpls-ppp.git] / chat / chat.c
blob6c614d49dbb12922fd3388cea21feff6c702c2f9
1 /*
2 * Chat -- a program for automatic session establishment (i.e. dial
3 * the phone and log in).
5 * This software is in the public domain.
7 * Please send all bug reports, requests for information, etc. to:
9 * Al Longyear (longyear@netcom.com)
10 * (I was the last person to change this code.)
12 * The original author is:
14 * Karl Fox <karl@MorningStar.Com>
15 * Morning Star Technologies, Inc.
16 * 1760 Zollinger Road
17 * Columbus, OH 43221
18 * (614)451-1883
21 static char rcsid[] = "$Id: chat.c,v 1.4 1994/05/30 00:30:37 paulus Exp $";
23 #include <stdio.h>
24 #include <fcntl.h>
25 #include <signal.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <syslog.h>
33 #ifndef TERMIO
34 #undef TERMIOS
35 #define TERMIOS
36 #endif
38 #ifdef sun
39 # if defined(SUNOS) && SUNOS >= 41
40 # ifndef HDB
41 # define HDB
42 # endif
43 # endif
44 #endif
46 #ifdef TERMIO
47 #include <termio.h>
48 #endif
49 #ifdef TERMIOS
50 #include <termios.h>
51 #endif
53 #define STR_LEN 1024
55 #ifndef SIGTYPE
56 #define SIGTYPE void
57 #endif
59 #ifdef __STDC__
60 #undef __P
61 #define __P(x) x
62 #else
63 #define __P(x) ()
64 #define const
65 #endif
67 /*************** Micro getopt() *********************************************/
68 #define OPTION(c,v) (_O&2&&**v?*(*v)++:!c||_O&4?0:(!(_O&1)&& \
69 (--c,++v),_O=4,c&&**v=='-'&&v[0][1]?*++*v=='-'\
70 &&!v[0][1]?(--c,++v,0):(_O=2,*(*v)++):0))
71 #define OPTARG(c,v) (_O&2?**v||(++v,--c)?(_O=1,--c,*v++): \
72 (_O=4,(char*)0):(char*)0)
73 #define OPTONLYARG(c,v) (_O&2&&**v?(_O=1,--c,*v++):(char*)0)
74 #define ARG(c,v) (c?(--c,*v++):(char*)0)
76 static int _O = 0; /* Internal state */
77 /*************** Micro getopt() *********************************************/
79 char *program_name;
81 #ifndef LOCK_DIR
82 # ifdef __NetBSD__
83 # define PIDSTRING
84 # define LOCK_DIR "/var/spool/lock"
85 # else
86 # ifdef HDB
87 # define PIDSTRING
88 # define LOCK_DIR "/usr/spool/locks"
89 # else /* HDB */
90 # define LOCK_DIR "/usr/spool/uucp"
91 # endif /* HDB */
92 # endif
93 #endif /* LOCK_DIR */
95 #define MAX_ABORTS 50
96 #define DEFAULT_CHAT_TIMEOUT 45
98 int verbose = 0;
99 int quiet = 0;
100 char *lock_file = (char *)0;
101 char *chat_file = (char *)0;
102 int timeout = DEFAULT_CHAT_TIMEOUT;
104 int have_tty_parameters = 0;
105 #ifdef TERMIO
106 struct termio saved_tty_parameters;
107 #endif
108 #ifdef TERMIOS
109 struct termios saved_tty_parameters;
110 #endif
112 char *abort_string[MAX_ABORTS], *fail_reason = (char *)0,
113 fail_buffer[50];
114 int n_aborts = 0, abort_next = 0, timeout_next = 0;
116 void *dup_mem __P((void *b, size_t c));
117 void *copy_of __P((char *s));
118 void usage __P((void));
119 void logf __P((const char *str));
120 void logflush __P((void));
121 void fatal __P((const char *msg));
122 void sysfatal __P((const char *msg));
123 SIGTYPE sigalrm __P((int signo));
124 SIGTYPE sigint __P((int signo));
125 SIGTYPE sigterm __P((int signo));
126 SIGTYPE sighup __P((int signo));
127 void unalarm __P((void));
128 void init __P((void));
129 void set_tty_parameters __P((void));
130 void break_sequence __P((void));
131 void terminate __P((int status));
132 void do_file __P((char *chat_file));
133 void lock __P((void));
134 void delay __P((void));
135 int get_string __P((register char *string));
136 int put_string __P((register char *s));
137 int write_char __P((int c));
138 int put_char __P((char c));
139 int get_char __P((void));
140 void chat_send __P((register char *s));
141 char *character __P((char c));
142 void chat_expect __P((register char *s));
143 char *clean __P((register char *s, int sending));
144 void unlock __P((void));
145 void lock __P((void));
146 void break_sequence __P((void));
147 void terminate __P((int status));
148 void die __P((void));
150 void *dup_mem(b, c)
151 void *b;
152 size_t c;
154 void *ans = malloc (c);
155 if (!ans)
156 fatal ("memory error!\n");
157 memcpy (ans, b, c);
158 return ans;
161 void *copy_of (s)
162 char *s;
164 return dup_mem (s, strlen (s) + 1);
168 * chat [ -v ] [ -t timeout ] [ -l lock-file ] [ -f chat-file ] \
169 * [...[[expect[-say[-expect...]] say expect[-say[-expect]] ...]]]
171 * Perform a UUCP-dialer-like chat script on stdin and stdout.
174 main(argc, argv)
175 int argc;
176 char **argv;
178 int option;
179 char *arg;
181 program_name = *argv;
183 while (option = OPTION(argc, argv))
184 switch (option)
186 case 'v':
187 ++verbose;
188 break;
190 case 'f':
191 if (arg = OPTARG(argc, argv))
192 chat_file = copy_of(arg);
193 else
194 usage();
196 break;
198 case 'l':
199 if (arg = OPTARG(argc, argv))
200 lock_file = copy_of(arg);
201 else
202 usage();
204 break;
206 case 't':
207 if (arg = OPTARG(argc, argv))
208 timeout = atoi(arg);
209 else
210 usage();
212 break;
214 default:
215 usage();
218 #ifdef ultrix
219 openlog("chat", LOG_PID);
220 #else
221 openlog("chat", LOG_PID | LOG_NDELAY, LOG_LOCAL2);
223 if (verbose) {
224 setlogmask(LOG_UPTO(LOG_INFO));
225 } else {
226 setlogmask(LOG_UPTO(LOG_WARNING));
228 #endif
230 init();
232 if (chat_file != NULL)
234 arg = ARG(argc, argv);
235 if (arg != NULL)
236 usage();
237 else
238 do_file (chat_file);
240 else
242 while (arg = ARG(argc, argv))
244 chat_expect(arg);
246 if (arg = ARG(argc, argv))
247 chat_send(arg);
251 terminate(0);
255 * Process a chat script when read from a file.
258 void do_file (chat_file)
259 char *chat_file;
261 int linect, len, sendflg;
262 char *sp, *arg, quote;
263 char buf [STR_LEN];
264 FILE *cfp;
266 if ((cfp = fopen (chat_file, "r")) == NULL)
268 syslog (LOG_ERR, "%s -- open failed: %m", chat_file);
269 terminate (1);
272 linect = 0;
273 sendflg = 0;
275 while (fgets(buf, STR_LEN, cfp) != NULL)
277 sp = strchr (buf, '\n');
278 if (sp)
279 *sp = '\0';
281 linect++;
282 sp = buf;
283 while (*sp != '\0')
285 if (*sp == ' ' || *sp == '\t')
287 ++sp;
288 continue;
291 if (*sp == '"' || *sp == '\'')
293 quote = *sp++;
294 arg = sp;
295 while (*sp != quote)
297 if (*sp == '\0')
299 syslog (LOG_ERR, "unterminated quote (line %d)",
300 linect);
301 terminate (1);
304 if (*sp++ == '\\')
305 if (*sp != '\0')
306 ++sp;
309 else
311 arg = sp;
312 while (*sp != '\0' && *sp != ' ' && *sp != '\t')
313 ++sp;
316 if (*sp != '\0')
317 *sp++ = '\0';
319 if (sendflg)
321 chat_send (arg);
323 else
325 chat_expect (arg);
327 sendflg = !sendflg;
330 fclose (cfp);
334 * We got an error parsing the command line.
336 void usage()
338 fprintf(stderr, "\
339 Usage: %s [-v] [-l lock-file] [-t timeout] {-f chat-file || chat-script}\n",
340 program_name);
341 exit(1);
344 char line[256];
345 char *p;
347 void logf (str)
348 const char *str;
350 p = line + strlen(line);
351 strcat (p, str);
353 if (str[strlen(str)-1] == '\n')
355 syslog (LOG_INFO, "%s", line);
356 line[0] = 0;
360 void logflush()
362 if (line[0] != 0)
364 syslog(LOG_INFO, "%s", line);
365 line[0] = 0;
370 * Unlock and terminate with an error.
372 void die()
374 unlock();
375 terminate(1);
379 * Print an error message and terminate.
382 void fatal (msg)
383 const char *msg;
385 syslog(LOG_ERR, "%s", msg);
386 unlock();
387 terminate(1);
391 * Print an error message along with the system error message and
392 * terminate.
395 void sysfatal (msg)
396 const char *msg;
398 syslog(LOG_ERR, "%s: %m", msg);
399 unlock();
400 terminate(1);
403 int alarmed = 0;
405 SIGTYPE sigalrm(signo)
406 int signo;
408 int flags;
410 alarm(1);
411 alarmed = 1; /* Reset alarm to avoid race window */
412 signal(SIGALRM, sigalrm); /* that can cause hanging in read() */
414 logflush();
415 if ((flags = fcntl(0, F_GETFL, 0)) == -1)
416 sysfatal("Can't get file mode flags on stdin");
417 else
418 if (fcntl(0, F_SETFL, flags | FNDELAY) == -1)
419 sysfatal("Can't set file mode flags on stdin");
421 if (verbose)
423 syslog(LOG_INFO, "alarm");
427 void unalarm()
429 int flags;
431 if ((flags = fcntl(0, F_GETFL, 0)) == -1)
432 sysfatal("Can't get file mode flags on stdin");
433 else
434 if (fcntl(0, F_SETFL, flags & ~FNDELAY) == -1)
435 sysfatal("Can't set file mode flags on stdin");
438 SIGTYPE sigint(signo)
439 int signo;
441 fatal("SIGINT");
444 SIGTYPE sigterm(signo)
445 int signo;
447 fatal("SIGTERM");
450 SIGTYPE sighup(signo)
451 int signo;
453 fatal("SIGHUP");
456 void init()
458 signal(SIGINT, sigint);
459 signal(SIGTERM, sigterm);
460 signal(SIGHUP, sighup);
462 if (lock_file)
463 lock();
465 set_tty_parameters();
466 signal(SIGALRM, sigalrm);
467 alarm(0);
468 alarmed = 0;
471 void set_tty_parameters()
473 #ifdef TERMIO
474 struct termio t;
476 if (ioctl(0, TCGETA, &t) < 0)
477 sysfatal("Can't get terminal parameters");
478 #endif
479 #ifdef TERMIOS
480 struct termios t;
482 if (tcgetattr(0, &t) < 0)
483 sysfatal("Can't get terminal parameters");
484 #endif
486 saved_tty_parameters = t;
487 have_tty_parameters = 1;
489 t.c_iflag |= IGNBRK | ISTRIP | IGNPAR;
490 t.c_oflag = 0;
491 t.c_lflag = 0;
492 t.c_cc[VERASE] = t.c_cc[VKILL] = 0;
493 t.c_cc[VMIN] = 1;
494 t.c_cc[VTIME] = 0;
496 #ifdef TERMIO
497 if (ioctl(0, TCSETA, &t) < 0)
498 sysfatal("Can't set terminal parameters");
499 #endif
500 #ifdef TERMIOS
501 if (tcsetattr(0, TCSANOW, &t) < 0)
502 sysfatal("Can't set terminal parameters");
503 #endif
506 void break_sequence()
508 #ifdef TERMIOS
509 tcsendbreak (0, 0);
510 #endif
513 void terminate(status)
514 int status;
516 if (have_tty_parameters &&
517 #ifdef TERMIO
518 ioctl(0, TCSETA, &saved_tty_parameters) < 0
519 #endif
520 #ifdef TERMIOS
521 tcsetattr(0, TCSANOW, &saved_tty_parameters) < 0
522 #endif
524 syslog(LOG_ERR, "Can't restore terminal parameters: %m");
525 unlock();
526 exit(1);
528 exit(status);
532 * Create a lock file for the named lock device
534 void lock()
536 int fd, pid;
537 # ifdef PIDSTRING
538 char hdb_lock_buffer[12];
539 # endif
541 lock_file = strcat(strcat(strcpy(malloc(strlen(LOCK_DIR)
542 + 1 + strlen(lock_file) + 1),
543 LOCK_DIR), "/"), lock_file);
545 if ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0)
547 char *s = lock_file;
548 lock_file = (char *)0; /* Don't remove someone else's lock file! */
549 syslog(LOG_ERR, "Can't get lock file '%s': %m", s);
550 die();
553 # ifdef PIDSTRING
554 sprintf(hdb_lock_buffer, "%10d\n", getpid());
555 write(fd, hdb_lock_buffer, 11);
556 # else
557 pid = getpid();
558 write(fd, &pid, sizeof pid);
559 # endif
561 close(fd);
565 * Remove our lockfile
567 void unlock()
569 if (lock_file)
571 unlink(lock_file);
572 lock_file = (char *)0;
577 * 'Clean up' this string.
579 char *clean(s, sending)
580 register char *s;
581 int sending;
583 char temp[STR_LEN], cur_chr;
584 register char *s1;
585 int add_return = sending;
586 #define isoctal(chr) (((chr) >= '0') && ((chr) <= '7'))
588 s1 = temp;
589 while (*s)
591 cur_chr = *s++;
592 if (cur_chr == '^')
594 cur_chr = *s++;
595 if (cur_chr == '\0')
597 *s1++ = '^';
598 break;
600 cur_chr &= 0x1F;
601 if (cur_chr != 0)
602 *s1++ = cur_chr;
603 continue;
606 if (cur_chr != '\\')
608 *s1++ = cur_chr;
609 continue;
612 cur_chr = *s++;
613 if (cur_chr == '\0')
615 if (sending)
617 *s1++ = '\\';
618 *s1++ = '\\';
620 break;
623 switch (cur_chr)
625 case 'b':
626 *s1++ = '\b';
627 break;
629 case 'c':
630 if (sending && *s == '\0')
631 add_return = 0;
632 else
633 *s1++ = cur_chr;
634 break;
636 case '\\':
637 case 'K':
638 case 'p':
639 case 'd':
640 if (sending)
641 *s1++ = '\\';
643 *s1++ = cur_chr;
644 break;
646 case 'q':
647 quiet = ! quiet;
648 break;
650 case 'r':
651 *s1++ = '\r';
652 break;
654 case 'n':
655 *s1++ = '\n';
656 break;
658 case 's':
659 *s1++ = ' ';
660 break;
662 case 't':
663 *s1++ = '\t';
664 break;
666 case 'N':
667 if (sending)
669 *s1++ = '\\';
670 *s1++ = '\0';
672 else
673 *s1++ = 'N';
674 break;
676 default:
677 if (isoctal (cur_chr))
679 cur_chr &= 0x07;
680 if (isoctal (*s))
682 cur_chr <<= 3;
683 cur_chr |= *s++ - '0';
684 if (isoctal (*s))
686 cur_chr <<= 3;
687 cur_chr |= *s++ - '0';
691 if (cur_chr != 0 || sending)
693 if (sending && (cur_chr == '\\' || cur_chr == 0))
694 *s1++ = '\\';
695 *s1++ = cur_chr;
697 break;
700 if (sending)
701 *s1++ = '\\';
702 *s1++ = cur_chr;
703 break;
707 if (add_return)
708 *s1++ = '\r';
710 *s1++ = '\0'; /* guarantee closure */
711 *s1++ = '\0'; /* terminate the string */
712 return dup_mem (temp, (size_t) (s1 - temp)); /* may have embedded nuls */
716 * Process the expect string
718 void chat_expect(s)
719 register char *s;
721 if (strcmp(s, "ABORT") == 0)
723 ++abort_next;
724 return;
727 if (strcmp(s, "TIMEOUT") == 0)
729 ++timeout_next;
730 return;
733 while (*s)
735 register char *hyphen;
737 for (hyphen = s; *hyphen; ++hyphen)
738 if (*hyphen == '-')
739 if (hyphen == s || hyphen[-1] != '\\')
740 break;
742 if (*hyphen == '-')
744 *hyphen = '\0';
746 if (get_string(s))
747 return;
748 else
750 s = hyphen + 1;
752 for (hyphen = s; *hyphen; ++hyphen)
753 if (*hyphen == '-')
754 if (hyphen == s || hyphen[-1] != '\\')
755 break;
757 if (*hyphen == '-')
759 *hyphen = '\0';
761 chat_send(s);
762 s = hyphen + 1;
764 else
766 chat_send(s);
767 return;
771 else
772 if (get_string(s))
773 return;
774 else
776 if (fail_reason)
777 syslog(LOG_INFO, "Failed (%s)", fail_reason);
778 else
779 syslog(LOG_INFO, "Failed");
781 unlock();
782 terminate(1);
787 char *character(c)
788 char c;
790 static char string[10];
791 char *meta;
793 meta = (c & 0x80) ? "M-" : "";
794 c &= 0x7F;
796 if (c < 32)
797 sprintf(string, "%s^%c", meta, (int)c + '@');
798 else
799 if (c == 127)
800 sprintf(string, "%s^?", meta);
801 else
802 sprintf(string, "%s%c", meta, c);
804 return (string);
808 * process the reply string
810 void chat_send (s)
811 register char *s;
813 if (abort_next)
815 char *s1;
817 abort_next = 0;
819 if (n_aborts >= MAX_ABORTS)
820 fatal("Too many ABORT strings");
822 s1 = clean(s, 0);
824 if (strlen(s1) > strlen(s) || strlen(s1) > sizeof fail_buffer - 1)
826 syslog(LOG_WARNING, "Illegal or too-long ABORT string ('%s')", s);
827 die();
830 abort_string[n_aborts++] = s1;
832 if (verbose)
834 logf("abort on (");
836 for (s1 = s; *s1; ++s1)
837 logf(character(*s1));
839 logf(")\n");
842 else
843 if (timeout_next)
845 timeout_next = 0;
846 timeout = atoi(s);
848 if (timeout <= 0)
849 timeout = DEFAULT_CHAT_TIMEOUT;
851 if (verbose)
853 syslog(LOG_INFO, "timeout set to %d seconds", timeout);
856 else
858 if (strcmp(s, "EOT") == 0)
859 s = "^D\\c";
860 else
861 if (strcmp(s, "BREAK") == 0)
862 s = "\\K\\c";
863 if ( ! put_string(s))
865 syslog(LOG_INFO, "Failed");
866 unlock();
867 terminate(1);
872 int get_char()
874 int status;
875 char c;
877 status = read(0, &c, 1);
879 switch (status)
881 case 1:
882 return ((int)c & 0x7F);
884 default:
885 syslog(LOG_WARNING, "warning: read() on stdin returned %d",
886 status);
888 case -1:
889 if ((status = fcntl(0, F_GETFL, 0)) == -1)
890 sysfatal("Can't get file mode flags on stdin");
891 else
892 if (fcntl(0, F_SETFL, status & ~FNDELAY) == -1)
893 sysfatal("Can't set file mode flags on stdin");
895 return (-1);
899 int put_char(c)
900 char c;
902 int status;
904 delay();
906 status = write(1, &c, 1);
908 switch (status)
910 case 1:
911 return (0);
913 default:
914 syslog(LOG_WARNING, "warning: write() on stdout returned %d",
915 status);
917 case -1:
918 if ((status = fcntl(0, F_GETFL, 0)) == -1)
919 sysfatal("Can't get file mode flags on stdin");
920 else
921 if (fcntl(0, F_SETFL, status & ~FNDELAY) == -1)
922 sysfatal("Can't set file mode flags on stdin");
924 return (-1);
928 int write_char (c)
929 int c;
931 if (alarmed || put_char(c) < 0)
933 extern int errno;
935 alarm(0); alarmed = 0;
937 if (verbose)
939 if (errno == EINTR || errno == EWOULDBLOCK)
940 syslog(LOG_INFO, " -- write timed out");
941 else
942 syslog(LOG_INFO, " -- write failed: %m");
944 return (0);
946 return (1);
949 int put_string (s)
950 register char *s;
952 s = clean(s, 1);
954 if (verbose)
956 logf("send (");
958 if (quiet)
959 logf("??????");
960 else
962 register char *s1 = s;
964 for (s1 = s; *s1; ++s1)
965 logf(character(*s1));
968 logf(")\n");
971 alarm(timeout); alarmed = 0;
973 while (*s)
975 register char c = *s++;
977 if (c != '\\')
979 if (!write_char (c))
980 return 0;
981 continue;
984 c = *s++;
985 switch (c)
987 case 'd':
988 sleep(1);
989 break;
991 case 'K':
992 break_sequence();
993 break;
995 case 'p':
996 usleep(10000); /* 1/100th of a second. */
997 break;
999 default:
1000 if (!write_char (c))
1001 return 0;
1002 break;
1006 alarm(0);
1007 alarmed = 0;
1008 return (1);
1012 * 'Wait for' this string to appear on this file descriptor.
1014 int get_string(string)
1015 register char *string;
1017 char temp[STR_LEN];
1018 int c, printed = 0, len, minlen;
1019 register char *s = temp, *end = s + STR_LEN;
1021 fail_reason = (char *)0;
1022 string = clean(string, 0);
1023 len = strlen(string);
1024 minlen = (len > sizeof(fail_buffer)? len: sizeof(fail_buffer)) - 1;
1026 if (verbose)
1028 register char *s1;
1030 logf("expect (");
1032 for (s1 = string; *s1; ++s1)
1033 logf(character(*s1));
1035 logf(")\n");
1038 if (len > STR_LEN)
1040 syslog(LOG_INFO, "expect string is too long");
1041 return 0;
1044 if (len == 0)
1046 if (verbose)
1048 syslog(LOG_INFO, "got it");
1051 return (1);
1054 alarm(timeout); alarmed = 0;
1056 while ( ! alarmed && (c = get_char()) >= 0)
1058 int n, abort_len;
1060 if (verbose)
1062 if (c == '\n')
1063 logf("\n");
1064 else
1065 logf(character(c));
1068 *s++ = c;
1070 if (s - temp >= len &&
1071 c == string[len - 1] &&
1072 strncmp(s - len, string, len) == 0)
1074 if (verbose)
1076 logf(" -- got it\n");
1079 alarm(0); alarmed = 0;
1080 return (1);
1083 for (n = 0; n < n_aborts; ++n)
1084 if (s - temp >= (abort_len = strlen(abort_string[n])) &&
1085 strncmp(s - abort_len, abort_string[n], abort_len) == 0)
1087 if (verbose)
1089 logf(" -- failed\n");
1092 alarm(0); alarmed = 0;
1093 strcpy(fail_reason = fail_buffer, abort_string[n]);
1094 return (0);
1097 if (s >= end)
1099 strncpy(temp, s - minlen, minlen);
1100 s = temp + minlen;
1103 if (alarmed && verbose)
1104 syslog(LOG_WARNING, "warning: alarm synchronization problem");
1107 alarm(0);
1109 if (verbose && printed)
1111 if (alarmed)
1112 logf(" -- read timed out\n");
1113 else
1115 logflush();
1116 syslog(LOG_INFO, " -- read failed: %m");
1120 alarmed = 0;
1121 return (0);
1124 #ifdef ultrix
1125 #undef NO_USLEEP
1126 #include <sys/types.h>
1127 #include <sys/time.h>
1130 usleep -- support routine for 4.2BSD system call emulations
1131 last edit: 29-Oct-1984 D A Gwyn
1134 extern int select();
1137 usleep( usec ) /* returns 0 if ok, else -1 */
1138 long usec; /* delay in microseconds */
1140 static struct /* `timeval' */
1142 long tv_sec; /* seconds */
1143 long tv_usec; /* microsecs */
1144 } delay; /* _select() timeout */
1146 delay.tv_sec = usec / 1000000L;
1147 delay.tv_usec = usec % 1000000L;
1149 return select( 0, (long *)0, (long *)0, (long *)0, &delay );
1151 #endif
1154 * Delay an amount appropriate for between typed characters.
1156 void delay()
1158 # ifdef NO_USLEEP
1159 register int i;
1161 for (i = 0; i < 30000; ++i) /* ... did we just say appropriate? */
1163 # else /* NO_USLEEP */
1164 usleep(100);
1165 # endif /* NO_USLEEP */