diff options
-rw-r--r-- | fetchmail.c | 52 | ||||
-rw-r--r-- | fetchmail.h | 5 | ||||
-rw-r--r-- | options.c | 12 | ||||
-rw-r--r-- | rcfile_y.y | 29 |
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); @@ -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: @@ -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;} |