This is ftprc.c in view mode; [Download] [Up]
/* ftprc.c */
/* $RCSfile: ftprc.c,v $
* $Revision: 14020.11 $
* $Date: 93/07/09 10:58:37 $
*/
#include "sys.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "util.h"
#include "ftprc.h"
#include "main.h"
#include "cmds.h"
#include "set.h"
#include "defaults.h"
#include "copyright.h"
/* ftprc.c global variables */
siteptr firstsite = NULL, lastsite = NULL;
recentsite recents[dMAXRECENTS];
int nRecents = 0;
int nSites = 0;
int keep_recent = dRECENT_ON;
longstring rcname;
longstring recent_file;
int parsing_rc = 0;
extern char *line, *margv[];
extern int margc, fromatty;
extern string anon_password; /* most likely your email address */
extern struct userinfo uinfo;
int thrash_rc(void)
{
struct stat st;
string word, str;
longstring cwd;
char *cp, *dp, *rc;
FILE *fp;
int i;
(void) get_cwd(cwd, sizeof(cwd));
if (cwd[strlen(cwd) - 1] != '/')
(void) Strncat(cwd, "/");
/* Because some versions of regular ftp complain about ncftp's
* #set commands, FTPRC takes precedence over NETRC.
*/
cp = getenv("DOTDIR");
for (i=0; i<2; i++) {
rc = (i == 0) ? FTPRC : NETRC;
(void) sprintf(rcname, "%s%s", cwd, rc);
if (stat(rcname, &st) == 0)
goto foundrc;
(void) sprintf(rcname, "%s.%s", cwd, rc);
if (stat(rcname, &st) == 0)
goto foundrc;
if (cp != NULL) {
(void) sprintf(rcname, "%s/.%s", cp, rc);
if (stat(rcname, &st) == 0)
goto foundrc;
}
(void) sprintf(rcname, "%s/.%s", uinfo.homedir, rc);
if (stat(rcname, &st) == 0)
goto foundrc;
}
return (0); /* it's OK not to have an rc. */
foundrc:
if ((st.st_mode & 077) != 0) /* rc must be unreadable by others. */
(void) chmod(rcname, 0600);
if ((fp = fopen(rcname, "r")) == NULL) {
PERROR("thrash_rc", rcname);
return -1;
}
parsing_rc = 1;
while (cp = FGets(str, fp)) {
while (isspace(*cp)) ++cp; /* skip leading space. */
if (*cp == '#') {
if ((strncmp("set", ++cp, (size_t)3) == 0) || (strncmp("unset", cp, (size_t)5) == 0)) {
(void) strcpy(line, cp);
makeargv();
(void) set(margc, margv);
/* setting or unsetting a variable. */
} /* else a comment. */
} else {
if (strncmp(cp, "machine", (size_t) 7) == 0) {
/* We have a new machine record. */
cp += 7;
while (isspace(*cp)) ++cp; /* skip delimiting space. */
dp = word;
while (*cp && !isspace(*cp)) *dp++ = *cp++; /* copy the name. */
*dp = 0;
AddNewSitePtr(word);
}
}
}
(void) fclose(fp);
parsing_rc = 0;
return 1;
} /* thrash_rc */
void AddNewSitePtr(char *word)
{
siteptr s;
if (s = (siteptr) malloc(sizeof(site))) {
s->next = NULL;
if (s->name = malloc(strlen(word) + 1)) {
(void) strcpy(s->name, word);
if (firstsite == NULL)
firstsite = lastsite = s;
else {
lastsite->next = s;
lastsite = s;
}
++nSites;
} else {
Free(s);
}
}
} /* AddNewSitePtr */
static int RecentCmp(recentsite *a, recentsite *b)
{
int i = 1;
if (a->lastcall > b->lastcall)
i = -1;
else if (a->lastcall == b->lastcall)
i = 0;
return i;
} /* RecentCmp */
static siteptr FindNetrcSite(char *host)
{
register siteptr s, s2;
/* see if 'host' is in our list of favorite sites (in NETRC). */
for (s = firstsite; s != NULL; s2=s->next, s=s2) {
if (strstr(s->name, host) != NULL) {
return s;
}
}
return NULL;
} /* FindNetrcSite */
static recentsite *FindRecentSite(char *host)
{
register recentsite *r;
register int i;
/* see if 'host' is in our list of favorite sites (in recent-log). */
for (i=0; i<nRecents; i++) {
r = &recents[i];
if (strstr(r->name, host) != NULL) {
return r;
}
}
return NULL;
} /* FindRecentSite */
void ReadRecentSitesFile(void)
{
FILE *rfp;
recentsite *r;
char name[64], dir[256];
string str;
nRecents = 0;
if (recent_file[0] != 0 && keep_recent) {
rfp = fopen(recent_file, "r");
if (rfp != NULL) {
for (; nRecents < dMAXRECENTS; ) {
r = &recents[nRecents];
if (FGets(str, rfp) == NULL)
break;
if (sscanf(str, "%s %lu %s", name, (unsigned long *) &r->lastcall, dir) == 3) {
if ((r->name = NewString(name)) != NULL) {
r->dir = NewString(dir);
if (r->dir != NULL)
nRecents++;
else free(r->name);
}
}
}
(void) fclose(rfp);
}
}
} /* ReadRecentSitesFile */
static void SortRecentList(void)
{
QSort(recents, nRecents, sizeof(recentsite), RecentCmp);
} /* SortRecentList */
void WriteRecentSitesFile(void)
{
FILE *rfp;
recentsite *r;
int i;
if ((recent_file[0] != 0) && (nRecents > 0) && (keep_recent)) {
rfp = fopen(recent_file, "w");
SortRecentList();
if (rfp != NULL) {
for (i=0; i<nRecents; i++) {
r = &recents[i];
(void) fprintf(rfp, "%-32s %11lu %s\n", r->name,
(unsigned long) r->lastcall, r->dir);
}
(void) fclose(rfp);
(void) chmod(recent_file, 0600);
}
}
} /* WriteRecentSitesFile */
void AddRecentSite(char *host, char *lastdir)
{
char *nhost, *ndir;
recentsite *r;
if (keep_recent) {
nhost = NewString(host);
/* Use '/' to denote that the current directory wasn't known,
* because we won't try to cd to the root directory.
*/
ndir = NewString(*lastdir ? lastdir : "/");
/* Don't bother if we don't have the memory, or if it is already
* in our NETRC.
*/
if ((ndir != NULL) && (nhost != NULL) && (FindNetrcSite(host) == NULL)) {
if (nRecents == dMAXRECENTS) {
SortRecentList();
r = &recents[dMAXRECENTS - 1];
if (r->name != NULL)
free(r->name);
if (r->dir != NULL)
free(r->dir);
} else {
r = &recents[nRecents];
nRecents++;
}
r->name = nhost;
r->dir = ndir;
(void) time(&r->lastcall);
SortRecentList();
}
}
} /* AddRecentSite */
/*
* After you are done with a site (by closing it or quitting), we
* need to update the list of recent sites called.
*/
void UpdateRecentSitesList(char *host, char *lastdir)
{
recentsite *r;
char *ndir;
if (keep_recent) {
r = FindRecentSite(host);
if (r == NULL)
AddRecentSite(host, lastdir);
else {
/* Update the last time connected, and the directory we left in. */
if ((ndir = NewString(*lastdir ? lastdir : "/")) != NULL) {
free(r->dir);
r->dir = ndir;
}
(void) time(&r->lastcall);
}
}
} /* UpdateRecentSitesList */
/*
* Prints out the number of sites we know about, so the user can figure out
* an abbreviation or type it's number to open (setpeer).
*/
void PrintSiteList(void)
{
int i, j;
siteptr s, s2;
if (fromatty) {
j = 0;
i = 1;
if (nRecents > 0) {
j++;
(void) printf("Recently called sites:\n");
for (; i<=nRecents; i++) {
(void) printf("%4d. %-32s", i, recents[i-1].name);
i++;
if (i <= nRecents) {
(void) printf("%5d. %-32s", i, recents[i-1].name);
} else {
(void) printf("\n");
break;
}
(void) printf("\n");
}
}
if (nSites > 0) {
j++;
(void) printf("Sites in your netrc (%s):\n", rcname);
for (s = firstsite; s != NULL; s2=s->next, s=s2, ++i) {
(void) printf("%4d. %-32s", i, s->name);
s2=s->next;
s=s2;
i++;
if (s != NULL) {
(void) printf("%5d. %-32s", i, s->name);
} else {
(void) printf("\n");
break;
}
(void) printf("\n");
}
}
if (j > 0) {
(void) printf("\
Note that you can specify an abbreviation of any name, or #x, where x is the\n\
number of the site you want to connect to.\n\n");
}
}
} /* PrintRecentSiteList */
/*
* Given a sitename, check to see if the name was really an abbreviation
* of a site in the NETRC, or a site in our list of recently connected
* sites. Also check if the name was in the format #x, where x which
* would mean to use recents[x].name as the site; if x was greater than
* the number of sites in the recent list, then index into the netrc
* site list.
*/
void GetFullSiteName(char *host, char *lastdir)
{
register siteptr s, s2;
register recentsite *r;
char *ndir, *nhost, *cp;
int x, i, isAllDigits;
ndir = nhost = NULL;
x = 0;
/* Don't allow just numbers as abbreviations; "open 2" could be
* confused between site numbers in the open 'menu,' like
* "2. unlinfo.unl.edu" and IP numbers "128.93.2.1" or even numbers
* in the site name like "simtel20.army.mil."
*/
for (isAllDigits = 1, cp = host; *cp != 0; cp++) {
if (!isdigit(*cp)) {
isAllDigits = 0;
break;
}
}
if (!isAllDigits) {
/* Try matching the abbreviation, since it isn't just a number. */
/* see if 'host' is in our list of favorite sites (in NETRC). */
if ((s = FindNetrcSite(host)) != NULL) {
nhost = s->name;
} else if ((r = FindRecentSite(host)) != NULL) {
nhost = r->name;
ndir = r->dir;
}
} else if (sscanf(host[0]=='#' ? host+1 : host, "%d", &x) != 1) {
x = 0;
}
if (--x >= 0) {
if (x < nRecents) {
nhost = recents[x].name;
ndir = recents[x].dir;
} else {
x -= nRecents;
if (x < nSites) {
for (i = 0, s = firstsite; i < x; s2=s->next, s=s2)
++i;
nhost = s->name;
}
}
}
if (nhost != NULL) {
(void) strcpy(host, nhost);
if (lastdir != NULL) {
*lastdir = 0;
/* Don't cd if the dir is the root directory. */
if (ndir != NULL && (strcmp("/", ndir) != 0))
(void) strcpy(lastdir, ndir);
}
}
} /* GetFullSiteName */
int ruserpass2(char *host, char **username, char **pass, char **acct)
{
FILE *fp;
char *cp, *dp, *dst, *ep;
str32 macname;
char *varname;
int site_found;
string str;
static string auser;
static str32 apass, aacct;
site_found = 0;
if ((fp = fopen(rcname, "r")) != NULL) {
parsing_rc = 1;
while (FGets(str, fp)) {
if (cp = strstr(str, "machine")) {
/* Look for the machine token. */
cp += 7;
while (isspace(*cp))
cp++;
} else
continue;
/* if (strstr(cp, host) != NULL) { */
if (strncmp(host, cp, strlen(host)) == 0) {
site_found = 1;
while (!isspace(*cp))
++cp; /* skip the site name. */
do {
/* Skip any comments ahead of time. */
for (dp=cp; *dp; dp++) {
if (*dp == '#') {
*dp = 0;
break;
}
}
ep = cp;
while (1) {
varname = strtok(ep, RC_DELIM);
if (!varname) break;
dst = ep = NULL;
switch (*varname) {
case 'u': /* user */
*username = dst = auser;
break;
case 'l': /* login */
*username = dst = auser;
break;
case 'p': /* password */
*pass = dst = apass;
break;
case 'a': /* account */
*acct = dst = aacct;
break;
/* case 'd': /o default */
/* unused -- use 'set anon_password.' */
case 'm': /* macdef or machine */
if (strcmp(varname, "macdef"))
goto done; /* new machine record... */
dst = macname;
break;
default:
(void) fprintf(stderr, "Unknown .netrc keyword \"%s\"\n",
varname
);
}
if (dst) {
dp = strtok(ep, RC_DELIM);
if (dp)
(void) strcpy(dst, dp);
if (dst == macname) {
/*
* Read in the lines of the macro.
* The macro's end is denoted by
* a blank line.
*/
(void) make_macro(macname, fp);
goto nextline;
}
}
}
nextline: ;
} while (cp = FGets(str, fp));
break;
} /* end if we found the machine record. */
}
done:
parsing_rc = 0;
(void) fclose(fp);
}
if (!site_found) {
/* didn't find it in the rc. */
return (0);
}
return (1); /* found */
} /* ruserpass2 */
/* eof ftprc.c */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.