/*
 * Copyright (c) 1992 Purdue University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by Purdue University.  The name of the University may not be used
 * to endorse or promote products derived * from this software without
 * specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Note: this copyright applies to portions of this software developed
 * at Purdue beyond the software covered by the original copyright.
 */

#include <stdio.h>
#include <malloc.h>
#include <fcntl.h>
#include <termios.h>

char *argv0;
int verbose;

main(argc, argv)
int argc;
char **argv;
{
    char *dev;
    char *file;
    int baud;
    int c;
    int err = 0;
    extern int optind;

    argv0 = argv[0];
    while ((c = getopt(argc, argv, "v")) >= 0)
	switch (c) {
	 case 'v':
	    verbose++;
	    break;
	 case '?':
	    err++;
	    break;
	}
    argv += optind;
    argc -= optind;
    if (err || argc < 2) {
	fprintf(stderr, "usage: %s [-v] scriptfile device [baud]\n", argv0);
	exit(33);
    }
    file = *argv++;
    if (**argv == '/')
	dev = *argv++;
    else {
	dev = malloc(strlen(*argv)+sizeof("/dev/"));
	(void)sprintf(dev, "/dev/%s", *argv++);
    }
    baud = argc > 2 ? atoi(*argv) : 38400;
    setmodem(dev, file, baud);
    if (verbose)
	fprintf(stderr, "Modem configuration complete\n");
    exit(0);
}

int orig_soft;

setmodem(dev, file, baud)
char *dev, *file;
int baud;
{
    FILE *od, *id, *f;
    char lnbuf[256], *l;
    int d;

    if ((d = open(dev, O_RDWR|O_NDELAY, 0)) < 0) {
	perror(dev);
	exit(34);
    }
    if (!(id = fdopen(d, "r"))) {
	perror(dev);
	exit(34);
    }
    if (!(od = fdopen(d, "w"))) {
	perror(dev);
	exit(34);
    }
    if (!(f = fopen(file, "r"))) {
	perror(file);
	exit(35);
    }
    orig_soft = softcar(d, 1);
    setbaud(d, baud);
    sendcom(od, id, "AT");
    while (fgets(lnbuf, sizeof(lnbuf), f)) {
	l = lnbuf + strlen(lnbuf) - 1;
	if (*l = '\n')
	    *l = '\0';
	sendcom(od, id, lnbuf);
    }
    softcar(d, orig_soft);
}

softcar(d, soft)
int d, soft;
{
    int osoft;
    if (ioctl(d, TIOCGSOFTCAR, &osoft) < 0)
	perror("TIOCGSOFTCAR");
    if (soft != osoft && ioctl(d, TIOCSSOFTCAR, &soft) < 0)
	    perror("TIOCSSOFTCAR");
}

#include <errno.h>

#define	TIMEOUT 3

sendcom(o, i, com)
FILE *o, *i;
char *com;
{
    char ln[128], *l;
    int c, n;
    int baud = -1;
    int timeout_ok = 0;
    while (*com == '#') {
	if (strncmp(com, "#T/", 3) == 0) {
	    timeout_ok = 1;
	    com += 3;
	}
	else if (sscanf(com, "#(%d)%n", &baud, &n) == 1)
	    com += n;
	else
	    return;
    }
    if (*com) {
	if (verbose)
	    fprintf(stderr, "Send: %s\n", com);
	fputs(com, o);
	putc('\r', o);
	fflush(o);
    }
    if (baud > 0) {
	setbaud(fileno(o), baud);
	if (verbose)
	    fprintf(stderr, "Setting baud rate to: %d\n", baud);
    }
    if (*com) {
	errno = 0;
	while (fgets(ln, sizeof(ln), i)) {
	    l = ln + strlen(ln) - 1;
	    while (l >= ln && (*l == '\n' || *l == '\r'))
		*l-- = '\0';
	    if (verbose && ln[0])
		fprintf(stderr, "Recv: %s\n", ln);
	    if (strcmp(ln, "OK") == 0)
		return;
	}
	if (errno) {
	    fprintf(stderr, "%s: ", argv0);
	    perror("Error reading from modem");
	}
	else {
	    if (timeout_ok)
		return;
	    fprintf(stderr, "%s: modem timeout\n", argv0);
	}
	softcar(fileno(o), orig_soft);
	exit(38);
    }
}


setbaud(d, baud)
int d, baud;
{
    int b;
    struct termios t;
    static int got_t;
    int baudext = 0;
    switch (baud) {
     case 300:	 b = B300; break;
     case 1200:  b = B1200; break;
     case 9600:  b = B9600; break;
     case 19200: b = B19200; break;
     default:
		 fprintf(stderr,
			"Invalid baud rate %d, setting baud rate to 38400\n",
			baud);
     case 38400: b = B38400; break;
#ifdef	STS
     case 57600: b = B38400; baudext = 1; break;
#endif	STS
    }
    if (!got_t && tcgetattr(d, &t) < 0) {
	perror("tcgetattr");
	softcar(d, orig_soft);
	exit(36);
    }
    got_t++;
    t.c_cflag &= ~(PARENB|CSIZE|HUPCL);
    t.c_cflag |= CS8;
    cfsetispeed(&t, b);
    cfsetospeed(&t, b);
    t.c_oflag &= ~OPOST;
    t.c_lflag &= ~(ICANON|ISIG|ECHO);
    t.c_cc[VTIME] = TIMEOUT*10;
    t.c_cc[VMIN] = 0;
    if (tcsetattr(d, TCSAFLUSH, &t) < 0) {
	perror("tcsetattr");
	softcar(d, orig_soft);
	exit(36);
    }
#ifdef	STS
    (void)stsbaudext(d, baudext);
#endif  STS
}
