imapext-2007

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

imap-2007e
author yuuji@gentei.org
date Mon, 14 Sep 2009 15:17:45 +0900
parents
children
rev   line source
yuuji@0 1 /* ========================================================================
yuuji@0 2 * Copyright 1988-2008 University of Washington
yuuji@0 3 *
yuuji@0 4 * Licensed under the Apache License, Version 2.0 (the "License");
yuuji@0 5 * you may not use this file except in compliance with the License.
yuuji@0 6 * You may obtain a copy of the License at
yuuji@0 7 *
yuuji@0 8 * http://www.apache.org/licenses/LICENSE-2.0
yuuji@0 9 *
yuuji@0 10 *
yuuji@0 11 * ========================================================================
yuuji@0 12 */
yuuji@0 13
yuuji@0 14 /*
yuuji@0 15 * Program: IPOP2D - IMAP to POP2 conversion server
yuuji@0 16 *
yuuji@0 17 * Author: Mark Crispin
yuuji@0 18 * UW Technology
yuuji@0 19 * University of Washington
yuuji@0 20 * Seattle, WA 98195
yuuji@0 21 * Internet: MRC@Washington.EDU
yuuji@0 22 *
yuuji@0 23 * Date: 28 October 1990
yuuji@0 24 * Last Edited: 13 February 2008
yuuji@0 25 */
yuuji@0 26
yuuji@0 27
yuuji@0 28 /* Parameter files */
yuuji@0 29
yuuji@0 30 #include <stdio.h>
yuuji@0 31 #include <ctype.h>
yuuji@0 32 #include <errno.h>
yuuji@0 33 extern int errno; /* just in case */
yuuji@0 34 #include <signal.h>
yuuji@0 35 #include <time.h>
yuuji@0 36 #include "c-client.h"
yuuji@0 37
yuuji@0 38
yuuji@0 39 /* Autologout timer */
yuuji@0 40 #define KODTIMEOUT 60*5
yuuji@0 41 #define LOGINTIMEOUT 60*3
yuuji@0 42 #define TIMEOUT 60*30
yuuji@0 43
yuuji@0 44
yuuji@0 45 /* Size of temporary buffers */
yuuji@0 46 #define TMPLEN 1024
yuuji@0 47
yuuji@0 48
yuuji@0 49 /* Server states */
yuuji@0 50
yuuji@0 51 #define LISN 0
yuuji@0 52 #define AUTH 1
yuuji@0 53 #define MBOX 2
yuuji@0 54 #define ITEM 3
yuuji@0 55 #define NEXT 4
yuuji@0 56 #define DONE 5
yuuji@0 57
yuuji@0 58 /* Global storage */
yuuji@0 59
yuuji@0 60 char *version = "75"; /* edit number of this server */
yuuji@0 61 short state = LISN; /* server state */
yuuji@0 62 short critical = NIL; /* non-zero if in critical code */
yuuji@0 63 MAILSTREAM *stream = NIL; /* mailbox stream */
yuuji@0 64 time_t idletime = 0; /* time we went idle */
yuuji@0 65 unsigned long nmsgs = 0; /* number of messages */
yuuji@0 66 unsigned long current = 1; /* current message number */
yuuji@0 67 unsigned long size = 0; /* size of current message */
yuuji@0 68 char status[MAILTMPLEN]; /* space for status string */
yuuji@0 69 char *user = ""; /* user name */
yuuji@0 70 char *pass = ""; /* password */
yuuji@0 71 unsigned long *msg = NIL; /* message translation vector */
yuuji@0 72 char *logout = "Logout";
yuuji@0 73 char *goodbye = "+ Sayonara\015\012";
yuuji@0 74
yuuji@0 75
yuuji@0 76 /* Function prototypes */
yuuji@0 77
yuuji@0 78 int main (int argc,char *argv[]);
yuuji@0 79 void sayonara (int status);
yuuji@0 80 void clkint ();
yuuji@0 81 void kodint ();
yuuji@0 82 void hupint ();
yuuji@0 83 void trmint ();
yuuji@0 84 short c_helo (char *t,int argc,char *argv[]);
yuuji@0 85 short c_fold (char *t);
yuuji@0 86 short c_read (char *t);
yuuji@0 87 short c_retr (char *t);
yuuji@0 88 short c_acks (char *t);
yuuji@0 89 short c_ackd (char *t);
yuuji@0 90 short c_nack (char *t);
yuuji@0 91
yuuji@0 92 /* Main program */
yuuji@0 93
yuuji@0 94 int main (int argc,char *argv[])
yuuji@0 95 {
yuuji@0 96 char *s,*t;
yuuji@0 97 char cmdbuf[TMPLEN];
yuuji@0 98 char *pgmname = (argc && argv[0]) ?
yuuji@0 99 (((s = strrchr (argv[0],'/')) || (s = strrchr (argv[0],'\\'))) ?
yuuji@0 100 s+1 : argv[0]) : "ipop2d";
yuuji@0 101 /* set service name before linkage */
yuuji@0 102 mail_parameters (NIL,SET_SERVICENAME,(void *) "pop");
yuuji@0 103 #include "linkage.c"
yuuji@0 104 if (mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL)) {
yuuji@0 105 goodbye = "- POP2 server disabled on this system\015\012";
yuuji@0 106 sayonara (1);
yuuji@0 107 }
yuuji@0 108 /* initialize server */
yuuji@0 109 server_init (pgmname,"pop",NIL,clkint,kodint,hupint,trmint,NIL);
yuuji@0 110 /* There are reports of POP2 clients which get upset if anything appears
yuuji@0 111 * between the "+" and the "POP2" in the greeting.
yuuji@0 112 */
yuuji@0 113 printf ("+ POP2 %s %s.%s server ready\015\012",tcp_serverhost (),
yuuji@0 114 CCLIENTVERSION,version);
yuuji@0 115 fflush (stdout); /* dump output buffer */
yuuji@0 116 state = AUTH; /* initial server state */
yuuji@0 117 while (state != DONE) { /* command processing loop */
yuuji@0 118 idletime = time (0); /* get a command under timeout */
yuuji@0 119 alarm ((state != AUTH) ? TIMEOUT : LOGINTIMEOUT);
yuuji@0 120 clearerr (stdin); /* clear stdin errors */
yuuji@0 121 while (!fgets (cmdbuf,TMPLEN-1,stdin)) {
yuuji@0 122 if (ferror (stdin) && (errno == EINTR)) clearerr (stdin);
yuuji@0 123 else {
yuuji@0 124 char *e = ferror (stdin) ?
yuuji@0 125 strerror (errno) : "Unexpected client disconnect";
yuuji@0 126 alarm (0); /* disable all interrupts */
yuuji@0 127 server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
yuuji@0 128 sprintf (logout = cmdbuf,"%.80s while reading line",e);
yuuji@0 129 state = DONE;
yuuji@0 130 stream = mail_close (stream);
yuuji@0 131 goodbye = NIL;
yuuji@0 132 sayonara (1);
yuuji@0 133 }
yuuji@0 134 }
yuuji@0 135 alarm (0); /* make sure timeout disabled */
yuuji@0 136 idletime = 0; /* no longer idle */
yuuji@0 137 /* find end of line */
yuuji@0 138 if (!strchr (cmdbuf,'\012')) {
yuuji@0 139 server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
yuuji@0 140 logout = "- Command line too long\015\012";
yuuji@0 141 state = DONE;
yuuji@0 142 }
yuuji@0 143 else if (!(s = strtok (cmdbuf," \015\012"))) {
yuuji@0 144 server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
yuuji@0 145 goodbye = "- Missing or null command\015\012";
yuuji@0 146 state = DONE;
yuuji@0 147 }
yuuji@0 148 else { /* dispatch based on command */
yuuji@0 149 ucase (s); /* canonicalize case */
yuuji@0 150 /* snarf argument */
yuuji@0 151 t = strtok (NIL,"\015\012");
yuuji@0 152 if ((state == AUTH) && !strcmp (s,"HELO")) state = c_helo (t,argc,argv);
yuuji@0 153 else if ((state == MBOX || state == ITEM) && !strcmp (s,"FOLD"))
yuuji@0 154 state = c_fold (t);
yuuji@0 155 else if ((state == MBOX || state == ITEM) && !strcmp (s,"READ"))
yuuji@0 156 state = c_read (t);
yuuji@0 157 else if ((state == ITEM) && !strcmp (s,"RETR")) state = c_retr (t);
yuuji@0 158 else if ((state == NEXT) && !strcmp (s,"ACKS")) state = c_acks (t);
yuuji@0 159 else if ((state == NEXT) && !strcmp (s,"ACKD")) state = c_ackd (t);
yuuji@0 160 else if ((state == NEXT) && !strcmp (s,"NACK")) state = c_nack (t);
yuuji@0 161 else if ((state == AUTH || state == MBOX || state == ITEM) &&
yuuji@0 162 !strcmp (s,"QUIT")) {
yuuji@0 163 server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
yuuji@0 164 state = DONE; /* done in either case */
yuuji@0 165 if (t) goodbye = "- Bogus argument given to QUIT\015\012";
yuuji@0 166 else { /* expunge the stream */
yuuji@0 167 if (stream && nmsgs) stream = mail_close_full (stream,CL_EXPUNGE);
yuuji@0 168 stream = NIL; /* don't repeat it */
yuuji@0 169 }
yuuji@0 170 }
yuuji@0 171 else { /* some other or inappropriate command */
yuuji@0 172 server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
yuuji@0 173 goodbye = "- Bogus or out of sequence command\015\012";
yuuji@0 174 state = DONE;
yuuji@0 175 }
yuuji@0 176 }
yuuji@0 177 fflush (stdout); /* make sure output blatted */
yuuji@0 178 }
yuuji@0 179 /* clean up the stream */
yuuji@0 180 if (stream) mail_close (stream);
yuuji@0 181 sayonara (0);
yuuji@0 182 return 0; /* stupid compilers */
yuuji@0 183 }
yuuji@0 184
yuuji@0 185
yuuji@0 186 /* Say goodbye
yuuji@0 187 * Accepts: exit status
yuuji@0 188 *
yuuji@0 189 * Does not return
yuuji@0 190 */
yuuji@0 191
yuuji@0 192 void sayonara (int status)
yuuji@0 193 {
yuuji@0 194 logouthook_t lgoh = (logouthook_t) mail_parameters (NIL,GET_LOGOUTHOOK,NIL);
yuuji@0 195 if (goodbye) { /* have a goodbye message? */
yuuji@0 196 fputs (goodbye,stdout);
yuuji@0 197 fflush (stdout); /* make sure blatted */
yuuji@0 198 }
yuuji@0 199 syslog (LOG_INFO,"%s user=%.80s host=%.80s",logout,
yuuji@0 200 user ? (char *) user : "???",tcp_clienthost ());
yuuji@0 201 /* do logout hook if needed */
yuuji@0 202 if (lgoh) (*lgoh) (mail_parameters (NIL,GET_LOGOUTDATA,NIL));
yuuji@0 203 _exit (status); /* all done */
yuuji@0 204 }
yuuji@0 205
yuuji@0 206 /* Clock interrupt
yuuji@0 207 */
yuuji@0 208
yuuji@0 209 void clkint ()
yuuji@0 210 {
yuuji@0 211 alarm (0); /* disable all interrupts */
yuuji@0 212 server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
yuuji@0 213 goodbye = "- Autologout; idle for too long\015\012";
yuuji@0 214 logout = "Autologout";
yuuji@0 215 state = DONE; /* mark state done in either case */
yuuji@0 216 if (!critical) { /* badly host if in critical code */
yuuji@0 217 if (stream && !stream->lock) mail_close (stream);
yuuji@0 218 stream = NIL;
yuuji@0 219 sayonara (1); /* die die die */
yuuji@0 220 }
yuuji@0 221 }
yuuji@0 222
yuuji@0 223
yuuji@0 224 /* Kiss Of Death interrupt
yuuji@0 225 */
yuuji@0 226
yuuji@0 227 void kodint ()
yuuji@0 228 {
yuuji@0 229 /* only if in command wait */
yuuji@0 230 if (idletime && ((time (0) - idletime) > KODTIMEOUT)) {
yuuji@0 231 alarm (0); /* disable all interrupts */
yuuji@0 232 server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
yuuji@0 233 goodbye = "- Killed (lost mailbox lock)\015\012";
yuuji@0 234 logout = "Killed (lost mailbox lock)";
yuuji@0 235 state = DONE; /* mark state done in either case */
yuuji@0 236 if (!critical) { /* badly host if in critical code */
yuuji@0 237 if (stream && !stream->lock) mail_close (stream);
yuuji@0 238 stream = NIL;
yuuji@0 239 sayonara (1); /* die die die */
yuuji@0 240 }
yuuji@0 241 }
yuuji@0 242 }
yuuji@0 243
yuuji@0 244
yuuji@0 245 /* Hangup interrupt
yuuji@0 246 */
yuuji@0 247
yuuji@0 248 void hupint ()
yuuji@0 249 {
yuuji@0 250 alarm (0); /* disable all interrupts */
yuuji@0 251 server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
yuuji@0 252 goodbye = NIL;
yuuji@0 253 logout = "Hangup";
yuuji@0 254 state = DONE; /* mark state done in either case */
yuuji@0 255 if (!critical) { /* badly host if in critical code */
yuuji@0 256 if (stream && !stream->lock) mail_close (stream);
yuuji@0 257 stream = NIL;
yuuji@0 258 sayonara (1); /* die die die */
yuuji@0 259 }
yuuji@0 260 }
yuuji@0 261
yuuji@0 262
yuuji@0 263 /* Termination interrupt
yuuji@0 264 */
yuuji@0 265
yuuji@0 266 void trmint ()
yuuji@0 267 {
yuuji@0 268 alarm (0); /* disable all interrupts */
yuuji@0 269 server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
yuuji@0 270 goodbye = "- Killed (terminated)\015\012";
yuuji@0 271 logout = "Killed (terminated)";
yuuji@0 272 if (critical) state = DONE; /* mark state done in either case */
yuuji@0 273 /* Make no attempt at graceful closure since a shutdown may be in
yuuji@0 274 * progress, and we won't have any time to do mail_close() actions.
yuuji@0 275 */
yuuji@0 276 else sayonara (1); /* die die die */
yuuji@0 277 }
yuuji@0 278
yuuji@0 279 /* Parse HELO command
yuuji@0 280 * Accepts: pointer to command argument
yuuji@0 281 * Returns: new state
yuuji@0 282 */
yuuji@0 283
yuuji@0 284 short c_helo (char *t,int argc,char *argv[])
yuuji@0 285 {
yuuji@0 286 char *s,*u,*p;
yuuji@0 287 char tmp[TMPLEN];
yuuji@0 288 if ((!(t && *t && (u = strtok (t," ")) && (p = strtok (NIL,"\015\012")))) ||
yuuji@0 289 (strlen (p) >= TMPLEN)) { /* get user name and password */
yuuji@0 290 fputs ("- Missing user or password\015\012",stdout);
yuuji@0 291 return DONE;
yuuji@0 292 }
yuuji@0 293 /* copy password, handle quoting */
yuuji@0 294 for (s = tmp; *p; p++) *s++ = (*p == '\\') ? *++p : *p;
yuuji@0 295 *s = '\0'; /* tie off string */
yuuji@0 296 pass = cpystr (tmp);
yuuji@0 297 if (!(s = strchr (u,':'))) { /* want remote mailbox? */
yuuji@0 298 /* no, delimit user from possible admin */
yuuji@0 299 if (s = strchr (u,'*')) *s++ = '\0';
yuuji@0 300 if (server_login (user = cpystr (u),pass,s,argc,argv)) {
yuuji@0 301 syslog (LOG_INFO,"%sLogin user=%.80s host=%.80s",s ? "Admin " : "",
yuuji@0 302 user,tcp_clienthost ());
yuuji@0 303 return c_fold ("INBOX"); /* local; select INBOX */
yuuji@0 304 }
yuuji@0 305 }
yuuji@0 306 #ifndef DISABLE_POP_PROXY
yuuji@0 307 /* can't do if can't log in as anonymous */
yuuji@0 308 else if (anonymous_login (argc,argv)) {
yuuji@0 309 *s++ = '\0'; /* separate host name from user name */
yuuji@0 310 user = cpystr (s); /* note user name */
yuuji@0 311 syslog (LOG_INFO,"IMAP login to host=%.80s user=%.80s host=%.80s",u,user,
yuuji@0 312 tcp_clienthost ());
yuuji@0 313 /* initially remote INBOX */
yuuji@0 314 sprintf (tmp,"{%.128s/user=%.128s}INBOX",u,user);
yuuji@0 315 /* disable rimap just in case */
yuuji@0 316 mail_parameters (NIL,SET_RSHTIMEOUT,0);
yuuji@0 317 return c_fold (tmp);
yuuji@0 318 }
yuuji@0 319 #endif
yuuji@0 320 fputs ("- Bad login\015\012",stdout);
yuuji@0 321 return DONE;
yuuji@0 322 }
yuuji@0 323
yuuji@0 324 /* Parse FOLD command
yuuji@0 325 * Accepts: pointer to command argument
yuuji@0 326 * Returns: new state
yuuji@0 327 */
yuuji@0 328
yuuji@0 329 short c_fold (char *t)
yuuji@0 330 {
yuuji@0 331 unsigned long i,j,flags;
yuuji@0 332 char *s = NIL,tmp[2*TMPLEN];
yuuji@0 333 NETMBX mb;
yuuji@0 334 if (!(t && *t)) { /* make sure there's an argument */
yuuji@0 335 fputs ("- Missing mailbox name\015\012",stdout);
yuuji@0 336 return DONE;
yuuji@0 337 }
yuuji@0 338 myusername_full (&flags); /* get user type flags */
yuuji@0 339 /* expunge old stream */
yuuji@0 340 if (stream && nmsgs) mail_expunge (stream);
yuuji@0 341 nmsgs = 0; /* no more messages */
yuuji@0 342 if (msg) fs_give ((void **) &msg);
yuuji@0 343 #ifndef DISABLE_POP_PROXY
yuuji@0 344 if (flags == MU_ANONYMOUS) { /* don't permit proxy to leave IMAP */
yuuji@0 345 if (stream) { /* not first time */
yuuji@0 346 if (!(stream->mailbox && (s = strchr (stream->mailbox,'}'))))
yuuji@0 347 fatal ("bad previous mailbox name");
yuuji@0 348 strncpy (tmp,stream->mailbox,i = (++s - stream->mailbox));
yuuji@0 349 if (i >= TMPLEN) fatal ("ridiculous network prefix");
yuuji@0 350 strcpy (tmp+i,t); /* append mailbox to initial spec */
yuuji@0 351 t = tmp;
yuuji@0 352 }
yuuji@0 353 /* must be net name first time */
yuuji@0 354 else if (!mail_valid_net_parse (t,&mb)) fatal ("anonymous folder bogon");
yuuji@0 355 }
yuuji@0 356 #endif
yuuji@0 357 /* open mailbox, note # of messages */
yuuji@0 358 if (j = (stream = mail_open (stream,t,NIL)) ? stream->nmsgs : 0) {
yuuji@0 359 sprintf (tmp,"1:%lu",j); /* fetch fast information for all messages */
yuuji@0 360 mail_fetch_fast (stream,tmp,NIL);
yuuji@0 361 msg = (unsigned long *) fs_get ((stream->nmsgs + 1) *
yuuji@0 362 sizeof (unsigned long));
yuuji@0 363 for (i = 1; i <= j; i++) /* find undeleted messages, add to vector */
yuuji@0 364 if (!mail_elt (stream,i)->deleted) msg[++nmsgs] = i;
yuuji@0 365 }
yuuji@0 366 #ifndef DISABLE_POP_PROXY
yuuji@0 367 if (!stream && (flags == MU_ANONYMOUS)) {
yuuji@0 368 fputs ("- Bad login\015\012",stdout);
yuuji@0 369 return DONE;
yuuji@0 370 }
yuuji@0 371 #endif
yuuji@0 372 printf ("#%lu messages in %s\015\012",nmsgs,stream ? stream->mailbox :
yuuji@0 373 "<none>");
yuuji@0 374 return MBOX;
yuuji@0 375 }
yuuji@0 376
yuuji@0 377 /* Parse READ command
yuuji@0 378 * Accepts: pointer to command argument
yuuji@0 379 * Returns: new state
yuuji@0 380 */
yuuji@0 381
yuuji@0 382 short c_read (char *t)
yuuji@0 383 {
yuuji@0 384 MESSAGECACHE *elt = NIL;
yuuji@0 385 if (t && *t) { /* have a message number argument? */
yuuji@0 386 /* validity check message number */
yuuji@0 387 if (((current = strtoul (t,NIL,10)) < 1) || (current > nmsgs)) {
yuuji@0 388 fputs ("- Invalid message number given to READ\015\012",stdout);
yuuji@0 389 return DONE;
yuuji@0 390 }
yuuji@0 391 }
yuuji@0 392 else if (current > nmsgs) { /* at end of mailbox? */
yuuji@0 393 fputs ("=0 No more messages\015\012",stdout);
yuuji@0 394 return MBOX;
yuuji@0 395 }
yuuji@0 396 /* set size if message valid and exists */
yuuji@0 397 size = msg[current] ? (elt = mail_elt(stream,msg[current]))->rfc822_size : 0;
yuuji@0 398 if (elt) sprintf (status,"Status: %s%s\015\012",
yuuji@0 399 elt->seen ? "R" : " ",elt->recent ? " " : "O");
yuuji@0 400 else status[0] = '\0'; /* no status */
yuuji@0 401 size += strlen (status); /* update size to reflect status */
yuuji@0 402 /* display results */
yuuji@0 403 printf ("=%lu characters in message %lu\015\012",size + 2,current);
yuuji@0 404 return ITEM;
yuuji@0 405 }
yuuji@0 406
yuuji@0 407
yuuji@0 408 /* Parse RETR command
yuuji@0 409 * Accepts: pointer to command argument
yuuji@0 410 * Returns: new state
yuuji@0 411 */
yuuji@0 412
yuuji@0 413 short c_retr (char *t)
yuuji@0 414 {
yuuji@0 415 unsigned long i,j;
yuuji@0 416 STRING *bs;
yuuji@0 417 if (t) { /* disallow argument */
yuuji@0 418 fputs ("- Bogus argument given to RETR\015\012",stdout);
yuuji@0 419 return DONE;
yuuji@0 420 }
yuuji@0 421 if (size) { /* message size valid? */
yuuji@0 422 t = mail_fetch_header (stream,msg[current],NIL,NIL,&i,FT_PEEK);
yuuji@0 423 if (i > 2) { /* only if there is something */
yuuji@0 424 i -= 2; /* lop off last two octets */
yuuji@0 425 while (i) { /* blat the header */
yuuji@0 426 if (!(j = fwrite (t,sizeof (char),i,stdout))) return DONE;
yuuji@0 427 if (i -= j) t += j; /* advance to incomplete data */
yuuji@0 428 }
yuuji@0 429 }
yuuji@0 430 fputs (status,stdout); /* yes, output message */
yuuji@0 431 fputs ("\015\012",stdout); /* delimit header from text */
yuuji@0 432 if (t = mail_fetch_text (stream,msg[current],NIL,&i,FT_RETURNSTRINGSTRUCT))
yuuji@0 433 while (i) { /* blat the text */
yuuji@0 434 if (!(j = fwrite (t,sizeof (char),i,stdout))) return DONE;
yuuji@0 435 if (i -= j) t += j; /* advance to incomplete data */
yuuji@0 436 }
yuuji@0 437 else for (bs = &stream->private.string; i--; )
yuuji@0 438 if (putc (SNX (bs),stdout) == EOF) return DONE;
yuuji@0 439 fputs ("\015\012",stdout); /* trailer to coddle PCNFS' NFSMAIL */
yuuji@0 440 }
yuuji@0 441 else return DONE; /* otherwise go away */
yuuji@0 442 return NEXT;
yuuji@0 443 }
yuuji@0 444
yuuji@0 445 /* Parse ACKS command
yuuji@0 446 * Accepts: pointer to command argument
yuuji@0 447 * Returns: new state
yuuji@0 448 */
yuuji@0 449
yuuji@0 450 short c_acks (char *t)
yuuji@0 451 {
yuuji@0 452 char tmp[TMPLEN];
yuuji@0 453 if (t) { /* disallow argument */
yuuji@0 454 fputs ("- Bogus argument given to ACKS\015\012",stdout);
yuuji@0 455 return DONE;
yuuji@0 456 }
yuuji@0 457 /* mark message as seen */
yuuji@0 458 sprintf (tmp,"%lu",msg[current++]);
yuuji@0 459 mail_setflag (stream,tmp,"\\Seen");
yuuji@0 460 return c_read (NIL); /* end message reading transaction */
yuuji@0 461 }
yuuji@0 462
yuuji@0 463
yuuji@0 464 /* Parse ACKD command
yuuji@0 465 * Accepts: pointer to command argument
yuuji@0 466 * Returns: new state
yuuji@0 467 */
yuuji@0 468
yuuji@0 469 short c_ackd (char *t)
yuuji@0 470 {
yuuji@0 471 char tmp[TMPLEN];
yuuji@0 472 if (t) { /* disallow argument */
yuuji@0 473 fputs ("- Bogus argument given to ACKD\015\012",stdout);
yuuji@0 474 return DONE;
yuuji@0 475 }
yuuji@0 476 /* mark message as seen and deleted */
yuuji@0 477 sprintf (tmp,"%lu",msg[current]);
yuuji@0 478 mail_setflag (stream,tmp,"\\Seen \\Deleted");
yuuji@0 479 msg[current++] = 0; /* mark message as deleted */
yuuji@0 480 return c_read (NIL); /* end message reading transaction */
yuuji@0 481 }
yuuji@0 482
yuuji@0 483
yuuji@0 484 /* Parse NACK command
yuuji@0 485 * Accepts: pointer to command argument
yuuji@0 486 * Returns: new state
yuuji@0 487 */
yuuji@0 488
yuuji@0 489 short c_nack (char *t)
yuuji@0 490 {
yuuji@0 491 if (t) { /* disallow argument */
yuuji@0 492 fputs ("- Bogus argument given to NACK\015\012",stdout);
yuuji@0 493 return DONE;
yuuji@0 494 }
yuuji@0 495 return c_read (NIL); /* end message reading transaction */
yuuji@0 496 }
yuuji@0 497
yuuji@0 498 /* Co-routines from MAIL library */
yuuji@0 499
yuuji@0 500
yuuji@0 501 /* Message matches a search
yuuji@0 502 * Accepts: MAIL stream
yuuji@0 503 * message number
yuuji@0 504 */
yuuji@0 505
yuuji@0 506 void mm_searched (MAILSTREAM *stream,unsigned long msgno)
yuuji@0 507 {
yuuji@0 508 /* Never called */
yuuji@0 509 }
yuuji@0 510
yuuji@0 511
yuuji@0 512 /* Message exists (i.e. there are that many messages in the mailbox)
yuuji@0 513 * Accepts: MAIL stream
yuuji@0 514 * message number
yuuji@0 515 */
yuuji@0 516
yuuji@0 517 void mm_exists (MAILSTREAM *stream,unsigned long number)
yuuji@0 518 {
yuuji@0 519 /* Can't use this mechanism. POP has no means of notifying the client of
yuuji@0 520 new mail during the session. */
yuuji@0 521 }
yuuji@0 522
yuuji@0 523
yuuji@0 524 /* Message expunged
yuuji@0 525 * Accepts: MAIL stream
yuuji@0 526 * message number
yuuji@0 527 */
yuuji@0 528
yuuji@0 529 void mm_expunged (MAILSTREAM *stream,unsigned long number)
yuuji@0 530 {
yuuji@0 531 if (state != DONE) { /* ignore if closing */
yuuji@0 532 /* someone else screwed us */
yuuji@0 533 goodbye = "- Mailbox expunged from under me!\015\012";
yuuji@0 534 if (stream && !stream->lock) mail_close (stream);
yuuji@0 535 stream = NIL;
yuuji@0 536 sayonara (1);
yuuji@0 537 }
yuuji@0 538 }
yuuji@0 539
yuuji@0 540
yuuji@0 541 /* Message status changed
yuuji@0 542 * Accepts: MAIL stream
yuuji@0 543 * message number
yuuji@0 544 */
yuuji@0 545
yuuji@0 546 void mm_flags (MAILSTREAM *stream,unsigned long number)
yuuji@0 547 {
yuuji@0 548 /* This isn't used */
yuuji@0 549 }
yuuji@0 550
yuuji@0 551
yuuji@0 552 /* Mailbox found
yuuji@0 553 * Accepts: MAIL stream
yuuji@0 554 * hierarchy delimiter
yuuji@0 555 * mailbox name
yuuji@0 556 * mailbox attributes
yuuji@0 557 */
yuuji@0 558
yuuji@0 559 void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
yuuji@0 560 {
yuuji@0 561 /* This isn't used */
yuuji@0 562 }
yuuji@0 563
yuuji@0 564
yuuji@0 565 /* Subscribe mailbox found
yuuji@0 566 * Accepts: MAIL stream
yuuji@0 567 * hierarchy delimiter
yuuji@0 568 * mailbox name
yuuji@0 569 * mailbox attributes
yuuji@0 570 */
yuuji@0 571
yuuji@0 572 void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
yuuji@0 573 {
yuuji@0 574 /* This isn't used */
yuuji@0 575 }
yuuji@0 576
yuuji@0 577
yuuji@0 578 /* Mailbox status
yuuji@0 579 * Accepts: MAIL stream
yuuji@0 580 * mailbox name
yuuji@0 581 * mailbox status
yuuji@0 582 */
yuuji@0 583
yuuji@0 584 void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
yuuji@0 585 {
yuuji@0 586 /* This isn't used */
yuuji@0 587 }
yuuji@0 588
yuuji@0 589 /* Notification event
yuuji@0 590 * Accepts: MAIL stream
yuuji@0 591 * string to log
yuuji@0 592 * error flag
yuuji@0 593 */
yuuji@0 594
yuuji@0 595 void mm_notify (MAILSTREAM *stream,char *string,long errflg)
yuuji@0 596 {
yuuji@0 597 mm_log (string,errflg); /* just do mm_log action */
yuuji@0 598 }
yuuji@0 599
yuuji@0 600
yuuji@0 601 /* Log an event for the user to see
yuuji@0 602 * Accepts: string to log
yuuji@0 603 * error flag
yuuji@0 604 */
yuuji@0 605
yuuji@0 606 void mm_log (char *string,long errflg)
yuuji@0 607 {
yuuji@0 608 switch (errflg) {
yuuji@0 609 case NIL: /* information message */
yuuji@0 610 case PARSE: /* parse glitch */
yuuji@0 611 break; /* too many of these to log */
yuuji@0 612 case WARN: /* warning */
yuuji@0 613 syslog (LOG_DEBUG,"%s",string);
yuuji@0 614 break;
yuuji@0 615 case BYE: /* driver broke connection */
yuuji@0 616 if (state != DONE) {
yuuji@0 617 char tmp[MAILTMPLEN];
yuuji@0 618 alarm (0); /* disable all interrupts */
yuuji@0 619 server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
yuuji@0 620 sprintf (logout = tmp,"Mailbox closed (%.80s)",string);
yuuji@0 621 sayonara (1);
yuuji@0 622 }
yuuji@0 623 break;
yuuji@0 624 case ERROR: /* error that broke command */
yuuji@0 625 default: /* default should never happen */
yuuji@0 626 syslog (LOG_NOTICE,"%s",string);
yuuji@0 627 break;
yuuji@0 628 }
yuuji@0 629 }
yuuji@0 630
yuuji@0 631
yuuji@0 632 /* Log an event to debugging telemetry
yuuji@0 633 * Accepts: string to log
yuuji@0 634 */
yuuji@0 635
yuuji@0 636 void mm_dlog (char *string)
yuuji@0 637 {
yuuji@0 638 /* Not doing anything here for now */
yuuji@0 639 }
yuuji@0 640
yuuji@0 641
yuuji@0 642 /* Get user name and password for this host
yuuji@0 643 * Accepts: parse of network mailbox name
yuuji@0 644 * where to return user name
yuuji@0 645 * where to return password
yuuji@0 646 * trial count
yuuji@0 647 */
yuuji@0 648
yuuji@0 649 void mm_login (NETMBX *mb,char *username,char *password,long trial)
yuuji@0 650 {
yuuji@0 651 /* set user name */
yuuji@0 652 strncpy (username,*mb->user ? mb->user : user,NETMAXUSER-1);
yuuji@0 653 strncpy (password,pass,255); /* and password */
yuuji@0 654 username[NETMAXUSER] = password[255] = '\0';
yuuji@0 655 }
yuuji@0 656
yuuji@0 657 /* About to enter critical code
yuuji@0 658 * Accepts: stream
yuuji@0 659 */
yuuji@0 660
yuuji@0 661 void mm_critical (MAILSTREAM *stream)
yuuji@0 662 {
yuuji@0 663 ++critical;
yuuji@0 664 }
yuuji@0 665
yuuji@0 666
yuuji@0 667 /* About to exit critical code
yuuji@0 668 * Accepts: stream
yuuji@0 669 */
yuuji@0 670
yuuji@0 671 void mm_nocritical (MAILSTREAM *stream)
yuuji@0 672 {
yuuji@0 673 --critical;
yuuji@0 674 }
yuuji@0 675
yuuji@0 676
yuuji@0 677 /* Disk error found
yuuji@0 678 * Accepts: stream
yuuji@0 679 * system error code
yuuji@0 680 * flag indicating that mailbox may be clobbered
yuuji@0 681 * Returns: abort flag
yuuji@0 682 */
yuuji@0 683
yuuji@0 684 long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
yuuji@0 685 {
yuuji@0 686 if (serious) { /* try your damnest if clobberage likely */
yuuji@0 687 syslog (LOG_ALERT,
yuuji@0 688 "Retrying after disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
yuuji@0 689 user,tcp_clienthost (),
yuuji@0 690 (stream && stream->mailbox) ? stream->mailbox : "???",
yuuji@0 691 strerror (errcode));
yuuji@0 692 alarm (0); /* make damn sure timeout disabled */
yuuji@0 693 sleep (60); /* give it some time to clear up */
yuuji@0 694 return NIL;
yuuji@0 695 }
yuuji@0 696 syslog (LOG_ALERT,"Fatal disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
yuuji@0 697 user,tcp_clienthost (),
yuuji@0 698 (stream && stream->mailbox) ? stream->mailbox : "???",
yuuji@0 699 strerror (errcode));
yuuji@0 700 return T;
yuuji@0 701 }
yuuji@0 702
yuuji@0 703
yuuji@0 704 /* Log a fatal error event
yuuji@0 705 * Accepts: string to log
yuuji@0 706 */
yuuji@0 707
yuuji@0 708 void mm_fatal (char *string)
yuuji@0 709 {
yuuji@0 710 mm_log (string,ERROR); /* shouldn't happen normally */
yuuji@0 711 }

UW-IMAP'd extensions by yuuji