700 lines
18 KiB
C
700 lines
18 KiB
C
/*****************************************************************************
|
|
*
|
|
* $Id$
|
|
* Purpose ...............: Fidonet mailer - respond to filerequests
|
|
*
|
|
*****************************************************************************
|
|
* Copyright (C) 1997-2002
|
|
*
|
|
* Michiel Broek FIDO: 2:280/2802
|
|
* Beekmansbos 10
|
|
* 1971 BV IJmuiden
|
|
* the Netherlands
|
|
*
|
|
* This file is part of MBSE BBS.
|
|
*
|
|
* This BBS is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2, or (at your option) any
|
|
* later version.
|
|
*
|
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*****************************************************************************/
|
|
|
|
#include "../config.h"
|
|
#include "../lib/libs.h"
|
|
#include "../lib/memwatch.h"
|
|
#include "../lib/structs.h"
|
|
#include "../lib/users.h"
|
|
#include "../lib/records.h"
|
|
#include "../lib/common.h"
|
|
#include "../lib/nodelist.h"
|
|
#include "../lib/clcomm.h"
|
|
#include "session.h"
|
|
#include "lutil.h"
|
|
#include "config.h"
|
|
#include "atoul.h"
|
|
#include "respfreq.h"
|
|
#include "filelist.h"
|
|
|
|
|
|
#ifndef S_ISDIR
|
|
#define S_ISDIR(st_mode) (((st_mode) & S_IFMT) == S_IFDIR)
|
|
#endif
|
|
#ifndef S_ISREG
|
|
#define S_ISREG(st_mode) (((st_mode) & S_IFMT) == S_IFREG)
|
|
#endif
|
|
|
|
|
|
extern char *freqname;
|
|
|
|
static void attach_report(file_list**);
|
|
static void add_report(char *, ...);
|
|
static char *report_text = NULL;
|
|
static unsigned long report_total = 0L;
|
|
static unsigned long report_count = 0L;
|
|
static int no_more = FALSE;
|
|
|
|
|
|
|
|
file_list *respond_wazoo(void)
|
|
{
|
|
char buf[256];
|
|
char *nm, *pw, *dt, *p;
|
|
file_list *fl=NULL, **tmpl;
|
|
FILE *fp;
|
|
|
|
if (freqname == NULL)
|
|
return NULL;
|
|
|
|
if ((fp=fopen(freqname,"r")) == NULL) {
|
|
WriteError("$cannot open received wazoo freq \"%s\"",freqname);
|
|
unlink(freqname);
|
|
free(freqname);
|
|
freqname=NULL;
|
|
return NULL;
|
|
}
|
|
|
|
tmpl=&fl;
|
|
while (fgets(buf,sizeof(buf)-1,fp)) {
|
|
nm = NULL;
|
|
pw = NULL;
|
|
dt = NULL;
|
|
p = strtok(buf," \n\r");
|
|
if ((p == NULL) || (*p == '\0'))
|
|
continue;
|
|
nm = p;
|
|
p = strtok(NULL," \n\r");
|
|
if (p && (*p == '!'))
|
|
pw = p+1;
|
|
else
|
|
if (p && ((*p == '+') || (*p == '-')))
|
|
dt = p;
|
|
p = strtok(NULL," \n\r");
|
|
if (p && (*p == '!'))
|
|
pw = p+1;
|
|
else
|
|
if (p && ((*p == '+') || (*p == '-')))
|
|
dt = p;
|
|
*tmpl = respfreq(nm, pw, dt);
|
|
while (*tmpl) tmpl=&((*tmpl)->next);
|
|
if (no_more)
|
|
break;
|
|
}
|
|
|
|
fclose(fp);
|
|
unlink(freqname);
|
|
free(freqname);
|
|
freqname = NULL;
|
|
for (tmpl = &fl; *tmpl; tmpl = &((*tmpl)->next)) {
|
|
Syslog('F', "resplist: %s",MBSE_SS((*tmpl)->local));
|
|
}
|
|
attach_report(&fl);
|
|
return fl;
|
|
}
|
|
|
|
|
|
|
|
file_list *respond_bark(char *buf)
|
|
{
|
|
char *nm, *pw, *dt, *p;
|
|
file_list *fl;
|
|
|
|
nm = buf;
|
|
pw = (char *)"";
|
|
dt = (char *)"0";
|
|
while (isspace(*nm))
|
|
nm++;
|
|
for (p = nm; *p && (!isspace(*p)); p++);
|
|
if (*p) {
|
|
*p++ = '\0';
|
|
dt = p;
|
|
while (isspace(*dt))
|
|
dt++;
|
|
for (p = dt; *p && (!isspace(*p)); p++);
|
|
if (*p) {
|
|
*p++ = '\0';
|
|
pw = p;
|
|
while (isspace(*pw))
|
|
pw++;
|
|
for (p = pw; *p && (!isspace(*p)); p++);
|
|
*p = '\0';
|
|
}
|
|
}
|
|
fl = respfreq(nm, pw, dt);
|
|
attach_report(&fl);
|
|
return fl;
|
|
}
|
|
|
|
|
|
|
|
file_list *respfreq(char *nm, char *pw, char *dt)
|
|
{
|
|
file_list *fl = NULL;
|
|
struct stat st;
|
|
char mask[256], *p, *q;
|
|
char *tnm, *t;
|
|
time_t upd = 0L;
|
|
int newer = 1;
|
|
FILE *fa, *fb, *fi;
|
|
long Area;
|
|
int Send;
|
|
struct FILEIndex idx;
|
|
|
|
if (localoptions & NOFREQS) {
|
|
Syslog('+', "File requests disabled");
|
|
add_report((char *)"ER: \"%s\" denied: file requests disabled", nm);
|
|
return NULL;
|
|
}
|
|
|
|
if (strchr(nm, '/') || strchr(nm, '\\') || strchr(nm, ':')) {
|
|
Syslog('+', "Illegal characters in request");
|
|
add_report((char *)"ER: \"%s\" denied: illegal characters", nm);
|
|
return NULL;
|
|
}
|
|
|
|
if (dt) {
|
|
if (*dt == '+') {
|
|
newer = 1;
|
|
dt++;
|
|
} else if (*dt == '-') {
|
|
newer = 0;
|
|
dt++;
|
|
} else
|
|
newer = 1;
|
|
upd=atoul(dt);
|
|
}
|
|
|
|
if (strlen(CFG.req_magic)) {
|
|
/*
|
|
* Check for uppercase and lowercase magic names.
|
|
*/
|
|
tnm = xstrcpy(CFG.req_magic);
|
|
tnm = xstrcat(tnm,(char *)"/");
|
|
tnm = xstrcat(tnm,tl(xstrcpy(nm)));
|
|
if ((stat(tnm, &st) == 0) &&
|
|
(S_ISREG(st.st_mode))) {
|
|
if (access(tnm, X_OK) == 0) {
|
|
return respmagic(tnm);
|
|
/* respmagic will free(tnm) */
|
|
} else if (access(tnm, R_OK) == 0) {
|
|
return resplist(tnm, pw, dt);
|
|
/* resplist will free(tnm) */
|
|
} else
|
|
free(tnm);
|
|
} else
|
|
free(tnm);
|
|
|
|
tnm = xstrcpy(CFG.req_magic);
|
|
tnm = xstrcat(tnm,(char *)"/");
|
|
t = xstrcpy(nm);
|
|
tnm = xstrcat(tnm,tu(t));
|
|
free(t);
|
|
if ((stat(tnm, &st) == 0) &&
|
|
(S_ISREG(st.st_mode))) {
|
|
if (access(tnm, X_OK) == 0) {
|
|
return respmagic(tnm);
|
|
/* respmagic will free(tnm) */
|
|
} else if (access(tnm, R_OK) == 0) {
|
|
return resplist(tnm, pw, dt);
|
|
/* resplist will free(tnm) */
|
|
} else
|
|
free(tnm);
|
|
} else free(tnm);
|
|
}
|
|
|
|
Syslog('+', "File request : %s (update (%s), password \"%s\")",MBSE_SS(nm),MBSE_SS(dt),MBSE_SS(pw));
|
|
add_report((char *)"RQ: Regular file \"%s\"",nm);
|
|
p = tl(nm);
|
|
q = mask;
|
|
*q++ = '^';
|
|
while ((*p) && (q < (mask + sizeof(mask) - 4))) {
|
|
switch (*p) {
|
|
case '\\': *q++ = '\\'; *q++ = '\\'; break;
|
|
case '?': *q++ = '.'; break;
|
|
case '.': *q++ = '\\'; *q++ = '.'; break;
|
|
case '+': *q++ = '\\'; *q++ = '+'; break;
|
|
case '*': *q++ = '.'; *q++ = '*'; break;
|
|
default: *q++ = toupper(*p); break;
|
|
}
|
|
p++;
|
|
}
|
|
*q++ = '$';
|
|
*q = '\0';
|
|
Syslog('f', "Search mask \"%s\"", mask);
|
|
re_comp(mask);
|
|
|
|
/*
|
|
* Open the areas database and request index.
|
|
*/
|
|
p = xstrcpy(getenv("MBSE_ROOT"));
|
|
p = xstrcat(p, (char *)"/etc/fareas.data");
|
|
if ((fa = fopen(p, "r")) == NULL) {
|
|
WriteError("$Can't open %s", p);
|
|
return NULL;
|
|
}
|
|
free(p);
|
|
fread(&areahdr, sizeof(areahdr), 1, fa);
|
|
|
|
p = xstrcpy(getenv("MBSE_ROOT"));
|
|
p = xstrcat(p, (char *)"/etc/request.index");
|
|
if ((fi = fopen(p, "r")) == NULL) {
|
|
WriteError("$Can't open %s", p);
|
|
return NULL;
|
|
}
|
|
Area = 0L;
|
|
free(p);
|
|
|
|
Syslog('f', "Start search ...");
|
|
while (!no_more && (fread(&idx, sizeof(idx), 1, fi) == 1)) {
|
|
if (re_exec(idx.Name) || re_exec(idx.LName)) {
|
|
Syslog('f', "Index found %s area %d record %d", idx.LName, idx.AreaNum, idx.Record);
|
|
if (fseek(fa, ((idx.AreaNum - 1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET) == -1) {
|
|
WriteError("$Can't seek in fareas.data");
|
|
return NULL;
|
|
}
|
|
if (fread(&area, areahdr.recsize, 1, fa) != 1) {
|
|
WriteError("$Can't read record %d in fareas.data", idx.AreaNum);
|
|
return NULL;
|
|
}
|
|
Syslog('f', "Area %s", area.Name);
|
|
p = calloc(128, sizeof(char));
|
|
sprintf(p, "%s/fdb/fdb%ld.data", getenv("MBSE_ROOT"), idx.AreaNum);
|
|
if ((fb = fopen(p, "r+")) == NULL) {
|
|
WriteError("$Can't open %s", p);
|
|
free(p);
|
|
} else {
|
|
free(p);
|
|
if (fseek(fb, idx.Record * sizeof(file), SEEK_SET) == -1) {
|
|
WriteError("$Can't seek filerecord %d", idx.Record);
|
|
} else {
|
|
if (fread(&file, sizeof(file), 1, fb) != 1) {
|
|
WriteError("$Can't read filerecord %d", idx.Record);
|
|
} else {
|
|
Send = FALSE;
|
|
Syslog('f', "Found \"%s\" in %s", file.LName, area.Name);
|
|
tnm = xstrcpy(area.Path);
|
|
tnm = xstrcat(tnm, (char *)"/");
|
|
tnm = xstrcat(tnm, file.LName);
|
|
if ((stat(tnm, &st) == 0) && (S_ISREG(st.st_mode)) &&
|
|
(access(tnm, R_OK) == 0) && ((upd == 0L) ||
|
|
((newer) && (st.st_mtime <= upd)))) {
|
|
Send = TRUE;
|
|
}
|
|
|
|
/*
|
|
* If no password is given, we do not respond
|
|
* on requests to password protected areas
|
|
* or files in case it was a wildcard request.
|
|
* Wrong passwords are honored with an error
|
|
* response.
|
|
*/
|
|
if (Send && strlen(area.Password)) {
|
|
if (pw != NULL) {
|
|
if (strcasecmp(area.Password, pw)) {
|
|
Send = FALSE;
|
|
Syslog('+', "Bad password for area %s", area.Name);
|
|
add_report((char *)"ER: bad password for area %s",
|
|
area.Name);
|
|
}
|
|
} else {
|
|
Send = FALSE;
|
|
}
|
|
}
|
|
|
|
if (Send && strlen(file.Password)) {
|
|
if (pw != NULL) {
|
|
if (strcasecmp(file.Password, pw)) {
|
|
Send = FALSE;
|
|
Syslog('+', "Bad password for file %s", file.Name);
|
|
add_report((char *)"ER: bad password for file %s",
|
|
file.LName);
|
|
}
|
|
} else {
|
|
Send = FALSE;
|
|
}
|
|
}
|
|
|
|
if (Send && CFG.Req_Files) {
|
|
if (report_count >= CFG.Req_Files) {
|
|
Send = FALSE;
|
|
add_report((char *)"ER: too many files requested");
|
|
Syslog('+', "Exceeding maximum files limit");
|
|
no_more = TRUE;
|
|
}
|
|
}
|
|
|
|
if (Send && CFG.Req_MBytes) {
|
|
if ((st.st_size + report_total) > (CFG.Req_MBytes * 1048576)) {
|
|
Send = FALSE;
|
|
add_report((char *)"ER: file %s will exceed the request limit",
|
|
file.Name);
|
|
Syslog('+', "Exceeding request size limit");
|
|
no_more = TRUE;
|
|
}
|
|
}
|
|
|
|
if (Send) {
|
|
Syslog('f', "Will send %s", file.LName);
|
|
report_total += st.st_size;
|
|
report_count++;
|
|
if (strcasecmp(file.Name, file.LName))
|
|
add_report((char *)"OK: Sending \"%s\" as \"%s\" (%lu bytes)",
|
|
file.LName, file.Name, file.Size);
|
|
else
|
|
add_report((char *)"OK: Sending \"%s\" (%lu bytes)",
|
|
file.LName, file.Size);
|
|
add_list(&fl, tnm, file.LName, 0, 0L, NULL, 1);
|
|
|
|
/*
|
|
* Update file information
|
|
*/
|
|
file.TimesReq++;
|
|
file.LastDL = time(NULL);
|
|
fseek(fb, - sizeof(file), SEEK_CUR);
|
|
fwrite(&file, sizeof(file), 1, fb);
|
|
}
|
|
free(tnm);
|
|
}
|
|
}
|
|
fclose(fb);
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(fa);
|
|
fclose(fi);
|
|
|
|
if (fl == NULL)
|
|
add_report((char *)"ER: No matching files found");
|
|
|
|
return fl;
|
|
}
|
|
|
|
|
|
|
|
#define MAXRECURSE 5
|
|
static int recurse=0;
|
|
|
|
/*
|
|
* Magic filerquests.
|
|
*/
|
|
file_list *resplist(char *listfn, char *pw, char *dt)
|
|
{
|
|
FILE *fp;
|
|
char buf[256], *p;
|
|
file_list *fl = NULL, **pfl;
|
|
|
|
Syslog('+', "Magic request: %s (update (%s), password \"%s\")",
|
|
strrchr(xstrcpy(listfn), '/')+1, MBSE_SS(dt), MBSE_SS(pw));
|
|
|
|
if (++recurse > MAXRECURSE) {
|
|
WriteError("Excessive recursion in file lists for \"%s\"", MBSE_SS(listfn));
|
|
add_report((char *)"ER: Exessive recursion for magic filename \"%s\", contact sysop", listfn);
|
|
recurse = 0;
|
|
free(listfn);
|
|
return NULL;
|
|
}
|
|
|
|
pfl = &fl;
|
|
if ((fp = fopen(listfn,"r")) == NULL) {
|
|
WriteError("$cannot open file list \"%s\"",listfn);
|
|
add_report((char *)"ER: Could not open magic file \"%s\", contact sysop", listfn);
|
|
free(listfn);
|
|
recurse--;
|
|
return NULL;
|
|
}
|
|
|
|
p = xstrcpy(listfn);
|
|
add_report((char *)"RQ: Magic filename \"%s\"", strrchr(p, '/')+1);
|
|
free(p);
|
|
|
|
while (fgets(buf, sizeof(buf)-1, fp)) {
|
|
if ((p = strchr(buf, '#')))
|
|
*p = '\0';
|
|
if ((p = strtok(buf," \t\n\r"))) {
|
|
*pfl = respfreq(p, pw, dt);
|
|
while (*pfl)
|
|
pfl = &((*pfl)->next);
|
|
}
|
|
}
|
|
fclose(fp);
|
|
|
|
free(listfn);
|
|
recurse--;
|
|
return fl;
|
|
}
|
|
|
|
|
|
|
|
file_list *respmagic(char *cmd) /* must free(cmd) before exit */
|
|
{
|
|
struct stat st;
|
|
char cmdbuf[256];
|
|
char tmpfn[PATH_MAX], tmptx[PATH_MAX];
|
|
char remname[32], *p, *q, *z, *buf;
|
|
int i, escaped;
|
|
file_list *fl = NULL;
|
|
FILE *fp, *ft;
|
|
long zeroes = 0L;
|
|
ftnmsg fmsg;
|
|
char *svname;
|
|
|
|
Syslog('+', "Magic execute: %s", strrchr(xstrcpy(cmd), '/')+1);
|
|
add_report((char *)"RQ: Magic \"%s\"",cmd);
|
|
sprintf(tmpfn, "%s/tmp/%08lX", getenv((char *)"MBSE_ROOT"), (unsigned long)sequencer());
|
|
Syslog('+', "tmpfn \"%s\"", tmpfn);
|
|
if ((p = strrchr(cmd,'/')))
|
|
p++;
|
|
else
|
|
p = cmd;
|
|
strncpy(remname, p, sizeof(remname)-1);
|
|
remname[sizeof(remname)-1] = '\0';
|
|
if (remote->addr->name == NULL)
|
|
remote->addr->name = xstrcpy((char *)"Sysop");
|
|
strncpy(cmdbuf, cmd, sizeof(cmdbuf)-2);
|
|
cmdbuf[sizeof(cmdbuf)-2] = '\0';
|
|
q = cmdbuf + strlen(cmdbuf);
|
|
z = cmdbuf + sizeof(cmdbuf)-2;
|
|
*q++ = ' ';
|
|
escaped = 0;
|
|
for (p = ascfnode(remote->addr,0x7f); *p && (q < z); p++) {
|
|
if (escaped) {
|
|
escaped = 0;
|
|
} else switch (*p) {
|
|
case '\\': escaped = 1; break;
|
|
case '\'':
|
|
case '`':
|
|
case '"':
|
|
case '(':
|
|
case ')':
|
|
case '<':
|
|
case '>':
|
|
case '|':
|
|
case ';':
|
|
case '$': *q++ = '\\'; break;
|
|
}
|
|
*q++ = *p;
|
|
}
|
|
*q++ = '\0';
|
|
|
|
/*
|
|
* Execute the shell, output goes into tmpfn
|
|
*/
|
|
if (execsh(cmdbuf,(char *)"/dev/null",tmpfn,(char *)"/dev/null")) {
|
|
WriteError("$Execute magic error");
|
|
add_report((char *)"ER: Magic command execution failed");
|
|
unlink(tmpfn);
|
|
} else {
|
|
if (stat(tmpfn, &st) == 0) {
|
|
sprintf(tmptx, "%s/tmp/%08lX", getenv((char *)"MBSE_ROOT"), (unsigned long)sequencer());
|
|
Syslog('+', "tmptx \"%s\"", tmptx);
|
|
|
|
if ((fp = fopen(tmptx, "w"))) {
|
|
fmsg.flags = M_PVT|M_KILLSENT;
|
|
fmsg.from = bestaka_s(remote->addr);
|
|
svname = fmsg.from->name;
|
|
fmsg.from->name = (char *)"mbcico FREQ processor";
|
|
fmsg.to = remote->addr;
|
|
fmsg.date = time((time_t*)NULL);
|
|
fmsg.subj = strrchr(xstrcpy(cmd), '/')+1;
|
|
fmsg.msgid_s = NULL;
|
|
fmsg.msgid_a = xstrcpy(ascfnode(fmsg.from, 0x1f));
|
|
fmsg.msgid_n = sequencer();
|
|
fmsg.reply_s = NULL;
|
|
fmsg.reply_a = NULL;
|
|
fmsg.reply_n = 0L;
|
|
fmsg.origin = NULL;
|
|
fmsg.area = NULL;
|
|
(void)ftnmsghdr(&fmsg, fp, NULL, 'f', (char *)"MBSE-CICO");
|
|
free(fmsg.msgid_a);
|
|
|
|
if ((ft = fopen(tmpfn, "r")) == NULL) {
|
|
WriteError("$Can't open %s", tmpfn);
|
|
} else {
|
|
buf = calloc(2049, sizeof(char));
|
|
while ((fgets(buf, 2048, ft)) != NULL) {
|
|
for (i = 0; i < strlen(buf); i++) {
|
|
if (*(buf + i) == '\0')
|
|
break;
|
|
if (*(buf + i) == '\n')
|
|
*(buf + i) = '\r';
|
|
}
|
|
fputs(buf, fp);
|
|
}
|
|
fprintf(fp, "\r%s\r", TearLine());
|
|
free(buf);
|
|
}
|
|
fwrite(&zeroes, 1, 3, fp);
|
|
fclose(fp);
|
|
sprintf(remname, "%08lX.PKT", (unsigned long)sequencer());
|
|
|
|
add_list(&fl, tmptx, remname, KFS, 0L, NULL, 0);
|
|
fmsg.from->name = svname;
|
|
add_report((char *)"OK: magic output is send by mail");
|
|
unlink(tmpfn);
|
|
} else {
|
|
WriteError("$cannot open temp file \"%s\"",MBSE_SS(tmpfn));
|
|
}
|
|
} else {
|
|
WriteError("$cannot stat() magic stdout \"%s\"",tmpfn);
|
|
add_report((char *)"ER: Could not get magic command output, contact sysop");
|
|
}
|
|
}
|
|
|
|
free(cmd);
|
|
return fl;
|
|
}
|
|
|
|
|
|
|
|
static void attach_report(file_list **fl)
|
|
{
|
|
FILE *fp;
|
|
char *tmpfn;
|
|
char remname[14];
|
|
long zeroes = 0L, recno, records;
|
|
ftnmsg fmsg;
|
|
char *svname;
|
|
|
|
tmpfn = calloc(PATH_MAX, sizeof(char));
|
|
|
|
if (report_text == NULL) {
|
|
WriteError("Empty FREQ report");
|
|
add_report((char *)"ER: empty request report, contact sysop");
|
|
}
|
|
|
|
add_report((char *)"\rTotal to send: %lu files, %lu bytes", report_count, report_total);
|
|
|
|
if (!CFG.Req_Files)
|
|
add_report((char *)"Maximum files: unlimited");
|
|
else
|
|
add_report((char *)"Maximum files: %d", CFG.Req_Files);
|
|
if (!CFG.Req_MBytes)
|
|
add_report((char *)"Maximum size : unlimited");
|
|
else
|
|
add_report((char *)"Maximum size : %d MBytes", CFG.Req_MBytes);
|
|
|
|
/*
|
|
* Add random quote
|
|
*/
|
|
sprintf(tmpfn, "%s/etc/oneline.data", getenv("MBSE_ROOT"));
|
|
if ((fp = fopen(tmpfn, "r+")) != NULL) {
|
|
fread(&olhdr, sizeof(olhdr), 1, fp);
|
|
fseek(fp, 0, SEEK_END);
|
|
records = (ftell(fp) - olhdr.hdrsize) / olhdr.recsize;
|
|
srand(getpid());
|
|
recno = 1+(int) (1.0 * records * rand() / (RAND_MAX + 1.0));
|
|
Syslog('f', "Selected quote %d out of %d records", recno, records);
|
|
if (fseek(fp, olhdr.hdrsize + (recno * olhdr.recsize), SEEK_SET) == 0) {
|
|
if (fread(&ol, olhdr.recsize, 1, fp) == 1) {
|
|
add_report((char *)"\r... %s", ol.Oneline);
|
|
} else {
|
|
WriteError("Can't read %s", tmpfn);
|
|
}
|
|
} else {
|
|
WriteError("$Can't seek record %d in %s", recno, tmpfn);
|
|
}
|
|
fclose(fp);
|
|
}
|
|
|
|
add_report((char *)"\r%s\r", TearLine());
|
|
|
|
sprintf(tmpfn, "%s/tmp/%08lX.rpl", getenv((char *)"MBSE_ROOT"), (unsigned long)sequencer());
|
|
if ((fp = fopen(tmpfn,"w"))) {
|
|
fmsg.flags = M_PVT|M_KILLSENT;
|
|
fmsg.from = bestaka_s(remote->addr);
|
|
svname = fmsg.from->name;
|
|
fmsg.from->name = (char *)"mbcico FREQ processor";
|
|
fmsg.to = remote->addr;
|
|
/*
|
|
* If we don't know the sysops name, fake it.
|
|
*/
|
|
if (fmsg.to->name == NULL)
|
|
fmsg.to->name = xstrcpy((char *)"Sysop");
|
|
fmsg.date = time((time_t*)NULL);
|
|
fmsg.subj = (char *)"File request status report";
|
|
fmsg.msgid_s = NULL;
|
|
fmsg.msgid_a = xstrcpy(ascfnode(fmsg.from, 0x1f));
|
|
fmsg.msgid_n = sequencer();
|
|
fmsg.reply_s = NULL;
|
|
fmsg.reply_a = NULL;
|
|
fmsg.reply_n = 0L;
|
|
fmsg.origin = NULL;
|
|
fmsg.area = NULL;
|
|
(void)ftnmsghdr(&fmsg, fp, NULL, 'f', (char *)"MBSE-CICO");
|
|
free(fmsg.msgid_a);
|
|
fwrite(report_text, 1, strlen(report_text), fp);
|
|
fwrite(&zeroes, 1, 3, fp);
|
|
fclose(fp);
|
|
sprintf(remname, "%08lX.PKT", (unsigned long)sequencer());
|
|
add_list(fl, tmpfn, remname, KFS, 0L, NULL, 0);
|
|
fmsg.from->name = svname;
|
|
} else {
|
|
WriteError("$cannot open temp file \"%s\"",MBSE_SS(tmpfn));
|
|
}
|
|
|
|
report_total = 0L;
|
|
free(report_text);
|
|
free(tmpfn);
|
|
report_text = NULL;
|
|
}
|
|
|
|
|
|
|
|
static void add_report(char *format, ...)
|
|
{
|
|
va_list va_ptr;
|
|
char buf[1024];
|
|
|
|
if (report_text == NULL) {
|
|
sprintf(buf,
|
|
" Status of file request\r\
|
|
======================\r\r\
|
|
Received By: %s\r\
|
|
",
|
|
ascfnode(bestaka_s(remote->addr),0x1f));
|
|
sprintf(buf+strlen(buf),
|
|
" From: %s\r\
|
|
On: %s\r\r\
|
|
",
|
|
ascfnode(remote->addr,0x1f),
|
|
date(0L));
|
|
report_text = xstrcat(report_text,buf);
|
|
}
|
|
|
|
va_start(va_ptr, format);
|
|
vsprintf(buf, format, va_ptr);
|
|
va_end(va_ptr);
|
|
strcat(buf,"\r");
|
|
report_text = xstrcat(report_text,buf);
|
|
}
|
|
|