home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume10 / callback_hg / part01 / callback0.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-01-06  |  8.6 KB  |  311 lines

  1. /*
  2.  * callback0 - get symbolic phone # from user & dial modem
  3.  */
  4.  
  5. #ifndef lint
  6. static char _cpyrgt[] = "Copyright 1990 Howard Lee Gayle";
  7. #endif lint
  8.  
  9. /*
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License version 1,
  12.  * as published by the Free Software Foundation.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <howard/port.h>
  26. #include <howard/version.h>
  27. #include <howard/usage.h>
  28.  
  29. MAINVER ("@(#)$Header: callback0.c,v 1.6 89/12/28 10:34:27 howard Exp $");
  30. USAGE ("flag name");
  31.  
  32. #include <fcntl.h>
  33. #include <signal.h>
  34. #include "callback.h"
  35.  
  36. #define MLINE 80 /* Max input line length.*/
  37. #define MCTLL 1024 /* Max control file line.*/
  38.  
  39. PRIVATE byteT lb[MLINE]; /* Input line.*/
  40. PRIVATE boolT talking; /* Talking to user.*/
  41.  
  42. PRIVATE void ws();
  43.  
  44. /* getmcs - look up modem control line */
  45.  
  46. PRIVATE void getmcs (ks, mcs)
  47. R4 cStrT ks;  /* Key string.  Must end in space.*/
  48. R5 cStrT mcs; /* Store modem control string here.*/
  49.  
  50. /* Function:
  51.  *    Search the control file for a line starting with the given key.
  52.  * Algorithm:
  53.  *    Linear search.  Call getlic() to read each line and strip comments.
  54.  * Returns:
  55.  *    On success, mcs points to the string to send to the modem to dial
  56.  *    the number.  On error, mcs points to the empty string.
  57.  * Notes:
  58.  *    1) There is no overflow checking when copying into mcs.
  59.  */
  60. {
  61. R2     streamT  cs;        /* Modem control file stream.*/
  62.        unsigned ln = 0;    /* Input line number.*/
  63. R3     boolT    m;         /* Loop control.*/
  64. R1     bStrT    p;         /* Returned by prefix (3 -lhoward).*/
  65.        byteT    ib[MCTLL]; /* Input line buffer.*/
  66. extern bStrT    getlic() ; /* (3 -lhoward).*/
  67.  
  68. cs = mfopen (ctlfn, "r");
  69. for (m = TRUE; m;)
  70.    {
  71.    if (NULBSTR == getlic (ib, MCTLL, cs, ctlfn, &ln, 1, ';'))
  72.       {
  73.       mcs[0] = EOS;
  74.       m = FALSE;
  75.       }
  76.    else if (NULBSTR != (p = prefix (ks, ib)))
  77.       {
  78.       while ((EOS != *p) && (' ' == *p))
  79.          ++p;
  80.       if (EOS == *p) malf1 ("%s: %u: No control string", ctlfn, ln);
  81.       STRCPY (mcs, p);
  82.       STRCAT (mcs, "\n");
  83.       m = FALSE;
  84.       }
  85.    }
  86. mfclose (cs, ctlfn);
  87. }
  88.  
  89. /* rs - read string from fd 0 */
  90.  
  91. PRIVATE void rs()
  92.  
  93. /* Function:
  94.  *    Read a line from standard input and log it.
  95.  * Algorithm:
  96.  *    Call read().  On error call malf1().  If characters are read,
  97.  *    NUL-terminate the result.  Treat EOF as an empty string.
  98.  *    Write the result on the log file.
  99.  * Returns:
  100.  *    The result is stored in lb[].
  101.  * Notes:
  102.  *    
  103.  */
  104. {
  105. R1 int i; /* Number of bytes read.*/
  106.  
  107. i = read (0, lb, MLINE);
  108. if (-1 == i) malf1 ("Read error on fd 0");
  109. if (i > 0)
  110.    lb[i - 1] = EOS;
  111. else if (0 == i)
  112.    lb[0] = EOS;
  113. logMMSS();
  114. FPUTS (lb, ls);
  115. PUTC ('\n', ls);
  116. FFLUSH (ls);
  117. }
  118.  
  119. /* sigalrm - print message if signal arrives */
  120.  
  121. PRIVATE void sigalrm ()
  122.  
  123. /* Function:
  124.  *    This function is called on timeout.  Write a message to the user and
  125.  *    the log file, then exit.
  126.  * Algorithm:
  127.  *    
  128.  * Notes:
  129.  *    1) The sleep() is to give the output tty time to flush before closing.
  130.  */
  131. {
  132. logMMSS();
  133. FPUTS ("timeout\n", ls);
  134. FFLUSH (ls);
  135. if (talking) ws ("TIMEOUT timeout\n");
  136. sleep (1);
  137. exit (3);
  138. }
  139.  
  140. /* ws - write a string on fd 1 */
  141.  
  142. PRIVATE void ws (s)
  143. R1 cStrT s; /* String to write.*/
  144.  
  145. /* Function:
  146.  *    Write string s on standard output and to the log file.
  147.  * Algorithm:
  148.  *    
  149.  * Notes:
  150.  *    1) If s does not end in a newline, an extra newline is written
  151.  *       to the logfile.
  152.  */
  153. {
  154. R2 int i; /* Length of string.*/
  155.  
  156. i = strlen (s);
  157. if (i != write (1, s, i)) malf1 ("Write error on fd 1");
  158. PUTC ('>', ls);
  159. FPUTS (s, ls);
  160. if ('\n' != s[i - 1]) PUTC ('\n', ls);
  161. FFLUSH (ls);
  162. }
  163.  
  164. /* main - main function                            */
  165.  
  166. PUBLIC int main (argc, argv)
  167.    int    argc; /* Number of arguments.*/
  168. R6 bStrT *argv; /* Points to array of argument strings.*/
  169.  
  170. /* Function:
  171.  *    Do callback.
  172.  * Algorithm:
  173.  *    Set real and effective group ID to 0.  Initialize.  Set tty
  174.  *    for user interaction.  Prompt user and get symbolic phone number.
  175.  *    Look it up in modem control file.  On failure, write error message,
  176.  *    sleep a little to discourage brute force attacks, and repeat until
  177.  *    success or timeout.  On success, hang up the line.  Sleep long
  178.  *    enough to make sure the line is really hung up.  Open the dial-out
  179.  *    (cua) device.  Write the string from the control file, read
  180.  *    the responses, and throw them away until one matches a prefix
  181.  *    in the modem reply code table.  Retry if the table says to,
  182.  *    until timeout.  On success, turn off the hang-up-on-close bit,
  183.  *    create the state file, and exit.
  184.  * Notes:
  185.  *    1) This program is exec'ed by the speciall getty instead of login,
  186.  *       so the tty is already set up correctly (speed, parity, case, etc.)
  187.  *    2) Turning off the HUPCL bit just before exiting means the line
  188.  *       does not get dropped on exit.  On exit, init starts up a new
  189.  *       callback process, which, because the state file is present,
  190.  *       execs a normal login.
  191.  */
  192.  
  193. {
  194. R2     boolT          m;              /* Loop control.*/
  195. R1     mrcT          *rp;             /* Steps through mrctab[].*/
  196. R4     streamT        ss;             /* State file stream.*/
  197.        ulongT         sp;             /* Line speed as code.*/
  198. R5     cStrT          sps;            /* Line speed as string.*/
  199. R3     unsigned       tries = 0;      /* Callback tries.*/
  200.        stateT         st;             /* Contents of state file.*/
  201.        struct termios ts;             /* TTY status.*/
  202.        char           prompt[12];     /* Prompt for user.*/
  203.        char           mcs[MCTLL];     /* Modem control string.*/
  204.        char           key[2 * MLINE]; /* Key in control file.*/
  205. extern cStrT          ttyname();      /* (3).*/
  206.  
  207. if (-1 == setregid (0, 0)) exit (3);
  208. initTty ((bStrT) tn, (bStrT) ttyname (0));
  209. initLog (S("callback0"));
  210. logArgs (S("argv:"), argv);
  211. if ((argc < 3) || (strlen ((cStrT) argv[2]) > 8)) usage();
  212. gts (&ts);
  213. ts.c_iflag |= (IGNPAR | IMAXBEL);
  214. ts.c_lflag |= (ECHO | ECHOE | ECHOK | TOSTOP | ECHOCTL | ECHOKE);
  215. sts (&ts);
  216. sp = CBAUD & ts.c_cflag;
  217. if ((sp < B50) || (sp > B38400)) malf1 ("Bad line speed: %lu", sp);
  218. sps = speeds[sp];
  219. FPRINTF (ls, "Speed %lu = %s\n", sp, sps);
  220. FFLUSH (ls);
  221. SPRINTF (prompt, "%s %s", sps, sps);
  222. if (-1 == (int) signal (SIGALRM, sigalrm)) malf1 ("Can not signal");
  223. talking = TRUE;
  224. (void) alarm (ABORTSEC);
  225. for (m = TRUE; m;)
  226.    {
  227.    ws (prompt);
  228.    rs();
  229.    if (EOS != lb[0])
  230.       {
  231.       SPRINTF (key, "%s@%s ", lb, sps);
  232.       getmcs (key, mcs);
  233.       if (EOS != mcs[0])
  234.          m = FALSE;
  235.       else
  236.          {
  237.          sleep (1);
  238.          ws (umNo);
  239.          sleep (4);
  240.          }
  241.       }
  242.    }
  243. talking = FALSE;
  244. ws (umBye);
  245. (void) alarm (ABORTSEC);
  246. st.stCflag = ts.c_cflag;
  247. STRCPY (st.stName, (cStrT) argv[2]);
  248. sleep (1);
  249. FPUTS ("Closing 1\n", ls);
  250. FFLUSH (ls);
  251. if (close (1)) malf1 ("Can not close 1");
  252. ts.c_cflag &= ~(CBAUD | CIBAUD | HUPCL);
  253. FPUTS ("TCSETS\n", ls);
  254. FFLUSH (ls);
  255. if (-1 == ioctl (0, TCSETS, &ts)) malf1 ("TCSETS failed");
  256. FPUTS ("TCFLSH\n", ls);
  257. FFLUSH (ls);
  258. if (-1 == ioctl (0, TCFLSH, 2)) malf1 ("TCFLSH failed");
  259. FPUTS ("Closing 0\n", ls);
  260. FFLUSH (ls);
  261. if (close (0)) malf1 ("Can not close 0");
  262. FPUTS ("sleep...", ls);
  263. FFLUSH (ls);
  264. sleep (DROPSEC);
  265. FPUTS ("ok\n", ls);
  266. FFLUSH (ls);
  267. if (0 != open (cun, O_RDWR)) malf1 ("%s: Can not open read/write", cun);
  268. if (1 != dup (0)) malf1 ("Can not dup 1");
  269. gts (&ts);
  270. ts.c_iflag |= (IGNPAR | IMAXBEL);
  271. ts.c_cflag = st.stCflag;
  272. ts.c_lflag &= ~ECHO;
  273. sts (&ts);
  274. for (m = TRUE; m;)
  275.    {
  276.    ++tries;
  277.    ws (mcs);
  278.    do
  279.       {
  280.       rs();
  281.       rp = mrctab;
  282.       while ((NULBSTR != rp->mrcStr) && (NULBSTR == prefix (rp->mrcStr, lb)))
  283.          ++rp;
  284.       }
  285.    while (NULBSTR == rp->mrcStr);
  286.    m = rp->mrcRetry;
  287.    }
  288. (void) alarm (0);
  289. ts.c_cflag = st.stCflag & (~HUPCL);
  290. ts.c_lflag |= ECHO;
  291. sts (&ts);
  292. ss = mfopen (statefn, "w");
  293. if ((1 != fwrite ((cStrT) &st, sizeof (stateT), 1, ss)) || ferror (ss))
  294.    malf1 ("%s: Write error", statefn);
  295. mfclose (ss, statefn);
  296. SPRINTF (prompt, "%s %u %s\n", sps, tries, sps);
  297. ws (prompt);
  298. FPUTS ("Closing stdin\n", ls);
  299. FFLUSH (ls);
  300. if (close (0)) malf1 ("Can not close 0");
  301. FPUTS ("Closing stdout\n", ls);
  302. FFLUSH (ls);
  303. if (close (1)) malf1 ("Can not close 1");
  304. FPUTS ("Exit\n", ls);
  305. FFLUSH (ls);
  306. exit (0);
  307. #ifdef lint
  308. return (SUCCESS);
  309. #endif
  310. }
  311.