📄 ipop2d.c
字号:
/* * Program: IPOP2D - IMAP to POP2 conversion server * * Author: Mark Crispin * Networks and Distributed Computing * Computing & Communications * University of Washington * Administration Building, AG-44 * Seattle, WA 98195 * Internet: MRC@CAC.Washington.EDU * * Date: 28 October 1990 * Last Edited: 19 May 2000 * * Copyright 2000 by the University of Washington * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appears in all copies and that both the * above copyright notice and this permission notice appear in supporting * documentation, and that the name of the University of Washington not be * used in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. This software is made * available "as is", and * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * *//* Parameter files */#include <stdio.h>#include <ctype.h>#include <errno.h>extern int errno; /* just in case */#include <signal.h>#include <time.h>#include "c-client.h"/* Autologout timer */#define KODTIMEOUT 60*5#define LOGINTIMEOUT 60*3#define TIMEOUT 60*30/* Size of temporary buffers */#define TMPLEN 1024/* Server states */#define LISN 0#define AUTH 1#define MBOX 2#define ITEM 3#define NEXT 4#define DONE 5/* Global storage */char *version = "2000.58"; /* server version */short state = LISN; /* server state */short critical = NIL; /* non-zero if in critical code */MAILSTREAM *stream = NIL; /* mailbox stream */long idletime = 0; /* time we went idle */unsigned long nmsgs = 0; /* number of messages */unsigned long current = 1; /* current message number */unsigned long size = 0; /* size of current message */char status[MAILTMPLEN]; /* space for status string */char *user = ""; /* user name */char *pass = ""; /* password */unsigned long *msg = NIL; /* message translation vector *//* Function prototypes */int main (int argc,char *argv[]);void clkint ();void kodint ();void hupint ();void trmint ();short c_helo (char *t,int argc,char *argv[]);short c_fold (char *t);short c_read (char *t);short c_retr (char *t);short c_acks (char *t);short c_ackd (char *t);short c_nack (char *t);/* Main program */int main (int argc,char *argv[]){ char *s,*t; char cmdbuf[TMPLEN];#ifdef PLAINTEXT_DISABLED printf ("- POP2 server disabled on this system\015\012"); fflush (stdout); _exit (1);#endif#include "linkage.c" /* initialize server */ server_init (argv[0],"pop",NIL,"pop",clkint,kodint,hupint,trmint); /* There are reports of POP2 clients which get upset if anything appears * between the "+" and the "POP2" in the greeting. */ printf ("+ POP2 %s v%s server ready\015\012",tcp_serverhost (),version); fflush (stdout); /* dump output buffer */ state = AUTH; /* initial server state */ while (state != DONE) { /* command processing loop */ idletime = time (0); /* get a command under timeout */ alarm ((state != AUTH) ? TIMEOUT : LOGINTIMEOUT); clearerr (stdin); /* clear stdin errors */ while (!fgets (cmdbuf,TMPLEN-1,stdin)) { if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); else { char *e = ferror (stdin) ? strerror (errno) : "Command stream end of file"; alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); syslog (LOG_INFO,"%s while reading line user=%.80s host=%.80s", e,user ? user : "???",tcp_clienthost ()); state = DONE; mail_close (stream); /* try to close the stream gracefully */ stream = NIL; _exit (1); } } alarm (0); /* make sure timeout disabled */ idletime = 0; /* no longer idle */ /* find end of line */ if (!strchr (cmdbuf,'\012')) { server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); fputs ("- Command line too long\015\012",stdout); state = DONE; } else if (!(s = strtok (cmdbuf," \015\012"))) { server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); fputs ("- Missing or null command\015\012",stdout); state = DONE; } else { /* dispatch based on command */ ucase (s); /* canonicalize case */ /* snarf argument */ t = strtok (NIL,"\015\012"); if ((state == AUTH) && !strcmp (s,"HELO")) state = c_helo (t,argc,argv); else if ((state == MBOX || state == ITEM) && !strcmp (s,"FOLD")) state = c_fold (t); else if ((state == MBOX || state == ITEM) && !strcmp (s,"READ")) state = c_read (t); else if ((state == ITEM) && !strcmp (s,"RETR")) state = c_retr (t); else if ((state == NEXT) && !strcmp (s,"ACKS")) state = c_acks (t); else if ((state == NEXT) && !strcmp (s,"ACKD")) state = c_ackd (t); else if ((state == NEXT) && !strcmp (s,"NACK")) state = c_nack (t); else if ((state == AUTH || state == MBOX || state == ITEM) && !strcmp (s,"QUIT")) { server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); state = DONE; /* done in either case */ if (t) fputs ("- Bogus argument given to QUIT\015\012",stdout); else { /* expunge the stream */ if (stream && nmsgs) stream = mail_close_full (stream,CL_EXPUNGE); stream = NIL; /* don't repeat it */ /* acknowledge the command */ fputs ("+ Sayonara\015\012",stdout); } } else { /* some other or inappropriate command */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); printf ("- Bogus or out of sequence command - %s\015\012",s); state = DONE; } } fflush (stdout); /* make sure output blatted */ } /* clean up the stream */ if (stream) mail_close (stream); syslog (LOG_INFO,"Logout user=%.80s host=%.80s",user ? user : "???", tcp_clienthost ()); return 0; /* all done */}/* Clock interrupt */void clkint (){ alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); fputs ("- Autologout; idle for too long\015\012",stdout); syslog (LOG_INFO,"Autologout user=%.80s host=%.80s",user ? user : "???", tcp_clienthost ()); fflush (stdout); /* make sure output blatted */ state = DONE; /* mark state done in either case */ if (!critical) { /* badly host if in critical code */ if (stream && !stream->lock) mail_close (stream); stream = NIL; _exit (1); /* die die die */ }}/* Kiss Of Death interrupt */void kodint (){ /* only if in command wait */ if (idletime && ((time (0) - idletime) > KODTIMEOUT)) { alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); fputs ("- Received Kiss of Death\015\012",stdout); syslog (LOG_INFO,"Killed (lost mailbox lock) user=%.80s host=%.80s", user ? user : "???",tcp_clienthost ()); fflush (stdout); /* make sure output blatted */ state = DONE; /* mark state done in either case */ if (!critical) { /* badly host if in critical code */ if (stream && !stream->lock) mail_close (stream); stream = NIL; _exit (1); /* die die die */ } }}/* Hangup interrupt */void hupint (){ alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); syslog (LOG_INFO,"Hangup user=%.80s host=%.80s",user ? user : "???", tcp_clienthost ()); state = DONE; /* mark state done in either case */ if (!critical) { /* badly host if in critical code */ if (stream && !stream->lock) mail_close (stream); stream = NIL; _exit (1); /* die die die */ }}/* Termination interrupt */void trmint (){ alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); fputs ("- Killed\015\012",stdout); syslog (LOG_INFO,"Killed user=%.80s host=%.80s",user ? user : "???", tcp_clienthost ()); fflush (stdout); /* make sure output blatted */ state = DONE; /* mark state done in either case */ if (!critical) { /* badly host if in critical code */ if (stream && !stream->lock) mail_close (stream); stream = NIL; _exit (1); /* die die die */ }}/* Parse HELO command * Accepts: pointer to command argument * Returns: new state */short c_helo (char *t,int argc,char *argv[]){ char *s,*u,*p; char tmp[TMPLEN]; if ((!(t && *t && (u = strtok (t," ")) && (p = strtok (NIL,"\015\012")))) || (strlen (p) >= TMPLEN)) { /* get user name and password */ fputs ("- Missing user or password\015\012",stdout); return DONE; } /* copy password, handle quoting */ for (s = tmp; *p; p++) *s++ = (*p == '\\') ? *++p : *p; *s = '\0'; /* tie off string */ pass = cpystr (tmp); if (!(s = strchr (u,':'))) { /* want remote mailbox? */ /* no, delimit user from possible admin */ if (s = strchr (u,'*')) *s++ = '\0'; if (server_login (user = cpystr (u),pass,s,argc,argv)) { syslog (LOG_INFO,"%sLogin user=%.80s host=%.80s",s ? "Admin " : "", user,tcp_clienthost ()); return c_fold ("INBOX"); /* local; select INBOX */ } }#ifndef DISABLE_POP_PROXY /* can't do if can't log in as anonymous */ else if (anonymous_login (argc,argv)) { *s++ = '\0'; /* separate host name from user name */ user = cpystr (s); /* note user name */ syslog (LOG_INFO,"IMAP login to host=%.80s user=%.80s host=%.80s",u,user, tcp_clienthost ()); /* initially remote INBOX */ sprintf (tmp,"{%.128s/user=%.128s}INBOX",u,user); /* disable rimap just in case */ mail_parameters (NIL,SET_RSHTIMEOUT,0); return c_fold (tmp); }#endif fputs ("- Bad login\015\012",stdout); return DONE;}/* Parse FOLD command * Accepts: pointer to command argument * Returns: new state */short c_fold (char *t){ unsigned long i,j,flags; char *s = NIL,tmp[2*TMPLEN]; NETMBX mb; if (!(t && *t)) { /* make sure there's an argument */ fputs ("- Missing mailbox name\015\012",stdout); return DONE; } myusername_full (&flags); /* get user type flags */ /* expunge old stream */ if (stream && nmsgs) mail_expunge (stream); nmsgs = 0; /* no more messages */ if (msg) fs_give ((void **) &msg);#ifndef DISABLE_POP_PROXY if (flags == MU_ANONYMOUS) { /* don't permit proxy to leave IMAP */ if (stream) { /* not first time */ if (!(stream->mailbox && (s = strchr (stream->mailbox,'}')))) fatal ("bad previous mailbox name"); strncpy (tmp,stream->mailbox,i = (++s - stream->mailbox)); if (i >= TMPLEN) fatal ("ridiculous network prefix");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -