home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / utilities / utilsf / gsm / GSM / sendpage_c < prev   
Encoding:
Text File  |  1995-06-05  |  16.2 KB  |  945 lines

  1. /*
  2.  * sendpage.c
  3.  *
  4.  * Talk to the VodoPhone pager service an send a number of messages.
  5.  *
  6.  * Based on the public domain chat.c prograsm for PPP setup chats.
  7.  */
  8.  
  9. # include    <stdio.h>
  10. # ifdef __arm
  11. #  include    <termios.h>
  12. # else
  13. #  include    <termio.h>
  14. # endif
  15. # include    <fcntl.h>
  16. # include    <signal.h>
  17. # include    <errno.h>
  18. # include    <sys/types.h>
  19. # include    <sys/stat.h>
  20.  
  21. #include <string.h>
  22. #include <dirent.h>
  23.  
  24. # ifdef sun
  25. # include    <pixrect/pr_impl_util.h>
  26. # if defined(SUNOS) && SUNOS >= 41
  27. # ifndef HDB
  28. # define    HDB
  29. # endif
  30. # endif
  31. # endif
  32.     
  33. # define    STR_LEN        1024
  34.     
  35. #if defined(sun) | defined(SYSV) | defined(POSIX_SOURCE)
  36. #define SIGTYPE void
  37. #else 
  38. #define SIGTYPE int
  39. #endif
  40.  
  41. /*************** Micro getopt() *********************************************/
  42. # define    OPTION(c,v)    (_O&2&&**v?*(*v)++:!c||_O&4?0:(!(_O&1)&& \
  43.                                    (--c,++v),_O=4,c&&**v=='-'&&v[0][1]?*++*v=='-'\
  44.                                    &&!v[0][1]?(--c,++v,0):(_O=2,*(*v)++):0))
  45. # define    OPTARG(c,v)    (_O&2?**v||(++v,--c)?(_O=1,--c,*v++): \
  46.                  (_O=4,(char*)0):(char*)0)
  47. # define    OPTONLYARG(c,v)    (_O&2&&**v?(_O=1,--c,*v++):(char*)0)
  48. # define    ARG(c,v)    (c?(--c,*v++):(char*)0)
  49.  
  50. static int _O = 0;        /* Internal state */
  51. /*************** Micro getopt() *********************************************/
  52.  
  53. char *program_name;
  54.  
  55. extern char *strcpy(), *strcat(), *malloc();
  56.  
  57. # define    copyof(s)    ((s) ? strcpy(malloc(strlen(s) + 1), s) : (s))
  58.  
  59. # ifndef LOCK_DIR
  60. #  ifdef HDB
  61. #   define    LOCK_DIR    "/usr/spool/locks"
  62. #  else /* HDB */
  63. #   ifdef __arm
  64. #     define    LOCK_DIR    "/var/spool/uucp"
  65. #   else
  66. #     define    LOCK_DIR    "/usr/spool/uucp"
  67. #   endif
  68. #  endif /* HDB */
  69. # endif /* LOCK_DIR */
  70.  
  71. # define    MAX_ABORTS    50
  72. # define    DEFAULT_CHAT_TIMEOUT    30
  73.  
  74. #define        MSGDIR    "/var/spool/pager"
  75.  
  76.  
  77. int verbose = 0;
  78. int quiet = 0;
  79. char *lock_file = (char *) 0;
  80.  
  81. int timeout = DEFAULT_CHAT_TIMEOUT;
  82.     
  83. int have_tty_parameters = 0;
  84. #ifdef __arm
  85. struct termios saved_tty_parameters;
  86. #else
  87. struct termio saved_tty_parameters;
  88. #endif
  89.  
  90. char *abort_string[MAX_ABORTS], *fail_reason = (char *)0, fail_buffer[50];
  91. int n_aborts = 0, abort_next = 0, timeout_next = 0;
  92.     
  93. /*
  94.  *    chat [ -v ] [ -t timeout ] [ -l lock-file ] \
  95.  *        [...[[expect[-say[-expect...]] say expect[-say[-expect]] ...]]]
  96.  *
  97.  *    Perform a UUCP-dialer-like chat script on stdin and stdout.
  98.  */
  99. main(argc, argv)
  100. int argc;
  101. char **argv;
  102. {
  103.     int option;
  104.     char *arg;
  105.     
  106.     program_name = *argv;
  107.     
  108.     while (option = OPTION(argc, argv))
  109.     switch (option)
  110.     {
  111.     case 'v':
  112.         ++verbose;
  113.         break;
  114.         
  115.     case 'l':
  116.         if (arg = OPTARG(argc, argv))
  117.         lock_file = copyof(arg);
  118.         else
  119.         usage();
  120.         
  121.         break;
  122.         
  123.     case 't':
  124.         if (arg = OPTARG(argc, argv))
  125.         timeout = atoi(arg);
  126.         else
  127.         usage();
  128.         
  129.         break;
  130.         
  131.     default:
  132.         usage();
  133.     }
  134.     
  135.     init();
  136.     
  137.     while (arg = ARG(argc, argv))
  138.     {
  139.     expect(arg);
  140.     
  141.     if (arg = ARG(argc, argv))
  142.         lsend(arg, 0);
  143.     }
  144.  
  145.     /* Now we need to look for files and send them */
  146.  
  147.     send_the_messages();
  148.  
  149.     /* We need to unlock */
  150.  
  151.     unlock();
  152.     
  153.     terminate(0);
  154. }
  155.  
  156. /* Do the message sending */
  157.  
  158. send_the_messages()
  159. {
  160.     DIR *dh;
  161.     struct dirent *item;
  162.  
  163.     dh = opendir(MSGDIR);
  164.     if (dh == NULL)
  165.     return;
  166.  
  167.     while ((item = readdir(dh)) != 0)
  168.     {
  169.     /* We only use items that don't start with a '.'. This gives us atomic queue insertion with 'mv' */
  170.     if (item->d_name[0] != '.')
  171.     {
  172.         char buffer[1024];
  173.         FILE *mf;
  174.         
  175.         strcpy(buffer, MSGDIR);
  176.         strcat(buffer, "/");
  177.         strcat(buffer, item->d_name);
  178.  
  179.         mf = fopen(buffer, "r");
  180.         if (mf != 0)
  181.         {
  182.         char number[64];
  183.         char message[161];
  184.  
  185.         fgets(number, sizeof(number), mf);
  186.         fgets(message, sizeof(message), mf);
  187.  
  188.         if (number[strlen(number)-1] != '\n')
  189.         {
  190.             fprintf(stderr, "Badly formed phone number in message file %s\n", buffer);
  191.         }
  192.         else
  193.         {
  194.             char *nl;
  195.  
  196.             number[strlen(number)-1] = 0;
  197.  
  198.             expect(">");
  199.             lsend(number, 1);
  200.             
  201.             nl = strchr(message, '\n');
  202.             if (nl)
  203.             *nl = 0;
  204.             
  205.             expect(">");
  206.             lsend(message, 1);
  207.             
  208.             /* @@@@ In here we should really look at the response */
  209.         }
  210.         fclose(mf);
  211.  
  212.         if (verbose)
  213.             fprintf(stderr, "remove(%s)\n", buffer);
  214.         remove(buffer);
  215.         }
  216.     }
  217.     }
  218.     closedir(dh);
  219.  
  220.     expect(">");
  221.     lsend("", 0);
  222. }
  223.  
  224. /*
  225.  *    We got an error parsing the command line.
  226.  */
  227. usage()
  228. {
  229.     fprintf(stderr,
  230.         "Usage: %s [ -v ] [ -l lock-file ] [ -t timeout ] chat-script\n",
  231.         program_name);
  232.     exit(1);
  233. }
  234.  
  235. /*
  236.  *    Print a warning message.
  237.  */
  238. /*VARARGS1*/
  239. warn(format, arg1, arg2, arg3, arg4)
  240.     char *format;
  241.     int arg1, arg2, arg3, arg4;
  242. {
  243.     fprintf(stderr, "%s: Warning: ", program_name);
  244.     fprintf(stderr, format, arg1, arg2, arg3, arg4);
  245.     fprintf(stderr, "\n");
  246. }
  247.  
  248. /*
  249.  *    Print an error message and terminate.
  250.  */
  251. /*VARARGS1*/
  252. fatal(format, arg1, arg2, arg3, arg4)
  253.     char *format;
  254.     int arg1, arg2, arg3, arg4;
  255. {
  256.     fprintf(stderr, "%s: ", program_name);
  257.     fprintf(stderr, format, arg1, arg2, arg3, arg4);
  258.     fprintf(stderr, "\n");
  259.     unlock();
  260.     terminate(1);
  261. }
  262.  
  263. /*
  264.  *    Print an error message along with the system error message and
  265.  *    terminate.
  266.  */
  267. /*VARARGS1*/
  268. sysfatal(format, arg1, arg2, arg3, arg4)
  269.     char *format;
  270.     int arg1, arg2, arg3, arg4;
  271. {
  272.     char message[STR_LEN];
  273.     
  274.     sprintf(message, "%s: ", program_name);
  275.     sprintf(message + strlen(message), format, arg1, arg2, arg3, arg4);
  276.     perror(message);
  277.     unlock();
  278.     terminate(1);
  279. }
  280.  
  281. int alarmed = 0;
  282.  
  283. SIGTYPE
  284.     sigalrm()
  285. {
  286.     int flags;
  287.     
  288.     alarm(1); alarmed = 1;        /* Reset alarm to avoid race window */
  289.     signal(SIGALRM, sigalrm);        /* that can cause hanging in read() */
  290.     
  291.     if ((flags = fcntl(0, F_GETFL, 0)) == -1)
  292.     sysfatal("Can't get file mode flags on stdin");
  293.     else
  294.     if (fcntl(0, F_SETFL, flags | FNDELAY) == -1)
  295.         sysfatal("Can't set file mode flags on stdin");
  296.     
  297.     if (verbose)
  298.     {
  299.     fprintf(stderr, "alarm\n");
  300.     fflush(stderr);
  301.     }
  302. }
  303.  
  304. unalarm()
  305. {
  306.     int flags;
  307.     
  308.     if ((flags = fcntl(0, F_GETFL, 0)) == -1)
  309.     sysfatal("Can't get file mode flags on stdin");
  310.     else
  311.     if (fcntl(0, F_SETFL, flags & ~FNDELAY) == -1)
  312.         sysfatal("Can't set file mode flags on stdin");
  313. }
  314.  
  315. SIGTYPE
  316.     sigint()
  317. {
  318.     fatal("SIGINT");
  319. }
  320.  
  321. SIGTYPE
  322.     sigterm()
  323. {
  324.     fatal("SIGTERM");
  325. }
  326.  
  327. SIGTYPE
  328.     sighup()
  329. {
  330.     fatal("SIGHUP");
  331. }
  332.  
  333. init()
  334. {
  335.     signal(SIGINT, sigint);
  336.     signal(SIGTERM, sigterm);
  337.     signal(SIGHUP, sighup);
  338.     
  339.     if (lock_file)
  340.     lock();
  341.     
  342.     set_tty_parameters();
  343.     signal(SIGALRM, sigalrm);
  344.     alarm(0); alarmed = 0;
  345. }
  346.  
  347. set_tty_parameters()
  348. {
  349.     int dtrbit;
  350. #ifdef __arm
  351.     struct termios t;
  352.     
  353.     if (tcgetattr(0, &t) < 0)
  354.     sysfatal("Can't get terminal parameters");
  355. #else
  356.     struct termio t;
  357.     
  358.     if (ioctl(0, TCGETA, &t) < 0)
  359.     sysfatal("Can't get terminal parameters");
  360. #endif
  361.  
  362.     /* Ditch any old stuff back from previous sessions */
  363.     tcflush(0, TCIFLUSH);
  364.     
  365.     saved_tty_parameters = t;
  366.     have_tty_parameters = 1;
  367.     
  368. #if 0
  369.     t.c_cflag = CREAD | CS8 | HUPCL | CLOCAL;
  370. #else
  371.     t.c_cflag = CREAD | CS8 | HUPCL | CLOCAL | CSTOPB;
  372. #endif
  373.     t.c_iflag = IGNBRK | IXOFF | IXON | ISTRIP | IGNPAR;
  374.     t.c_lflag = 0;
  375.     t.c_cc[VERASE] = t.c_cc[VKILL] = 0;
  376.     t.c_cc[VMIN] = 1;
  377.     t.c_cc[VTIME] = 0;
  378.     
  379. #ifdef __arm
  380.     if (tcsetattr(0, TCSADRAIN, &t) < 0)
  381.     sysfatal("Can't set terminal parameters");
  382. #else
  383.     if (ioctl(0, TCSETA, &t) < 0)
  384.     sysfatal("Can't set terminal parameters");
  385.     dtrbit = TIOCM_DTR;
  386.     if (ioctl(0, TIOCMBIS, &dtrbit) < 0)
  387.         sysfatal("Can't enable DTR bit on modem");
  388. #endif
  389. }
  390.  
  391. terminate(status)
  392. {
  393. #ifdef __arm
  394.     if (have_tty_parameters &&
  395.     tcsetattr(0, TCSADRAIN, &saved_tty_parameters) < 0) {
  396.     perror("Can't restore terminal parameters");
  397.     unlock();
  398.     exit(1);
  399.     }
  400. #else
  401.     if (have_tty_parameters && ioctl(0, TCSETA, &saved_tty_parameters) < 0) {
  402.     perror("Can't restore terminal parameters");
  403.     unlock();
  404.     exit(1);
  405.     }
  406. #endif
  407.     exit(status);
  408. }
  409.  
  410. /*
  411.  *    Create a lock file for the named lock device
  412.  */
  413. lock()
  414. {
  415.     int fd, pid;
  416.     
  417.     lock_file = strcat(strcat(strcpy(malloc(strlen(LOCK_DIR)
  418.                         + 1 + strlen(lock_file) + 1),
  419.                      LOCK_DIR), "/"), lock_file);
  420.     
  421.     if ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0)
  422.     {
  423.     char *s = lock_file;
  424.     
  425.     lock_file = (char *)0;    /* Don't remove someone else's lock file! */
  426.     sysfatal("Can't get lock file '%s'", s);
  427.     }
  428.     
  429. # ifdef HDB
  430.     sprintf(hdb_lock_buffer, "%10d\n", getpid());
  431.     write(fd, hdb_lock_buffer, 11);
  432. # else /* HDB */
  433.     pid = getpid();
  434.     write(fd, &pid, sizeof pid);
  435. # endif /* HDB */
  436.     
  437.     close(fd);
  438. }
  439.  
  440. /*
  441.  *    Remove our lockfile
  442.  */
  443. unlock()
  444. {
  445.     if (lock_file)
  446.     {
  447.     unlink(lock_file);
  448.     lock_file = (char *)0;
  449.     }
  450. }
  451.  
  452. /*
  453.  *    'Clean up' this string.
  454.  */
  455. char *clean(s, sending)
  456.     register char *s;
  457.     int sending;
  458. {
  459.     char temp[STR_LEN];
  460.     register char *s1;
  461.     int add_return = sending;
  462.     
  463.     for (s1 = temp; *s; ++s)
  464.     switch (*s)
  465.     {
  466.     case '\\':
  467.         switch (*++s)
  468.         {
  469.         case '\\':
  470.         case 'd':    if (sending)
  471.         *s1++ = '\\';
  472.         
  473.         *s1++ = *s;
  474.         break;
  475.         
  476.         case 'q':    quiet = ! quiet; break;
  477.         case 'r':    *s1++ = '\r'; break;
  478.         case 'n':    *s1++ = '\n'; break;
  479.         case 's':    *s1++ = ' '; break;
  480.         
  481.         case 'c':    if (sending && s[1] == '\0')
  482.         add_return = 0;
  483.         else
  484.         *s1++ = *s;
  485.         
  486.         break;
  487.         
  488.         default:    *s1++ = *s;
  489.         }
  490.         
  491.         break;
  492.         
  493.     case '^':
  494.         *s1++ = (int)(*++s) & 0x1F;
  495.         break;
  496.         
  497.     default:
  498.         *s1++ = *s;
  499.     }
  500.     
  501.     if (add_return)
  502.     *s1++ = '\r';
  503.     
  504.     *s1 = '\0';
  505.     return (copyof(temp));
  506. }
  507.  
  508. /*
  509.  *
  510.  */
  511. expect(s)
  512.     register char *s;
  513. {
  514.     if (strcmp(s, "ABORT") == 0)
  515.     {
  516.     ++abort_next;
  517.     return;
  518.     }
  519.     
  520.     if (strcmp(s, "TIMEOUT") == 0)
  521.     {
  522.     ++timeout_next;
  523.     return;
  524.     }
  525.     
  526.     while (*s)
  527.     {
  528.     register char *hyphen;
  529.     
  530.     for (hyphen = s; *hyphen; ++hyphen)
  531.         if (*hyphen == '-')
  532.         if (hyphen == s || hyphen[-1] != '\\')
  533.             break;
  534.     
  535.     if (*hyphen == '-')
  536.     {
  537.         *hyphen = '\0';
  538.         
  539.         if (get_string(s))
  540.         return;
  541.         else
  542.         {
  543.         s = hyphen + 1;
  544.         
  545.         for (hyphen = s; *hyphen; ++hyphen)
  546.             if (*hyphen == '-')
  547.             if (hyphen == s || hyphen[-1] != '\\')
  548.                 break;
  549.         
  550.         if (*hyphen == '-')
  551.         {
  552.             *hyphen = '\0';
  553.             
  554.             lsend(s, 0);
  555.             s = hyphen + 1;
  556.         }
  557.         else
  558.         {
  559.             lsend(s, 0);
  560.             return;
  561.         }
  562.         }
  563.     }
  564.     else
  565.         if (get_string(s))
  566.         return;
  567.         else
  568.         {
  569.         if (fail_reason)
  570.             fprintf(stderr, "Failed(%s)\n", fail_reason);
  571.         else
  572.             fprintf(stderr, "Failed\n");
  573.         
  574.         fflush(stderr);
  575.         unlock();
  576.         terminate(1);
  577.         }
  578.     }
  579. }
  580.  
  581. char *character(c)
  582.     char c;
  583. {
  584.     static char string[10];
  585.     char *meta;
  586.     
  587.     meta = (c & 0x80) ? "M-" : "";
  588.     c &= 0x7F;
  589.     
  590.     if (c < 32)
  591.     sprintf(string, "%s^%c", meta, (int)c + '@');
  592.     else
  593.     if (c == 127)
  594.         sprintf(string, "%s^?", meta);
  595.     else
  596.         sprintf(string, "%s%c", meta, c);
  597.     
  598.     return (string);
  599. }
  600.  
  601. /*
  602.  *
  603.  */
  604. lsend(s, catchup)
  605.     register char *s;
  606.     int catchup;
  607. {
  608.     if (abort_next)
  609.     {
  610.     char *s1;
  611.     
  612.     abort_next = 0;
  613.     
  614.     if (n_aborts >= MAX_ABORTS)
  615.         fatal("Too many ABORT strings");
  616.     
  617.     s1 = clean(s, 0);
  618.     
  619.     if (strlen(s1) > strlen(s))
  620.         fatal("Illegal ABORT string ('%s')\n", s);
  621.     
  622.     if (strlen(s1) > sizeof fail_buffer - 1)
  623.         fatal("Too long ABORT string ('%s')\n", s);
  624.     
  625.     strcpy(s, s1);
  626.     abort_string[n_aborts++] = s;
  627.     
  628.     if (verbose)
  629.     {
  630.         register char *s1 = s;
  631.         
  632.         fprintf(stderr, "abort on (");
  633.         
  634.         for (s1 = s; *s1; ++s1)
  635.         fprintf(stderr, "%s", character(*s1));
  636.         
  637.         fprintf(stderr, ")\n");
  638.         fflush(stderr);
  639.     }
  640.     }
  641.     else
  642.     if (timeout_next)
  643.     {
  644.         timeout_next = 0;
  645.         timeout = atoi(s);
  646.         
  647.         if (timeout <= 0)
  648.         timeout = DEFAULT_CHAT_TIMEOUT;
  649.         
  650.         if (verbose)
  651.         {
  652.         fprintf(stderr, "timeout set to %d seconds\n", timeout);
  653.         fflush(stderr);
  654.         }
  655.     }
  656.     else
  657.     {
  658.         if ( ! put_string(s, catchup ? 0 : 1))
  659.         {
  660.         fprintf(stderr, "Failed\n");
  661.         fflush(stderr);
  662.         unlock();
  663.         terminate(1);
  664.         }
  665.         if (catchup)
  666.         {
  667.         tcflush(0, TCIFLUSH);
  668.  
  669.         alarm(timeout); alarmed = 0;
  670.  
  671.         if (alarmed || put_char('\r') < 0)
  672.         {
  673.             extern int errno;
  674.         
  675.             alarm(0); alarmed = 0;
  676.         
  677.             if (verbose)
  678.             {
  679.             if (errno == EINTR || errno == EWOULDBLOCK)
  680.                 fprintf(stderr, " -- write timed out\n");
  681.             else
  682.                 perror(" -- write failed");
  683.         
  684.             fflush(stderr);
  685.             }
  686.             unlock();
  687.             terminate(1);
  688.         }
  689.         alarm(0); alarmed = 0;
  690.         }
  691.     }
  692. }
  693.  
  694. int get_char()
  695. {
  696.     int status;
  697.     char c;
  698.     
  699.     status = read(0, &c, 1);
  700.     
  701.     switch (status)
  702.     {
  703.     case 1:
  704.     return ((int)c & 0x7F);
  705.     
  706.     default:
  707.     warn("read() on stdin returned %d", status);
  708.     
  709.     case -1:
  710.     if ((status = fcntl(0, F_GETFL, 0)) == -1)
  711.         sysfatal("Can't get file mode flags on stdin");
  712.     else
  713.         if (fcntl(0, F_SETFL, status & ~FNDELAY) == -1)
  714.         sysfatal("Can't set file mode flags on stdin");
  715.     
  716.     return (-1);
  717.     }
  718. }
  719.  
  720. int put_char(c)
  721.     char c;
  722. {
  723.     int status;
  724.     
  725.     delay();
  726.     
  727.     status = write(1, &c, 1);
  728.     
  729.     switch (status)
  730.     {
  731.     case 1:
  732.     return (0);
  733.     
  734.     default:
  735.     warn("write() on stdout returned %d", status);
  736.     
  737.     case -1:
  738.     if ((status = fcntl(0, F_GETFL, 0)) == -1)
  739.         sysfatal("Can't get file mode flags on stdin");
  740.     else
  741.         if (fcntl(0, F_SETFL, status & ~FNDELAY) == -1)
  742.         sysfatal("Can't set file mode flags on stdin");
  743.     
  744.     return (-1);
  745.     }
  746. }
  747.  
  748. int put_string(s, withcr)
  749.     register char *s;
  750.     int withcr;
  751. {
  752.     s = clean(s, withcr);
  753.     
  754.     if (verbose)
  755.     {
  756.     fprintf(stderr, "lsend (");
  757.     
  758.     if (quiet)
  759.         fprintf(stderr, "??????");
  760.     else
  761.     {
  762.         register char *s1 = s;
  763.         
  764.         for (s1 = s; *s1; ++s1)
  765.         fprintf(stderr, "%s", character(*s1));
  766.     }
  767.     
  768.     fprintf(stderr, ")\n");
  769.     fflush(stderr);
  770.     }
  771.     
  772.     alarm(timeout); alarmed = 0;
  773.     
  774.     for ( ; *s; ++s)
  775.     {
  776.     register char c = *s;
  777.     
  778.     if (c == '\\')
  779.     {
  780.         if ((c = *++s) == '\0')
  781.         break;
  782.         else
  783.         if (c == 'd')        /* \d -- Delay */
  784.         {
  785.             sleep(2);
  786.             continue;
  787.         }
  788.     }
  789.     
  790.     if (alarmed || put_char(*s) < 0)
  791.     {
  792.         extern int errno;
  793.         
  794.         alarm(0); alarmed = 0;
  795.         
  796.         if (verbose)
  797.         {
  798.         if (errno == EINTR || errno == EWOULDBLOCK)
  799.             fprintf(stderr, " -- write timed out\n");
  800.         else
  801.             perror(" -- write failed");
  802.         
  803.         fflush(stderr);
  804.         }
  805.         
  806.         return (0);
  807.     }
  808.     }
  809.     
  810.     alarm(0); alarmed = 0;
  811.     return (1);
  812. }
  813.  
  814. /*
  815.  *    'Wait for' this string to appear on this file descriptor.
  816.  */
  817. int get_string(string)
  818.     register char *string;
  819. {
  820.     char temp[STR_LEN];
  821.     int c, printed = 0, len;
  822.     register char *s = temp, *end = s + STR_LEN;
  823.     
  824.     fail_reason = (char *)0;
  825.     string = clean(string, 0);
  826.     len = strlen(string);
  827.     
  828.     if (verbose)
  829.     {
  830.     register char *s1;
  831.     
  832.     fprintf(stderr, "expect (");
  833.     
  834.     for (s1 = string; *s1; ++s1)
  835.         fprintf(stderr, "%s", character(*s1));
  836.     
  837.     fprintf(stderr, ")\n");
  838.     fflush(stderr);
  839.     }
  840.     
  841.     if (len == 0)
  842.     {
  843.     if (verbose)
  844.     {
  845.         fprintf(stderr, "got it\n");
  846.         fflush(stderr);
  847.     }
  848.     
  849.     return (1);
  850.     }
  851.     
  852.     alarm(timeout); alarmed = 0;
  853.     
  854.     while ( ! alarmed && (c = get_char()) >= 0)
  855.     {
  856.     int n, abort_len;
  857.     
  858.     if (verbose)
  859.     {
  860.         if (c == '\n')
  861.         fprintf(stderr, "\n");
  862.         else
  863.         fprintf(stderr, "%s", character(c));
  864.         
  865.         fflush(stderr);
  866.     }
  867.     
  868.     *s++ = c;
  869.     
  870.     if (s >= end)
  871.     {
  872.         if (verbose)
  873.         {
  874.         fprintf(stderr, " -- too much data\n");
  875.         fflush(stderr);
  876.         }
  877.         
  878.         alarm(0); alarmed = 0;
  879.         return (0);
  880.     }
  881.     
  882.     if (s - temp >= len &&
  883.         c == string[len - 1] &&
  884.         strncmp(s - len, string, len) == 0)
  885.     {
  886.         if (verbose)
  887.         {
  888.         fprintf(stderr, "got it\n");
  889.         fflush(stderr);
  890.         }
  891.         
  892.         alarm(0); alarmed = 0;
  893.         return (1);
  894.     }
  895.     
  896.     for (n = 0; n < n_aborts; ++n)
  897.         if (s - temp >= (abort_len = strlen(abort_string[n])) &&
  898.         strncmp(s - abort_len, abort_string[n], abort_len) == 0)
  899.         {
  900.         if (verbose)
  901.         {
  902.             fprintf(stderr, " -- failed\n");
  903.             fflush(stderr);
  904.         }
  905.         
  906.         alarm(0); alarmed = 0;
  907.         strcpy(fail_reason = fail_buffer, abort_string[n]);
  908.         return (0);
  909.         }
  910.     
  911.     if (alarmed && verbose)
  912.         warn("Alarm synchronization problem");
  913.     }
  914.     
  915.     alarm(0);
  916.     
  917.     if (verbose && printed)
  918.     {
  919.     if (alarmed)
  920.         fprintf(stderr, " -- read timed out\n");
  921.     else
  922.         perror(" -- read failed");
  923.     
  924.     fflush(stderr);
  925.     }
  926.     
  927.     alarmed = 0;
  928.     return (0);
  929. }
  930.  
  931. /*
  932.  *    Delay an amount appropriate for between typed characters.
  933.  */
  934. delay()
  935. {
  936. # ifdef NO_USLEEP
  937.     register int i;
  938.     
  939.     for (i = 0; i < 30000; ++i)        /* ... did we just say appropriate? */
  940.     ;
  941. # else /* NO_USLEEP */
  942.     usleep(100);
  943. # endif /* NO_USLEEP */
  944. }
  945.