home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume39 / ncftp / part04 / ftprc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-25  |  10.9 KB  |  530 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. #include <sys/types.h>
  10. #include <sys/param.h>
  11. #include <sys/stat.h>
  12.  
  13. #include <string.h>
  14. #include <ctype.h>
  15. #include <time.h>
  16.  
  17. #include "util.h"
  18. #include "ftprc.h"
  19. #include "main.h"
  20. #include "cmds.h"
  21. #include "set.h"
  22. #include "defaults.h"
  23. #include "copyright.h"
  24.  
  25. /* ftprc.c global variables */
  26. siteptr                    firstsite = NULL, lastsite = NULL;
  27. recentsite                recents[dMAXRECENTS];
  28. int                        nRecents = 0;
  29. int                        nSites = 0;
  30. int                        keep_recent = dRECENT_ON;
  31. longstring                rcname;
  32. longstring                recent_file;
  33. int                        parsing_rc = 0;
  34.  
  35. extern char                *line, *margv[];
  36. extern int                margc, fromatty;
  37. extern string            anon_password;        /* most likely your email address */
  38. extern struct userinfo    uinfo;
  39.  
  40. int thrash_rc(void)
  41. {
  42.     struct stat            st;
  43.     string                word, str;
  44.     longstring            cwd;
  45.     char                *cp, *dp, *rc;
  46.     FILE                *fp;
  47.     int                    i;
  48.  
  49.     (void) get_cwd(cwd, sizeof(cwd));
  50.     if (cwd[strlen(cwd) - 1] != '/')
  51.         (void) Strncat(cwd, "/");
  52.  
  53.     /* Because some versions of regular ftp complain about ncftp's
  54.      * #set commands, FTPRC takes precedence over NETRC.
  55.      */
  56.     cp = getenv("DOTDIR");
  57.     for (i=0; i<2; i++) {
  58.         rc = (i == 0) ? FTPRC : NETRC;
  59.  
  60.         (void) sprintf(rcname, "%s%s", cwd, rc);
  61.         if (stat(rcname, &st) == 0)
  62.             goto foundrc;
  63.         
  64.         (void) sprintf(rcname, "%s.%s", cwd, rc);
  65.         if (stat(rcname, &st) == 0)
  66.             goto foundrc;
  67.  
  68.         if (cp != NULL) {
  69.             (void) sprintf(rcname, "%s/.%s", cp, rc);
  70.             if (stat(rcname, &st) == 0)
  71.                 goto foundrc;
  72.         }
  73.  
  74.         (void) sprintf(rcname, "%s/.%s", uinfo.homedir, rc);
  75.         if (stat(rcname, &st) == 0)
  76.             goto foundrc;
  77.     }
  78.  
  79.     return (0);    /* it's OK not to have an rc. */
  80.     
  81. foundrc:    
  82.     if ((st.st_mode & 077) != 0)                /* rc must be unreadable by others. */
  83.         (void) chmod(rcname, 0600);
  84.  
  85.     if ((fp = fopen(rcname, "r")) == NULL) {
  86.         PERROR("thrash_rc", rcname);
  87.         return -1;
  88.     }
  89.     
  90.     parsing_rc = 1;
  91.     while (cp = FGets(str, fp)) {
  92.         while (isspace(*cp)) ++cp;        /* skip leading space. */
  93.         if (*cp == '#') {
  94.             if ((strncmp("set", ++cp, (size_t)3) == 0) || (strncmp("unset", cp, (size_t)5) == 0)) {
  95.                 (void) strcpy(line, cp);
  96.                 makeargv();
  97.                 (void) set(margc, margv);            
  98.                 /* setting or unsetting a variable. */
  99.             } /* else a comment. */
  100.         } else {
  101.             if (strncmp(cp, "machine", (size_t) 7) == 0) {
  102.                 /* We have a new machine record. */
  103.                 cp += 7;
  104.                 while (isspace(*cp)) ++cp;    /* skip delimiting space. */
  105.                 dp = word;
  106.                 while (*cp && !isspace(*cp)) *dp++ = *cp++;    /* copy the name. */
  107.                 *dp = 0;
  108.                 AddNewSitePtr(word);
  109.             }
  110.         }
  111.     }
  112.     (void) fclose(fp);
  113.     parsing_rc = 0;
  114.     return 1;
  115. }    /* thrash_rc */
  116.  
  117.  
  118.  
  119.  
  120. void AddNewSitePtr(char *word)
  121. {
  122.     siteptr            s;
  123.  
  124.     if (s = (siteptr) malloc(sizeof(site))) {
  125.         s->next = NULL;
  126.         if (s->name = malloc(strlen(word) + 1)) {
  127.             (void) strcpy(s->name, word);
  128.             if (firstsite == NULL)
  129.                 firstsite = lastsite = s;
  130.             else {
  131.                 lastsite->next = s;
  132.                 lastsite = s;
  133.             }
  134.             ++nSites;
  135.         } else {
  136.             free(s);
  137.         }
  138.     }
  139. }    /* AddNewSitePtr */
  140.  
  141.  
  142.  
  143.  
  144. static int RecentCmp(recentsite *a, recentsite *b)
  145. {
  146.     int i = 1;
  147.     
  148.     if (a->lastcall > b->lastcall)
  149.         i = -1;
  150.     else if (a->lastcall == b->lastcall)
  151.         i = 0;
  152.     return i;
  153. }    /* RecentCmp */
  154.  
  155.  
  156.  
  157.  
  158. static siteptr FindNetrcSite(char *host)
  159. {
  160.     register siteptr s, s2;
  161.  
  162.     /* see if 'host' is in our list of favorite sites (in NETRC). */
  163.     for (s = firstsite; s != NULL; s2=s->next, s=s2) {
  164.         if (strstr(s->name, host) != NULL) {
  165.             return s;
  166.         }
  167.     }
  168.     return NULL;
  169. }    /* FindNetrcSite */
  170.  
  171.  
  172.  
  173.  
  174. static recentsite *FindRecentSite(char *host)
  175. {
  176.     register recentsite        *r;
  177.     register int            i;
  178.  
  179.     /* see if 'host' is in our list of favorite sites (in recent-log). */
  180.     for (i=0; i<nRecents; i++) {
  181.         r = &recents[i];
  182.         if (strstr(r->name, host) != NULL) {
  183.             return r;
  184.         }
  185.     }
  186.     return NULL;
  187. }    /* FindRecentSite */
  188.  
  189.  
  190.  
  191.  
  192. void ReadRecentSitesFile(void)
  193. {
  194.     FILE *rfp;
  195.     recentsite *r;
  196.     char name[64], dir[256];
  197.     string str;
  198.  
  199.     nRecents = 0;
  200.     if (recent_file[0] != 0 && keep_recent) {
  201.         rfp = fopen(recent_file, "r");
  202.         if (rfp != NULL) {
  203.             for (; nRecents < dMAXRECENTS; ) {
  204.                 r = &recents[nRecents];
  205.                 if (FGets(str, rfp) == NULL)
  206.                     break;
  207.                 if (sscanf(str, "%s %lu %s", name, (unsigned long *) &r->lastcall, dir) == 3) {
  208.                     if ((r->name = NewString(name)) != NULL) {
  209.                         r->dir = NewString(dir);
  210.                         if (r->dir != NULL)
  211.                             nRecents++;
  212.                         else free(r->name);
  213.                     }
  214.                 }
  215.             }
  216.             (void) fclose(rfp);
  217.         }
  218.     }
  219. }    /* ReadRecentSitesFile */
  220.  
  221.  
  222.  
  223. static void SortRecentList(void)
  224. {
  225.     QSort(recents, nRecents, sizeof(recentsite), RecentCmp);
  226. }    /* SortRecentList */
  227.  
  228.  
  229.  
  230.  
  231. void WriteRecentSitesFile(void)
  232. {
  233.     FILE            *rfp;
  234.     recentsite        *r;
  235.     int                i;
  236.  
  237.     if ((recent_file[0] != 0) && (nRecents > 0) && (keep_recent)) {
  238.         rfp = fopen(recent_file, "w");
  239.         SortRecentList();
  240.         if (rfp != NULL) {
  241.             for (i=0; i<nRecents; i++) {
  242.                 r = &recents[i];
  243.                 (void) fprintf(rfp, "%-32s %11lu %s\n", r->name,
  244.                     (unsigned long) r->lastcall, r->dir);
  245.             }
  246.             (void) fclose(rfp);
  247.             (void) chmod(recent_file, 0600);
  248.         }
  249.     }
  250. }    /* WriteRecentSitesFile */
  251.  
  252.  
  253.  
  254.  
  255. void AddRecentSite(char *host, char *lastdir)
  256. {
  257.     char            *nhost, *ndir;
  258.     recentsite        *r;
  259.     
  260.     if (keep_recent) {
  261.         nhost = NewString(host);
  262.         /* Use '/' to denote that the current directory wasn't known,
  263.          * because we won't try to cd to the root directory.
  264.          */
  265.         ndir = NewString(*lastdir ? lastdir : "/");
  266.         
  267.         /* Don't bother if we don't have the memory, or if it is already
  268.          * in our NETRC.
  269.          */
  270.         if ((ndir != NULL) && (nhost != NULL) && (FindNetrcSite(host) == NULL)) {
  271.             if (nRecents == dMAXRECENTS) {
  272.                 SortRecentList();
  273.                 r = &recents[dMAXRECENTS - 1];
  274.                 if (r->name != NULL)
  275.                     free(r->name);
  276.                 if (r->dir != NULL)
  277.                     free(r->dir);
  278.             } else {
  279.                 r = &recents[nRecents];
  280.                 nRecents++;
  281.             }
  282.             r->name = nhost;            
  283.             r->dir = ndir;
  284.             (void) time(&r->lastcall);
  285.             SortRecentList();
  286.         }
  287.     }
  288. }    /* AddRecentSite */
  289.  
  290.  
  291.  
  292.  
  293. /*
  294.  * After you are done with a site (by closing it or quitting), we
  295.  * need to update the list of recent sites called.
  296.  */
  297. void UpdateRecentSitesList(char *host, char *lastdir)
  298. {
  299.     recentsite *r;
  300.     char *ndir;
  301.  
  302.     if (keep_recent) {    
  303.         r = FindRecentSite(host);
  304.         if (r == NULL)
  305.             AddRecentSite(host, lastdir);
  306.         else {
  307.             /* Update the last time connected, and the directory we left in. */
  308.             if ((ndir = NewString(*lastdir ? lastdir : "/")) != NULL) {
  309.                 free(r->dir);
  310.                 r->dir = ndir;
  311.             }
  312.             (void) time(&r->lastcall);
  313.         }
  314.     }
  315. }    /* UpdateRecentSitesList */
  316.  
  317.  
  318.  
  319. /*
  320.  * Prints out the number of sites we know about, so the user can figure out
  321.  * an abbreviation or type it's number to open (setpeer).
  322.  */
  323. void PrintSiteList(void)
  324. {
  325.     int                        i, j;
  326.     siteptr                    s, s2;
  327.  
  328.     if (fromatty) {
  329.         j = 0;
  330.         i = 1;
  331.         if (nRecents > 0) {
  332.             j++;
  333.             (void) printf("Recently called sites:\n");
  334.             for (; i<=nRecents; i++) {
  335.                 (void) printf("%4d. %-32s", i, recents[i-1].name);
  336.                 i++;
  337.                 if (i <= nRecents) {
  338.                     (void) printf("%5d. %-32s", i, recents[i-1].name);
  339.                 } else {
  340.                     (void) printf("\n");
  341.                     break;
  342.                 }
  343.                 (void) printf("\n");
  344.             }
  345.         }
  346.         if (nSites > 0) {
  347.             j++;
  348.             (void) printf("Sites in your netrc (%s):\n", rcname);
  349.             for (s = firstsite; s != NULL; s2=s->next, s=s2, ++i) {
  350.                 (void) printf("%4d. %-32s", i, s->name);
  351.                 s2=s->next;
  352.                 s=s2;
  353.                 i++;
  354.                 if (s != NULL) {
  355.                     (void) printf("%5d. %-32s", i, s->name);
  356.                 } else {
  357.                     (void) printf("\n");
  358.                     break;
  359.                 }
  360.                 (void) printf("\n");
  361.             }
  362.         }
  363.         if (j > 0) {
  364.             (void) printf("\
  365. Note that you can specify an abbreviation of any name, or #x, where x is the\n\
  366. number of the site you want to connect to.\n\n");
  367.         }
  368.     }
  369. }    /* PrintRecentSiteList */
  370.  
  371.  
  372.  
  373.  
  374. /*
  375.  * Given a sitename, check to see if the name was really an abbreviation
  376.  * of a site in the NETRC, or a site in our list of recently connected
  377.  * sites.  Also check if the name was in the format #x, where x which
  378.  * would mean to use recents[x].name as the site; if x was greater than
  379.  * the number of sites in the recent list, then index into the netrc
  380.  * site list.
  381.  */
  382. void GetFullSiteName(char *host, char *lastdir)
  383. {
  384.     register siteptr        s, s2;
  385.     register recentsite        *r;
  386.     char                    *ndir, *nhost;
  387.     int                        x, i;
  388.  
  389.     ndir = nhost = NULL;
  390.     x = 0;
  391.  
  392.     /* see if 'host' is in our list of favorite sites (in NETRC). */
  393.     if ((s = FindNetrcSite(host)) != NULL) {
  394.         nhost = s->name;
  395.     } else if ((r = FindRecentSite(host)) != NULL) {
  396.         nhost = r->name;
  397.         ndir = r->dir;
  398.     } else if (sscanf(host[0]=='#' ? host+1 : host, "%d", &x) != 1) {
  399.         x = 0;
  400.     }
  401.  
  402.     if (--x >= 0) {
  403.         if (x < nRecents) {
  404.             nhost = recents[x].name;
  405.             ndir = recents[x].dir;
  406.         } else {
  407.             x -= nRecents;
  408.             if (x < nSites) {
  409.                 for (i = 0, s = firstsite; i < x; s2=s->next, s=s2)
  410.                     ++i;                
  411.                 nhost = s->name;
  412.             }
  413.         }
  414.     }
  415.  
  416.     if (nhost != NULL) {
  417.         (void) strcpy(host, nhost);
  418.         if (lastdir != NULL) {
  419.             *lastdir = 0;
  420.             /* Don't cd if the dir is the root directory. */
  421.             if (ndir != NULL && (strcmp("/", ndir) != 0))
  422.                 (void) strcpy(lastdir, ndir);
  423.         }
  424.     }
  425. }    /* GetFullSiteName */
  426.  
  427.  
  428.  
  429.  
  430. int ruserpass2(char *host, char **username, char **pass, char **acct)
  431. {
  432.     FILE            *fp;
  433.     char            *cp, *dp, *dst, *ep;
  434.     str32            macname;
  435.     char            *varname;
  436.     int                site_found;
  437.     string            str;
  438.     static string    auser;
  439.     static str32    apass, aacct;
  440.  
  441.     site_found = 0;
  442.  
  443.     if ((fp = fopen(rcname, "r")) != NULL) {
  444.         parsing_rc = 1;
  445.         while (FGets(str, fp)) {
  446.             if (cp = strstr(str, "machine")) {
  447.                 /* Look for the machine token. */
  448.                 cp += 7;
  449.                 while (isspace(*cp))
  450.                     cp++;
  451.             } else
  452.                 continue;
  453.             if (strncmp(cp, host, strlen(host)) == 0) {
  454.                 site_found = 1;
  455.                 while (!isspace(*cp))
  456.                     ++cp;        /* skip the site name. */
  457.                 do {
  458.                     /* Skip any comments ahead of time. */
  459.                     for (dp=cp; *dp; dp++) {
  460.                         if (*dp == '#') {
  461.                             *dp = 0;
  462.                             break;
  463.                         }
  464.                     }
  465.  
  466.                     ep = cp;
  467.                     while (1) {
  468.                         varname = strtok(ep, RC_DELIM);
  469.                         if (!varname) break;
  470.                         dst = ep = NULL;
  471.                         switch (*varname) {
  472.                             case 'u':    /* user */
  473.                                 *username = dst = auser;
  474.                                 break;
  475.                             case 'l':    /* login */
  476.                                 *username = dst = auser;
  477.                                 break;
  478.                             case 'p':    /* password */
  479.                                 *pass = dst = apass;
  480.                                 break;
  481.                             case 'a':    /* account */
  482.                                 *acct = dst = aacct;
  483.                                 break;
  484.                         /*    case 'd':  /o default */
  485.                         /* unused -- use 'set anon_password.' */
  486.                             case 'm':    /* macdef or machine */
  487.                                 if (strcmp(varname, "macdef"))
  488.                                     goto done;    /* new machine record... */
  489.                                 dst = macname;
  490.                                 break;
  491.                             default:
  492.                                 (void) fprintf(stderr, "Unknown .netrc keyword \"%s\"\n",
  493.                                     varname
  494.                                 );
  495.                         }
  496.                         if (dst) {
  497.                             dp = strtok(ep, RC_DELIM);
  498.                             if (dp)
  499.                                 (void) strcpy(dst, dp);
  500.                             if (dst == macname) {
  501.                                 /*
  502.                                  *    Read in the lines of the macro.
  503.                                  *    The macro's end is denoted by
  504.                                  *    a blank line.
  505.                                  */
  506.                                 (void) make_macro(macname, fp);
  507.                                 goto nextline;
  508.                             }
  509.                         }
  510.                     }
  511. nextline: ;
  512.                 } while (cp = FGets(str, fp));
  513.                 break;
  514.             }        /* end if we found the machine record. */
  515.         }
  516. done:
  517.         parsing_rc = 0;
  518.         (void) fclose(fp);
  519.     }
  520.  
  521.     if (!site_found) {
  522.         /* didn't find it in the rc. */
  523.         return (0);
  524.     }
  525.  
  526.     return (1);    /* found */
  527. }    /* ruserpass2 */
  528.  
  529. /* eof ftprc.c */
  530.