⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mailbox.c

📁 TCP_IPprotocol.rar
💻 C
📖 第 1 页 / 共 3 页
字号:
/* There are only two functions in this mailbox code that depend on the
 * underlying protocol, namely mbx_getname() and dochat(). All the other
 * functions can hopefully be used without modification on other stream
 * oriented protocols than AX.25 or NET/ROM.
 *
 */
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#ifdef	UNIX
#include <sys/types.h>
#include <sys/stat.h>
#endif

#include "global.h"
#include "config.h"
#include "timer.h"
#include "proc.h"
#include "socket.h"
#include "usock.h"
#include "session.h"
#include "smtp.h"
#include "dirutil.h"
#include "telnet.h"
#include "ftp.h"
#include "ftpserv.h"
#include "commands.h"
#include "netuser.h"
#include "files.h"
#include "bm.h"
#include "mailbox.h"
#include "ax25mail.h"
#include "nr4mail.h"
#include "cmdparse.h"

/*
#define MBDEBUG
*/

struct mbx *Mbox[NUMMBX];
static char *Motd = NULL;
static int Attended = TRUE;	/* default to attended mode */
unsigned Maxlet = BM_NLET;

char Noperm[] = "Permission denied.\n";
char Nosock[] = "Can't create socket\n";

static char Mbbanner[] = "[NET-H$]\nWelcome %s to the %s TCP/IP Mailbox (%s)\n%s";
static char Mbmenu[] = "Current msg# %d : A,B,C,D,E,F,G,H,I,J,K,L,N,R,S,T,U,V,W,Z,? >\n";
static char Longmenu1[] = "(?)help    (A)rea     (B)ye      (C)hat     (D)ownload (E)scape   (F)inger\n";
static char Longmenu2[] = "(G)ateway  (H)elp     (I)nfo     (J)heard   (K)ill     (L)ist     (N)etrom\n";
static char Longmenu3[] = "(R)ead     (S)end     (T)elnet   (U)pload   (V)erbose  (W)hat     (Z)ap\n";
static char Loginbanner[] = "\nKA9Q NOS (%s)\n\n";
static char Howtoend[] = "Terminate with /EX or ^Z in first column (^A aborts):\n";

static int doarea(int argc,char *argv[],void *p);
static int mbx_getname(struct mbx *m);

/************************************************************************/
/*			C O M M A N D S					*/
/************************************************************************/

static int doattend(int argc,char *argv[],void *p);
static int domaxmsg(int argc,char *argv[],void *p);
static int domotd(int argc,char *argv[],void *p);
static int dotimeout(int argc,char *argv[],void *p);

/* mbox subcommand table */
static struct cmds Mbtab[] = {
	"attend",	doattend,	0, 0, NULL,
#ifdef	AX25
	"kick",		dombkick,	0, 0, NULL,
#endif
	"maxmsg",	domaxmsg,	0, 0, NULL,
	"motd",		domotd,		0, 0, NULL,
	"status",	domboxdisplay,	0, 0, NULL,
#ifdef	AX25
	"timer",	dombtimer,	0, 0, NULL,
#endif
	"tiptimeout",	dotimeout,	0, 0, NULL,
	NULL,
};


int
dombox(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	if(argc == 1)
		return domboxdisplay(argc,argv,p);
	return subcmd(Mbtab,argc,argv,p);
}

/* if unattended mode is set, ax25, telnet and maybe other sessions will
 * be restricted.
 */
static int
doattend(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setbool(&Attended,"Attended flag",argc,argv);
}

static int
domaxmsg(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setuns(&Maxlet,"Maximum messages per area",argc,argv);
}

static int
domotd(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	if(argc > 2) {
		printf("Usage: mbox motd \"<your message>\"\n");
		return 0;
	}

	if(argc < 2) {
		if(Motd != NULL)
			puts(Motd);
	}
	else {
		if(Motd != NULL){
			free(Motd);
			Motd = NULL;	/* reset the pointer */
		}
		if(!strlen(argv[1]))
			return 0;		/* clearing the buffer */
		Motd = mallocw(strlen(argv[1])+5);/* allow for the EOL char */
		strcpy(Motd, argv[1]);
		strcat(Motd, "\n");		/* add the EOL char */
	}
	return 0;
}

int
domboxdisplay(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	int i, j, len;
	struct mbx *m;
	struct sockaddr fsocket;
	static char *states[] = {"LOGIN","CMD","SUBJ","DATA","REVFWD",
				"TRYING","FORWARD"};

	printf("User       State    S#  Where\n");

	for (i = 0; i < NUMMBX; i++){
		if((m = Mbox[i]) != NULL){
			len = MAXSOCKSIZE;
			j = getpeername(fileno(m->user),&fsocket,&len);
			printf("%-11s%-9s%-4u%s\n",m->name,
			 states[m->state],fileno(m->user),
			 j != -1 ? psocket(&fsocket): "");
		}
	}
	return 0;
}

static int
dotimeout(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setuns(&Tiptimeout,"Tip connection timeout",argc,argv);
}


/**********************************************************************/

void
listusers(network)
FILE *network;
{
	FILE *outsave;

	fprintf(network,"\nCurrent remote users:\n");
	outsave = stdout;
	stdout = network;
	domboxdisplay(0,NULL,NULL);
	stdout = outsave;
}

struct mbx *
newmbx()
{
	int i;
	struct mbx *m;

	for(i = 0; i < NUMMBX; i++){
		if(Mbox[i] == NULL){
			m = Mbox[i] = (struct mbx *)callocw(1,sizeof(struct mbx));
			m->mbnum = i;
			return m;
		}
	}
	/* If we get here, there are no free mailbox sessions */
	return NULL;
}

static int
mbx_getname(m)
struct mbx *m;
{
#ifdef	AX25
	char *cp;
#endif
	union sp sp;
	struct sockaddr tmp;
	char buf[MBXLINE];
	int len = MAXSOCKSIZE;
	int anony = 0;
	int oldmode;

	sp.sa = &tmp;
	sp.sa->sa_family = AF_LOCAL;	/* default to AF_LOCAL */
	getpeername(fileno(m->user),&tmp,&len);
	m->path = mallocw(MBXLINE);
	/* This is one of the two parts of the mbox code that depends on the
	 * underlying protocol. We have to figure out the name of the
	 * calling station. This is only practical when AX.25 or NET/ROM is
	 * used. Telnet users have to identify themselves by a login procedure.
	 */
	switch(sp.sa->sa_family){
#ifdef	AX25
	case AF_NETROM:
	case AF_AX25:
		/* NETROM and AX25 socket address structures are "compatible" */
		pax25(m->name,sp.ax->ax25_addr);
		cp = strchr(m->name,'-');
		if(cp != NULL)			/* get rid of SSID */
			*cp = '\0';
		/* SMTP wants the name to be in lower case */
		cp = m->name;
		while(*cp){
			if(isupper(*cp))
				*cp = tolower(*cp);
			++cp;
		}
		anony = 1;
		/* Try to find the privileges of this user from the userfile */
		if((m->privs = userlogin(m->name,buf,&m->path,MBXLINE,&anony)) == -1)
			if((m->privs = userlogin("bbs",buf,&m->path,MBXLINE,&anony)) == -1)
				if((m->privs = userlogin("anonymous",buf,&m->path,MBXLINE,
					 &anony)) == -1){
						m->privs = 0;
						free(m->path);
						m->path = NULL;
				}
		if(m->privs & EXCLUDED_CMD)
			return -1;
		return 0;
#endif
	case AF_LOCAL:
	case AF_INET:
		m->state = MBX_LOGIN;
		printf(Loginbanner,Hostname);
		for(;;){
			fputs("login: ",stdout);
			if(mbxrecvline(m->user,m->name,sizeof(m->name),-1) == EOF)
				return -1;
			if(*m->name == '\0')
				continue;
			printf("Password: %c%c%c",IAC,WILL,TN_ECHO);
			oldmode = fmode(m->user,STREAM_BINARY);
			if(mbxrecvline(m->user,buf,MBXLINE,-1) == EOF)
				return -1;
			printf("%c%c%c",IAC,WONT,TN_ECHO);
			fmode(m->user,oldmode);
			putchar('\n');
#ifdef	notdef
			/* This is needed if the password was send before the
			 * telnet no-echo options were received. We neeed to
			 * flush the eold sequence from the input buffers, sigh
			 */
			if(socklen(fileno(m->user),0))/* discard any remaining input */
				recv_mbuf(fileno(m->user),NULL,0,NULL,0);
#endif
			if((m->privs = userlogin(m->name,buf,&m->path,MBXLINE,&anony))
			 != -1){
				if(anony)
					logmsg(fileno(m->user),"MBOX login: %s Password: %s",m->name,buf);
				else
					logmsg(fileno(m->user),"MBOX login: %s",m->name);
				if(m->privs & EXCLUDED_CMD)
					return -1;
				return 0;
			}
			printf("Login incorrect\n");
			*m->name = '\0';	/* wipe any garbage */
		}
	}
	return 0;
}

/* Incoming mailbox session */
void
mbx_incom(s,t,p)
int s;
void *t;
void *p;
{
	struct mbx *m;
	struct usock *up;
	char *buf[3];
	int rval;
	FILE *network;

	sockowner(s,Curproc);	/* We own it now */
	if(p == NULL)
		network = fdopen(s,"r+t");
	else
		network = (FILE *)p;
	
	/* Secede from the parent's sockets, and use the network socket that
	 * was passed to us for both input and output. The reference
	 * count on this socket will still be 1; this allows the domboxbye()
	 * command to work by closing that socket with a single call.
	 * If we return, the socket will be closed automatically.
	 */
	fclose(stdin);
	stdin = fdup(network);
	fclose(stdout);
	stdout = fdup(network);

	logmsg(fileno(network),"open MBOX");
	if((m = newmbx()) == NULL){
		printf("Too many mailbox sessions\n");
		return;
	}
	m->user = network;
	m->escape = 24;		/* default escape character is Ctrl-X */
	m->type = (int) t;
	/* get the name of the remote station */
	if(mbx_getname(m) == -1) {
		exitbbs(m);
		return;
	}

	m->state = MBX_CMD;	/* start in command state */

	/* Now say hi */
	printf(Mbbanner,m->name,Hostname,Version,
		Motd != NULL ? Motd : "");
	/* Enable our local message area */
	buf[1] = m->name;
	doarea(2,buf,m);
	printf(Mbmenu,m->current);
	while(mbxrecvline(network,m->line,MBXLINE,-1) != EOF){
		if((rval = mbx_parse(m)) == -2)
			break;
		if(rval == 1)
			printf("Bad syntax.\n");
		if(!(m->sid & MBX_SID) && isnewprivmail(m) > 0L)
			printf("You have new mail.\n");
		scanmail(m);
		printf((m->sid & MBX_SID) ? ">\n" : Mbmenu, m->current);
		m->state = MBX_CMD;
	}
	exitbbs(m);
	/* nasty hack! we may have screwed up reference count */
	/* by invoking newproc("smtp_send",....); Fudge it!   */
	if((up = itop(fileno(stdout))) != NULL)
		up->refcnt = 1;
	fclose(stdout);
}

void
exitbbs(m)
struct mbx *m;
{
	closenotes(m);
	free(m->to);
	free(m->tofrom);
	free(m->origto);
	free(m->tomsgid);
	free(m->path);
	free(m->mbox);
	Mbox[m->mbnum] = NULL;
	free(m);
}

/**********************************************************************/

static int dochat(int argc,char *argv[],void *p);
static int dodownload(int argc,char *argv[],void *p);
static int dombupload(int argc,char *argv[],void *p);
static int dowhat(int argc,char *argv[],void *p);
static int dozap(int argc,char *argv[],void *p);
static int dosend(int argc,char *argv[],void *p);
static int dosid(int argc,char *argv[],void *p);
static int dosysop(int argc,char *argv[],void *p);
static int dostars(int argc,char *argv[],void *p);
static int dombhelp(int argc,char *argv[],void *p);
static int dombtelnet(int argc,char *argv[],void *p);
static int dombfinger(int argc,char *argv[],void *p);
static void gw_alarm(void *p);
static void gw_input(int s,void *notused,void *p);
static void gw_superv(int null,void *proc,void *p);
static int mbx_to(int argc,char *argv[],void *p);
static int mbx_data(struct mbx *m,struct list *cclist,char *extra);
static int msgidcheck(char *string);
static int uuencode(FILE *infile,FILE *outfile,char *infilename);

static struct cmds Mbcmds[] = {
	"",		doreadnext,	0, 0, NULL,
	"area",		doarea,		0, 0, NULL,
	"send",		dosend,		0, 0, NULL,
	"read",		doreadmsg,	0, 2, "R numbers",
	"verbose",	doreadmsg,	0, 2, "V numbers",
#ifdef	AX25
	"jheard",	doaxheard,	0, 0, NULL,
#endif
	"kill",		dodelmsg,	0, 2, "K numbers",
	"list",		dolistnotes,	0, 0, NULL,
	"escape",	dombescape,	0, 0, NULL,
	"download",	dodownload,	0, 2, "D[U] filename",
	"upload",	dombupload,	0, 2, "U filename",
	"what",		dowhat,		0, 0, NULL,
	"zap",		dozap,		0, 2, "Z filename",
#ifdef AX25
	"gateway",	dogateway,	0, 3, "G interface callsigns",
#endif
	"telnet",	dombtelnet,	0, 2, "T hostname",
	"finger",	dombfinger,	0, 0, NULL,
#ifdef	NETROM
	"netrom",	dombnetrom,	0, 0, NULL,
#endif
	"chat",		dochat,		0, 0, NULL,
	"bye",		domboxbye,	0, 0, NULL,
	"help",		dombhelp,	0, 0, NULL,
	"info",		dombhelp,	0, 0, NULL,
	"?",		dombhelp,	0, 0, NULL,
	"[",		dosid,		0, 0, NULL,
#ifdef	AX25
	"f>",		dorevfwd,	0, 0, NULL,
#endif
	"@",		dosysop,	0, 0, NULL,
	"***",		dostars,	0, 0, NULL,
	NULL,	NULL,		0, 0, "Huh?",
};

/* "twocmds" defines the MBL/RLI two-letter commands, eg. "SB", "SP" and so on.
 * They have to be treated specially since cmdparse() wants a space between
 * the actual command and its arguments.
 * "SP FOO" is converted to "s  foo" and the second command letter is saved
 * in m->stype. Longer commands like "SEND" are unaffected, except for
 * commands starting with "[", i.e. the SID, since we don't know what it will
 * look like.
 */
static char twocmds[] = "slrd[";	/* S,L,R,D are two-letter commands */
int
mbx_parse(m)
struct mbx *m;
{
	char *cp;
	int i;
	char *newargv[2];
	/* Translate entire buffer to lower case */
	for (cp = m->line; *cp != '\0'; ++cp)
		if(isupper(*cp))
			*cp = tolower(*cp);
	/* Skip any spaces at the begining */
	for(cp = m->line;isspace(*cp);++cp)
		;
	m->stype = ' ';
	if(*cp != '\0' && *(cp+1) != '\0')
	for(i=0; i<strlen(twocmds); ++i){
		if(*cp == twocmds[i] && (isspace(*(cp+2)) || *(cp+2) == '\0'
		 || *cp == '[')){
			if(islower(*(++cp)))
				m->stype = toupper(*cp); /* Save the second character */
			else
				m->stype = *cp;
			*cp = ' ';
			break;
		}
	}
	/* See if the input line consists solely of digits */
	cp = m->line;
	for(cp = m->line;isspace(*cp);++cp)
		;
	newargv[1] = cp;
	for(;*cp != '\0' && isdigit(*cp);++cp)
		;
	if(*cp == '\0' && strlen(newargv[1]) > 0) {
		newargv[0] = "read";
		return doreadmsg(2,newargv,(void *)m);
	}
	else
		return cmdparse(Mbcmds,m->line,(void *)m);
}

/* This works like recvline(), but telnet options are answered and the
 * terminating newline character is not put into the buffer. If the
 * incoming character equals the value of escape, any queued input is
 * flushed and -2 returned.
 */
int
mbxrecvline(network,buf,len,escape)
FILE *network;
char *buf;
int len;
int escape;
{
	int c, cnt = 0, opt;
	if(buf == NULL)
		return 0;
	fflush(stdout);
	while((c = getc(network)) != EOF){
		if(c == IAC){		/* Telnet command escape */
			if((c = getc(network)) == EOF)
				break;
			if(c > 250 && c < 255 && (opt = getc(network)) != EOF){
#ifdef	foo
				switch(c){
				case WILL:
					printf("%c%c%c",IAC,DONT,opt);
					break;
				case WONT:
					printf("%c%c%c",IAC,DONT,opt);
					break;
				case DO:
					printf("%c%c%c",IAC,WONT,opt);
					break;
				case DONT:
					printf("%c%c%c",IAC,WONT,opt);
				}
#endif
/* to be fixed 			fflush(stdout);*/
				continue;
			}
			if(c != IAC && (c = fgetc(network)) == EOF)
				break;
		}
		/* ordinary character */
		if(c == '\r' || c == '\n')
			break;
		if(c == escape){
			if(socklen(fileno(network),0)) /* discard any remaining input */
				recv_mbuf(fileno(network),NULL,0,NULL,0);
			cnt = -2;
			break;
		}
		*buf++ = c;
		++cnt;
		if(cnt == len - 1)
			break;
	}
	if(c == EOF && cnt == 0)
		return -1;
	*buf = '\0';
	return cnt;
}

int
domboxbye(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	struct mbx *m;

	m = (struct mbx *)p;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -