#include "setup.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef __VMS
#include <unixlib.h>
#endif
#include <curl/curl.h>
#include "netrc.h"
#include "strequal.h"
#include "strtok.h"
#include "curl_memory.h"
#include "rawstr.h"
#define _MPRINTF_REPLACE
#include <curl/mprintf.h>
#include "memdebug.h"
enum host_lookup_state {
NOTHING,
HOSTFOUND,
HOSTCOMPLETE,
HOSTVALID,
HOSTEND
};
int Curl_parsenetrc(const char *host,
char *login,
char *password,
char *netrcfile)
{
FILE *file;
int retcode=1;
int specific_login = (login[0] != 0);
char *home = NULL;
bool home_alloc = FALSE;
bool netrc_alloc = FALSE;
enum host_lookup_state state=NOTHING;
char state_login=0;
char state_password=0;
int state_our_login=FALSE;
#define NETRC DOT_CHAR "netrc"
#ifdef DEBUGBUILD
{
char *override = curl_getenv("CURL_DEBUG_NETRC");
if(override) {
fprintf(stderr, "NETRC: overridden " NETRC " file: %s\n", override);
netrcfile = override;
netrc_alloc = TRUE;
}
}
#endif
if(!netrcfile) {
home = curl_getenv("HOME");
if(home) {
home_alloc = TRUE;
#if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
}
else {
struct passwd *pw;
pw= getpwuid(geteuid());
if(pw) {
#ifdef __VMS
home = decc_translate_vms(pw->pw_dir);
#else
home = pw->pw_dir;
#endif
}
#endif
}
if(!home)
return -1;
netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC);
if(!netrcfile) {
if(home_alloc)
free(home);
return -1;
}
netrc_alloc = TRUE;
}
file = fopen(netrcfile, "r");
if(file) {
char *tok;
char *tok_buf;
bool done=FALSE;
char netrcbuffer[256];
int netrcbuffsize = (int)sizeof(netrcbuffer);
while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
while(!done && tok) {
if(login[0] && password[0]) {
done=TRUE;
break;
}
switch(state) {
case NOTHING:
if(Curl_raw_equal("machine", tok)) {
state=HOSTFOUND;
}
break;
case HOSTFOUND:
if(Curl_raw_equal(host, tok)) {
state=HOSTVALID;
#ifdef _NETRC_DEBUG
fprintf(stderr, "HOST: %s\n", tok);
#endif
retcode=0;
}
else
state=NOTHING;
break;
case HOSTVALID:
if(state_login) {
if(specific_login) {
state_our_login = Curl_raw_equal(login, tok);
}
else {
strncpy(login, tok, LOGINSIZE-1);
#ifdef _NETRC_DEBUG
fprintf(stderr, "LOGIN: %s\n", login);
#endif
}
state_login=0;
}
else if(state_password) {
if(state_our_login || !specific_login) {
strncpy(password, tok, PASSWORDSIZE-1);
#ifdef _NETRC_DEBUG
fprintf(stderr, "PASSWORD: %s\n", password);
#endif
}
state_password=0;
}
else if(Curl_raw_equal("login", tok))
state_login=1;
else if(Curl_raw_equal("password", tok))
state_password=1;
else if(Curl_raw_equal("machine", tok)) {
state = HOSTFOUND;
state_our_login = FALSE;
}
break;
case HOSTCOMPLETE:
case HOSTEND:
DEBUGASSERT(0);
}
tok = strtok_r(NULL, " \t\n", &tok_buf);
}
}
fclose(file);
}
if(home_alloc)
free(home);
if(netrc_alloc)
free(netrcfile);
return retcode;
}