imapext-2007

diff src/ipopd/ipop2d.c @ 0:ada5e610ab86

imap-2007e
author yuuji@gentei.org
date Mon, 14 Sep 2009 15:17:45 +0900
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/ipopd/ipop2d.c	Mon Sep 14 15:17:45 2009 +0900
     1.3 @@ -0,0 +1,711 @@
     1.4 +/* ========================================================================
     1.5 + * Copyright 1988-2008 University of Washington
     1.6 + *
     1.7 + * Licensed under the Apache License, Version 2.0 (the "License");
     1.8 + * you may not use this file except in compliance with the License.
     1.9 + * You may obtain a copy of the License at
    1.10 + *
    1.11 + *     http://www.apache.org/licenses/LICENSE-2.0
    1.12 + *
    1.13 + * 
    1.14 + * ========================================================================
    1.15 + */
    1.16 +
    1.17 +/*
    1.18 + * Program:	IPOP2D - IMAP to POP2 conversion server
    1.19 + *
    1.20 + * Author:	Mark Crispin
    1.21 + *		UW Technology
    1.22 + *		University of Washington
    1.23 + *		Seattle, WA  98195
    1.24 + *		Internet: MRC@Washington.EDU
    1.25 + *
    1.26 + * Date:	28 October 1990
    1.27 + * Last Edited:	13 February 2008
    1.28 + */
    1.29 +
    1.30 +
    1.31 +/* Parameter files */
    1.32 +
    1.33 +#include <stdio.h>
    1.34 +#include <ctype.h>
    1.35 +#include <errno.h>
    1.36 +extern int errno;		/* just in case */
    1.37 +#include <signal.h>
    1.38 +#include <time.h>
    1.39 +#include "c-client.h"
    1.40 +
    1.41 +
    1.42 +/* Autologout timer */
    1.43 +#define KODTIMEOUT 60*5
    1.44 +#define LOGINTIMEOUT 60*3
    1.45 +#define TIMEOUT 60*30
    1.46 +
    1.47 +
    1.48 +/* Size of temporary buffers */
    1.49 +#define TMPLEN 1024
    1.50 +
    1.51 +
    1.52 +/* Server states */
    1.53 +
    1.54 +#define LISN 0
    1.55 +#define AUTH 1
    1.56 +#define MBOX 2
    1.57 +#define ITEM 3
    1.58 +#define NEXT 4
    1.59 +#define DONE 5
    1.60 +
    1.61 +/* Global storage */
    1.62 +
    1.63 +char *version = "75";		/* edit number of this server */
    1.64 +short state = LISN;		/* server state */
    1.65 +short critical = NIL;		/* non-zero if in critical code */
    1.66 +MAILSTREAM *stream = NIL;	/* mailbox stream */
    1.67 +time_t idletime = 0;		/* time we went idle */
    1.68 +unsigned long nmsgs = 0;	/* number of messages */
    1.69 +unsigned long current = 1;	/* current message number */
    1.70 +unsigned long size = 0;		/* size of current message */
    1.71 +char status[MAILTMPLEN];	/* space for status string */
    1.72 +char *user = "";		/* user name */
    1.73 +char *pass = "";		/* password */
    1.74 +unsigned long *msg = NIL;	/* message translation vector */
    1.75 +char *logout = "Logout";
    1.76 +char *goodbye = "+ Sayonara\015\012";
    1.77 +
    1.78 +
    1.79 +/* Function prototypes */
    1.80 +
    1.81 +int main (int argc,char *argv[]);
    1.82 +void sayonara (int status);
    1.83 +void clkint ();
    1.84 +void kodint ();
    1.85 +void hupint ();
    1.86 +void trmint ();
    1.87 +short c_helo (char *t,int argc,char *argv[]);
    1.88 +short c_fold (char *t);
    1.89 +short c_read (char *t);
    1.90 +short c_retr (char *t);
    1.91 +short c_acks (char *t);
    1.92 +short c_ackd (char *t);
    1.93 +short c_nack (char *t);
    1.94 +
    1.95 +/* Main program */
    1.96 +
    1.97 +int main (int argc,char *argv[])
    1.98 +{
    1.99 +  char *s,*t;
   1.100 +  char cmdbuf[TMPLEN];
   1.101 +  char *pgmname = (argc && argv[0]) ?
   1.102 +    (((s = strrchr (argv[0],'/')) || (s = strrchr (argv[0],'\\'))) ?
   1.103 +     s+1 : argv[0]) : "ipop2d";
   1.104 +				/* set service name before linkage */
   1.105 +  mail_parameters (NIL,SET_SERVICENAME,(void *) "pop");
   1.106 +#include "linkage.c"
   1.107 +  if (mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL)) {
   1.108 +    goodbye = "- POP2 server disabled on this system\015\012";
   1.109 +    sayonara (1);
   1.110 +  }
   1.111 +				/* initialize server */
   1.112 +  server_init (pgmname,"pop",NIL,clkint,kodint,hupint,trmint,NIL);
   1.113 +  /* There are reports of POP2 clients which get upset if anything appears
   1.114 +   * between the "+" and the "POP2" in the greeting.
   1.115 +   */
   1.116 +  printf ("+ POP2 %s %s.%s server ready\015\012",tcp_serverhost (),
   1.117 +	  CCLIENTVERSION,version);
   1.118 +  fflush (stdout);		/* dump output buffer */
   1.119 +  state = AUTH;			/* initial server state */
   1.120 +  while (state != DONE) {	/* command processing loop */
   1.121 +    idletime = time (0);	/* get a command under timeout */
   1.122 +    alarm ((state != AUTH) ? TIMEOUT : LOGINTIMEOUT);
   1.123 +    clearerr (stdin);		/* clear stdin errors */
   1.124 +    while (!fgets (cmdbuf,TMPLEN-1,stdin)) {
   1.125 +      if (ferror (stdin) && (errno == EINTR)) clearerr (stdin);
   1.126 +      else {
   1.127 +	char *e = ferror (stdin) ?
   1.128 +	  strerror (errno) : "Unexpected client disconnect";
   1.129 +	alarm (0);		/* disable all interrupts */
   1.130 +	server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
   1.131 +	sprintf (logout = cmdbuf,"%.80s while reading line",e);
   1.132 +	state = DONE;
   1.133 +	stream = mail_close (stream);
   1.134 +	goodbye = NIL;
   1.135 +	sayonara (1);
   1.136 +      }
   1.137 +    }
   1.138 +    alarm (0);			/* make sure timeout disabled */
   1.139 +    idletime = 0;		/* no longer idle */
   1.140 +				/* find end of line */
   1.141 +    if (!strchr (cmdbuf,'\012')) {
   1.142 +      server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
   1.143 +      logout = "- Command line too long\015\012";
   1.144 +      state = DONE;
   1.145 +    }
   1.146 +    else if (!(s = strtok (cmdbuf," \015\012"))) {
   1.147 +      server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
   1.148 +      goodbye = "- Missing or null command\015\012";
   1.149 +      state = DONE;
   1.150 +    }
   1.151 +    else {			/* dispatch based on command */
   1.152 +      ucase (s);		/* canonicalize case */
   1.153 +				/* snarf argument */
   1.154 +      t = strtok (NIL,"\015\012");
   1.155 +      if ((state == AUTH) && !strcmp (s,"HELO")) state = c_helo (t,argc,argv);
   1.156 +      else if ((state == MBOX || state == ITEM) && !strcmp (s,"FOLD"))
   1.157 + 	state = c_fold (t);
   1.158 +      else if ((state == MBOX || state == ITEM) && !strcmp (s,"READ"))
   1.159 +	state = c_read (t);
   1.160 +      else if ((state == ITEM) && !strcmp (s,"RETR")) state = c_retr (t);
   1.161 +      else if ((state == NEXT) && !strcmp (s,"ACKS")) state = c_acks (t);
   1.162 +      else if ((state == NEXT) && !strcmp (s,"ACKD")) state = c_ackd (t);
   1.163 +      else if ((state == NEXT) && !strcmp (s,"NACK")) state = c_nack (t);
   1.164 +      else if ((state == AUTH || state == MBOX || state == ITEM) &&
   1.165 +	       !strcmp (s,"QUIT")) {
   1.166 +	server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
   1.167 +	state = DONE;		/* done in either case */
   1.168 +	if (t) goodbye = "- Bogus argument given to QUIT\015\012";
   1.169 +	else {			/* expunge the stream */
   1.170 +	  if (stream && nmsgs) stream = mail_close_full (stream,CL_EXPUNGE);
   1.171 +	  stream = NIL;		/* don't repeat it */
   1.172 +	}
   1.173 +      }
   1.174 +      else {			/* some other or inappropriate command */
   1.175 +	server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
   1.176 +	goodbye = "- Bogus or out of sequence command\015\012";
   1.177 +	state = DONE;
   1.178 +      }
   1.179 +    }
   1.180 +    fflush (stdout);		/* make sure output blatted */
   1.181 +  }
   1.182 +				/* clean up the stream */
   1.183 +  if (stream) mail_close (stream);
   1.184 +  sayonara (0);
   1.185 +  return 0;			/* stupid compilers */
   1.186 +}
   1.187 +
   1.188 +
   1.189 +/* Say goodbye
   1.190 + * Accepts: exit status
   1.191 + *
   1.192 + * Does not return
   1.193 + */
   1.194 +
   1.195 +void sayonara (int status)
   1.196 +{
   1.197 +  logouthook_t lgoh = (logouthook_t) mail_parameters (NIL,GET_LOGOUTHOOK,NIL);
   1.198 +  if (goodbye) {		/* have a goodbye message? */
   1.199 +    fputs (goodbye,stdout);
   1.200 +    fflush (stdout);		/* make sure blatted */
   1.201 +  }
   1.202 +  syslog (LOG_INFO,"%s user=%.80s host=%.80s",logout,
   1.203 +	  user ? (char *) user : "???",tcp_clienthost ());
   1.204 +				/* do logout hook if needed */
   1.205 +  if (lgoh) (*lgoh) (mail_parameters (NIL,GET_LOGOUTDATA,NIL));
   1.206 +  _exit (status);		/* all done */
   1.207 +}
   1.208 +
   1.209 +/* Clock interrupt
   1.210 + */
   1.211 +
   1.212 +void clkint ()
   1.213 +{
   1.214 +  alarm (0);		/* disable all interrupts */
   1.215 +  server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
   1.216 +  goodbye = "- Autologout; idle for too long\015\012";
   1.217 +  logout = "Autologout";
   1.218 +  state = DONE;			/* mark state done in either case */
   1.219 +  if (!critical) {		/* badly host if in critical code */
   1.220 +    if (stream && !stream->lock) mail_close (stream);
   1.221 +    stream = NIL;
   1.222 +    sayonara (1);		/* die die die */
   1.223 +  }
   1.224 +}
   1.225 +
   1.226 +
   1.227 +/* Kiss Of Death interrupt
   1.228 + */
   1.229 +
   1.230 +void kodint ()
   1.231 +{
   1.232 +				/* only if in command wait */
   1.233 +  if (idletime && ((time (0) - idletime) > KODTIMEOUT)) {
   1.234 +    alarm (0);		/* disable all interrupts */
   1.235 +    server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
   1.236 +    goodbye = "- Killed (lost mailbox lock)\015\012";
   1.237 +    logout = "Killed (lost mailbox lock)";
   1.238 +    state = DONE;		/* mark state done in either case */
   1.239 +    if (!critical) {		/* badly host if in critical code */
   1.240 +      if (stream && !stream->lock) mail_close (stream);
   1.241 +      stream = NIL;
   1.242 +      sayonara (1);		/* die die die */
   1.243 +    }
   1.244 +  }
   1.245 +}
   1.246 +
   1.247 +
   1.248 +/* Hangup interrupt
   1.249 + */
   1.250 +
   1.251 +void hupint ()
   1.252 +{
   1.253 +  alarm (0);		/* disable all interrupts */
   1.254 +  server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
   1.255 +  goodbye = NIL;
   1.256 +  logout = "Hangup";
   1.257 +  state = DONE;			/* mark state done in either case */
   1.258 +  if (!critical) {		/* badly host if in critical code */
   1.259 +    if (stream && !stream->lock) mail_close (stream);
   1.260 +    stream = NIL;
   1.261 +    sayonara (1);		/* die die die */
   1.262 +  }
   1.263 +}
   1.264 +
   1.265 +
   1.266 +/* Termination interrupt
   1.267 + */
   1.268 +
   1.269 +void trmint ()
   1.270 +{
   1.271 +  alarm (0);		/* disable all interrupts */
   1.272 +  server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
   1.273 +  goodbye = "- Killed (terminated)\015\012";
   1.274 +  logout = "Killed (terminated)";
   1.275 +  if (critical) state = DONE;	/* mark state done in either case */
   1.276 +  /* Make no attempt at graceful closure since a shutdown may be in
   1.277 +   * progress, and we won't have any time to do mail_close() actions.
   1.278 +   */
   1.279 +  else sayonara (1);		/* die die die */
   1.280 +}
   1.281 +
   1.282 +/* Parse HELO command
   1.283 + * Accepts: pointer to command argument
   1.284 + * Returns: new state
   1.285 + */
   1.286 +
   1.287 +short c_helo (char *t,int argc,char *argv[])
   1.288 +{
   1.289 +  char *s,*u,*p;
   1.290 +  char tmp[TMPLEN];
   1.291 +  if ((!(t && *t && (u = strtok (t," ")) && (p = strtok (NIL,"\015\012")))) ||
   1.292 +      (strlen (p) >= TMPLEN)) {	/* get user name and password */
   1.293 +    fputs ("- Missing user or password\015\012",stdout);
   1.294 +    return DONE;
   1.295 +  }
   1.296 +				/* copy password, handle quoting */
   1.297 +  for (s = tmp; *p; p++) *s++ = (*p == '\\') ? *++p : *p;
   1.298 +  *s = '\0';			/* tie off string */
   1.299 +  pass = cpystr (tmp);
   1.300 +  if (!(s = strchr (u,':'))) {	/* want remote mailbox? */
   1.301 +				/* no, delimit user from possible admin */
   1.302 +    if (s = strchr (u,'*')) *s++ = '\0';
   1.303 +    if (server_login (user = cpystr (u),pass,s,argc,argv)) {
   1.304 +      syslog (LOG_INFO,"%sLogin user=%.80s host=%.80s",s ? "Admin " : "",
   1.305 +	      user,tcp_clienthost ());
   1.306 +      return c_fold ("INBOX");	/* local; select INBOX */
   1.307 +    }
   1.308 +  }
   1.309 +#ifndef DISABLE_POP_PROXY
   1.310 +				/* can't do if can't log in as anonymous */
   1.311 +  else if (anonymous_login (argc,argv)) {
   1.312 +    *s++ = '\0';		/* separate host name from user name */
   1.313 +    user = cpystr (s);		/* note user name */
   1.314 +    syslog (LOG_INFO,"IMAP login to host=%.80s user=%.80s host=%.80s",u,user,
   1.315 +	    tcp_clienthost ());
   1.316 +				/* initially remote INBOX */
   1.317 +    sprintf (tmp,"{%.128s/user=%.128s}INBOX",u,user);
   1.318 +				/* disable rimap just in case */
   1.319 +    mail_parameters (NIL,SET_RSHTIMEOUT,0);
   1.320 +    return c_fold (tmp);
   1.321 +  }
   1.322 +#endif
   1.323 +  fputs ("- Bad login\015\012",stdout);
   1.324 +  return DONE;
   1.325 +}
   1.326 +
   1.327 +/* Parse FOLD command
   1.328 + * Accepts: pointer to command argument
   1.329 + * Returns: new state
   1.330 + */
   1.331 +
   1.332 +short c_fold (char *t)
   1.333 +{
   1.334 +  unsigned long i,j,flags;
   1.335 +  char *s = NIL,tmp[2*TMPLEN];
   1.336 +  NETMBX mb;
   1.337 +  if (!(t && *t)) {		/* make sure there's an argument */
   1.338 +    fputs ("- Missing mailbox name\015\012",stdout);
   1.339 +    return DONE;
   1.340 +  }
   1.341 +  myusername_full (&flags);	/* get user type flags */
   1.342 +				/* expunge old stream */
   1.343 +  if (stream && nmsgs) mail_expunge (stream);
   1.344 +  nmsgs = 0;			/* no more messages */
   1.345 +  if (msg) fs_give ((void **) &msg);
   1.346 +#ifndef DISABLE_POP_PROXY
   1.347 +  if (flags == MU_ANONYMOUS) {	/* don't permit proxy to leave IMAP */
   1.348 +    if (stream) {		/* not first time */
   1.349 +      if (!(stream->mailbox && (s = strchr (stream->mailbox,'}'))))
   1.350 +	fatal ("bad previous mailbox name");
   1.351 +      strncpy (tmp,stream->mailbox,i = (++s - stream->mailbox));
   1.352 +      if (i >= TMPLEN) fatal ("ridiculous network prefix");
   1.353 +      strcpy (tmp+i,t);		/* append mailbox to initial spec */
   1.354 +      t = tmp;
   1.355 +    }
   1.356 +				/* must be net name first time */
   1.357 +    else if (!mail_valid_net_parse (t,&mb)) fatal ("anonymous folder bogon");
   1.358 +  }
   1.359 +#endif
   1.360 +				/* open mailbox, note # of messages */
   1.361 +  if (j = (stream = mail_open (stream,t,NIL)) ? stream->nmsgs : 0) {
   1.362 +    sprintf (tmp,"1:%lu",j);	/* fetch fast information for all messages */
   1.363 +    mail_fetch_fast (stream,tmp,NIL);
   1.364 +    msg = (unsigned long *) fs_get ((stream->nmsgs + 1) *
   1.365 +				    sizeof (unsigned long));
   1.366 +    for (i = 1; i <= j; i++)	/* find undeleted messages, add to vector */
   1.367 +      if (!mail_elt (stream,i)->deleted) msg[++nmsgs] = i;
   1.368 +  }
   1.369 +#ifndef DISABLE_POP_PROXY
   1.370 +  if (!stream && (flags == MU_ANONYMOUS)) {
   1.371 +    fputs ("- Bad login\015\012",stdout);
   1.372 +    return DONE;
   1.373 +  }
   1.374 +#endif
   1.375 +  printf ("#%lu messages in %s\015\012",nmsgs,stream ? stream->mailbox :
   1.376 +	  "<none>");
   1.377 +  return MBOX;
   1.378 +}
   1.379 +
   1.380 +/* Parse READ command
   1.381 + * Accepts: pointer to command argument
   1.382 + * Returns: new state
   1.383 + */
   1.384 +
   1.385 +short c_read (char *t)
   1.386 +{
   1.387 +  MESSAGECACHE *elt = NIL;
   1.388 +  if (t && *t) {		/* have a message number argument? */
   1.389 +				/* validity check message number */
   1.390 +    if (((current = strtoul (t,NIL,10)) < 1) || (current > nmsgs)) {
   1.391 +      fputs ("- Invalid message number given to READ\015\012",stdout);
   1.392 +      return DONE;
   1.393 +    }
   1.394 +  }
   1.395 +  else if (current > nmsgs) {	/* at end of mailbox? */
   1.396 +    fputs ("=0 No more messages\015\012",stdout);
   1.397 +    return MBOX;
   1.398 +  }
   1.399 +				/* set size if message valid and exists */
   1.400 +  size = msg[current] ? (elt = mail_elt(stream,msg[current]))->rfc822_size : 0;
   1.401 +  if (elt) sprintf (status,"Status: %s%s\015\012",
   1.402 +		    elt->seen ? "R" : " ",elt->recent ? " " : "O");
   1.403 +  else status[0] = '\0';	/* no status */
   1.404 +  size += strlen (status);	/* update size to reflect status */
   1.405 +				/* display results */
   1.406 +  printf ("=%lu characters in message %lu\015\012",size + 2,current);
   1.407 +  return ITEM;
   1.408 +}
   1.409 +
   1.410 +
   1.411 +/* Parse RETR command
   1.412 + * Accepts: pointer to command argument
   1.413 + * Returns: new state
   1.414 + */
   1.415 +
   1.416 +short c_retr (char *t)
   1.417 +{
   1.418 +  unsigned long i,j;
   1.419 +  STRING *bs;
   1.420 +  if (t) {			/* disallow argument */
   1.421 +    fputs ("- Bogus argument given to RETR\015\012",stdout);
   1.422 +    return DONE;
   1.423 +  }
   1.424 +  if (size) {			/* message size valid? */
   1.425 +    t = mail_fetch_header (stream,msg[current],NIL,NIL,&i,FT_PEEK);
   1.426 +    if (i > 2) {		/* only if there is something */
   1.427 +      i -= 2;			/* lop off last two octets */
   1.428 +      while (i) {		/* blat the header */
   1.429 +	if (!(j = fwrite (t,sizeof (char),i,stdout))) return DONE;
   1.430 +	if (i -= j) t += j;	/* advance to incomplete data */
   1.431 +      }
   1.432 +    }
   1.433 +    fputs (status,stdout);	/* yes, output message */
   1.434 +    fputs ("\015\012",stdout);	/* delimit header from text */
   1.435 +    if (t = mail_fetch_text (stream,msg[current],NIL,&i,FT_RETURNSTRINGSTRUCT))
   1.436 +      while (i) {		/* blat the text */
   1.437 +	if (!(j = fwrite (t,sizeof (char),i,stdout))) return DONE;
   1.438 +	if (i -= j) t += j;	/* advance to incomplete data */
   1.439 +      }
   1.440 +    else for (bs = &stream->private.string; i--; )
   1.441 +      if (putc (SNX (bs),stdout) == EOF) return DONE;
   1.442 +    fputs ("\015\012",stdout);	/* trailer to coddle PCNFS' NFSMAIL */
   1.443 +  }
   1.444 +  else return DONE;		/* otherwise go away */
   1.445 +  return NEXT;
   1.446 +}
   1.447 +
   1.448 +/* Parse ACKS command
   1.449 + * Accepts: pointer to command argument
   1.450 + * Returns: new state
   1.451 + */
   1.452 +
   1.453 +short c_acks (char *t)
   1.454 +{
   1.455 +  char tmp[TMPLEN];
   1.456 +  if (t) {			/* disallow argument */
   1.457 +    fputs ("- Bogus argument given to ACKS\015\012",stdout);
   1.458 +    return DONE;
   1.459 +  }
   1.460 +				/* mark message as seen */
   1.461 +  sprintf (tmp,"%lu",msg[current++]);
   1.462 +  mail_setflag (stream,tmp,"\\Seen");
   1.463 +  return c_read (NIL);		/* end message reading transaction */
   1.464 +}
   1.465 +
   1.466 +
   1.467 +/* Parse ACKD command
   1.468 + * Accepts: pointer to command argument
   1.469 + * Returns: new state
   1.470 + */
   1.471 +
   1.472 +short c_ackd (char *t)
   1.473 +{
   1.474 +  char tmp[TMPLEN];
   1.475 +  if (t) {			/* disallow argument */
   1.476 +    fputs ("- Bogus argument given to ACKD\015\012",stdout);
   1.477 +    return DONE;
   1.478 +  }
   1.479 +				/* mark message as seen and deleted */
   1.480 +  sprintf (tmp,"%lu",msg[current]);
   1.481 +  mail_setflag (stream,tmp,"\\Seen \\Deleted");
   1.482 +  msg[current++] = 0;		/* mark message as deleted */
   1.483 +  return c_read (NIL);		/* end message reading transaction */
   1.484 +}
   1.485 +
   1.486 +
   1.487 +/* Parse NACK command
   1.488 + * Accepts: pointer to command argument
   1.489 + * Returns: new state
   1.490 + */
   1.491 +
   1.492 +short c_nack (char *t)
   1.493 +{
   1.494 +  if (t) {			/* disallow argument */
   1.495 +    fputs ("- Bogus argument given to NACK\015\012",stdout);
   1.496 +    return DONE;
   1.497 +  }
   1.498 +  return c_read (NIL);		/* end message reading transaction */
   1.499 +}
   1.500 +
   1.501 +/* Co-routines from MAIL library */
   1.502 +
   1.503 +
   1.504 +/* Message matches a search
   1.505 + * Accepts: MAIL stream
   1.506 + *	    message number
   1.507 + */
   1.508 +
   1.509 +void mm_searched (MAILSTREAM *stream,unsigned long msgno)
   1.510 +{
   1.511 +  /* Never called */
   1.512 +}
   1.513 +
   1.514 +
   1.515 +/* Message exists (i.e. there are that many messages in the mailbox)
   1.516 + * Accepts: MAIL stream
   1.517 + *	    message number
   1.518 + */
   1.519 +
   1.520 +void mm_exists (MAILSTREAM *stream,unsigned long number)
   1.521 +{
   1.522 +  /* Can't use this mechanism.  POP has no means of notifying the client of
   1.523 +     new mail during the session. */
   1.524 +}
   1.525 +
   1.526 +
   1.527 +/* Message expunged
   1.528 + * Accepts: MAIL stream
   1.529 + *	    message number
   1.530 + */
   1.531 +
   1.532 +void mm_expunged (MAILSTREAM *stream,unsigned long number)
   1.533 +{
   1.534 +  if (state != DONE) {		/* ignore if closing */
   1.535 +				/* someone else screwed us */
   1.536 +    goodbye = "- Mailbox expunged from under me!\015\012";
   1.537 +    if (stream && !stream->lock) mail_close (stream);
   1.538 +    stream = NIL;
   1.539 +    sayonara (1);
   1.540 +  }
   1.541 +}
   1.542 +
   1.543 +
   1.544 +/* Message status changed
   1.545 + * Accepts: MAIL stream
   1.546 + *	    message number
   1.547 + */
   1.548 +
   1.549 +void mm_flags (MAILSTREAM *stream,unsigned long number)
   1.550 +{
   1.551 +  /* This isn't used */
   1.552 +}
   1.553 +
   1.554 +
   1.555 +/* Mailbox found
   1.556 + * Accepts: MAIL stream
   1.557 + *	    hierarchy delimiter
   1.558 + *	    mailbox name
   1.559 + *	    mailbox attributes
   1.560 + */
   1.561 +
   1.562 +void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
   1.563 +{
   1.564 +  /* This isn't used */
   1.565 +}
   1.566 +
   1.567 +
   1.568 +/* Subscribe mailbox found
   1.569 + * Accepts: MAIL stream
   1.570 + *	    hierarchy delimiter
   1.571 + *	    mailbox name
   1.572 + *	    mailbox attributes
   1.573 + */
   1.574 +
   1.575 +void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
   1.576 +{
   1.577 +  /* This isn't used */
   1.578 +}
   1.579 +
   1.580 +
   1.581 +/* Mailbox status
   1.582 + * Accepts: MAIL stream
   1.583 + *	    mailbox name
   1.584 + *	    mailbox status
   1.585 + */
   1.586 +
   1.587 +void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
   1.588 +{
   1.589 +  /* This isn't used */
   1.590 +}
   1.591 +
   1.592 +/* Notification event
   1.593 + * Accepts: MAIL stream
   1.594 + *	    string to log
   1.595 + *	    error flag
   1.596 + */
   1.597 +
   1.598 +void mm_notify (MAILSTREAM *stream,char *string,long errflg)
   1.599 +{
   1.600 +  mm_log (string,errflg);	/* just do mm_log action */
   1.601 +}
   1.602 +
   1.603 +
   1.604 +/* Log an event for the user to see
   1.605 + * Accepts: string to log
   1.606 + *	    error flag
   1.607 + */
   1.608 +
   1.609 +void mm_log (char *string,long errflg)
   1.610 +{
   1.611 +  switch (errflg) {
   1.612 +  case NIL:			/* information message */
   1.613 +  case PARSE:			/* parse glitch */
   1.614 +    break;			/* too many of these to log */
   1.615 +  case WARN:			/* warning */
   1.616 +    syslog (LOG_DEBUG,"%s",string);
   1.617 +    break;
   1.618 +  case BYE:			/* driver broke connection */
   1.619 +    if (state != DONE) {
   1.620 +      char tmp[MAILTMPLEN];
   1.621 +      alarm (0);		/* disable all interrupts */
   1.622 +      server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
   1.623 +      sprintf (logout = tmp,"Mailbox closed (%.80s)",string);
   1.624 +      sayonara (1);
   1.625 +    }
   1.626 +    break;
   1.627 +  case ERROR:			/* error that broke command */
   1.628 +  default:			/* default should never happen */
   1.629 +    syslog (LOG_NOTICE,"%s",string);
   1.630 +    break;
   1.631 +  }
   1.632 +}
   1.633 +
   1.634 +
   1.635 +/* Log an event to debugging telemetry
   1.636 + * Accepts: string to log
   1.637 + */
   1.638 +
   1.639 +void mm_dlog (char *string)
   1.640 +{
   1.641 +  /* Not doing anything here for now */
   1.642 +}
   1.643 +
   1.644 +
   1.645 +/* Get user name and password for this host
   1.646 + * Accepts: parse of network mailbox name
   1.647 + *	    where to return user name
   1.648 + *	    where to return password
   1.649 + *	    trial count
   1.650 + */
   1.651 +
   1.652 +void mm_login (NETMBX *mb,char *username,char *password,long trial)
   1.653 +{
   1.654 +				/* set user name */
   1.655 +  strncpy (username,*mb->user ? mb->user : user,NETMAXUSER-1);
   1.656 +  strncpy (password,pass,255);	/* and password */
   1.657 +  username[NETMAXUSER] = password[255] = '\0';
   1.658 +}
   1.659 +
   1.660 +/* About to enter critical code
   1.661 + * Accepts: stream
   1.662 + */
   1.663 +
   1.664 +void mm_critical (MAILSTREAM *stream)
   1.665 +{
   1.666 +  ++critical;
   1.667 +}
   1.668 +
   1.669 +
   1.670 +/* About to exit critical code
   1.671 + * Accepts: stream
   1.672 + */
   1.673 +
   1.674 +void mm_nocritical (MAILSTREAM *stream)
   1.675 +{
   1.676 +  --critical;
   1.677 +}
   1.678 +
   1.679 +
   1.680 +/* Disk error found
   1.681 + * Accepts: stream
   1.682 + *	    system error code
   1.683 + *	    flag indicating that mailbox may be clobbered
   1.684 + * Returns: abort flag
   1.685 + */
   1.686 +
   1.687 +long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
   1.688 +{
   1.689 +  if (serious) {		/* try your damnest if clobberage likely */
   1.690 +    syslog (LOG_ALERT,
   1.691 +	    "Retrying after disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
   1.692 +	    user,tcp_clienthost (),
   1.693 +	    (stream && stream->mailbox) ? stream->mailbox : "???",
   1.694 +	    strerror (errcode));
   1.695 +    alarm (0);			/* make damn sure timeout disabled */
   1.696 +    sleep (60);			/* give it some time to clear up */
   1.697 +    return NIL;
   1.698 +  }
   1.699 +  syslog (LOG_ALERT,"Fatal disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
   1.700 +	  user,tcp_clienthost (),
   1.701 +	  (stream && stream->mailbox) ? stream->mailbox : "???",
   1.702 +	  strerror (errcode));
   1.703 +  return T;
   1.704 +}
   1.705 +
   1.706 +
   1.707 +/* Log a fatal error event
   1.708 + * Accepts: string to log
   1.709 + */
   1.710 +
   1.711 +void mm_fatal (char *string)
   1.712 +{
   1.713 +  mm_log (string,ERROR);	/* shouldn't happen normally */
   1.714 +}

UW-IMAP'd extensions by yuuji