home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / AP / TERMNET / NCFTP183 / FTPRC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-20  |  13.3 KB  |  613 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. void WriteRecentSitesFile(void)
  262. {
  263.     FILE            *rfp;
  264.     recentsite        *r;
  265.     int                i;
  266.  
  267.     if ((recent_file[0] != 0) && (nRecents > 0) && (keep_recent)) {
  268.         dbprintf("Attempting to write %s...\n", recent_file);
  269.         rfp = fopen(recent_file, "w");
  270.         if (rfp != NULL) {
  271.             SortRecentList();
  272.             for (i=0; i<nRecents; i++) {
  273.                 r = &recents[i];
  274.                 (void) fprintf(rfp, "%-32s %11lu %s\n", r->name,
  275.                     (unsigned long) r->lastcall, r->dir);
  276.             }
  277.             (void) fclose(rfp);
  278.             dbprintf("%s written successfully.\n", recent_file);
  279.             (void) chmod(recent_file, 0600);
  280.         } else {
  281.             perror(recent_file);
  282.         }
  283.     }
  284. }    /* WriteRecentSitesFile */
  285.  
  286.  
  287.  
  288.  
  289. void AddRecentSite(char *host, char *lastdir)
  290. {
  291.     char            *nhost, *ndir;
  292.     recentsite        *r;
  293.     
  294.     if (keep_recent) {
  295.         nhost = NewString(host);
  296.         /* Use '/' to denote that the current directory wasn't known,
  297.          * because we won't try to cd to the root directory.
  298.          */
  299.         ndir = NewString(*lastdir ? lastdir : "/");
  300.         
  301.         /* Don't bother if we don't have the memory, or if it is already
  302.          * in our NETRC.
  303.          */
  304.         if ((ndir != NULL) && (nhost != NULL) &&
  305.             (FindNetrcSite(host, 1) == NULL)) {
  306.             if (nRecents == dMAXRECENTS) {
  307.                 SortRecentList();
  308.                 r = &recents[dMAXRECENTS - 1];
  309.                 if (r->name != NULL)
  310.                     free(r->name);
  311.                 if (r->dir != NULL)
  312.                     free(r->dir);
  313.             } else {
  314.                 r = &recents[nRecents];
  315.                 nRecents++;
  316.             }
  317.             r->name = nhost;            
  318.             r->dir = ndir;
  319.             (void) time(&r->lastcall);
  320.             SortRecentList();
  321.         }
  322.     }
  323. }    /* AddRecentSite */
  324.  
  325.  
  326.  
  327.  
  328. /*
  329.  * After you are done with a site (by closing it or quitting), we
  330.  * need to update the list of recent sites called.
  331.  */
  332. void UpdateRecentSitesList(char *host, char *lastdir)
  333. {
  334.     recentsite *r;
  335.     char *ndir;
  336.  
  337.     if (keep_recent) {    
  338.         r = FindRecentSite(host, 1);
  339.         if (r == NULL)
  340.             AddRecentSite(host, lastdir);
  341.         else {
  342.             /* Update the last time connected, and the directory we left in. */
  343.             if ((ndir = NewString(*lastdir ? lastdir : "/")) != NULL) {
  344.                 free(r->dir);
  345.                 r->dir = ndir;
  346.             }
  347.             (void) time(&r->lastcall);
  348.         }
  349.     }
  350. }    /* UpdateRecentSitesList */
  351.  
  352.  
  353.  
  354. /*
  355.  * Prints out the number of sites we know about, so the user can figure out
  356.  * an abbreviation or type it's number to open (setpeer).
  357.  */
  358. void PrintSiteList(void)
  359. {
  360.     int                        i, j;
  361.     siteptr                    s, s2;
  362.     FILE                    *pagerfp;
  363.     Sig_t                    sigpipe;
  364.  
  365.     if (fromatty) {
  366.         j = 0;
  367.         i = 1;
  368.         sigpipe = Signal(SIGPIPE, SIG_IGN);
  369.         if ((pagerfp = popen(pager + 1, "w")) == NULL)
  370.             pagerfp = stdout;
  371.         if (nRecents > 0) {
  372.             j++;
  373.             (void) fprintf(pagerfp, "\nRecently called sites:\n");
  374.             for (; i<=nRecents; i++) {
  375.                 (void) fprintf(pagerfp, "%4d. %-32s", i, recents[i-1].name);
  376.                 i++;
  377.                 if (i <= nRecents) {
  378.                     (void) fprintf(pagerfp, "%5d. %-32s", i, recents[i-1].name);
  379.                 } else {
  380.                     (void) fprintf(pagerfp, "\n");
  381.                     break;
  382.                 }
  383.                 (void) fprintf(pagerfp, "\n");
  384.             }
  385.         }
  386.         if (nSites > 0) {
  387.             j++;
  388.             (void) fprintf(pagerfp, "Sites in your netrc (%s):\n", rcname);
  389.             for (s = firstsite; s != NULL; s2=s->next, s=s2, ++i) {
  390.                 (void) fprintf(pagerfp, "%4d. %-32s", i, s->name);
  391.                 s2=s->next;
  392.                 s=s2;
  393.                 i++;
  394.                 if (s != NULL) {
  395.                     (void) fprintf(pagerfp, "%5d. %-32s", i, s->name);
  396.                 } else {
  397.                     (void) fprintf(pagerfp, "\n");
  398.                     break;
  399.                 }
  400.                 (void) fprintf(pagerfp, "\n");
  401.             }
  402.         }
  403.         if (j > 0) {
  404.             (void) fprintf(pagerfp, "\
  405. Note that you can specify an abbreviation of any name, or #x, where x is the\n\
  406. number of the site you want to connect to.\n\n");
  407.         }
  408.  
  409.         if (pagerfp != stdout)
  410.             (void) pclose(pagerfp);
  411.         Signal(SIGPIPE, sigpipe);
  412.     }
  413. }    /* PrintRecentSiteList */
  414.  
  415.  
  416.  
  417.  
  418. /*
  419.  * Given a sitename, check to see if the name was really an abbreviation
  420.  * of a site in the NETRC, or a site in our list of recently connected
  421.  * sites.  Also check if the name was in the format #x, where x which
  422.  * would mean to use recents[x].name as the site; if x was greater than
  423.  * the number of sites in the recent list, then index into the netrc
  424.  * site list.
  425.  */
  426. #include <netdb.h>
  427. void GetFullSiteName(char *host, char *lastdir)
  428. {
  429.     register siteptr        s, s2;
  430.     register recentsite        *r;
  431.     char                    *ndir, *nhost, *cp;
  432.     int                        x, i, isAllDigits, exact;
  433.     struct hostent            *hostentp;
  434.  
  435.     ndir = nhost = NULL;
  436.     x = exact = 0;
  437.  
  438.     /* First, see if the "abbreviation" is really just the name of
  439.      * a machine in the local domain, or if it was a full hostname
  440.      * already.  That way we can avoid problems associated with
  441.      * short names, such as having "ce" as a machine in the local
  442.      * domain, but having "faces.unl.edu", where we would most likely
  443.      * want to use ce instead of faces if the user said "open ce".
  444.      * This will also prevent problems when you have a host named
  445.      * xx.yy.unl.edu, and another host named yy.unl.edu.  If the user
  446.      * said "open yy.unl.edu" we should use yy.unl.edu, and not look
  447.      * for matches containing yy.unl.edu.
  448.      */
  449.     if ((hostentp = gethostbyname(host)) != NULL) {
  450.         strcpy(host, hostentp->h_name);
  451.         exact = 1;
  452.     }
  453.  
  454.     /* Don't allow just numbers as abbreviations;  "open 2" could be
  455.      * confused between site numbers in the open 'menu,' like
  456.      * "2. unlinfo.unl.edu" and IP numbers "128.93.2.1" or even numbers
  457.      * in the site name like "simtel20.army.mil."
  458.      */
  459.     
  460.     for (isAllDigits = 1, cp = host; *cp != 0; cp++) {
  461.         if (!isdigit(*cp)) {
  462.             isAllDigits = 0;
  463.             break;
  464.         }
  465.     }
  466.  
  467.     if (!isAllDigits) {
  468.         if (host[0] == '#')
  469.             (void) sscanf(host + 1, "%d", &x);
  470.         /* Try matching the abbreviation, since it isn't just a number. */
  471.         /* see if 'host' is in our list of favorite sites (in NETRC). */
  472.  
  473.         if (x == 0) {
  474.             if ((s = FindNetrcSite(host, exact)) != NULL) {
  475.                 nhost = s->name;
  476.             } else if ((r = FindRecentSite(host, exact)) != NULL) {
  477.                 nhost = r->name;
  478.                 ndir = r->dir;
  479.             }
  480.         }
  481.     } else if (sscanf(host, "%d", &x) != 1) {
  482.         x = 0;
  483.     }
  484.  
  485.     if (--x >= 0) {
  486.         if (x < nRecents) {
  487.             nhost = recents[x].name;
  488.             ndir = recents[x].dir;
  489.         } else {
  490.             x -= nRecents;
  491.             if (x < nSites) {
  492.                 for (i = 0, s = firstsite; i < x; s2=s->next, s=s2)
  493.                     ++i;                
  494.                 nhost = s->name;
  495.             }
  496.         }
  497.     }
  498.  
  499.     if (nhost != NULL) {
  500.         (void) strcpy(host, nhost);
  501.         if (lastdir != NULL) {
  502.             *lastdir = 0;
  503.             /* Don't cd if the dir is the root directory. */
  504.             if (ndir != NULL && (strcmp("/", ndir) != 0))
  505.                 (void) strcpy(lastdir, ndir);
  506.         }
  507.     }
  508. }    /* GetFullSiteName */
  509.  
  510.  
  511.  
  512.  
  513. int ruserpass2(char *host, char **username, char **pass, char **acct)
  514. {
  515.     FILE            *fp;
  516.     char            *cp, *dp, *dst, *ep;
  517.     str32            macname;
  518.     char            *varname;
  519.     int                site_found;
  520.     string            str;
  521.     static string    auser;
  522.     static str32    apass, aacct;
  523.  
  524.     site_found = 0;
  525.  
  526.     if ((fp = fopen(rcname, "r")) != NULL) {
  527.         parsing_rc = 1;
  528.         while (FGets(str, fp)) {
  529.             if ((cp = strstr(str, "machine")) != 0) {
  530.                 /* Look for the machine token. */
  531.                 cp += 7;
  532.                 while (isspace(*cp))
  533.                     cp++;
  534.             } else
  535.                 continue;
  536.             if (strncmp(host, cp, strlen(host)) == 0) {
  537.                 site_found = 1;
  538.                 while (!isspace(*cp))
  539.                     ++cp;        /* skip the site name. */
  540.                 do {
  541.                     /* Skip any comments ahead of time. */
  542.                     for (dp=cp; *dp; dp++) {
  543.                         if (*dp == '#') {
  544.                             *dp = 0;
  545.                             break;
  546.                         }
  547.                     }
  548.  
  549.                     ep = cp;
  550.                     while (1) {
  551.                         varname = strtok(ep, RC_DELIM);
  552.                         if (!varname) break;
  553.                         dst = ep = NULL;
  554.                         switch (*varname) {
  555.                             case 'u':    /* user */
  556.                                 *username = dst = auser;
  557.                                 break;
  558.                             case 'l':    /* login */
  559.                                 *username = dst = auser;
  560.                                 break;
  561.                             case 'p':    /* password */
  562.                                 *pass = dst = apass;
  563.                                 break;
  564.                             case 'a':    /* account */
  565.                                 *acct = dst = aacct;
  566.                                 break;
  567.                         /*    case 'd':  /o default */
  568.                         /* unused -- use 'set anon_password.' */
  569.                             case 'm':    /* macdef or machine */
  570.                                 if (strcmp(varname, "macdef"))
  571.                                     goto done;    /* new machine record... */
  572.                                 dst = macname;
  573.                                 break;
  574.                             default:
  575.                                 (void) fprintf(stderr, "Unknown .netrc keyword \"%s\"\n",
  576.                                     varname
  577.                                 );
  578.                         }
  579.                         if (dst) {
  580.                             dp = strtok(ep, RC_DELIM);
  581.                             if (dp)
  582.                                 (void) strcpy(dst, dp);
  583.                             if (dst == macname) {
  584.                                 /*
  585.                                  *    Read in the lines of the macro.
  586.                                  *    The macro's end is denoted by
  587.                                  *    a blank line.
  588.                                  */
  589.                                 (void) make_macro(macname, fp);
  590.                                 goto nextline;
  591.                             }
  592.                         }
  593.                     }
  594. nextline: ;
  595.                 } while ((cp = FGets(str, fp)) != 0);
  596.                 break;
  597.             }        /* end if we found the machine record. */
  598.         }
  599. done:
  600.         parsing_rc = 0;
  601.         (void) fclose(fp);
  602.     }
  603.  
  604.     if (!site_found) {
  605.         /* didn't find it in the rc. */
  606.         return (0);
  607.     }
  608.  
  609.     return (1);    /* found */
  610. }    /* ruserpass2 */
  611.  
  612. /* eof ftprc.c */
  613.