home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / slip / cslip-2.6 / tip / login.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-08  |  11.2 KB  |  561 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] =
  20.     "@(#) $Header: login.c,v 1.27 92/10/08 20:26:48 leres Exp $ (LBL)";
  21. #endif
  22.  
  23. #include "tip.h"
  24. #include <sys/time.h>
  25. #include <ctype.h>
  26. #include <strings.h>
  27.  
  28. static FILE *fp;
  29. static int line;
  30.  
  31. static int largc;
  32. static char *largv[10];        /* loginargs()/loginparse() assume args 0-9 */
  33. #define MAXARGS (sizeof(largv) / sizeof(*largv))
  34.  
  35. static char *loginargs(), *dosend(), *dorecv(), *dogoto();
  36. static int loginparse(), lread(), lputc();
  37. extern char *getpass();
  38. static void errputc(), errputs();
  39.  
  40. #define LOGIN_DELAY 0x81    /* pause for one second */
  41. #define LOGIN_BREAK 0x82    /* send break */
  42.  
  43. #define WRITE_DELAY 40        /* ms between each character written to modem */
  44.  
  45. char *
  46. login()
  47. {
  48.     register int n;
  49.     register char *cp;
  50.     char *cmd, *arg1, *arg2, *arg3;
  51.     static char errmsg[128];
  52.  
  53.     if (LS == NOSTR)
  54.         return(0);
  55.  
  56.     /* Split up arguments */
  57.     if (cp = loginargs(LS))
  58.         return(cp);
  59.  
  60.     if ((fp = fopen(largv[0], "r")) == NULL) {
  61.         (void)sprintf(errmsg, "login: %s: %s",
  62.             largv[0], strerror(errno));
  63.         return(errmsg);
  64.     }
  65.  
  66.     line = 0;
  67.     while (n = loginparse(&cmd, &arg1, &arg2, &arg3)) {
  68.         if (equal(cmd, "done")) {
  69.             fclose(fp);
  70.             return(0);
  71.         } else if (equal(cmd, "fail")) {
  72.             fclose(fp);
  73.             return("login failed");
  74.         } else if (equal(cmd, "send")) {
  75.             if (n != 2)
  76.                 break;
  77.             if (cp = dosend(arg1, 0)) {
  78.                 fclose(fp);
  79.                 return(cp);
  80.             }
  81.         } else if (equal(cmd, "sendpass")) {
  82.             if (n != 2)
  83.                 break;
  84.             if (cp = dosend(arg1, 1)) {
  85.                 fclose(fp);
  86.                 return(cp);
  87.             }
  88.         } else if (equal(cmd, "recv")) {
  89.             if (n == 3) {
  90.                 /* No label (fall through on timeout) */
  91.                 if (cp = dorecv(arg1, "", arg2)) {
  92.                     fclose(fp);
  93.                     return(cp);
  94.                 }
  95.             } else if (n == 4) {
  96.                 if (cp = dorecv(arg1, arg2, arg3)) {
  97.                     fclose(fp);
  98.                     return(cp);
  99.                 }
  100.             } else
  101.                 break;
  102.         } else if (equal(cmd, "pass")) {
  103.             if (n != 2)
  104.                 break;
  105.             if (cp = dosend(getpass(arg1), 1)) {
  106.                 fclose(fp);
  107.                 return(cp);
  108.             }
  109.         } else if (equal(cmd, "label"))
  110.             continue;
  111.         else if (equal(cmd, "goto")) {
  112.             if (n != 2)
  113.                 break;
  114.             if (cp = dogoto(arg1)) {
  115.                 fclose(fp);
  116.                 return(cp);
  117.             }
  118.         } else
  119.             break;
  120.     }
  121.     if (ferror(fp)) {
  122.         (void)sprintf(errmsg, "login: %s", strerror(errno));
  123.         fclose(fp);
  124.         return(errmsg);
  125.     }
  126.     if (feof(fp)) {
  127.         (void)sprintf(errmsg, "login: %s: premature EOF", LS);
  128.         fclose(fp);
  129.         return(errmsg);
  130.     }
  131.  
  132.     /* Must be a format error */
  133.     (void)sprintf(errmsg, "login: %s: format error at line %d", LS, line);
  134.     fclose(fp);
  135.     return(errmsg);
  136. }
  137.  
  138. static char *
  139. dosend(cp, ispass)
  140.     register char *cp;
  141.     int ispass;
  142. {
  143.     register char *cp2, *ret = 0, c;
  144.     struct timeval t;
  145.  
  146.     if (debug) {
  147.         (void)fputs("=> \"", stderr);
  148.         (void)fflush(stderr);
  149.     }
  150.     if (ispass) {
  151.         /* Auto-carriage return for passwords */
  152.         cp2 = cp + strlen(cp) - 1;
  153.         if (cp2 >= cp && *cp2 != '\r') {
  154.             *++cp2 = '\r';
  155.             *++cp2 = '\0';
  156.         }
  157.     }
  158.     t.tv_sec = 0;
  159.     t.tv_usec = WRITE_DELAY * 1000000;
  160.     while (*cp) {
  161.         c = *cp;
  162.         if (ispass)
  163.             *cp = '\0';
  164.         ++cp;
  165.         if ((unsigned char)c == LOGIN_DELAY)
  166.             sleep(1);
  167.         else if ((unsigned char)c == LOGIN_BREAK)
  168.             genbrk();
  169.         else if (lputc(c) != 1) {
  170.             ret = "dosend: write error to remote site";
  171.             goto bail;
  172.         }
  173.         if (debug) {
  174.             if (ispass && (c != '\r' || *cp != '\0'))
  175.                 c = '?';
  176.             errputc(c);
  177.         }
  178.         (void) select(32, 0, 0, 0, &t);
  179.     }
  180. bail:
  181.     if (debug) {
  182.         (void)fputs("\"\n", stderr);
  183.         (void)fflush(stderr);
  184.     }
  185.     return(ret);
  186. }
  187.  
  188. static char *
  189. dorecv(timeout, label, want)
  190.     char *timeout, *label, *want;
  191. {
  192.     register int i, j, n, size, secs;
  193.     register char *ret = 0;
  194.     static char buf[128], lastch;
  195.     char *cstr = "\"\n<= \"";
  196.     
  197.     size = strlen(want);
  198.     if (size >= sizeof(buf)) {
  199.         (void)sprintf(buf, "dorecv: size too big  (%d >= %d)",
  200.             size, sizeof(buf));
  201.         ret = buf;
  202.         goto bail;
  203.     }
  204.     if (debug) {
  205.         (void)fputs("<? \"", stderr);
  206.         errputs(want);
  207.         (void)fputs(cstr, stderr);
  208.         (void)fflush(stderr);
  209.     }
  210.     secs = atoi(timeout);
  211.     lastch = -1;
  212.     for (i = 0; i < size; ) {
  213.         /* Read as much as we can, handle timeout and errors */
  214.         if ((n = lread(FD, &buf[i], size - i, (u_int)secs)) < 0) {
  215.             (void)sprintf(buf, "dorecv: lread(1): %s\n",
  216.                 strerror(errno));
  217.             ret = buf;
  218.             goto bail;
  219.         } else if (n == 0) {
  220.             /* Timeout */
  221.             ret = (char *)-1;
  222.             goto bail;
  223.         }
  224.  
  225.         /* Gag, ANYP is all it's cracked up to be */
  226.         for (j = i; j < i + n; ++j)
  227.             buf[j] &= 0177;
  228.         if (debug)
  229.             for (j = i; j < i + n; ++j) {
  230.                 if (lastch == '\n')
  231.                     (void)fputs(cstr, stderr);
  232.                 errputc(buf[j]);
  233.                 lastch = buf[j];
  234.             }
  235.         i += n;
  236.         buf[i] = '\0';
  237.     }
  238.     i = size - 1;
  239.     while (strncmp(buf, want, size)) {
  240.         bcopy(buf + 1, buf, i);
  241.         if ((n = lread(FD, &buf[i], 1, (u_int)secs)) < 0) {
  242.             (void)sprintf(buf, "dorecv: lread(2): %s\n",
  243.                 strerror(errno));
  244.             ret = buf;
  245.             goto bail;
  246.         } else if (n == 0) {
  247.             /* Timeout */
  248.             ret = (char *)-1;
  249.             goto bail;
  250.         }
  251.         buf[i] &= 0177;
  252.         if (debug) {
  253.             if (lastch == '\n')
  254.                 (void)fputs(cstr, stderr);
  255.             errputc(buf[i]);
  256.             lastch = buf[i];
  257.         }
  258.     }
  259. bail:
  260.     if (debug) {
  261.         (void)fputs("\"\n", stderr);
  262.         (void)fflush(stderr);
  263.     }
  264.     if (ret == (char *)-1) {
  265.         if (*label) {
  266.             if (debug) {
  267.                 (void)fputs("recv: timeout\n", stderr);
  268.                 (void)fflush(stderr);
  269.             }
  270.             return(dogoto(label));
  271.         }
  272.         if (debug) {
  273.             (void)fputs("recv: timeout, falling through\n", stderr);
  274.             (void)fflush(stderr);
  275.         }
  276.         ret = 0;
  277.     }
  278.     return(ret);
  279. }
  280.  
  281. static char *
  282. dogoto(label)
  283.     char *label;
  284. {            
  285.     register int n;
  286.     char *cmd, *arg1, *arg2, *arg3;
  287.     static char buf[128];
  288.  
  289.     if (debug) {
  290.         (void)fprintf(stderr, "goto %s\n", label);
  291.         (void)fflush(stderr);
  292.     }
  293.     rewind(fp);
  294.     line = 0;
  295.     (void)strcpy(buf, label);
  296.     while (n = loginparse(&cmd, &arg1, &arg2, &arg3))
  297.         if (n == 2 && equal(cmd, "label") && equal(arg1, buf))
  298.             break;
  299.     if (ferror(fp)) {
  300.         (void)sprintf(buf, "dogoto: %s", strerror(errno));
  301.         return(buf);
  302.     }
  303.     return(0);
  304. }
  305.  
  306. /*
  307.  * Split up login script and its arguments
  308.  */
  309. static char *
  310. loginargs(str)
  311.     char *str;
  312. {
  313.     register int i, j;
  314.     register char *cp;
  315.     static char errmsg[128];
  316.     char buf[128];
  317.     char hostname[128];
  318.  
  319.     /* Get simple hostname */
  320.     (void) gethostname(hostname, sizeof(hostname));
  321.     hostname[sizeof(hostname) - 1] = '\0';
  322.     if (cp = index(hostname, '.'))
  323.         *cp = '\0';
  324.  
  325.     /* Save string (leave room for hostname expansion) */
  326.     if ((cp = malloc(2 * strlen(str))) == 0)
  327.         return("loginargs(): malloc failed");
  328.     strcpy(cp, str);
  329.     str = cp;
  330.  
  331.     /* hostname hack */
  332.     cp = str;
  333.     while (cp = index(cp, '%'))
  334.         if (cp[1] == 'h') {
  335.             /* Make room */
  336.             j = strlen(hostname);
  337.             i = strlen(&cp[2]);
  338.             /* Scoot last part over */
  339.             bcopy(&cp[2], &cp[j], i);
  340.             /* Stuff in hostname */
  341.             bcopy(hostname, cp, j);
  342.             /* Step over hostname */
  343.             cp += j;
  344.         }
  345.  
  346.     /* XXX might want to allow blanks to be escaped */
  347.     i = 0;
  348.     cp = str;
  349.     for (;;) {
  350.         if (i >= MAXARGS) {
  351.             sprintf(errmsg, "LS has more than %d args", MAXARGS);
  352.             return(errmsg);
  353.         }
  354.         largv[i++] = cp;
  355.         if ((cp = index(cp, ' ')) == 0)
  356.             break;
  357.         *cp++ = '\0';
  358.     }
  359.     largc = i;
  360.     return((char *)0);
  361. }
  362.  
  363.  
  364. /*
  365.  * Reads input file until a line is parsed
  366.  */
  367. static int
  368. loginparse(cmd, arg1, arg2, arg3)
  369.     char **cmd, **arg1, **arg2, **arg3;
  370. {
  371.     register int i, n;
  372.     register char *cp, *scp;
  373.     char buf[512];
  374.     static char sbuf[512];
  375.  
  376.     /* Get a non-blank, non-comment line */
  377.     do {
  378.         /* Get next line */
  379.         if (fgets(buf, sizeof(buf), fp) == 0)
  380.             return(0);
  381.         ++line;
  382.  
  383.         /* Nail trailing newline */
  384.         i = strlen(buf) - 1;
  385.         if (i >= 0 && buf[i] == '\n')
  386.             buf[i] = '\0';
  387.     } while (buf[0] == '\0' || buf[0] == '#');
  388.  
  389.     /* Do argument substitution */
  390.     cp = buf;
  391.     while (cp = index(cp, '$'))
  392.         if (cp[1] == '$') {
  393.             /* Fold doubled up $'s to singles */
  394.             i = strlen(cp) + 1;
  395.             bcopy(&cp[1], cp, i);
  396.             ++cp;
  397.         } else if (!isdigit(cp[1])) {
  398.             /* Leave single $'s alone */
  399.             ++cp;
  400.         } else {
  401.             /* Substitute */
  402.             n = cp[1] - '0';
  403.             /* Fetch argument */
  404.             if (n >= largc)
  405.                 scp = "";
  406.             else
  407.                 scp = largv[n];
  408.             n = strlen(scp);
  409.             i = strlen(&cp[2]) + 1;
  410.             /* Scoot last part over */
  411.             bcopy(&cp[2], &cp[n], i);
  412.             /* Stuff in argument */
  413.             bcopy(scp, cp, n);
  414.             /* Step over argument */
  415.             cp += n;
  416.         }
  417.  
  418.     /* Parse */
  419.     n = 1;
  420.     *cmd = sbuf;
  421.     *arg1 = *arg2 = *arg3 = "";
  422.     for (cp = buf, scp = sbuf; *cp != '\0'; ++cp, ++scp)
  423.         if (*cp == '\\') {
  424.             ++cp;
  425.             if (*cp == '\0')
  426.                 break;
  427.             if (*cp == 'b')
  428.                 *scp = '\b';
  429.             else if (*cp == 'f')
  430.                 *scp = '\f';
  431.             else if (*cp == 'n')
  432.                 *scp = '\n';
  433.             else if (*cp == 'r')
  434.                 *scp = '\r';
  435.             else if (*cp == 't')
  436.                 *scp = '\t';
  437.             else if (*cp == 'd')
  438.                 *scp = LOGIN_DELAY;
  439.             else if (*cp == 'x')
  440.                 *scp = LOGIN_BREAK;
  441.             else if (*cp == '?')
  442.                 *scp = 0177;
  443.             else
  444.                 *scp = *cp;
  445.         } else if (*cp == ' ' || *cp == '\t') {
  446.             *scp = '\0';
  447.             if (++n == 2)
  448.                 *arg1 = scp + 1;
  449.             else if (n == 3)
  450.                 *arg2 = scp + 1;
  451.             else if (n == 4)
  452.                 *arg3 = scp + 1;
  453.             else
  454.                 return(n);    /* too many arguments */
  455.             /* Eat white space */
  456.             while (*cp == ' ' || *cp == '\t')
  457.                 ++cp;
  458.             --cp;
  459.         } else
  460.             *scp = *cp;
  461.     *scp = '\0';
  462.     if (debug > 1) {
  463.         (void)fprintf(stderr, "loginparse: line %d, n %d,\t\"",
  464.             line, n);
  465.         errputs(*cmd);
  466.         (void)fputs("\"\t\"", stderr);
  467.         errputs(*arg1);
  468.         (void)fputs("\"\t\"", stderr);
  469.         errputs(*arg2);
  470.         (void)fputs("\"\t\"", stderr);
  471.         errputs(*arg3);
  472.         (void)fputs("\"\n", stderr);
  473.         (void)fflush(stderr);
  474.     }
  475.     return(n);
  476. }
  477.  
  478. static int
  479. lread(f, buf, len, secs)
  480.     int f;
  481.     char *buf;
  482.     int len;
  483.     u_int secs;
  484. {
  485.     register int n;
  486.     struct timeval t;
  487.     fd_set readfds;
  488.  
  489.     t.tv_sec = secs;
  490.     t.tv_usec = 0;
  491.     FD_ZERO(&readfds);
  492.     FD_SET(f, &readfds);
  493.     if ((n = select(f + 1, &readfds, 0, 0, &t)) <= 0)
  494.         return(n);
  495.     return(read(f, buf, len));
  496. }
  497.  
  498. static int
  499. lputc(c)
  500.     char c;
  501. {
  502.     struct timeval t;
  503.  
  504.     if (write(FD, &c, 1) != 1)
  505.         return(-1);
  506.     t.tv_sec = 0;
  507.     t.tv_usec = WRITE_DELAY * 1000000;
  508.     (void) select(32, 0, 0, 0, &t);
  509.     return(1);
  510. }
  511.  
  512. static void
  513. errputs(s)
  514.     register char *s;
  515. {
  516.     while (*s)
  517.         errputc(*s++);
  518. }
  519.  
  520. static void
  521. errputc(c)
  522.     char c;
  523. {
  524.  
  525.     if ((unsigned char) c == LOGIN_DELAY) {
  526.         (void)fputs("\\d", stderr);
  527.         (void)fflush(stderr);
  528.         return;
  529.     } else if ((unsigned char) c == LOGIN_BREAK) {
  530.         (void)fputs("\\x", stderr);
  531.         (void)fflush(stderr);
  532.         return;
  533.     }
  534.  
  535.     if (c & ~ 0177) {
  536.         (void)fputs("M-", stderr);
  537.         c &= 0177;
  538.     }
  539.     if (c < 0x20 || c == 0177) {
  540.         if (c == '\b')
  541.             (void)fputs("\\b", stderr);
  542.         else if (c == '\f')
  543.             (void)fputs("\\f", stderr);
  544.         else if (c == '\n')
  545.             (void)fputs("\\n", stderr);
  546.         else if (c == '\r')
  547.             (void)fputs("\\r", stderr);
  548.         else if (c == '\t')
  549.             (void)fputs("\\t", stderr);
  550.         else if (c == '"')
  551.             (void)fputs("\\\"", stderr);
  552.         else {
  553.             (void)putc('^', stderr);
  554.             /* DEL to ?, others to alpha */
  555.             (void)putc(c ^ 0x40, stderr);
  556.         }
  557.     } else
  558.         (void)putc(c, stderr);
  559.     (void)fflush(stderr);
  560. }
  561.