📄 mailbox.c
字号:
len = MAXSOCKSIZE;
i = getpeername(fileno(m->user),&dsocket,&len);
sprintf(m->startmsg,"*** Incoming call from %s@%s ***\n",
m->name,i != -1 ? psocket(&dsocket): Hostname);
}
return gw_connect(m,s,(struct sockaddr *)&fsocket,SOCKSIZE);
}
static int
dombfinger(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
char *host, *user = NULL, buf[8], *newargv[3];
if(argc > 2){
printf("Usage: F user@host or F @host or F user.\n");
return 0;
}
host = Hostname;
if(argc == 2){
if((host = strchr(argv[1], '@')) != NULL){
*host = '\0';
host++;
} else
host = Hostname;
user = argv[1];
}
m = (struct mbx *) p;
m->startmsg = mallocw(80);
if(user != NULL)
sprintf(m->startmsg,"%s\n",user);
else
strcpy(m->startmsg,"\n");
newargv[0] = "telnet";
newargv[1] = host;
sprintf(buf,"%d",IPPORT_FINGER);
newargv[2] = buf;
return dombtelnet(3,newargv,p);
}
/* Generic mbox gateway code. It sends and frees the contents of m->startmsg
* when the connection has been established unless it a null pointer.
*/
int
gw_connect(m,s,fsocket,len)
struct mbx *m;
int s;
struct sockaddr *fsocket;
int len;
{
int c;
char *cp;
struct proc *child;
struct gwalarm *gwa;
FILE *network;
child = newproc("gateway supervisor",256,gw_superv,0,Curproc,m,0);
printf("Trying %s... ",psocket(fsocket));
dombescape(0,NULL,(void *)m);
fflush(stdout);
if(connect(s,fsocket,len) == -1){
cp = sockerr(s);
printf("Connection failed: ");
if(cp != NULL)
printf("%s errno %d\n",cp,errno);
else
printf("Escape character sent.\n");
free(m->startmsg);
m->startmsg = NULL;
killproc(child);
close_s(s);
return 0;
}
network = fdopen(s,"r+t");
/* The user did not type the escape character */
killproc(child);
puts("Connected.");
if(m->startmsg != NULL){
fputs(m->startmsg,network);
free(m->startmsg);
m->startmsg = NULL;
}
/* Since NOS does not flush the output socket after a certain
* period of time, we have to arrange that ourselves.
*/
gwa = (struct gwalarm *) mallocw(sizeof(struct gwalarm));
gwa->s1 = stdout;
gwa->s2 = network;
set_timer(&gwa->t,240L);
gwa->t.func = gw_alarm;
gwa->t.arg = (void *) gwa;
start_timer(&gwa->t);
/* Fork off the receive process */
child = newproc("gateway in",1024,gw_input,s,(void *)network,Curproc,0);
for(;;){
if((c = getchar()) == EOF)
break;
if(c == m->escape){
puts("Disconnecting.");
if(socklen(fileno(stdin),0))
recv_mbuf(fileno(stdin),NULL,0,NULL,0);
break;
}
if(putc(c,network) == EOF)
break;
}
stop_timer(&gwa->t);
free(gwa);
fclose(network);
killproc(child); /* get rid of the receive process */
printf("%c%c%c\n",IAC,WONT,TN_ECHO);
return 0;
}
static void
gw_input(s,n,p)
int s;
void *n;
void *p;
{
int c;
char *cp;
struct proc *parent;
FILE *network;
network = (FILE *)n;
parent = (struct proc *) p;
while((c = getc(network)) != EOF)
putchar((char)c);
printf("Disconnected ");
cp = sockerr(fileno(network));
if(cp != NULL)
puts(cp);
/* Tell the parent that we are no longer connected */
alert(parent,ENOTCONN);
kwait(Curproc); /* Now wait to be killed */
}
/* Check if the escape character is typed while the parent process is busy
* doing other things.
*/
static void
gw_superv(null,proc,p)
int null;
void *proc;
void *p;
{
struct proc *parent;
struct mbx *m;
int c;
parent = (struct proc *) proc;
m = (struct mbx *) p;
while((c = getchar()) != EOF)
if(c == m->escape){
/* flush anything in the input queue */
if(socklen(fileno(stdin),0))
recv_mbuf(fileno(stdin),NULL,0,NULL,0);
break;
}
alert(parent,EINTR); /* Tell the parent to quit */
kwait(Curproc); /* Please kill me */
}
static void
gw_alarm(p)
void *p;
{
struct gwalarm *gwa = (struct gwalarm *)p;
char oldbl;
struct usock *up;
/* Flush sockets s1 and s2, but first make sure that the socket
* is set to non-blocking mode, to prevent the flush from blocking
* if the high water mark has been reached.
*/
if((up = itop(fileno(gwa->s1))) != NULL) {
oldbl = up->noblock;
up->noblock = 1;
fflush(gwa->s1);
up->noblock = oldbl;
}
if((up = itop(fileno(gwa->s2))) != NULL) {
oldbl = up->noblock;
up->noblock = 1;
fflush(gwa->s2);
up->noblock = oldbl;
}
start_timer(&gwa->t);
}
/* States for send line parser state machine */
#define LOOK_FOR_USER 2
#define IN_USER 3
#define AFTER_USER 4
#define LOOK_FOR_HOST 5
#define IN_HOST 6
#define AFTER_HOST 7
#define LOOK_FOR_FROM 8
#define IN_FROM 9
#define AFTER_FROM 10
#define LOOK_FOR_MSGID 11
#define IN_MSGID 12
#define FINAL_STATE 13
#define ERROR_STATE 14
/* Prepare the addressee. If the address is bad, return -1, otherwise
* return 0
*/
static int
mbx_to(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register char *cp;
int state, i;
char *user, *host, *from, *msgid;
int userlen = 0, hostlen = 0, fromlen = 0, msgidlen = 0;
struct mbx *m;
m = (struct mbx *)p;
/* Free anything that might be allocated
* since the last call to mbx_to() or mbx_reply()
*/
free(m->to);
m->to = NULL;
free(m->tofrom);
m->tofrom = NULL;
free(m->tomsgid);
m->tomsgid = NULL;
free(m->origto);
m->origto = NULL;
if(argc == 1)
return -1;
i = 1;
cp = argv[i];
state = LOOK_FOR_USER;
while(state < FINAL_STATE){
#ifdef MBDEBUG
printf("State is %d, char is %c\n", state, *cp);
#endif
switch(state){
case LOOK_FOR_USER:
if(*cp == '@' || *cp == '<' || *cp == '$'){
state = ERROR_STATE; /* no user */
} else {
user = cp; /* point at start */
userlen++; /* start counting */
state = IN_USER;
}
break;
case IN_USER:
switch(*cp){
case '\0':
state = AFTER_USER; /* done with username */
break;
case '@':
state = LOOK_FOR_HOST; /* hostname should follow */
break;
case '<':
state = LOOK_FOR_FROM; /* from name should follow */
break;
case '$':
state = LOOK_FOR_MSGID; /* message id should follow */
break;
default:
userlen++; /* part of username */
}
break;
case AFTER_USER:
switch(*cp){
case '@':
state = LOOK_FOR_HOST; /* hostname follows */
break;
case '<':
state = LOOK_FOR_FROM; /* fromname follows */
break;
case '$':
state = LOOK_FOR_MSGID; /* message id follows */
break;
default:
state = ERROR_STATE;
}
break;
case LOOK_FOR_HOST:
if(*cp == '@' || *cp == '<' || *cp == '$'){
state = ERROR_STATE;
break;
}
if(*cp == '\0')
break;
host = cp;
hostlen++;
state = IN_HOST;
break;
case IN_HOST:
switch(*cp){
case '\0':
state = AFTER_HOST; /* found user@host */
break;
case '@':
state = ERROR_STATE; /* user@host@? */
break;
case '<':
state = LOOK_FOR_FROM; /* fromname follows */
break;
case '$':
state = LOOK_FOR_MSGID; /* message id follows */
break;
default:
hostlen++;
}
break;
case AFTER_HOST:
switch(*cp){
case '@':
state = ERROR_STATE; /* user@host @ */
break;
case '<':
state = LOOK_FOR_FROM; /* user@host < */
break;
case '$':
state = LOOK_FOR_MSGID; /* user@host $ */
break;
default:
state = ERROR_STATE; /* user@host foo */
}
break;
case LOOK_FOR_FROM:
if(*cp == '@' || *cp == '<' || *cp == '$'){
state = ERROR_STATE;
break;
}
if(*cp == '\0')
break;
from = cp;
fromlen++;
state = IN_FROM;
break;
case IN_FROM:
switch(*cp){
case '\0':
state = AFTER_FROM; /* user@host <foo */
break;
case '<':
state = ERROR_STATE; /* user@host <foo< */
break;
case '$':
state = LOOK_FOR_MSGID; /* message id follows */
break;
default:
fromlen++;
}
break;
case AFTER_FROM:
switch(*cp){
case '@': /* user@host <foo @ */
case '<': /* user@host <foo < */
state = ERROR_STATE;
break;
case '$':
state = LOOK_FOR_MSGID; /* user@host <foo $ */
break;
default:
state = ERROR_STATE; /* user@host foo */
}
break;
case LOOK_FOR_MSGID:
if(*cp == '\0')
break;
msgid = cp;
msgidlen++;
state = IN_MSGID;
break;
case IN_MSGID:
if(*cp == '\0')
state = FINAL_STATE;
else
msgidlen++;
break;
default:
/* what are we doing in this state? */
state = ERROR_STATE;
}
if(*(cp) == '\0'){
++i;
if(i < argc)
cp = argv[i];
else break;
} else
++cp;
}
if(state == ERROR_STATE || state == LOOK_FOR_HOST
|| state == LOOK_FOR_FROM || state == LOOK_FOR_MSGID)
return -1; /* syntax error */
m->to = mallocw(userlen + hostlen + 2);
strncpy(m->to, user, userlen);
m->to[userlen] = '\0';
if(hostlen){
m->to[userlen] = '@';
strncpy(m->to + userlen + 1, host, hostlen);
m->to[userlen + hostlen + 1] = '\0';
}
if(fromlen){
m->tofrom = mallocw(fromlen + 1);
strncpy(m->tofrom, from, fromlen);
m->tofrom[fromlen] = '\0';
}
if(msgidlen){
m->tomsgid = mallocw(msgidlen + 1);
strncpy(m->tomsgid, msgid, msgidlen);
m->tomsgid[msgidlen] = '\0';
}
return 0;
}
/* This opens the data file and writes the mail header into it.
* Returns 0 if OK, and -1 if not.
*/
static int
mbx_data(m,cclist,extra)
struct mbx *m;
struct list *cclist; /* list of carbon copy recipients */
char *extra; /* optional extra header lines */
{
time_t t;
struct list *ap;
int cccnt = 0;
if((m->tfile = tmpfile()) == NULL)
return -1;
time(&t);
fprintf(m->tfile,Hdrs[RECEIVED]);
if(m->tofrom != NULL)
fprintf(m->tfile,"from %s.bbs ",m->name);
fprintf(m->tfile,"by %s (%s)\n\tid AA%ld ; %s",
Hostname, Version, get_msgid(), ptime(&t));
fprintf(m->tfile,"%s%s",Hdrs[DATE],ptime(&t));
fprintf(m->tfile,Hdrs[MSGID]);
if(m->tomsgid)
fprintf(m->tfile,"<%s@%s.bbs>\n", m->tomsgid, m->name);
else
fprintf(m->tfile,"<%ld@%s>\n",get_msgid(), Hostname);
fprintf(m->tfile,Hdrs[FROM]);
if(m->tofrom)
fprintf(m->tfile,"%s%%%s.bbs@%s\n",
m->tofrom, m->name, Hostname);
else
fprintf(m->tfile,"%s@%s\n", m->name, Hostname);
fprintf(m->tfile,"%s%s\n",Hdrs[TO],m->origto != NULL ? m->origto : m->to);
/* Write Cc: line */
for(ap = cclist; ap != NULL; ap = ap->next) {
if(cccnt == 0){
fprintf(m->tfile,"%s",Hdrs[CC]);
cccnt = 4;
}
else {
fprintf(m->tfile,", ");
cccnt += 2;
}
if(cccnt + strlen(ap->val) > 80 - 3) {
fprintf(m->tfile,"\n ");
cccnt = 4;
}
fputs(ap->val,m->tfile);
cccnt += strlen(ap->val);
}
if(cccnt)
fputc('\n',m->tfile);
fprintf(m->tfile,"%s%s\n",Hdrs[SUBJECT],m->line);
if(!isspace(m->stype) && ((m->stype != 'R' && m->stype != 'F') ||
(m->sid & MBX_SID) !=0))
fprintf(m->tfile,"%s%c\n", Hdrs[BBSTYPE],m->stype);
if(extra != NULL)
fprintf(m->tfile,extra);
fprintf(m->tfile,"\n");
return 0;
}
/* Returns true if string is in history file or if string appears to be a
* message id generated by our system.
*/
static int
msgidcheck(string)
char *string;
{
FILE *fp;
char buf[LINELEN], *cp;
if(string == NULL)
return 0;
/* BID's that we have generated ourselves are not kept in the history
* file. Such BID's are in the nnnn_hhhh form, where hhhh is a part of
* our hostname, truncated so that the BID is no longer than 11
* characters.
*/
if((cp = strchr(string,'_')) != NULL && *(cp+1) != '\0' &&
strnicmp(cp+1,Hostname,strlen(cp+1)) == 0)
return 1;
if((fp = fopen(Historyfile,READ_TEXT)) == NULL)
return 0;
while(fgets(buf,LINELEN,fp) != NULL) {
rip(buf);
if(stricmp(string,buf) == 0) { /* found */
fclose(fp);
return 1;
}
}
fclose(fp);
return 0;
}
/* uuencode a file -- translated from C++; both versions copyright 1990
by David R. Evans, G4AMJ/NQ0I
*/
static int
uuencode(infile,outfile,infilename)
FILE *infile;
FILE *outfile;
char *infilename;
{
int n_read_so_far = 0, n_written_so_far = 0, in_chars, n, mode = 0755;
int32 cnt = 0;
unsigned char in[3], out[4], line[100];
#ifdef UNIX
struct stat stb;
if(stat(infilename,&stb) != -1)
mode = stb.st_mode & 0777; /* get real file protection mode */
#endif
fprintf(outfile, "begin %03o %s\n", mode, infilename);
/* do the encode */
for(;;) {
in_chars = fread(in, 1, 3, infile);
out[0] = in[0] >> 2;
out[1] = in[0] << 6;
out[1] = out[1] >> 2;
out[1] = out[1] | (in[1] >> 4);
out[2] = in[1] << 4;
out[2] = out[2] >> 2;
out[2] = out[2] | (in[2] >> 6);
out[3] = in[2] << 2;
out[3] = out[3] >> 2;
for (n = 0; n < 4; n++)
out[n] += ' ';
n_read_so_far += in_chars;
for (n = 0; n < 4; n++)
line[n_written_so_far++] = out[n];
if (((in_chars != 3) || (n_written_so_far == 60)) && n_read_so_far > 0) {
line[(n_read_so_far + 2) / 3 * 4] = '\0';
fprintf(outfile,"%c%s\n",n_read_so_far + ' ', line);
cnt += n_read_so_far;
n_read_so_far = 0;
n_written_so_far = 0;
}
if (in_chars == 0)
break;
}
if (fprintf(outfile," \nend\nsize %lu\n", cnt) == EOF)
return 1;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -