#include "curl_setup.h"
#ifdef HAVE_PWD_H
#include <pwd.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,
HOSTVALID
};
int Curl_parsenetrc(const char *host,
char **loginp,
char **passwordp,
char *netrcfile)
{
FILE *file;
int retcode=1;
int specific_login = (*loginp && **loginp != 0);
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"
if(!netrcfile) {
bool home_alloc = FALSE;
char *home = curl_getenv("HOME");
if(home) {
home_alloc = TRUE;
#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
}
else {
struct passwd pw, *pw_res;
char pwbuf[1024];
if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res)
&& pw_res) {
home = strdup(pw.pw_dir);
if(!home)
return CURLE_OUT_OF_MEMORY;
home_alloc = TRUE;
}
#elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
}
else {
struct passwd *pw;
pw= getpwuid(geteuid());
if(pw) {
home = pw->pw_dir;
}
#endif
}
if(!home)
return retcode;
netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC);
if(home_alloc)
Curl_safefree(home);
if(!netrcfile) {
return -1;
}
netrc_alloc = TRUE;
}
file = fopen(netrcfile, "r");
if(netrc_alloc)
Curl_safefree(netrcfile);
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((*loginp && **loginp) && (*passwordp && **passwordp)) {
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;
retcode=0;
}
else
state=NOTHING;
break;
case HOSTVALID:
if(state_login) {
if(specific_login) {
state_our_login = Curl_raw_equal(*loginp, tok);
}
else {
free(*loginp);
*loginp = strdup(tok);
if(!*loginp) {
retcode = -1;
goto out;
}
}
state_login=0;
}
else if(state_password) {
if(state_our_login || !specific_login) {
free(*passwordp);
*passwordp = strdup(tok);
if(!*passwordp) {
retcode = -1;
goto out;
}
}
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;
}
tok = strtok_r(NULL, " \t\n", &tok_buf);
}
}
out:
fclose(file);
}
return retcode;
}