2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2003 Net Integration Technologies, Inc.
5 * Avery's insanely fast alternative to Fetchmail
7 * This code is LGPL - see the file COPYING.LIB for a full copy of the
13 #include "uniconfroot.h"
14 #include "wvlockfile.h"
19 #include "wvistreamlist.h"
21 #include "wvsslstream.h"
22 #include "wvhashtable.h"
27 #include "wvsendmail.h"
28 #include "wvpopclient.h"
33 #include <sys/types.h>
41 // cheesy hash function to do the job, basically
42 unsigned int WvHash(const WvLog
*x
)
44 return WvHash((int)x
);
48 DeclareWvDict(LogNum
, const WvLog
*, src
);
50 class RetchLog
: public WvLogConsole
53 RetchLog(WvLog::LogLevel _max_level
)
54 : WvLogConsole(1, _max_level
), lognums(5)
56 virtual ~RetchLog() { }
58 virtual void _begin_line();
65 void RetchLog::_begin_line()
67 if (!strncmp(last_source
->app
, "PopRetriever ", 13))
69 LogNum
*lognum
= lognums
[last_source
];
73 lognum
->num
= maxnum
++;
74 lognum
->src
= last_source
;
75 lognums
.add(lognum
, true);
78 // identify the connectionw without being too verbose
82 str
[0] = 'A' + lognum
->num
;
88 if (last_level
<= WvLog::Info
)
94 WvLogConsole::_begin_line(); // just print the whole thing
99 static volatile bool want_to_die
= false;
100 void signal_handler(int signum
)
102 fprintf(stderr
, "\nCaught signal %d; cleaning up and terminating.\n",
105 signal(signum
, SIG_DFL
);
109 static WvPopClient
*newpop(WvIStreamList
&l
, WvStringParm acct
,
110 WvStringParm _pass
, WvStringParm _deliverto
,
111 WvStringParm _mda
, bool flush
, bool apop_en
,
112 bool apop_fall_en
, bool explode
)
115 WvString
user(acct
), serv
, pass(_pass
), deliverto(_deliverto
),
119 char *cptr
= strrchr(user
.edit(), '@');
128 cptr
= strchr(serv
.edit(), ':');
132 cptr
= strchr(serv
.edit(), ':'); // guaranteed to work now!
135 if (atoi(cptr
+1) == 995)
138 WvTCPConn
*tcp
= new WvTCPConn(serv
);
139 WvStream
*conn
= tcp
;
140 if (ssl
) // FIXME: ssl verify should probably be set to something.
141 conn
= new WvSSLStream(tcp
, NULL
);
143 return new WvPopClient(conn
, l
, acct
, pass
, deliverto
, mda
, flush
, apop_en
, apop_fall_en
, explode
);
147 static void usage(char *argv0
, WvStringParm deliverto
)
149 wvcon
->print("Usage: %s [-d] [-dd] [-q] [-qq] [-V] [-F] [-c moniker ] "
150 "[-t deliverto] [acct...]\n"
151 " -d Print debug messages\n"
152 " -dd Print lots of debug messages\n"
153 " -q Quieter: don't print every message header\n"
154 " -qq Way quieter: only print errors\n"
155 " -V Print version and exit\n"
156 " -c Use <moniker> instead of "
157 "ini:~/.retchmail/retchmail\n"
158 " -F Flush (delete) messages after downloading\n"
159 " -E Send mail to the user on the system corresponding to the user the mail is sent to\n"
160 " -t Deliver mail to <deliverto> (default '%s')\n"
161 " acct... list of email accounts (username@host) to "
163 argv0
, (const char *)deliverto
);
171 int main(int argc
, char **argv
)
173 bool flush
= false, explode
= false;
175 WvLog::LogLevel lvl
= WvLog::Debug1
;
176 WvString
deliverto("");
177 WvString
confmoniker("");
180 wvcrash_setup(argv
[0]);
182 // make sure electric fence works
185 // Initialize wvcrash
186 wvcrash_setup(argv
[0]);
188 signal(SIGPIPE
, SIG_IGN
);
190 struct passwd
*pw
= getpwuid(getuid());
192 deliverto
= pw
->pw_name
;
194 while ((c
= getopt(argc
, argv
, "dqVFEt:c:h?")) >= 0)
199 if (lvl
<= WvLog::Debug1
)
205 if (lvl
>= WvLog::Debug1
)
211 wvcon
->print("Retchmail version %s\n", RETCHMAIL_VER_STRING
);
220 confmoniker
= optarg
;
228 usage(argv
[0], deliverto
);
233 WvString
lockname("/tmp/retchmail.%s.pid", getlogin());
234 WvLockFile
lockfile(lockname
);
236 if (!lockfile
.lock())
238 if (lockfile
.readpid() == -1)
239 fprintf(stderr
, "retchmail: can't access lockfile at %s.\n",
242 fprintf(stderr
, "retchmail: already running (%i).\n",
249 fprintf(stderr
, "retchmail: can't get username for uid#%u. "
250 "You must give the -t option.\n", getuid());
255 RetchLog
logrcv(lvl
);
259 // attempting to use $HOME/.retchmail/retchmail.conf\n");
260 confmoniker
= "ini:";
261 confmoniker
.append(getenv("HOME"));
262 confmoniker
.append("/.retchmail/retchmail.conf");
265 UniConfRoot
cfg(confmoniker
);
267 if (!cfg
.haschildren())
269 wvcon
->print("No data found, aborting\n");
275 bool apop_enable
= cfg
["retchmail"]["Enable APOP"].getmeint(0);
276 bool apop_enable_fallback
= cfg
["retchmail"]["Enable APOP Fallback"].getmeint(0);
280 UniConf sect
= cfg
["POP Servers"];
281 if (sect
.haschildren())
283 UniConf::Iter
i(sect
);
284 for (i
.rewind(); i
.next(); )
286 cli
= newpop(l
, i
->key(), i
->getme(),
287 cfg
["POP Targets"][i
->key()].getme(deliverto
),
288 cfg
["MDA Override"][i
->key()].getme(
289 "/usr/sbin/sendmail"),
290 flush
, apop_enable
, apop_enable_fallback
,
291 explode
? : cfg
["Explode"][i
->key()].getmeint(0));
292 l
.append(cli
, true, "client");
297 fprintf(stderr
, "\n-- No config file and no accounts given on the "
299 usage(argv
[0], deliverto
);
304 for (count
= optind
; count
< argc
; count
++)
306 WvString pass
= cfg
["POP Servers"][argv
[count
]].getme();
309 wvcon
->print("Password for <%s>: ", argv
[count
]);
311 system("stty -echo 2>/dev/null");
312 pass
= wvcon
->blocking_getline(-1);
313 system("stty echo 2>/dev/null");
318 cli
= newpop(l
, argv
[count
], pass
,
319 cfg
["POP Targets"][argv
[count
]].getme(deliverto
),
320 cfg
["MDA Override"][argv
[count
]].getme(
321 "/usr/sbin/sendmail"),
322 flush
, apop_enable
, apop_enable_fallback
, explode
);
323 l
.append(cli
, true, "client");
327 signal(SIGINT
, signal_handler
);
328 signal(SIGTERM
, signal_handler
);
330 while (!l
.isempty() && !want_to_die
)