aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fetchmail.c52
-rw-r--r--fetchmail.h5
-rw-r--r--options.c12
-rw-r--r--rcfile_y.y29
4 files changed, 70 insertions, 28 deletions
diff --git a/fetchmail.c b/fetchmail.c
index 78f3993f..aa078140 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -159,10 +159,7 @@ int main(int argc, char **argv)
}
#define IDFILE_NAME ".fetchids"
- run.idfile = (char *) xmalloc(strlen(fmhome)+sizeof(IDFILE_NAME)+2);
- strcpy(run.idfile, fmhome);
- strcat(run.idfile, "/");
- strcat(run.idfile, IDFILE_NAME);
+ run.idfile = prependdir (IDFILE_NAME, fmhome);
outlevel = O_NORMAL;
@@ -176,6 +173,14 @@ int main(int argc, char **argv)
*/
lock_dispose();
+#ifdef HAVE_GETCWD
+ /* save the current directory */
+ if (getcwd (currentwd, sizeof (currentwd)) == NULL) {
+ report(stderr, GT_("could not get current working directory\n"));
+ currentwd[0] = 0;
+ }
+#endif
+
if ((parsestatus = parsecmdline(argc,argv, &cmd_run, &cmd_opts)) < 0)
exit(PS_SYNTAX);
@@ -281,10 +286,7 @@ int main(int argc, char **argv)
#define NETRC_FILE ".netrc"
/* parse the ~/.netrc file (if present) for future password lookups. */
- xalloca(netrc_file, char *, strlen(home) + sizeof(NETRC_FILE) + 2);
- strcpy (netrc_file, home);
- strcat (netrc_file, "/");
- strcat (netrc_file, NETRC_FILE);
+ netrc_file = prependdir (NETRC_FILE, home);
netrc_list = parse_netrc(netrc_file);
#undef NETRC_FILE
@@ -406,17 +408,14 @@ int main(int argc, char **argv)
pid);
return(PS_EXCLUDE);
}
+ else if (getpid() == pid)
+ /* this test enables re-execing on a changed rcfile */
+ lock_assert();
else if (argc > 1)
{
- /* this test enables re-execing on a changed rcfile */
- if (getpid() == pid)
- lock_assert();
- else
- {
- fprintf(stderr,
- GT_("fetchmail: can't accept options while a background fetchmail is running.\n"));
- return(PS_EXCLUDE);
- }
+ fprintf(stderr,
+ GT_("fetchmail: can't accept options while a background fetchmail is running.\n"));
+ return(PS_EXCLUDE);
}
else if (kill(pid, SIGUSR1) == 0)
{
@@ -546,6 +545,13 @@ int main(int argc, char **argv)
else if (rcstat.st_mtime > parsetime)
{
report(stdout, GT_("restarting fetchmail (%s changed)\n"), rcfile);
+
+#ifdef HAVE_GETCWD
+ /* restore the startup directory */
+ if (!currentwd[0] || chdir (currentwd) == -1)
+ report(stderr, GT_("attempt to re-exec may fail as directory has not been restored\n"));
+#endif
+
/*
* Matthias Andree: Isn't this prone to introduction of
* "false" programs by interfering with PATH? Those
@@ -879,6 +885,7 @@ static int load_params(int argc, char **argv, int optind)
struct passwd *pw;
struct query def_opts, *ctl;
struct stat rcstat;
+ char *p;
run.bouncemail = TRUE;
run.spambounce = FALSE; /* don't bounce back to innocent bystanders */
@@ -901,6 +908,17 @@ static int load_params(int argc, char **argv, int optind)
def_opts.remotename = user;
def_opts.listener = SMTP_MODE;
+ /* get the location of rcfile */
+ rcfiledir[0] = 0;
+ p = strrchr (rcfile, '/');
+ if (p && (p - rcfile) < sizeof (rcfiledir)) {
+ *p = 0; /* replace '/' by '0' */
+ strcpy (rcfiledir, rcfile);
+ *p = '/'; /* restore '/' */
+ if (!rcfiledir[0]) /* "/.fetchmailrc" case */
+ strcpy (rcfiledir, "/");
+ }
+
/* note the parse time, so we can pick up on modifications */
parsetime = 0; /* foil compiler warnings */
if (stat(rcfile, &rcstat) != -1)
diff --git a/fetchmail.h b/fetchmail.h
index 7b2f0436..394ed269 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -587,8 +587,13 @@ int do_gssauth(int sock, char *command, char *hostname, char *username);
int do_otp(int sock, char *command, struct query *ctl);
/* miscellanea */
+
+/* these should be of size PATH_MAX */
+extern char currentwd[1024], rcfiledir[1024];
+
struct query *hostalloc(struct query *);
int parsecmdline (int, char **, struct runctl *, struct query *);
+char *prependdir (const char *, const char *);
char *MD5Digest (unsigned char *);
void hmac_md5 (unsigned char *, size_t, unsigned char *, size_t, unsigned char *, size_t);
int POP3_auth_rpa(unsigned char *, unsigned char *, int socket);
diff --git a/options.c b/options.c
index f74100e8..000270ee 100644
--- a/options.c
+++ b/options.c
@@ -313,7 +313,7 @@ struct query *ctl; /* option record to be initialized */
break;
case 'L':
case LA_LOGFILE:
- rctl->logfile = optarg;
+ rctl->logfile = prependdir (optarg, currentwd);
break;
case LA_INVISIBLE:
rctl->invisible = TRUE;
@@ -323,11 +323,11 @@ struct query *ctl; /* option record to be initialized */
break;
case 'f':
case LA_RCFILE:
- rcfile = (char *) xstrdup(optarg);
+ rcfile = prependdir (optarg, currentwd);
break;
case 'i':
case LA_IDFILE:
- rctl->idfile = (char *) xstrdup(optarg);
+ rctl->idfile = prependdir (optarg, currentwd);
break;
case LA_POSTMASTER:
rctl->postmaster = (char *) xstrdup(optarg);
@@ -538,7 +538,7 @@ struct query *ctl; /* option record to be initialized */
ocount++;
break;
case LA_BSMTP:
- ctl->bsmtp = xstrdup(optarg);
+ ctl->bsmtp = prependdir (optarg, currentwd);
ocount++;
break;
case LA_LMTP:
@@ -578,11 +578,11 @@ struct query *ctl; /* option record to be initialized */
break;
case LA_SSLKEY:
- ctl->sslkey = xstrdup(optarg);
+ ctl->sslkey = prependdir (optarg, currentwd);
break;
case LA_SSLCERT:
- ctl->sslcert = xstrdup(optarg);
+ ctl->sslcert = prependdir (optarg, currentwd);
break;
case LA_SSLPROTO:
diff --git a/rcfile_y.y b/rcfile_y.y
index 5b0c5088..46b8d314 100644
--- a/rcfile_y.y
+++ b/rcfile_y.y
@@ -47,6 +47,9 @@ static void record_current(void);
static void user_reset(void);
static void reset_server(const char *name, int skip);
+/* these should be of size PATH_MAX */
+char currentwd[1024] = "", rcfiledir[1024] = "";
+
/* using Bison, this arranges that yydebug messages will show actual tokens */
extern char * yytext;
#define YYPRINT(fp, type, val) fprintf(fp, " = \"%s\"", yytext)
@@ -90,8 +93,8 @@ statement_list : statement
optmap : MAP | /* EMPTY */;
/* future global options should also have the form SET <name> optmap <value> */
-statement : SET LOGFILE optmap STRING {run.logfile = xstrdup($4);}
- | SET IDFILE optmap STRING {run.idfile = xstrdup($4);}
+statement : SET LOGFILE optmap STRING {run.logfile = prependdir ($4, rcfiledir);}
+ | SET IDFILE optmap STRING {run.idfile = prependdir ($4, rcfiledir);}
| SET DAEMON optmap NUMBER {run.poll_interval = $4;}
| SET POSTMASTER optmap STRING {run.postmaster = xstrdup($4);}
| SET BOUNCEMAIL {run.bouncemail = TRUE;}
@@ -323,7 +326,7 @@ user_option : TO localnames HERE
| SMTPNAME STRING {current.smtpname = xstrdup($2);}
| SPAMRESPONSE num_list
| MDA STRING {current.mda = xstrdup($2);}
- | BSMTP STRING {current.bsmtp = xstrdup($2);}
+ | BSMTP STRING {current.bsmtp = prependdir ($2, rcfiledir);}
| LMTP {current.listener = LMTP_MODE;}
| PRECONNECT STRING {current.preconnect = xstrdup($2);}
| POSTCONNECT STRING {current.postconnect = xstrdup($2);}
@@ -347,8 +350,8 @@ user_option : TO localnames HERE
yyerror(GT_("SSL is not enabled"));
#endif
}
- | SSLKEY STRING {current.sslkey = xstrdup($2);}
- | SSLCERT STRING {current.sslcert = xstrdup($2);}
+ | SSLKEY STRING {current.sslkey = prependdir ($2, rcfiledir);}
+ | SSLCERT STRING {current.sslcert = prependdir ($2, rcfiledir);}
| SSLPROTO STRING {current.sslproto = xstrdup($2);}
| SSLCERTCK {current.sslcertck = FLAG_TRUE;}
| SSLCERTPATH STRING {current.sslcertpath = xstrdup($2);}
@@ -570,6 +573,22 @@ static void record_current(void)
trailer = TRUE;
}
+char *prependdir (const char *file, const char *dir)
+/* if a filename is relative to dir, convert it to an absolute path */
+{
+ char *newfile;
+ if (!file[0] || /* null path */
+ file[0] == '/' || /* absolute path */
+ !dir[0]) /* we don't HAVE_GETCWD */
+ return xstrdup (file);
+ newfile = xmalloc (strlen (dir) + 1 + strlen (file) + 1);
+ if (dir[strlen(dir) - 1] != '/')
+ sprintf (newfile, "%s/%s", dir, file);
+ else
+ sprintf (newfile, "%s%s", dir, file);
+ return newfile;
+}
+
/* easier to do this than cope with variations in where the library lives */
int yywrap(void) {return 1;}