/* pe7pho.c */ /* * P h o n e File Transfer Utility * * usage: * phone -i -d -v -l -b -a -p -h -c * * where i=init modem , d=debug level , v=verbose , * l=line , b=baud rate , a=answer , * p=phone number , h=hang-up request <'a' or 'o'>, * c=direct connect <'a' or 'o'> */ /* * Modification History: * * June 85 - Init write. Dan L. Eisner, Perkin-Elmer Corp. * */ #include /* Standard IDRIS definitions */ #include /* Idris system subroutines */ /*#include "sgtty.h" /* Special TTY speed definations */ #include "pe7tty.h" /* Special TTY speed definations */ /* Symbol Definitions */ #define BUFSIZE 80 /* A buffer size for I/O */ #define MYTIME 10 /* Seconds after which I should be timed out */ #define TRUE -1 /* Boolean constants */ #define FALSE 0 /* Global Variables */ int iflg {0}, /* Indicates to init the modem */ aflg {0}, /* Indicates modem mode */ vflg {0}, /* Indicates verbose mode */ hflg {0}, /* Indicates to hang up the phone */ cflg {0}, /* direct connection thru a modem flag */ timint {0}, /* This is the present time out interval */ debug {0}; /* indicates level of debugging output (0=none) */ char modem_data[BUFSIZE] {0};/* Temp buffer for modem command data */ FILE ttyfd {0}; /* File descriptor of tty for I/O */ struct tty savemode {0}, /* tty saved mode */ ttymode {0}; /* tty raw mode */ /* * m a i n * * Main routine - parse command and options, set up the * tty lines, and dispatch to the appropriate routine. */ main(argc,argv) int argc; /* Character pointers to and count of */ char **argv; /* command line arguments */ { char *ttyname, /* tty name for LINE argument */ *ph_num, /* Phone number for PHONE argument */ result_code, /* The code the modem answered with */ tmp[6]; /* Retry counter buffer */ int speed; /* speed of assigned tty, */ int dial_count; /* Number of times we have dialed the phone */ int answer_count; /* The number of times we tried to answer phone */ int pflg; /* A flag to set if there is a phone number */ int pdial; /* Pulse dialing flag */ /* Make sure there's a command line */ if (argc < 2) Usage("phone -i -d# -v -l/dev/tty# -b -a -p -h -c\n"); iflg = FALSE; aflg = FALSE; hflg = FALSE; vflg = FALSE; cflg = FALSE; /* Turn off all parse flags */ ttyname = 0; /* We did not get a line assignment (pointer) */ ph_num = NULL; /* Set the phone number pointer to a null */ pflg = FALSE; /* ... and the flag to FALSE */ speed = 0; /* Preset the speed to no change */ debug = FALSE; /* Turn off the debug mode */ getflags(&argc,&argv, "i,a,v,h?,c?,l*,p*,b#,d#:F", &iflg, &aflg, &vflg, &hflg, &cflg, &ttyname, &ph_num, &speed, &debug); /* Done parsing */ if (debug > 0) vflg = TRUE; /* Force verbose during debug */ pflg = (ph_num != 0);/* Set up a phone number flag */ if (!aflg && !pflg && !hflg && !cflg && !iflg) Usage("We need to do something?"); if ((aflg + pflg) > 1) Usage("Dial and answer the phone?"); if (cflg && (aflg || pflg)) Usage("Direct connect and dial at same time?"); if (hflg != 0 && (aflg || pflg)) Usage("Hang-up after connecting?"); if (cflg == 'a' || cflg == 'A') aflg = TRUE; /* make it answer */ if (cflg == 'o' || cflg == 'O') pflg = TRUE; /* force the dial routine to work */ if (aflg || pflg) iflg = TRUE; /* force int of modem */ if (ttyname == 0) /* If LINE was not specified, we */ ttyname = "/dev/lnk0";/* operate with link tty */ ttyfd = open(ttyname, UPDATE, 0);/* Open the tty line */ if (ttyfd < 0) Usage("Cannot open %s.", ttyname); /* Put the proper tty into the correct mode */ egtty(ttyfd, &savemode);/* Save the inputed mode */ egtty(ttyfd,&ttymode); /* set for changing the setup */ ttymode.t_mode |= (M_ALL|M_RAW|MR_XON); ttymode.t_mode &= ~(M_ECHO | M_2STOP); ttymode.t_min = 128; ttymode.t_time = 0; timint = 0; if (speed) /* User specified a speed? */ { switch(speed) /* Get internal system code */ { case 110: speed = B110; ttymode.t_mode &= M_2STOP; break; case 150: speed = B150; break; case 300: speed = B300; break; case 1200: speed = B1200; break; case 2400: speed = B2400; break; case 4800: speed = B4800; break; case 9600: speed = B9600; break; default: Usage("Bad line speed."); } ttymode.t_ispeed = speed; ttymode.t_ospeed = speed; } estty(ttyfd, &ttymode); /* Put asg'd tty in raw mode */ if (debug) { printf("Main 1: A=%d, H=%d, D=%d, ", aflg, hflg, cflg); printf("L=%s, P=%s\n", ttyname, ph_num); printf(" Line speed to remote host is %d\n",speed); printf("Main 2: Bits for ttyfd %x\n",ttymode.t_mode); } /* All set up, now execute the command that was given. */ if (iflg) /* Init the modem */ { timint = MYTIME / 2; ttymode.t_time = timint * 10; estty(ttyfd, &ttymode); /* Put tty in short time mode */ if (vflg) printmsg("Initializing the modem"); if ((result_code = init_modem()) <= 0) Usage("Can not initilize the modem, return = %d\n",result_code); } if (pflg) { timint = 0; ttymode.t_time = 0; estty(ttyfd, &ttymode); /* Put tty in long time mode */ /* If the first character of the phone number is a p then set up pulse dialing. */ if (*ph_num == 'p' || *ph_num == 'P') { pdial = TRUE; ph_num++; } else pdial = FALSE; /* Set pulse dialing to FALSE */ dial_count = 0; if (vflg) printmsg("Dialing %s", ph_num); do { if (dial_count++ >= 5) Usage("Dial count expired"); modem_write(pdial ? "ATPD" : "ATTD", FALSE); if (!cflg) modem_write(ph_num,FALSE); modem_write("\r",FALSE); if(vflg) write(STDERR, &tmp, decode(&tmp, 3, "%2i\r", dial_count)); } while ((result_code = get_result()) == '3'); /* keep dialing */ if (result_code != '1' && result_code != '5') { init_modem(); Usage(" \007ERROR, BAD RESULT CODE: 0x%x\r",result_code); } if (vflg) printmsg("Connect at %s\n", result_code == '5' ? "1200 Baud" : "300 Baud"); sleep(2); /* Wait for other side to be ready */ timint = MYTIME; ttymode.t_time = timint * 10; /* Reset time out */ estty(ttyfd, &ttymode); } /* End of pflg */ if (aflg) { answer_count = 0; if (!cflg) /* Direct mode is off? */ { timint = 30; /* set the time to 30 sec. */ ttymode.t_time = 50;/* Make the time out as big as I can */ estty(ttyfd, &ttymode); if (vflg) printmsg("Waiting for ring"); do { if (answer_count++ >= 10) Usage("Answer count expired."); if(vflg) write(STDERR, &tmp, decode(&tmp, 3, "%2i\r", answer_count)); } /* wait for phone to ring (but count tries) */ while ((result_code = get_result()) != '2'); modem_write("ATS2=28A\r",FALSE); /* Answer the phone */ result_code = get_result(); } else /* !cflg */ { timint = 0; ttymode.t_time = 0; /* set time out */ estty(ttyfd, &ttymode); if (vflg) printmsg("Waiting for connection"); do { if (answer_count++ >= 5) Usage("Answer counter expired."); modem_write("ATS2=28A\r",FALSE); /* Answer the phone */ if(vflg) write(STDERR, &tmp, decode(&tmp, 3, "%2i\r", answer_count)); } while ((result_code = get_result()) == '3'); } /* end of else !cflg */ if (result_code != '1' && result_code != '5') Usage("Modem failed to answer correctly."); if (vflg) printmsg("Answered at %s\n", result_code == '5' ? "1200 Baud" : "300 Baud"); timint = MYTIME; ttymode.t_time = timint * 10; /* Reset time out */ estty(ttyfd, &ttymode); /* Put tty in time out mode */ } /* end of aflg */ if (hflg) { timint = MYTIME / 5; ttymode.t_time = timint * 10; /* restore time out count */ estty(ttyfd, &ttymode); if(vflg) printmsg("Hanging up"); hang_modem(); /* Hang up the phone */ } /* end of else !hflg */ estty(ttyfd, &savemode); exit(YES); } /* * p r i n t m s g * * printmsg - like printf with "Phone: " preappended */ printmsg(fmt, a1, a2, a3, a4, a5) TEXT *fmt; { char cp[BUFSIZE]; cpystr(&cp, "Phone: ", fmt, "\n", NULL); printf(&cp, a1, a2, a3, a4, a5); } /* * U s a g e * * Print formatted message and the exit with a status of NO */ Usage(message, a1, a2, a3, a4, a5) char *message; { char cp[BUFSIZE]; cpystr(&cp, "Phone usage: ", message, "\n", NULL); printf(&cp, a1, a2, a3, a4, a5); if (ttyfd > 0) estty(ttyfd, &savemode); /* restore the tty */ exit(NO); } /* * p r i n t f * * Print formatted output. Convert from UNIX to IDRIS */ printf(msg, a1, a2, a3, a4, a5) char *msg; { char t, *cpp, cp[BUFSIZE]; /* Line pointer for the reformatted string */ cpp = cp; /* Init the buffer pointer */ while ((t = *cpp++ = *msg++) != NULL) if (t == '%') switch(t = *msg) { case 'd': *cpp++ = 'i'; t = *msg++; /* Scrap character */ break; case 'c': *cpp++ = 'a'; *cpp++ = 'c'; t = *msg++; /* Scrap character */ break; case 'x': *cpp++ = 'h'; *cpp++ = 'i'; t = *msg++; /* Scrap character */ break; case 's': *cpp++ = 'p'; t = *msg++; /* Scrap character */ break; case '\0': break; default: *cpp++ = *msg++; } putfmt(&cp, a1, a2, a3, a4, a5); } /* * i n i t _ m o d e m * * Init the modem. first try to reset then if not successful then try to * escape the modem, and reset. * The routine returns a result of '0' to '5' or a negative number for timeout */ char init_modem() { int tries; char tmp; if (debug) printf("Init_modem 1:\n"); for (tries = 1; tries <= 4; tries++) { sleep(1); /* Wait for a bit */ if (tries >= 2) { modem_write("\34\34\34",FALSE); if ((tmp = get_result()) != '0') { modem_write("\35\35\35",FALSE); if ((tmp = get_result()) != '0') { modem_write("+++",FALSE); tmp = get_result(); } } } modem_write("\rATZ\r", FALSE); if ((tmp = get_result()) == '0') break; if (debug) printf("Init_modem 2: tries = %d\n",tries); } if (tries > 4) return(tmp); sleep(2); /* wait for a while while the modem resets */ modem_write("AT E0 F1 Q0 V1 X1 S0=0 S5=255 S2=29 \r",TRUE); if (debug) printf("Init_modem exit\n"); return(get_result()); } /* * h a n g _ m o d e m * * Hang up the modem. First escape to the command mode, then hang up the * phone. * The routine returns a result of '0' or a negative number for timeout */ char hang_modem() { int tries; char tmp; if (debug) printf("Hang_modem 1:\n"); for (tries = 1; tries <= 4; tries++) { sleep(2); /* Wait for a bit each time */ modem_write((hflg == 'a' || hflg == 'A') ? "\34\34\34" : "\35\35\35", FALSE); if ((tmp = get_result()) != '0') { modem_write("\34\34\34",FALSE); if ((tmp = get_result()) != '0') { modem_write("\35\35\35",FALSE); if ((tmp = get_result()) != '0') { modem_write("+++",FALSE); tmp = get_result(); } } } modem_write("ATH0\r", FALSE); if ((tmp = get_result()) == '0') break; if (debug) printf("Hang_modem 2: tries = %d\n",tries); } if (debug) printf("Hang_modem exit\n"); return(tmp); } /* * g e t _ r e s u l t * * This routine finds out the result code from the modem. */ char get_result() { int tmpx; /* The status and goes here */ char result; result = 0; /* Reset the result flag */ while (result == 0) /* do till something comes in that we recognize */ { if ((tmpx = modem_read(&modem_data)) <= 0) result = -1; else if (modem_data[substr(&modem_data, "OK")]) result = '0'; else if (modem_data[substr(&modem_data, "CONNECT 1200")]) result = '5'; else if (modem_data[substr(&modem_data, "RING")]) result = '2'; else if (modem_data[substr(&modem_data, "NO CARRIER")]) result = '3'; else if (modem_data[substr(&modem_data, "ERROR")]) result = '4'; else if (modem_data[substr(&modem_data, "CONNECT")]) result = '1'; if (debug) printf("Get_result 1: %c, %d, \"%s\"\n",result,tmpx,modem_data); } /* End of while loop */ if (debug) printf("Get_result 2: %c, %d, \"%s\"\n",result,tmpx,modem_data); return(result); } /* * m o d e m _ w r i t e * * send a string to the modem. If eat is TRUE, eat a single echo per xmitted * character. Does not account for echoed \n's after \r's. Current version * turns off command echo anyway, so no difference. */ modem_write(s, eat) char *s; int eat; { char t; int tmpx; tmpx = 1; while (*s) { write(ttyfd, s++, 1); if (eat) if ((tmpx = ioread(&t)) <= 0) break; } return(tmpx); } /* * m o d e m _ r e a d * * Modem read routine. This routine reads the returned control data from * The modem. */ modem_read(t) char *t; { char chr; BYTES point; point = t; /* Set pointer to start of the string */ while (TRUE) { if (ioread(t) <= 0) break; /* If an error or eof then exit */ if (*t == '\n') /* What was the last character? */ { *t++ = '\134'; *t++ = 'n'; /* Make the return into a \n */ break; /* If it was an EOL then exit */ } if ((chr = *t) < ' ') { *t++ = '\134'; *t = chr + '@'; /* Make control to alpha */ } t++; /* Bump the pointer */ } *t = NULL; /* Make sure the string ends with a null */ return(t - point); /* Return a character counter */ } /* * i o r e a d * * Read a character from the i/o channel */ ioread(t) char *t; { ULONG time_end, time(); int result; if (timint > 0) { time_end = time() + timint; while (time_end >= time()) if ((result = read(ttyfd, t, 1)) > 0) break; } else result = read(ttyfd, t, 1); return(result); } /* pe7pho.c End-of-file */