home *** CD-ROM | disk | FTP | other *** search
/ ftp.ncftp.com / ftp.ncftp.com.zip / ftp.ncftp.com / ncftp / ncftp-1.9.5.tar.gz / ncftp-1.9.5.tar / ncftp-1.9.5 / ftprc.c < prev    next >
C/C++ Source or Header  |  1995-10-01  |  14KB  |  616 lines

  1. /* ftprc.c */
  2.  
  3. /*  $RCSfile: ftprc.c,v $
  4.  *  $Revision: 14020.11 $
  5.  *  $Date: 93/07/09 10:58:37 $
  6.  */
  7.  
  8. #include "sys.h"
  9.  
  10. #include <sys/stat.h>
  11.  
  12. #include <ctype.h>
  13. #include <signal.h>
  14.  
  15. #include "util.h"
  16. #include "ftprc.h"
  17. #include "main.h"
  18. #include "cmds.h"
  19. #include "set.h"
  20. #include "defaults.h"
  21. #include "copyright.h"
  22.  
  23. /* ftprc.c global variables */
  24. siteptr                    firstsite = NULL, lastsite = NULL;
  25. recentsite                recents[dMAXRECENTS];
  26. int                        nRecents = 0;
  27. int                        nSites = 0;
  28. int                        keep_recent = dRECENT_ON;
  29. longstring                rcname;
  30. longstring                recent_file;
  31. int                        parsing_rc = 0;
  32.  
  33. extern char                *line, *margv[];
  34. extern int                margc, fromatty;
  35. extern string            anon_password;        /* most likely your email address */
  36. extern string            pager;
  37. extern struct userinfo    uinfo;
  38.  
  39. int thrash_rc(void)
  40. {
  41.     struct stat            st;
  42.     string                word, str;
  43.     longstring            cwd;
  44.     char                *cp, *dp, *rc;
  45.     FILE                *fp;
  46.     int                    i;
  47.  
  48.     (void) get_cwd(cwd, sizeof(cwd));
  49.     if (cwd[strlen(cwd) - 1] != '/')
  50.         (void) Strncat(cwd, "/");
  51.  
  52.     /* Because some versions of regular ftp complain about ncftp's
  53.      * #set commands, FTPRC takes precedence over NETRC.
  54.      */
  55.     cp = getenv("DOTDIR");
  56.     for (i=0; i<2; i++) {
  57.         rc = (i == 0) ? FTPRC : NETRC;
  58.  
  59.         (void) sprintf(rcname, "%s%s", cwd, rc);
  60.         if (stat(rcname, &st) == 0)
  61.             goto foundrc;
  62.         
  63.         (void) sprintf(rcname, "%s.%s", cwd, rc);
  64.         if (stat(rcname, &st) == 0)
  65.             goto foundrc;
  66.  
  67.         if (cp != NULL) {
  68.             (void) sprintf(rcname, "%s/.%s", cp, rc);
  69.             if (stat(rcname, &st) == 0)
  70.                 goto foundrc;
  71.         }
  72.  
  73.         (void) sprintf(rcname, "%s/.%s", uinfo.homedir, rc);
  74.         if (stat(rcname, &st) == 0)
  75.             goto foundrc;
  76.     }
  77.  
  78.     return (0);    /* it's OK not to have an rc. */
  79.     
  80. foundrc:    
  81.     if ((st.st_mode & 077) != 0)                /* rc must be unreadable by others. */
  82.         (void) chmod(rcname, 0600);
  83.  
  84.     if ((fp = fopen(rcname, "r")) == NULL) {
  85.         PERROR("thrash_rc", rcname);
  86.         return -1;
  87.     }
  88.     
  89.     parsing_rc = 1;
  90.     while ((cp = FGets(str, fp)) != 0) {
  91.         while (isspace(*cp)) ++cp;        /* skip leading space. */
  92.         if (*cp == '#') {
  93.             if ((strncmp("set", ++cp, (size_t)3) == 0) || (strncmp("unset", cp, (size_t)5) == 0)) {
  94.                 (void) strcpy(line, cp);
  95.                 makeargv();
  96.                 (void) set(margc, margv);            
  97.                 /* setting or unsetting a variable. */
  98.             } /* else a comment. */
  99.         } else {
  100.             if (strncmp(cp, "machine", (size_t) 7) == 0) {
  101.                 /* We have a new machine record. */
  102.                 cp += 7;
  103.                 while (isspace(*cp)) ++cp;    /* skip delimiting space. */
  104.                 dp = word;
  105.                 while (*cp && !isspace(*cp)) *dp++ = *cp++;    /* copy the name. */
  106.                 *dp = 0;
  107.                 AddNewSitePtr(word);
  108.             }
  109.         }
  110.     }
  111.     (void) fclose(fp);
  112.     parsing_rc = 0;
  113.     return 1;
  114. }    /* thrash_rc */
  115.  
  116.  
  117.  
  118.  
  119. void AddNewSitePtr(char *word)
  120. {
  121.     siteptr            s;
  122.  
  123.     if ((s = (siteptr) malloc(sizeof(site))) != 0) {
  124.         s->next = NULL;
  125.         if ((s->name = malloc(strlen(word) + 1)) != 0) {
  126.             (void) strcpy(s->name, word);
  127.             if (firstsite == NULL)
  128.                 firstsite = lastsite = s;
  129.             else {
  130.                 lastsite->next = s;
  131.                 lastsite = s;
  132.             }
  133.             ++nSites;
  134.         } else {
  135.             Free(s);
  136.         }
  137.     }
  138. }    /* AddNewSitePtr */
  139.  
  140.  
  141.  
  142.  
  143. static int RecentCmp(recentsite *a, recentsite *b)
  144. {
  145.     int i = 1;
  146.     
  147.     if (a->lastcall > b->lastcall)
  148.         i = -1;
  149.     else if (a->lastcall == b->lastcall)
  150.         i = 0;
  151.     return i;
  152. }    /* RecentCmp */
  153.  
  154.  
  155.  
  156.  
  157. static siteptr FindNetrcSite(char *host, int exact)
  158. {
  159.     register siteptr s, s2;
  160.     string str, host2;
  161.  
  162.     (void) Strncpy(host2, host);
  163.     StrLCase(host2);
  164.     
  165.     /* see if 'host' is in our list of favorite sites (in NETRC). */
  166.     for (s = firstsite; s != NULL; s2=s->next, s=s2) {
  167.         (void) Strncpy(str, s->name);
  168.         StrLCase(str);
  169.         if (exact) {
  170.             if (strcmp(str, host2) == 0)
  171.                 return s;
  172.         } else {
  173.             if (strstr(str, host2) != NULL) 
  174.                 return s;
  175.         }
  176.     }
  177.     return NULL;
  178. }    /* FindNetrcSite */
  179.  
  180.  
  181.  
  182.  
  183. static recentsite *FindRecentSite(char *host, int exact)
  184. {
  185.     register recentsite        *r;
  186.     register int            i;
  187.     string                    str, host2;
  188.  
  189.     (void) Strncpy(host2, host);
  190.     StrLCase(host2);
  191.  
  192.     /* see if 'host' is in our list of favorite sites (in recent-log). */
  193.     for (i=0; i<nRecents; i++) {
  194.         r = &recents[i];
  195.         (void) Strncpy(str, r->name);
  196.         StrLCase(str);
  197.         if (exact) {
  198.             if (strcmp(str, host2) == 0)
  199.                 return r;
  200.         } else {
  201.             if (strstr(str, host2) != NULL)
  202.                 return r;
  203.         }
  204.     }
  205.     return NULL;
  206. }    /* FindRecentSite */
  207.  
  208.  
  209.  
  210.  
  211. void ReadRecentSitesFile(void)
  212. {
  213.     FILE *rfp;
  214.     recentsite *r;
  215.     char name[64];
  216.     int offset;
  217.     longstring str;
  218.  
  219.     nRecents = 0;
  220.     if (recent_file[0] != 0 && keep_recent) {
  221.         rfp = fopen(recent_file, "r");
  222.         if (rfp != NULL) {
  223.             for (; nRecents < dMAXRECENTS; ) {
  224.                 r = &recents[nRecents];
  225.                 if (FGets(str, rfp) == NULL)
  226.                     break;
  227.                 (void) RemoveTrailingNewline(str, NULL);
  228.                 name[0] = 0;
  229.                 offset = 45;
  230.                 if (sscanf(str, "%s %lu %n",
  231.                     name,
  232.                     (unsigned long *) &r->lastcall,
  233.                     &offset) >= 2)
  234.                 {
  235.                     if ((r->name = NewString(name)) != NULL) {
  236.                         r->dir = NewString(str + offset);
  237.                         if (r->dir != NULL)
  238.                             nRecents++;
  239.                         else {
  240.                             free(r->name);
  241.                             r->name = r->dir = NULL;
  242.                         }
  243.                     }
  244.                 }
  245.             }
  246.             (void) fclose(rfp);
  247.         }
  248.     }
  249. }    /* ReadRecentSitesFile */
  250.  
  251.  
  252.  
  253. static void SortRecentList(void)
  254. {
  255.     QSort(recents, nRecents, sizeof(recentsite), RecentCmp);
  256. }    /* SortRecentList */
  257.  
  258.  
  259.  
  260.  
  261. int WriteRecentSitesFile(void)
  262. {
  263.     FILE            *rfp;
  264.     recentsite        *r;
  265.     int                i;
  266.     int retcode = 0;
  267.  
  268.     if ((recent_file[0] != 0) && (nRecents > 0) && (keep_recent)) {
  269.         dbprintf("Attempting to write %s...\n", recent_file);
  270.         rfp = fopen(recent_file, "w");
  271.         if (rfp != NULL) {
  272.             SortRecentList();
  273.             for (i=0; i<nRecents; i++) {
  274.                 r = &recents[i];
  275.                 (void) fprintf(rfp, "%-32s %11lu %s\n", r->name,
  276.                     (unsigned long) r->lastcall, r->dir);
  277.             }
  278.             (void) fclose(rfp);
  279.             dbprintf("%s written successfully.\n", recent_file);
  280.             (void) chmod(recent_file, 0600);
  281.         } else {
  282.             perror(recent_file);
  283.             ++retcode;
  284.         }
  285.     }
  286.     return retcode;
  287. }    /* WriteRecentSitesFile */
  288.  
  289.  
  290.  
  291.  
  292. void AddRecentSite(char *host, char *lastdir)
  293. {
  294.     char            *nhost, *ndir;
  295.     recentsite        *r;
  296.     
  297.     if (keep_recent) {
  298.         nhost = NewString(host);
  299.         /* Use '/' to denote that the current directory wasn't known,
  300.          * because we won't try to cd to the root directory.
  301.          */
  302.         ndir = NewString(*lastdir ? lastdir : "/");
  303.         
  304.         /* Don't bother if we don't have the memory, or if it is already
  305.          * in our NETRC.
  306.          */
  307.         if ((ndir != NULL) && (nhost != NULL) &&
  308.             (FindNetrcSite(host, 1) == NULL)) {
  309.             if (nRecents == dMAXRECENTS) {
  310.                 SortRecentList();
  311.                 r = &recents[dMAXRECENTS - 1];
  312.                 if (r->name != NULL)
  313.                     free(r->name);
  314.                 if (r->dir != NULL)
  315.                     free(r->dir);
  316.             } else {
  317.                 r = &recents[nRecents];
  318.                 nRecents++;
  319.             }
  320.             r->name = nhost;            
  321.             r->dir = ndir;
  322.             (void) time(&r->lastcall);
  323.             SortRecentList();
  324.         }
  325.     }
  326. }    /* AddRecentSite */
  327.  
  328.  
  329.  
  330.  
  331. /*
  332.  * After you are done with a site (by closing it or quitting), we
  333.  * need to update the list of recent sites called.
  334.  */
  335. void UpdateRecentSitesList(char *host, char *lastdir)
  336. {
  337.     recentsite *r;
  338.     char *ndir;
  339.  
  340.     if (keep_recent) {    
  341.         r = FindRecentSite(host, 1);
  342.         if (r == NULL)
  343.             AddRecentSite(host, lastdir);
  344.         else {
  345.             /* Update the last time connected, and the directory we left in. */
  346.             if ((ndir = NewString(*lastdir ? lastdir : "/")) != NULL) {
  347.                 free(r->dir);
  348.                 r->dir = ndir;
  349.             }
  350.             (void) time(&r->lastcall);
  351.         }
  352.     }
  353. }    /* UpdateRecentSitesList */
  354.  
  355.  
  356.  
  357. /*
  358.  * Prints out the number of sites we know about, so the user can figure out
  359.  * an abbreviation or type it's number to open (setpeer).
  360.  */
  361. void PrintSiteList(void)
  362. {
  363.     int                        i, j;
  364.     siteptr                    s, s2;
  365.     FILE                    *pagerfp;
  366.     Sig_t                    sigpipe;
  367.  
  368.     if (fromatty) {
  369.         j = 0;
  370.         i = 1;
  371.         sigpipe = Signal(SIGPIPE, SIG_IGN);
  372.         if ((pagerfp = popen(pager + 1, "w")) == NULL)
  373.             pagerfp = stdout;
  374.         if (nRecents > 0) {
  375.             j++;
  376.             (void) fprintf(pagerfp, "\nRecently called sites:\n");
  377.             for (; i<=nRecents; i++) {
  378.                 (void) fprintf(pagerfp, "%4d. %-32s", i, recents[i-1].name);
  379.                 i++;
  380.                 if (i <= nRecents) {
  381.                     (void) fprintf(pagerfp, "%5d. %-32s", i, recents[i-1].name);
  382.                 } else {
  383.                     (void) fprintf(pagerfp, "\n");
  384.                     break;
  385.                 }
  386.                 (void) fprintf(pagerfp, "\n");
  387.             }
  388.         }
  389.         if (nSites > 0) {
  390.             j++;
  391.             (void) fprintf(pagerfp, "Sites in your netrc (%s):\n", rcname);
  392.             for (s = firstsite; s != NULL; s2=s->next, s=s2, ++i) {
  393.                 (void) fprintf(pagerfp, "%4d. %-32s", i, s->name);
  394.                 s2=s->next;
  395.                 s=s2;
  396.                 i++;
  397.                 if (s != NULL) {
  398.                     (void) fprintf(pagerfp, "%5d. %-32s", i, s->name);
  399.                 } else {
  400.                     (void) fprintf(pagerfp, "\n");
  401.                     break;
  402.                 }
  403.                 (void) fprintf(pagerfp, "\n");
  404.             }
  405.         }
  406.         if (j > 0) {
  407.             (void) fprintf(pagerfp, "\
  408. Note that you can specify an abbreviation of any name, or #x, where x is the\n\
  409. number of the site you want to connect to.\n\n");
  410.         }
  411.  
  412.         if (pagerfp != stdout)
  413.             (void) pclose(pagerfp);
  414.         Signal(SIGPIPE, sigpipe);
  415.     }
  416. }    /* PrintRecentSiteList */
  417.  
  418.  
  419.  
  420.  
  421. /*
  422.  * Given a sitename, check to see if the name was really an abbreviation
  423.  * of a site in the NETRC, or a site in our list of recently connected
  424.  * sites.  Also check if the name was in the format #x, where x which
  425.  * would mean to use recents[x].name as the site; if x was greater than
  426.  * the number of sites in the recent list, then index into the netrc
  427.  * site list.
  428.  */
  429. #include <netdb.h>
  430. void GetFullSiteName(char *host, char *lastdir)
  431. {
  432.     register siteptr        s, s2;
  433.     register recentsite        *r;
  434.     char                    *ndir, *nhost, *cp;
  435.     int                        x, i, isAllDigits, exact;
  436.     struct hostent            *hostentp;
  437.  
  438.     ndir = nhost = NULL;
  439.     x = exact = 0;
  440.  
  441.     /* First, see if the "abbreviation" is really just the name of
  442.      * a machine in the local domain, or if it was a full hostname
  443.      * already.  That way we can avoid problems associated with
  444.      * short names, such as having "ce" as a machine in the local
  445.      * domain, but having "faces.unl.edu", where we would most likely
  446.      * want to use ce instead of faces if the user said "open ce".
  447.      * This will also prevent problems when you have a host named
  448.      * xx.yy.unl.edu, and another host named yy.unl.edu.  If the user
  449.      * said "open yy.unl.edu" we should use yy.unl.edu, and not look
  450.      * for matches containing yy.unl.edu.
  451.      */
  452.     if ((hostentp = gethostbyname(host)) != NULL) {
  453.         strcpy(host, hostentp->h_name);
  454.         exact = 1;
  455.     }
  456.  
  457.     /* Don't allow just numbers as abbreviations;  "open 2" could be
  458.      * confused between site numbers in the open 'menu,' like
  459.      * "2. unlinfo.unl.edu" and IP numbers "128.93.2.1" or even numbers
  460.      * in the site name like "simtel20.army.mil."
  461.      */
  462.     
  463.     for (isAllDigits = 1, cp = host; *cp != 0; cp++) {
  464.         if (!isdigit(*cp)) {
  465.             isAllDigits = 0;
  466.             break;
  467.         }
  468.     }
  469.  
  470.     if (!isAllDigits) {
  471.         if (host[0] == '#')
  472.             (void) sscanf(host + 1, "%d", &x);
  473.         /* Try matching the abbreviation, since it isn't just a number. */
  474.         /* see if 'host' is in our list of favorite sites (in NETRC). */
  475.  
  476.         if (x == 0) {
  477.             if ((s = FindNetrcSite(host, exact)) != NULL) {
  478.                 nhost = s->name;
  479.             } else if ((r = FindRecentSite(host, exact)) != NULL) {
  480.                 nhost = r->name;
  481.                 ndir = r->dir;
  482.             }
  483.         }
  484.     } else if (sscanf(host, "%d", &x) != 1) {
  485.         x = 0;
  486.     }
  487.  
  488.     if (--x >= 0) {
  489.         if (x < nRecents) {
  490.             nhost = recents[x].name;
  491.             ndir = recents[x].dir;
  492.         } else {
  493.             x -= nRecents;
  494.             if (x < nSites) {
  495.                 for (i = 0, s = firstsite; i < x; s2=s->next, s=s2)
  496.                     ++i;                
  497.                 nhost = s->name;
  498.             }
  499.         }
  500.     }
  501.  
  502.     if (nhost != NULL) {
  503.         (void) strcpy(host, nhost);
  504.         if (lastdir != NULL) {
  505.             *lastdir = 0;
  506.             /* Don't cd if the dir is the root directory. */
  507.             if (ndir != NULL && (strcmp("/", ndir) != 0))
  508.                 (void) strcpy(lastdir, ndir);
  509.         }
  510.     }
  511. }    /* GetFullSiteName */
  512.  
  513.  
  514.  
  515.  
  516. int ruserpass2(char *host, char **username, char **pass, char **acct)
  517. {
  518.     FILE            *fp;
  519.     char            *cp, *dp, *dst, *ep;
  520.     str32            macname;
  521.     char            *varname;
  522.     int                site_found;
  523.     string            str;
  524.     static string    auser;
  525.     static str32    apass, aacct;
  526.  
  527.     site_found = 0;
  528.  
  529.     if ((fp = fopen(rcname, "r")) != NULL) {
  530.         parsing_rc = 1;
  531.         while (FGets(str, fp)) {
  532.             if ((cp = strstr(str, "machine")) != 0) {
  533.                 /* Look for the machine token. */
  534.                 cp += 7;
  535.                 while (isspace(*cp))
  536.                     cp++;
  537.             } else
  538.                 continue;
  539.             if (strncmp(host, cp, strlen(host)) == 0) {
  540.                 site_found = 1;
  541.                 while (!isspace(*cp))
  542.                     ++cp;        /* skip the site name. */
  543.                 do {
  544.                     /* Skip any comments ahead of time. */
  545.                     for (dp=cp; *dp; dp++) {
  546.                         if (*dp == '#') {
  547.                             *dp = 0;
  548.                             break;
  549.                         }
  550.                     }
  551.  
  552.                     ep = cp;
  553.                     while (1) {
  554.                         varname = strtok(ep, RC_DELIM);
  555.                         if (!varname) break;
  556.                         dst = ep = NULL;
  557.                         switch (*varname) {
  558.                             case 'u':    /* user */
  559.                                 *username = dst = auser;
  560.                                 break;
  561.                             case 'l':    /* login */
  562.                                 *username = dst = auser;
  563.                                 break;
  564.                             case 'p':    /* password */
  565.                                 *pass = dst = apass;
  566.                                 break;
  567.                             case 'a':    /* account */
  568.                                 *acct = dst = aacct;
  569.                                 break;
  570.                         /*    case 'd':  /o default */
  571.                         /* unused -- use 'set anon_password.' */
  572.                             case 'm':    /* macdef or machine */
  573.                                 if (strcmp(varname, "macdef"))
  574.                                     goto done;    /* new machine record... */
  575.                                 dst = macname;
  576.                                 break;
  577.                             default:
  578.                                 (void) fprintf(stderr, "Unknown .netrc keyword \"%s\"\n",
  579.                                     varname
  580.                                 );
  581.                         }
  582.                         if (dst) {
  583.                             dp = strtok(ep, RC_DELIM);
  584.                             if (dp)
  585.                                 (void) strcpy(dst, dp);
  586.                             if (dst == macname) {
  587.                                 /*
  588.                                  *    Read in the lines of the macro.
  589.                                  *    The macro's end is denoted by
  590.                                  *    a blank line.
  591.                                  */
  592.                                 (void) make_macro(macname, fp);
  593.                                 goto nextline;
  594.                             }
  595.                         }
  596.                     }
  597. nextline: ;
  598.                 } while ((cp = FGets(str, fp)) != 0);
  599.                 break;
  600.             }        /* end if we found the machine record. */
  601.         }
  602. done:
  603.         parsing_rc = 0;
  604.         (void) fclose(fp);
  605.     }
  606.  
  607.     if (!site_found) {
  608.         /* didn't find it in the rc. */
  609.         return (0);
  610.     }
  611.  
  612.     return (1);    /* found */
  613. }    /* ruserpass2 */
  614.  
  615. /* eof ftprc.c */
  616.