/*
 * Filename:	dial
 * Author:	David Ljung Madison <DaveSource.com>
 * See License:	http://MarginalHacks.com/License
 * Description:	Dials numbers using the modem
 * Requires:	SUID on most systems! (that's why it's not in perl :)
 * Bugs:
 *   It ain't perfect.
 *   1)  You may need to use kermit or somesuch to init the modem
 *   2)  You probably can't do multiple commands with a single invocation
 *       (such as "dial =atz =ats11=50 922-2697") which you should, but I'd
 *       need to figure out how to read the responses and quit after a delay.
 *   3)  Sometimes if you pick up a real phone right after the modem picks up,
 *       the modem gets confused (because of the noise?) and thinks there is
 *       no dialtone.  Either pick up the handset at exactly the same time that
 *       you issue the dial command, or else wait till it starts dialing.
 */

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

#define	MODEM_DEVICE	"/dev/modem"
#define MODEM_WRITE(s)	write(MODEM_FD,(s),strlen(s))
#define MODEM_READ(s,l)	read(MODEM_FD,(s),(l))

main(int argc, char **argv) {
  int MODEM_FD;
  int a = 1;
  int dialed = 0;
  int pauses = 0;

  /* Usage */
  if (argc<2 || !strcmp(argv[1],"-h") || !strcmp(argv[1],"-?")) {
    char *progname = argv[0]+strlen(argv[0]);
    while(*(progname-1) != '/' && progname != argv[0]) progname--;
    fprintf(stderr,"Usage:  %s [-d] [str...]\n",progname);
    fprintf(stderr,"\n");
    fprintf(stderr,"Dial a number using the modem\n");
    fprintf(stderr,"\n");
    fprintf(stderr,"Any string starting with '=' is sent without the atdt prefix.\n");
    fprintf(stderr,"\n");
    fprintf(stderr,"Examples:\n");
    fprintf(stderr,"%% %s 411                  # Call information\n",progname);
    fprintf(stderr,"%% %s =ats11=50 555-1212   # Send init string [ats11=50] first\n",progname);
    fprintf(stderr,"\n");
    fprintf(stderr,"The -d option gives you a simple terminal to the modem.\n");
    fprintf(stderr,"\n");
    exit(-1);
  }

  /* Open the modem */
  if ((MODEM_FD = open(MODEM_DEVICE, O_RDWR | O_APPEND)) == -1) {
    fprintf(stderr,"Couldn't open modem [%s] (must be suid?)\n",MODEM_DEVICE);
    exit(-1);
  }

  /* Simple terminal? */
  if (!strcmp(argv[1],"-d")) {
    char buf[1024];
    if (fork()) {
      while(fgets(buf,1023,stdin)) MODEM_WRITE(buf);
    } else {
      while(MODEM_READ(buf,1)) fprintf(stderr,"%c",buf[0]);
    }
    exit(0);
  }

  /* We need at least an "at" command */
  MODEM_WRITE("at\r");

  /* Go through args */
  while(a<argc) {
    if ((argv[a][0] == '=') && argv[a][1] != '\0') {
      /* Exact string:  Just send it */
      MODEM_WRITE(argv[a]+1);
    } else {
      /* Number:  Dial it */
      char *ptr = argv[a];
      dialed++;
      while(*ptr) {
        if (*ptr==',') pauses++;	// Count pauses ','
        if (*ptr=='.') *ptr='-';	// Convert '.' to '-'
        ptr++;
      }
      MODEM_WRITE("atdt ");
      MODEM_WRITE(argv[a]);
    }
    MODEM_WRITE("\r");
    a++;
  }

  if (dialed) sleep(4+pauses*2);	/* Make sure the dialed number goes out */
  close(MODEM_FD);
}
