home *** CD-ROM | disk | FTP | other *** search
- /*
- * sendpage.c
- *
- * Talk to the VodoPhone pager service an send a number of messages.
- *
- * Based on the public domain chat.c prograsm for PPP setup chats.
- */
-
- # include <stdio.h>
- # ifdef __arm
- # include <termios.h>
- # else
- # include <termio.h>
- # endif
- # include <fcntl.h>
- # include <signal.h>
- # include <errno.h>
- # include <sys/types.h>
- # include <sys/stat.h>
-
- #include <string.h>
- #include <dirent.h>
-
- # ifdef sun
- # include <pixrect/pr_impl_util.h>
- # if defined(SUNOS) && SUNOS >= 41
- # ifndef HDB
- # define HDB
- # endif
- # endif
- # endif
-
- # define STR_LEN 1024
-
- #if defined(sun) | defined(SYSV) | defined(POSIX_SOURCE)
- #define SIGTYPE void
- #else
- #define SIGTYPE int
- #endif
-
- /*************** Micro getopt() *********************************************/
- # define OPTION(c,v) (_O&2&&**v?*(*v)++:!c||_O&4?0:(!(_O&1)&& \
- (--c,++v),_O=4,c&&**v=='-'&&v[0][1]?*++*v=='-'\
- &&!v[0][1]?(--c,++v,0):(_O=2,*(*v)++):0))
- # define OPTARG(c,v) (_O&2?**v||(++v,--c)?(_O=1,--c,*v++): \
- (_O=4,(char*)0):(char*)0)
- # define OPTONLYARG(c,v) (_O&2&&**v?(_O=1,--c,*v++):(char*)0)
- # define ARG(c,v) (c?(--c,*v++):(char*)0)
-
- static int _O = 0; /* Internal state */
- /*************** Micro getopt() *********************************************/
-
- char *program_name;
-
- extern char *strcpy(), *strcat(), *malloc();
-
- # define copyof(s) ((s) ? strcpy(malloc(strlen(s) + 1), s) : (s))
-
- # ifndef LOCK_DIR
- # ifdef HDB
- # define LOCK_DIR "/usr/spool/locks"
- # else /* HDB */
- # ifdef __arm
- # define LOCK_DIR "/var/spool/uucp"
- # else
- # define LOCK_DIR "/usr/spool/uucp"
- # endif
- # endif /* HDB */
- # endif /* LOCK_DIR */
-
- # define MAX_ABORTS 50
- # define DEFAULT_CHAT_TIMEOUT 30
-
- #define MSGDIR "/var/spool/pager"
-
-
- int verbose = 0;
- int quiet = 0;
- char *lock_file = (char *) 0;
-
- int timeout = DEFAULT_CHAT_TIMEOUT;
-
- int have_tty_parameters = 0;
- #ifdef __arm
- struct termios saved_tty_parameters;
- #else
- struct termio saved_tty_parameters;
- #endif
-
- char *abort_string[MAX_ABORTS], *fail_reason = (char *)0, fail_buffer[50];
- int n_aborts = 0, abort_next = 0, timeout_next = 0;
-
- /*
- * chat [ -v ] [ -t timeout ] [ -l lock-file ] \
- * [...[[expect[-say[-expect...]] say expect[-say[-expect]] ...]]]
- *
- * Perform a UUCP-dialer-like chat script on stdin and stdout.
- */
- main(argc, argv)
- int argc;
- char **argv;
- {
- int option;
- char *arg;
-
- program_name = *argv;
-
- while (option = OPTION(argc, argv))
- switch (option)
- {
- case 'v':
- ++verbose;
- break;
-
- case 'l':
- if (arg = OPTARG(argc, argv))
- lock_file = copyof(arg);
- else
- usage();
-
- break;
-
- case 't':
- if (arg = OPTARG(argc, argv))
- timeout = atoi(arg);
- else
- usage();
-
- break;
-
- default:
- usage();
- }
-
- init();
-
- while (arg = ARG(argc, argv))
- {
- expect(arg);
-
- if (arg = ARG(argc, argv))
- lsend(arg, 0);
- }
-
- /* Now we need to look for files and send them */
-
- send_the_messages();
-
- /* We need to unlock */
-
- unlock();
-
- terminate(0);
- }
-
- /* Do the message sending */
-
- send_the_messages()
- {
- DIR *dh;
- struct dirent *item;
-
- dh = opendir(MSGDIR);
- if (dh == NULL)
- return;
-
- while ((item = readdir(dh)) != 0)
- {
- /* We only use items that don't start with a '.'. This gives us atomic queue insertion with 'mv' */
- if (item->d_name[0] != '.')
- {
- char buffer[1024];
- FILE *mf;
-
- strcpy(buffer, MSGDIR);
- strcat(buffer, "/");
- strcat(buffer, item->d_name);
-
- mf = fopen(buffer, "r");
- if (mf != 0)
- {
- char number[64];
- char message[161];
-
- fgets(number, sizeof(number), mf);
- fgets(message, sizeof(message), mf);
-
- if (number[strlen(number)-1] != '\n')
- {
- fprintf(stderr, "Badly formed phone number in message file %s\n", buffer);
- }
- else
- {
- char *nl;
-
- number[strlen(number)-1] = 0;
-
- expect(">");
- lsend(number, 1);
-
- nl = strchr(message, '\n');
- if (nl)
- *nl = 0;
-
- expect(">");
- lsend(message, 1);
-
- /* @@@@ In here we should really look at the response */
- }
- fclose(mf);
-
- if (verbose)
- fprintf(stderr, "remove(%s)\n", buffer);
- remove(buffer);
- }
- }
- }
- closedir(dh);
-
- expect(">");
- lsend("", 0);
- }
-
- /*
- * We got an error parsing the command line.
- */
- usage()
- {
- fprintf(stderr,
- "Usage: %s [ -v ] [ -l lock-file ] [ -t timeout ] chat-script\n",
- program_name);
- exit(1);
- }
-
- /*
- * Print a warning message.
- */
- /*VARARGS1*/
- warn(format, arg1, arg2, arg3, arg4)
- char *format;
- int arg1, arg2, arg3, arg4;
- {
- fprintf(stderr, "%s: Warning: ", program_name);
- fprintf(stderr, format, arg1, arg2, arg3, arg4);
- fprintf(stderr, "\n");
- }
-
- /*
- * Print an error message and terminate.
- */
- /*VARARGS1*/
- fatal(format, arg1, arg2, arg3, arg4)
- char *format;
- int arg1, arg2, arg3, arg4;
- {
- fprintf(stderr, "%s: ", program_name);
- fprintf(stderr, format, arg1, arg2, arg3, arg4);
- fprintf(stderr, "\n");
- unlock();
- terminate(1);
- }
-
- /*
- * Print an error message along with the system error message and
- * terminate.
- */
- /*VARARGS1*/
- sysfatal(format, arg1, arg2, arg3, arg4)
- char *format;
- int arg1, arg2, arg3, arg4;
- {
- char message[STR_LEN];
-
- sprintf(message, "%s: ", program_name);
- sprintf(message + strlen(message), format, arg1, arg2, arg3, arg4);
- perror(message);
- unlock();
- terminate(1);
- }
-
- int alarmed = 0;
-
- SIGTYPE
- sigalrm()
- {
- int flags;
-
- alarm(1); alarmed = 1; /* Reset alarm to avoid race window */
- signal(SIGALRM, sigalrm); /* that can cause hanging in read() */
-
- if ((flags = fcntl(0, F_GETFL, 0)) == -1)
- sysfatal("Can't get file mode flags on stdin");
- else
- if (fcntl(0, F_SETFL, flags | FNDELAY) == -1)
- sysfatal("Can't set file mode flags on stdin");
-
- if (verbose)
- {
- fprintf(stderr, "alarm\n");
- fflush(stderr);
- }
- }
-
- unalarm()
- {
- int flags;
-
- if ((flags = fcntl(0, F_GETFL, 0)) == -1)
- sysfatal("Can't get file mode flags on stdin");
- else
- if (fcntl(0, F_SETFL, flags & ~FNDELAY) == -1)
- sysfatal("Can't set file mode flags on stdin");
- }
-
- SIGTYPE
- sigint()
- {
- fatal("SIGINT");
- }
-
- SIGTYPE
- sigterm()
- {
- fatal("SIGTERM");
- }
-
- SIGTYPE
- sighup()
- {
- fatal("SIGHUP");
- }
-
- init()
- {
- signal(SIGINT, sigint);
- signal(SIGTERM, sigterm);
- signal(SIGHUP, sighup);
-
- if (lock_file)
- lock();
-
- set_tty_parameters();
- signal(SIGALRM, sigalrm);
- alarm(0); alarmed = 0;
- }
-
- set_tty_parameters()
- {
- int dtrbit;
- #ifdef __arm
- struct termios t;
-
- if (tcgetattr(0, &t) < 0)
- sysfatal("Can't get terminal parameters");
- #else
- struct termio t;
-
- if (ioctl(0, TCGETA, &t) < 0)
- sysfatal("Can't get terminal parameters");
- #endif
-
- /* Ditch any old stuff back from previous sessions */
- tcflush(0, TCIFLUSH);
-
- saved_tty_parameters = t;
- have_tty_parameters = 1;
-
- #if 0
- t.c_cflag = CREAD | CS8 | HUPCL | CLOCAL;
- #else
- t.c_cflag = CREAD | CS8 | HUPCL | CLOCAL | CSTOPB;
- #endif
- t.c_iflag = IGNBRK | IXOFF | IXON | ISTRIP | IGNPAR;
- t.c_lflag = 0;
- t.c_cc[VERASE] = t.c_cc[VKILL] = 0;
- t.c_cc[VMIN] = 1;
- t.c_cc[VTIME] = 0;
-
- #ifdef __arm
- if (tcsetattr(0, TCSADRAIN, &t) < 0)
- sysfatal("Can't set terminal parameters");
- #else
- if (ioctl(0, TCSETA, &t) < 0)
- sysfatal("Can't set terminal parameters");
- dtrbit = TIOCM_DTR;
- if (ioctl(0, TIOCMBIS, &dtrbit) < 0)
- sysfatal("Can't enable DTR bit on modem");
- #endif
- }
-
- terminate(status)
- {
- #ifdef __arm
- if (have_tty_parameters &&
- tcsetattr(0, TCSADRAIN, &saved_tty_parameters) < 0) {
- perror("Can't restore terminal parameters");
- unlock();
- exit(1);
- }
- #else
- if (have_tty_parameters && ioctl(0, TCSETA, &saved_tty_parameters) < 0) {
- perror("Can't restore terminal parameters");
- unlock();
- exit(1);
- }
- #endif
- exit(status);
- }
-
- /*
- * Create a lock file for the named lock device
- */
- lock()
- {
- int fd, pid;
-
- lock_file = strcat(strcat(strcpy(malloc(strlen(LOCK_DIR)
- + 1 + strlen(lock_file) + 1),
- LOCK_DIR), "/"), lock_file);
-
- if ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0)
- {
- char *s = lock_file;
-
- lock_file = (char *)0; /* Don't remove someone else's lock file! */
- sysfatal("Can't get lock file '%s'", s);
- }
-
- # ifdef HDB
- sprintf(hdb_lock_buffer, "%10d\n", getpid());
- write(fd, hdb_lock_buffer, 11);
- # else /* HDB */
- pid = getpid();
- write(fd, &pid, sizeof pid);
- # endif /* HDB */
-
- close(fd);
- }
-
- /*
- * Remove our lockfile
- */
- unlock()
- {
- if (lock_file)
- {
- unlink(lock_file);
- lock_file = (char *)0;
- }
- }
-
- /*
- * 'Clean up' this string.
- */
- char *clean(s, sending)
- register char *s;
- int sending;
- {
- char temp[STR_LEN];
- register char *s1;
- int add_return = sending;
-
- for (s1 = temp; *s; ++s)
- switch (*s)
- {
- case '\\':
- switch (*++s)
- {
- case '\\':
- case 'd': if (sending)
- *s1++ = '\\';
-
- *s1++ = *s;
- break;
-
- case 'q': quiet = ! quiet; break;
- case 'r': *s1++ = '\r'; break;
- case 'n': *s1++ = '\n'; break;
- case 's': *s1++ = ' '; break;
-
- case 'c': if (sending && s[1] == '\0')
- add_return = 0;
- else
- *s1++ = *s;
-
- break;
-
- default: *s1++ = *s;
- }
-
- break;
-
- case '^':
- *s1++ = (int)(*++s) & 0x1F;
- break;
-
- default:
- *s1++ = *s;
- }
-
- if (add_return)
- *s1++ = '\r';
-
- *s1 = '\0';
- return (copyof(temp));
- }
-
- /*
- *
- */
- expect(s)
- register char *s;
- {
- if (strcmp(s, "ABORT") == 0)
- {
- ++abort_next;
- return;
- }
-
- if (strcmp(s, "TIMEOUT") == 0)
- {
- ++timeout_next;
- return;
- }
-
- while (*s)
- {
- register char *hyphen;
-
- for (hyphen = s; *hyphen; ++hyphen)
- if (*hyphen == '-')
- if (hyphen == s || hyphen[-1] != '\\')
- break;
-
- if (*hyphen == '-')
- {
- *hyphen = '\0';
-
- if (get_string(s))
- return;
- else
- {
- s = hyphen + 1;
-
- for (hyphen = s; *hyphen; ++hyphen)
- if (*hyphen == '-')
- if (hyphen == s || hyphen[-1] != '\\')
- break;
-
- if (*hyphen == '-')
- {
- *hyphen = '\0';
-
- lsend(s, 0);
- s = hyphen + 1;
- }
- else
- {
- lsend(s, 0);
- return;
- }
- }
- }
- else
- if (get_string(s))
- return;
- else
- {
- if (fail_reason)
- fprintf(stderr, "Failed(%s)\n", fail_reason);
- else
- fprintf(stderr, "Failed\n");
-
- fflush(stderr);
- unlock();
- terminate(1);
- }
- }
- }
-
- char *character(c)
- char c;
- {
- static char string[10];
- char *meta;
-
- meta = (c & 0x80) ? "M-" : "";
- c &= 0x7F;
-
- if (c < 32)
- sprintf(string, "%s^%c", meta, (int)c + '@');
- else
- if (c == 127)
- sprintf(string, "%s^?", meta);
- else
- sprintf(string, "%s%c", meta, c);
-
- return (string);
- }
-
- /*
- *
- */
- lsend(s, catchup)
- register char *s;
- int catchup;
- {
- if (abort_next)
- {
- char *s1;
-
- abort_next = 0;
-
- if (n_aborts >= MAX_ABORTS)
- fatal("Too many ABORT strings");
-
- s1 = clean(s, 0);
-
- if (strlen(s1) > strlen(s))
- fatal("Illegal ABORT string ('%s')\n", s);
-
- if (strlen(s1) > sizeof fail_buffer - 1)
- fatal("Too long ABORT string ('%s')\n", s);
-
- strcpy(s, s1);
- abort_string[n_aborts++] = s;
-
- if (verbose)
- {
- register char *s1 = s;
-
- fprintf(stderr, "abort on (");
-
- for (s1 = s; *s1; ++s1)
- fprintf(stderr, "%s", character(*s1));
-
- fprintf(stderr, ")\n");
- fflush(stderr);
- }
- }
- else
- if (timeout_next)
- {
- timeout_next = 0;
- timeout = atoi(s);
-
- if (timeout <= 0)
- timeout = DEFAULT_CHAT_TIMEOUT;
-
- if (verbose)
- {
- fprintf(stderr, "timeout set to %d seconds\n", timeout);
- fflush(stderr);
- }
- }
- else
- {
- if ( ! put_string(s, catchup ? 0 : 1))
- {
- fprintf(stderr, "Failed\n");
- fflush(stderr);
- unlock();
- terminate(1);
- }
- if (catchup)
- {
- tcflush(0, TCIFLUSH);
-
- alarm(timeout); alarmed = 0;
-
- if (alarmed || put_char('\r') < 0)
- {
- extern int errno;
-
- alarm(0); alarmed = 0;
-
- if (verbose)
- {
- if (errno == EINTR || errno == EWOULDBLOCK)
- fprintf(stderr, " -- write timed out\n");
- else
- perror(" -- write failed");
-
- fflush(stderr);
- }
- unlock();
- terminate(1);
- }
- alarm(0); alarmed = 0;
- }
- }
- }
-
- int get_char()
- {
- int status;
- char c;
-
- status = read(0, &c, 1);
-
- switch (status)
- {
- case 1:
- return ((int)c & 0x7F);
-
- default:
- warn("read() on stdin returned %d", status);
-
- case -1:
- if ((status = fcntl(0, F_GETFL, 0)) == -1)
- sysfatal("Can't get file mode flags on stdin");
- else
- if (fcntl(0, F_SETFL, status & ~FNDELAY) == -1)
- sysfatal("Can't set file mode flags on stdin");
-
- return (-1);
- }
- }
-
- int put_char(c)
- char c;
- {
- int status;
-
- delay();
-
- status = write(1, &c, 1);
-
- switch (status)
- {
- case 1:
- return (0);
-
- default:
- warn("write() on stdout returned %d", status);
-
- case -1:
- if ((status = fcntl(0, F_GETFL, 0)) == -1)
- sysfatal("Can't get file mode flags on stdin");
- else
- if (fcntl(0, F_SETFL, status & ~FNDELAY) == -1)
- sysfatal("Can't set file mode flags on stdin");
-
- return (-1);
- }
- }
-
- int put_string(s, withcr)
- register char *s;
- int withcr;
- {
- s = clean(s, withcr);
-
- if (verbose)
- {
- fprintf(stderr, "lsend (");
-
- if (quiet)
- fprintf(stderr, "??????");
- else
- {
- register char *s1 = s;
-
- for (s1 = s; *s1; ++s1)
- fprintf(stderr, "%s", character(*s1));
- }
-
- fprintf(stderr, ")\n");
- fflush(stderr);
- }
-
- alarm(timeout); alarmed = 0;
-
- for ( ; *s; ++s)
- {
- register char c = *s;
-
- if (c == '\\')
- {
- if ((c = *++s) == '\0')
- break;
- else
- if (c == 'd') /* \d -- Delay */
- {
- sleep(2);
- continue;
- }
- }
-
- if (alarmed || put_char(*s) < 0)
- {
- extern int errno;
-
- alarm(0); alarmed = 0;
-
- if (verbose)
- {
- if (errno == EINTR || errno == EWOULDBLOCK)
- fprintf(stderr, " -- write timed out\n");
- else
- perror(" -- write failed");
-
- fflush(stderr);
- }
-
- return (0);
- }
- }
-
- alarm(0); alarmed = 0;
- return (1);
- }
-
- /*
- * 'Wait for' this string to appear on this file descriptor.
- */
- int get_string(string)
- register char *string;
- {
- char temp[STR_LEN];
- int c, printed = 0, len;
- register char *s = temp, *end = s + STR_LEN;
-
- fail_reason = (char *)0;
- string = clean(string, 0);
- len = strlen(string);
-
- if (verbose)
- {
- register char *s1;
-
- fprintf(stderr, "expect (");
-
- for (s1 = string; *s1; ++s1)
- fprintf(stderr, "%s", character(*s1));
-
- fprintf(stderr, ")\n");
- fflush(stderr);
- }
-
- if (len == 0)
- {
- if (verbose)
- {
- fprintf(stderr, "got it\n");
- fflush(stderr);
- }
-
- return (1);
- }
-
- alarm(timeout); alarmed = 0;
-
- while ( ! alarmed && (c = get_char()) >= 0)
- {
- int n, abort_len;
-
- if (verbose)
- {
- if (c == '\n')
- fprintf(stderr, "\n");
- else
- fprintf(stderr, "%s", character(c));
-
- fflush(stderr);
- }
-
- *s++ = c;
-
- if (s >= end)
- {
- if (verbose)
- {
- fprintf(stderr, " -- too much data\n");
- fflush(stderr);
- }
-
- alarm(0); alarmed = 0;
- return (0);
- }
-
- if (s - temp >= len &&
- c == string[len - 1] &&
- strncmp(s - len, string, len) == 0)
- {
- if (verbose)
- {
- fprintf(stderr, "got it\n");
- fflush(stderr);
- }
-
- alarm(0); alarmed = 0;
- return (1);
- }
-
- for (n = 0; n < n_aborts; ++n)
- if (s - temp >= (abort_len = strlen(abort_string[n])) &&
- strncmp(s - abort_len, abort_string[n], abort_len) == 0)
- {
- if (verbose)
- {
- fprintf(stderr, " -- failed\n");
- fflush(stderr);
- }
-
- alarm(0); alarmed = 0;
- strcpy(fail_reason = fail_buffer, abort_string[n]);
- return (0);
- }
-
- if (alarmed && verbose)
- warn("Alarm synchronization problem");
- }
-
- alarm(0);
-
- if (verbose && printed)
- {
- if (alarmed)
- fprintf(stderr, " -- read timed out\n");
- else
- perror(" -- read failed");
-
- fflush(stderr);
- }
-
- alarmed = 0;
- return (0);
- }
-
- /*
- * Delay an amount appropriate for between typed characters.
- */
- delay()
- {
- # ifdef NO_USLEEP
- register int i;
-
- for (i = 0; i < 30000; ++i) /* ... did we just say appropriate? */
- ;
- # else /* NO_USLEEP */
- usleep(100);
- # endif /* NO_USLEEP */
- }
-