📄 bmutil.c
字号:
/*
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "global.h"
#include "ftpserv.h"
#include "smtp.h"
#include "proc.h"
#include "usock.h"
#include "socket.h"
#include "telnet.h"
#include "timer.h"
#include "session.h"
#include "files.h"
#define SETVBUF
#if defined(UNIX) || defined(MICROSOFT)
#include <sys/types.h>
#endif
/*
#if defined(UNIX) || defined(MICROSOFT) || defined(__TURBOC__)
#include <sys/stat.h>
#endif
#ifdef AZTEC
#include <stat.h>
#endif
*/
#include <fcntl.h>
#include "bm.h"
#include "mailbox.h"
#ifdef SETVBUF
#define MYBUF 1024
#endif
extern long ftell();
static char Badmsg[] = "Invalid Message number %d\n";
static char Nomail[] = "No messages\n";
static char Noaccess[] = "Unable to access %s\n";
static int readnotes(struct mbx *m,FILE *ifile,int update);
static long isnewmail(struct mbx *m);
static int initnotes(struct mbx *m);
static int lockit(struct mbx *m);
static long fsize(char *name);
static void mfclose(struct mbx *m);
static int tkeywait(char *prompt,int flush);
static int
initnotes(m)
struct mbx *m;
{
FILE *tmpfile();
FILE *ifile;
register struct let *cmsg;
char buf[256];
int i, ret;
sprintf(buf,"%s/%s.txt",Mailspool,m->area);
if ((ifile = fopen(buf,READ_TEXT)) == NULL)
return 0;
fseek(ifile,0L,2); /* go to end of file */
m->mboxsize = ftell(ifile);
rewind(ifile);
if(!stricmp(m->area,m->name)) /* our private mail area */
m->mysize = m->mboxsize;
if ((m->mfile = tmpfile()) == NULL) {
(void) fclose(ifile);
return -1;
}
#ifdef SETVBUF
if (m->stdinbuf == NULL)
m->stdinbuf = mallocw(MYBUF);
setvbuf(ifile, m->stdinbuf, _IOFBF, MYBUF);
if (m->stdoutbuf == NULL)
m->stdoutbuf = mallocw(MYBUF);
setvbuf(m->mfile, m->stdoutbuf, _IOFBF, MYBUF);
#endif
m->nmsgs = 0;
m->current = 0;
m->change = 0;
m->newmsgs = 0;
m->anyread = 0;
/* Allocate space for reading messages */
free(m->mbox);
m->mbox = (struct let *)callocw(Maxlet+1,sizeof(struct let));
ret = readnotes(m,ifile,0);
(void) fclose(ifile);
#ifdef SETVBUF
free(m->stdinbuf);
m->stdinbuf = NULL;
#endif
if (ret != 0)
return -1;
for (cmsg = &m->mbox[1],i = 1; i <= m->nmsgs; i++, cmsg++)
if ((cmsg->status & BM_READ) == 0) {
m->newmsgs++;
if (m->current == 0)
m->current = i;
}
/* start at one if no new messages */
if (m->current == 0)
m->current++;
return 0;
}
/* readnotes assumes that ifile is pointing to the first
* message that needs to be read. For initial reads of a
* notesfile, this will be the beginning of the file. For
* rereads when new mail arrives, it will be the first new
* message.
*/
static int
readnotes(m,ifile,update)
struct mbx *m;
FILE *ifile ;
int update; /* true if this is not the initial read of the notesfile */
{
char tstring[LINELEN];
long cpos;
register struct let *cmsg;
register char *line;
cmsg = (struct let *)NULL;
line = tstring;
while(fgets(line,LINELEN,ifile) != NULL) {
/* scan for begining of a message */
if(strncmp(line,"From ",5) == 0) {
kwait(NULL);
cpos = ftell(m->mfile);
fputs(line,m->mfile);
if (m->nmsgs == Maxlet) {
printf("Mail box full: > %d messages\n",Maxlet);
mfclose(m);
return -1;
}
m->nmsgs++;
cmsg = &m->mbox[m->nmsgs];
cmsg->start = cpos;
if(!update)
cmsg->status = 0;
cmsg->size = strlen(line);
while (fgets(line,LINELEN,ifile) != NULL) {
if (*line == '\n') { /* done header part */
cmsg->size++;
putc(*line, m->mfile);
break;
}
if (htype(line) == STATUS) {
if (line[8] == 'R')
cmsg->status |= BM_READ;
continue;
}
cmsg->size += strlen(line);
if (fputs(line,m->mfile) == EOF) {
printf("tmp file: %s",sys_errlist[errno]);
mfclose(m);
return -1;
}
}
} else if (cmsg) {
cmsg->size += strlen(line);
fputs(line,m->mfile);
}
}
return 0;
}
/* list headers of a notesfile a message */
int
dolistnotes(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
register struct let *cmsg;
register char *cp, *s;
char smtp_date[SLINELEN], smtp_from[SLINELEN];
char smtp_subject[SLINELEN], tstring[LINELEN], type;
int start, stop;
long size;
char *area;
m = (struct mbx *) p;
if (m->mfile == NULL) {
printf(Nomail);
return 0;
}
area = strdup(m->area);
while((cp = strchr(area,'/')) != NULL)
*cp = '.';
printf("Mail area: %s %d message%s - %d new\n\n",area,m->nmsgs,
m->nmsgs == 1 ? " " : "s ", m->newmsgs);
free(area);
stop = m->nmsgs;
if(m->stype == 'L') { /* LL (List Latest) command */
if(argc > 1)
start = stop - atoi(argv[1]) + 1;
else
start = stop;
}
else {
if(argc > 1)
start = atoi(argv[1]);
else
start = 1;
if(argc > 2)
stop = atoi(argv[2]);
}
if(stop > m->nmsgs)
stop = m->nmsgs;
if(start < 1 || start > stop) {
printf("Invalid range.\n");
return 0;
}
for (cmsg = &m->mbox[start]; start <= stop; start++, cmsg++) {
*smtp_date = '\0';
*smtp_from = '\0';
*smtp_subject = '\0';
type = ' ';
fseek(m->mfile,cmsg->start,0);
size = cmsg->size;
while (size > 0 && fgets(tstring,sizeof(tstring),m->mfile)
!= NULL) {
if (*tstring == '\n') /* end of header */
break;
size -= strlen(tstring);
rip(tstring);
/* handle continuation later */
if (*tstring == ' '|| *tstring == '\t')
continue;
switch(htype(tstring)) {
case FROM:
cp = getaddress(tstring,0);
sprintf(smtp_from,"%.30s",
cp != NULL ? cp : "");
break;
case SUBJECT:
sprintf(smtp_subject,"%.34s",&tstring[9]);
break;
case DATE:
if ((cp = strchr(tstring,',')) == NULL)
cp = &tstring[6];
else
cp++;
/* skip spaces */
while (*cp == ' ') cp++;
if(strlen(cp) < 17)
break; /* not a valid length */
s = smtp_date;
/* copy day */
if (atoi(cp) < 10 && *cp != '0') {
*s++ = ' ';
} else
*s++ = *cp++;
*s++ = *cp++;
*s++ = ' ';
*s = '\0';
while (*cp == ' ')
cp++;
strncat(s,cp,3); /* copy month */
cp += 3;
while (*cp == ' ')
cp++;
/* skip year */
while (isdigit(*cp))
cp++;
/* copy time */
strncat(s,cp,6); /* space hour : min */
break;
case BBSTYPE:
type = tstring[16];
break;
case NOHEADER:
break;
}
}
if((type == m->stype && m->stype != ' ') || m->stype == ' '
|| m->stype == 'L')
printf("%c%c%c%3d %-27.27s %-12.12s %5ld %.25s\n",
(start == m->current ? '>' : ' '),
(cmsg->status & BM_DELETE ? 'D' : ' '),
(cmsg->status & BM_READ ? 'Y' : 'N'),
start, smtp_from, smtp_date,
cmsg->size, smtp_subject);
}
return 0;
}
/* save msg on stream - if noheader set don't output the header */
int
msgtofile(m,msg,tfile,noheader)
struct mbx *m;
int msg;
FILE *tfile; /* already open for write */
int noheader;
{
char tstring[LINELEN];
long size;
if (m->mfile == NULL) {
printf(Nomail);
return -1;
}
fseek(m->mfile,m->mbox[msg].start,0);
size = m->mbox[msg].size;
if (noheader) {
/* skip header */
while (size > 0 && fgets(tstring,sizeof(tstring),m->mfile)
!= NULL) {
size -= strlen(tstring);
if (*tstring == '\n')
break;
}
}
while (size > 0 && fgets(tstring,sizeof(tstring),m->mfile)
!= NULL) {
size -= strlen(tstring);
fputs(tstring,tfile);
if (ferror(tfile)) {
printf("Error writing mail file\n");
return -1;
}
}
return 0;
}
/* dodelmsg - delete message in current notesfile */
int
dodelmsg(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
int msg,i;
m = (struct mbx *) p;
if (m->mfile == NULL) {
printf(Nomail);
return 0;
}
for(i = 1; i < argc; ++i) {
msg = atoi(argv[i]);
if(msg < 0 || msg > m->nmsgs) {
printf(Badmsg,msg);
continue;
}
/* Check if we have permission to delete others mail */
if(!(m->privs & FTP_WRITE) && stricmp(m->area,m->name)) {
printf(Noperm);
return 0;
}
m->mbox[msg].status |= BM_DELETE;
printf("Msg %d Killed.\n", msg);
m->change = 1;
}
return 0;
}
/* close the temp file while coping mail back to the mailbox */
int
closenotes(m)
struct mbx *m;
{
register struct let *cmsg;
register char *line;
char tstring[LINELEN], buf[256];
long size;
int i, nostatus = 0, nodelete;
FILE *nfile;
if (m->mfile == NULL)
return 0;
if(!m->change) { /* no changes were made */
mfclose(m);
m->mboxsize = 0;
return 0;
}
/* If this area is a public message area, then we will not add a
* Status line to indicate that the message has been read.
*/
nostatus = isarea(m->area);
/* Don't delete messages from public message areas unless you are
* a BBS.
*/
if(nostatus)
nodelete = !(m->privs & SYSOP_CMD);
else
nodelete = 0;
/* See if any messages have been forwarded, otherwise just close
* the file and return since there is nothing to write back.
*/
if(nostatus && nodelete) {
for(i=1; i <= m->nmsgs; ++i)
if(m->mbox[i].status & BM_FORWARDED)
break;
if(i > m->nmsgs) {
mfclose(m);
m->mboxsize = 0;
return 0;
}
}
line = tstring;
scanmail(m);
if(lockit(m))
return -1;
sprintf(buf,"%s/%s.txt",Mailspool,m->area);
if ((nfile = fopen(buf,WRITE_TEXT)) == NULL) {
printf(Noaccess,buf);
mfclose(m);
m->mboxsize = 0;
rmlock(Mailspool,m->area);
return -1;
}
/* copy tmp file back to notes file */
for (cmsg = &m->mbox[1],i = 1; i <= m->nmsgs; i++, cmsg++) {
fseek(m->mfile,cmsg->start,0);
size = cmsg->size;
/* It is not possible to delete messages if nodelete is set */
if ((cmsg->status & BM_DELETE) && !nodelete)
continue;
/* copy the header */
while (size > 0 && fgets(line,LINELEN,m->mfile) != NULL) {
size -= strlen(line);
if (*line == '\n') {
if (cmsg->status & BM_FORWARDED)
fprintf(nfile,"%s%s\n",Hdrs[XFORWARD],
m->name);
if ((cmsg->status & BM_READ) != 0 && !nostatus)
fprintf(nfile,"%sR\n",Hdrs[STATUS]);
fprintf(nfile,"\n");
break;
}
fputs(line,nfile);
/* kwait(NULL); can cause problems if exiting NOS */
}
while (size > 0 && fgets(line,LINELEN,m->mfile) != NULL) {
fputs(line,nfile);
size -= strlen(line);
/* kwait(NULL); dont want no damaged files */
if (ferror(nfile)) {
printf("Error writing mail file\n");
(void) fclose(nfile);
mfclose(m);
m->mboxsize = 0;
rmlock(Mailspool,m->area);
return -1;
}
}
}
m->nmsgs = 0;
if (!stricmp(m->name,m->area))
m->mysize = ftell(nfile); /* Update the size of our mailbox */
/* remove a zero length file */
if (ftell(nfile) == 0L)
(void) unlink(buf);
(void) fclose(nfile);
mfclose(m);
m->mboxsize = 0;
rmlock(Mailspool,m->area);
kwait(NULL);
return 0;
}
/* Returns 1 if name is a public message Area, 0 otherwise */
int
isarea(name)
char *name;
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -