home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / imap-3.0 / ANSI / ipopd / ipop2d.c next >
Encoding:
C/C++ Source or Header  |  1993-06-10  |  11.4 KB  |  454 lines

  1. /*
  2.  * Program:    IPOP2D - IMAP2 to POP2 conversion server
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    28 October 1990
  13.  * Last Edited:    10 June 1993
  14.  *
  15.  * Copyright 1993 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35.  
  36.  
  37. /* Parameter files */
  38.  
  39. #include "mail.h"
  40. #include "osdep.h"
  41. #include <stdio.h>
  42. #include <ctype.h>
  43. #include <pwd.h>
  44. #include "misc.h"
  45.  
  46.  
  47. /* Size of temporary buffers */
  48. #define TMPLEN 1024
  49.  
  50.  
  51. /* Server states */
  52.  
  53. #define LISN 0
  54. #define AUTH 1
  55. #define MBOX 2
  56. #define ITEM 3
  57. #define NEXT 4
  58. #define DONE 5
  59.  
  60. /* Global storage */
  61.  
  62. char *version = "2.2(8)";    /* server version */
  63. short state = LISN;        /* server state */
  64. MAILSTREAM *stream = NIL;    /* mailbox stream */
  65. long nmsgs = 0;            /* number of messages */
  66. long current = 0;        /* current message number */
  67. long size = 0;            /* size of current message */
  68. char *user = "";        /* user name */
  69. char *pass = "";        /* password */
  70. short *msg = NIL;        /* message translation vector */
  71.  
  72.  
  73. /* Drivers we use */
  74.  
  75. extern DRIVER imapdriver,tenexdriver,mhdriver,mboxdriver,bezerkdriver;
  76.  
  77.  
  78. /* Function prototypes */
  79.  
  80. void main (int argc,char *argv[]);
  81. short c_helo (char *t,int argc,char *argv[]);
  82. short c_fold (char *t);
  83. short c_read (char *t);
  84. short c_retr (char *t);
  85. short c_acks (char *t);
  86. short c_ackd (char *t);
  87. short c_nack (char *t);
  88.  
  89. extern char *crypt (char *key,char *salt);
  90.  
  91. /* Main program */
  92.  
  93. void main (int argc,char *argv[])
  94. {
  95.   char *s,*t;
  96.   char cmdbuf[TMPLEN];
  97.   mail_link (&imapdriver);    /* install the IMAP driver */
  98.   mail_link (&tenexdriver);    /* install the Tenex mail driver */
  99.   mail_link (&mhdriver);    /* install the mh mail driver */
  100.   mail_link (&mboxdriver);    /* install the mbox mail driver */
  101.   mail_link (&bezerkdriver);    /* install the Berkeley mail driver */
  102.   printf ("+ POP2 %s w/IMAP2 client (Comments to MRC@CAC.Washington.EDU)\015\012",
  103.       version);
  104.   fflush (stdout);        /* dump output buffer */
  105.   state = AUTH;            /* initial server state */
  106.                 /* command processing loop */
  107.   while ((state != DONE) && fgets (cmdbuf,TMPLEN-1,stdin)) {
  108.                 /* find end of line */
  109.     if (!strchr (cmdbuf,'\012')) {
  110.       puts ("- Command line too long\015");
  111.       state = DONE;
  112.     }
  113.     else if (!(s = strtok (cmdbuf," \015\012"))) {
  114.       puts ("- Missing or null command\015");
  115.       state = DONE;
  116.     }
  117.     else {            /* dispatch based on command */
  118.       ucase (s);        /* canonicalize case */
  119.                 /* snarf argument */
  120.       t = strtok (NIL,"\015\012");
  121.       if ((state == AUTH) && !strcmp (s,"HELO")) state = c_helo (t,argc,argv);
  122.       else if ((state == MBOX || state == ITEM) && !strcmp (s,"FOLD"))
  123.     state = c_fold (t);
  124.       else if ((state == MBOX || state == ITEM) && !strcmp (s,"READ"))
  125.     state = c_read (t);
  126.       else if ((state == ITEM) && !strcmp (s,"RETR")) state = c_retr (t);
  127.       else if ((state == NEXT) && !strcmp (s,"ACKS")) state = c_acks (t);
  128.       else if ((state == NEXT) && !strcmp (s,"ACKD")) state = c_ackd (t);
  129.       else if ((state == NEXT) && !strcmp (s,"NACK")) state = c_nack (t);
  130.       else if ((state == AUTH || state == MBOX || state == ITEM) &&
  131.            !strcmp (s,"QUIT")) {
  132.     if (t) puts ("- Bogus argument given to QUIT\015");
  133.     else {            /* valid sayonara */
  134.                 /* expunge the stream */
  135.       if (stream && nmsgs) mail_expunge (stream);
  136.       puts ("+ Sayonara\015");/* acknowledge the command */
  137.     }
  138.     state = DONE;        /* done in either case */
  139.       }
  140.       else {            /* some other or inappropriate command */
  141.     printf ("- Bogus or out of sequence command - %s\015\012",s);
  142.     state = DONE;
  143.       }
  144.     }
  145.     fflush (stdout);        /* make sure output blatted */
  146.   }
  147.   mail_close (stream);        /* clean up the stream */
  148.   exit (0);            /* all done */
  149. }
  150.  
  151. /* Parse HELO command
  152.  * Accepts: pointer to command argument
  153.  * Returns: new state
  154.  */
  155.  
  156. short c_helo (char *t,int argc,char *argv[])
  157. {
  158.   char *s,*u,*p;
  159.   char tmp[TMPLEN];
  160.   struct passwd *pwd = getpwnam ("nobody");
  161.   if (!(t && *t && (u = strtok (t," ")) && (p = strtok (NIL,"\015\012")))) {
  162.     puts ("- Missing user or password\015");
  163.     return DONE;
  164.   }
  165.                 /* copy password, handle quoting */
  166.   for (s = tmp; *p; p++) *s++ = (*p == '\\') ? *++p : *p;
  167.   *s = '\0';            /* tie off string */
  168.   pass = cpystr (tmp);
  169.   if (s = strchr (u,':')) {    /* want remote mailbox? */
  170.     *s++ = '\0';        /* separate host name from user name */
  171.     user = cpystr (s);        /* note user name */
  172.     sprintf (tmp,"{%s}INBOX",u);/* initially remote INBOX */
  173.     if (pwd) {            /* try to become someone harmless */
  174.       setgid (pwd->pw_gid);    /* set group ID */
  175.       setuid (pwd->pw_uid);    /* and user ID */
  176.     }
  177.   }
  178.   else if (server_login (user = cpystr (u),pass,NIL,argc,argv))
  179.     strcpy (tmp,"INBOX");    /* local; attempt login, select INBOX */
  180.   else {
  181.     puts ("- Bad login\015");
  182.     return DONE;
  183.   }
  184.   return c_fold (tmp);        /* open default mailbox */
  185. }
  186.  
  187. /* Parse FOLD command
  188.  * Accepts: pointer to command argument
  189.  * Returns: new state
  190.  */
  191.  
  192. short c_fold (char *t)
  193. {
  194.   long i,j;
  195.   char tmp[TMPLEN];
  196.   if (!(t && *t)) {        /* make sure there's an argument */
  197.     puts ("- Missing mailbox name\015");
  198.     return DONE;
  199.   }
  200.                 /* expunge old stream */
  201.   if (stream && nmsgs) mail_expunge (stream);
  202.   nmsgs = 0;            /* no more messages */
  203.   if (msg) fs_give ((void **) &msg);
  204.                 /* open mailbox, note # of messages */
  205.   if (j = (stream = mail_open (stream,t,NIL)) ? stream->nmsgs : 0) {
  206.     sprintf (tmp,"1:%d",j);    /* fetch fast information for all messages */
  207.     mail_fetchfast (stream,tmp);
  208.     msg = (short *) fs_get ((stream->nmsgs + 1) * sizeof (short));
  209.     for (i = 1; i <= j; i++)    /* find undeleted messages, add to vector */
  210.       if (!mail_elt (stream,i)->deleted) msg[++nmsgs] = i;
  211.   }
  212.   printf ("#%d messages in %s\015\012",nmsgs,stream ? stream->mailbox :
  213.       "<none>");
  214.   return MBOX;
  215. }
  216.  
  217. /* Parse READ command
  218.  * Accepts: pointer to command argument
  219.  * Returns: new state
  220.  */
  221.  
  222. short c_read (char *t)
  223. {
  224.   MESSAGECACHE *elt = NIL;;
  225.                 /* set message number if possible */
  226.   if (t && *t) current = atoi (t);
  227.                 /* validity check message number */
  228.   if (current < 1 || current > nmsgs) current = 0;
  229.                 /* set size if message valid and exists */
  230.   size = msg[current] ? mail_elt (stream,msg[current])->rfc822_size : 0;
  231.                 /* display results */
  232.   printf ("=%d characters in message %d\015\012",size,current);
  233.   return ITEM;
  234. }
  235.  
  236.  
  237. /* Parse RETR command
  238.  * Accepts: pointer to command argument
  239.  * Returns: new state
  240.  */
  241.  
  242. short c_retr (char *t)
  243. {
  244.   if (t) {            /* disallow argument */
  245.     puts ("- Bogus argument given to RETR\015");
  246.     return DONE;
  247.   }
  248.   if (size) {            /* message size valid? */
  249.                 /* yes, output messages */
  250.     fputs (mail_fetchheader (stream,msg[current]),stdout);
  251.     fputs (mail_fetchtext (stream,msg[current]),stdout);
  252.   }
  253.   else return DONE;        /* otherwise go away */
  254.   return NEXT;
  255. }
  256.  
  257. /* Parse ACKS command
  258.  * Accepts: pointer to command argument
  259.  * Returns: new state
  260.  */
  261.  
  262. short c_acks (char *t)
  263. {
  264.   char tmp[TMPLEN];
  265.   if (t) {            /* disallow argument */
  266.     puts ("- Bogus argument given to ACKS\015");
  267.     return DONE;
  268.   }
  269.                 /* mark message as seen */
  270.   sprintf (tmp,"%d",msg[current++]);
  271.   mail_setflag (stream,tmp,"\\Seen");
  272.   return c_read (NIL);        /* end message reading transaction */
  273. }
  274.  
  275.  
  276. /* Parse ACKD command
  277.  * Accepts: pointer to command argument
  278.  * Returns: new state
  279.  */
  280.  
  281. short c_ackd (char *t)
  282. {
  283.   char tmp[TMPLEN];
  284.   if (t) {            /* disallow argument */
  285.     puts ("- Bogus argument given to ACKD\015");
  286.     return DONE;
  287.   }
  288.                 /* mark message as seen and deleted */
  289.   sprintf (tmp,"%d",msg[current]);
  290.   mail_setflag (stream,tmp,"\\Seen \\Deleted");
  291.   msg[current++] = 0;        /* mark message as deleted */
  292.   return c_read (NIL);        /* end message reading transaction */
  293. }
  294.  
  295.  
  296. /* Parse NACK command
  297.  * Accepts: pointer to command argument
  298.  * Returns: new state
  299.  */
  300.  
  301. short c_nack (char *t)
  302. {
  303.   if (t) {            /* disallow argument */
  304.     puts ("- Bogus argument given to NACK\015");
  305.     return DONE;
  306.   }
  307.   return c_read (NIL);        /* end message reading transaction */
  308. }
  309.  
  310. /* Co-routines from MAIL library */
  311.  
  312.  
  313. /* Message matches a search
  314.  * Accepts: IMAP2 stream
  315.  *        message number
  316.  */
  317.  
  318. void mm_searched (MAILSTREAM *stream,long msgno)
  319. {
  320.   /* Never called */
  321. }
  322.  
  323.  
  324. /* Message exists (i.e. there are that many messages in the mailbox)
  325.  * Accepts: IMAP2 stream
  326.  *        message number
  327.  */
  328.  
  329. void mm_exists (MAILSTREAM *stream,long number)
  330. {
  331.   /* Can't use this mechanism.  POP has no means of notifying the client of
  332.      new mail during the session. */
  333. }
  334.  
  335.  
  336. /* Message expunged
  337.  * Accepts: IMAP2 stream
  338.  *        message number
  339.  */
  340.  
  341. void mm_expunged (MAILSTREAM *stream,long number)
  342. {
  343.   /* This isn't used */
  344. }
  345.  
  346.  
  347. /* Mailbox found
  348.  * Accepts: Mailbox name
  349.  */
  350.  
  351. void mm_mailbox (char *string)
  352. {
  353.   /* This isn't used */
  354. }
  355.  
  356.  
  357. /* BBoard found
  358.  * Accepts: BBoard name
  359.  */
  360.  
  361. void mm_bboard (char *string)
  362. {
  363.   /* This isn't used */
  364. }
  365.  
  366. /* Notification event
  367.  * Accepts: IMAP2 stream
  368.  *        string to log
  369.  *        error flag
  370.  */
  371.  
  372. void mm_notify (MAILSTREAM *stream,char *string,long errflg)
  373. {
  374.   mm_log (string,errflg);    /* just do mm_log action */
  375. }
  376.  
  377.  
  378. /* Log an event for the user to see
  379.  * Accepts: string to log
  380.  *        error flag
  381.  */
  382.  
  383. void mm_log (char *string,long errflg)
  384. {
  385.   /* Not doing anything here for now */
  386. }
  387.  
  388.  
  389. /* Log an event to debugging telemetry
  390.  * Accepts: string to log
  391.  */
  392.  
  393. void mm_dlog (char *string)
  394. {
  395.   /* Not doing anything here for now */
  396. }
  397.  
  398.  
  399. /* Get user name and password for this host
  400.  * Accepts: host name
  401.  *        where to return user name
  402.  *        where to return password
  403.  *        trial count
  404.  */
  405.  
  406. void mm_login (char *host,char *username,char *password,long trial)
  407. {
  408.   strcpy (username,user);    /* set user name */
  409.   strcpy (password,pass);    /* and password */
  410. }
  411.  
  412. /* About to enter critical code
  413.  * Accepts: stream
  414.  */
  415.  
  416. void mm_critical (MAILSTREAM *stream)
  417. {
  418.   /* Not doing anything here for now */
  419. }
  420.  
  421.  
  422. /* About to exit critical code
  423.  * Accepts: stream
  424.  */
  425.  
  426. void mm_nocritical (MAILSTREAM *stream)
  427. {
  428.   /* Not doing anything here for now */
  429. }
  430.  
  431.  
  432. /* Disk error found
  433.  * Accepts: stream
  434.  *        system error code
  435.  *        flag indicating that mailbox may be clobbered
  436.  * Returns: abort flag
  437.  */
  438.  
  439. long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
  440. {
  441.   sleep (5);            /* can't do much better than this! */
  442.   return NIL;
  443. }
  444.  
  445.  
  446. /* Log a fatal error event
  447.  * Accepts: string to log
  448.  */
  449.  
  450. void mm_fatal (char *string)
  451. {
  452.   mm_log (string,ERROR);    /* shouldn't happen normally */
  453. }
  454.