Factor out code to read mailboxes, and make read more robust

New tel_read_header(), tel_read_body().  Use them in rea(),
show_first_tel(), copy_and_expire().

rea() now stops when it encounters a corrupt telegram, and logs the
problem.  Before, error detection was incomplete, and errors were not
logged.  Corrupt mailboxes could make it crash.

show_first_tel() and copy_and_expire() can now cope with telegrams of
arbitrary length, like rea(), and sanity-check the header fields they
don't actually use.
This commit is contained in:
Markus Armbruster 2009-02-08 11:13:25 +01:00
parent 6f1e669bea
commit 4238323d63
5 changed files with 114 additions and 76 deletions

View file

@ -43,6 +43,8 @@
#include "optlist.h"
#include "tel.h"
static int print_sink(char *, size_t, void *);
int
rea(void)
{
@ -57,23 +59,20 @@ rea(void)
FILE *telfp;
int teles;
int size;
unsigned nbytes;
char buf[1024];
char msgbuf[4096]; /* UTF-8 */
int lasttype;
int lastcnum;
time_t lastdate;
int header;
int filelen;
char *kind;
int n;
int n, res;
int num = player->cnum;
struct natstr *np = getnatp(player->cnum);
time_t now;
time_t then;
time_t delta;
int first = 1;
int readit;
int may_delete = 1; /* may messages be deleted? */
now = time(NULL);
@ -112,21 +111,14 @@ rea(void)
lastdate = 0;
lastcnum = -1;
lasttype = -1;
while (fread(&tgm, sizeof(tgm), 1, telfp) == 1) {
readit = 1;
if (tgm.tel_type > TEL_LAST) {
pr("Bad telegram header. Skipping telegram...\n");
readit = 0;
goto skip;
}
while ((res = tel_read_header(telfp, mbox, &tgm)) > 0) {
if (*kind == 'a') {
if (!player->god && (getrejects(tgm.tel_from, np) & REJ_ANNO)) {
readit = 0;
goto skip;
}
if (tgm.tel_date < then) {
readit = 0;
goto skip;
if ((!player->god && (getrejects(tgm.tel_from, np) & REJ_ANNO))
|| tgm.tel_date < then) {
res = tel_read_body(telfp, mbox, &tgm, NULL, NULL);
if (res < 0)
break;
continue;
}
}
if (first && *kind == 'a') {
@ -151,18 +143,13 @@ rea(void)
lastdate = tgm.tel_date;
}
teles++;
skip:
while (tgm.tel_length > 0) {
nbytes = tgm.tel_length;
if (nbytes > sizeof(msgbuf) - 1)
nbytes = sizeof(msgbuf) - 1;
fread(msgbuf, 1, nbytes, telfp);
msgbuf[nbytes] = 0;
if (readit)
uprnf(msgbuf);
tgm.tel_length -= nbytes;
}
res = tel_read_body(telfp, mbox, &tgm, print_sink, NULL);
if (res < 0)
break;
}
if (res < 0)
pr("\n> Mailbox corrupt, tell the deity.\n");
if (teles > 0 && player->cnum == num && may_delete) {
pr("\n");
if (teles == 1) {
@ -212,3 +199,10 @@ rea(void)
}
return RET_OK;
}
static int
print_sink(char *chunk, size_t sz, void *arg)
{
uprnf(chunk);
return 0;
}