imapext-2007

diff src/mtest/mtest.c @ 0:ada5e610ab86

imap-2007e
author yuuji@gentei.org
date Mon, 14 Sep 2009 15:17:45 +0900
parents
children cd53ed0e4bb2
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/mtest/mtest.c	Mon Sep 14 15:17:45 2009 +0900
     1.3 @@ -0,0 +1,813 @@
     1.4 +/* ========================================================================
     1.5 + * Copyright 1988-2007 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:	Mail library test program
    1.19 + *
    1.20 + * Author:	Mark Crispin
    1.21 + *		Networks and Distributed Computing
    1.22 + *		Computing & Communications
    1.23 + *		University of Washington
    1.24 + *		Administration Building, AG-44
    1.25 + *		Seattle, WA  98195
    1.26 + *		Internet: MRC@CAC.Washington.EDU
    1.27 + *
    1.28 + * Date:	8 July 1988
    1.29 + * Last Edited:	5 November 2007
    1.30 + *
    1.31 + * This original version of this file is
    1.32 + * Copyright 1988 Stanford University
    1.33 + * and was developed in the Symbolic Systems Resources Group of the Knowledge
    1.34 + * Systems Laboratory at Stanford University in 1987-88, and was funded by the
    1.35 + * Biomedical Research Technology Program of the NationalInstitutes of Health
    1.36 + * under grant number RR-00785.
    1.37 + */
    1.38 +
    1.39 +#include <stdio.h>
    1.40 +#include <ctype.h>
    1.41 +#include <signal.h>
    1.42 +#include "c-client.h"
    1.43 +#include "imap4r1.h"
    1.44 +
    1.45 +/* Excellent reasons to hate ifdefs, and why my real code never uses them */
    1.46 +
    1.47 +#ifndef unix
    1.48 +# define unix 0
    1.49 +#endif
    1.50 +
    1.51 +#if unix
    1.52 +# define UNIXLIKE 1
    1.53 +# define MACOS 0
    1.54 +# include <pwd.h>
    1.55 +#else
    1.56 +# define UNIXLIKE 0
    1.57 +# ifdef noErr
    1.58 +#  define MACOS 1
    1.59 +#  include <Memory.h>
    1.60 +# else
    1.61 +#  define MACOS 0
    1.62 +# endif
    1.63 +#endif
    1.64 +
    1.65 +char *curhst = NIL;		/* currently connected host */
    1.66 +char *curusr = NIL;		/* current login user */
    1.67 +char personalname[MAILTMPLEN];	/* user's personal name */
    1.68 +
    1.69 +static char *hostlist[] = {	/* SMTP server host list */
    1.70 +  "mailhost",
    1.71 +  "localhost",
    1.72 +  NIL
    1.73 +};
    1.74 +
    1.75 +static char *newslist[] = {	/* Netnews server host list */
    1.76 +  "news",
    1.77 +  NIL
    1.78 +};
    1.79 +
    1.80 +int main (void);
    1.81 +void mm (MAILSTREAM *stream,long debug);
    1.82 +void overview_header (MAILSTREAM *stream,unsigned long uid,OVERVIEW *ov,
    1.83 +		      unsigned long msgno);
    1.84 +void header (MAILSTREAM *stream,long msgno);
    1.85 +void display_body (BODY *body,char *pfx,long i);
    1.86 +void status (MAILSTREAM *stream);
    1.87 +void prompt (char *msg,char *txt);
    1.88 +void smtptest (long debug);
    1.89 +
    1.90 +/* Main program - initialization */
    1.91 +
    1.92 +int main ()
    1.93 +{
    1.94 +  MAILSTREAM *stream = NIL;
    1.95 +  void *sdb = NIL;
    1.96 +  char *s,tmp[MAILTMPLEN];
    1.97 +  long debug;
    1.98 +#include "linkage.c"
    1.99 +#if MACOS
   1.100 +  {
   1.101 +    size_t *base = (size_t *) 0x000908;
   1.102 +				/* increase stack size on a Mac */
   1.103 +    SetApplLimit ((Ptr) (*base - (size_t) 65535L));
   1.104 +  }
   1.105 +#endif
   1.106 +  curusr = cpystr (((s = myusername ()) && *s) ? s : "somebody");
   1.107 +#if UNIXLIKE
   1.108 +  {
   1.109 +    char *suffix;
   1.110 +    struct passwd *pwd = getpwnam (curusr);
   1.111 +    if (pwd) {
   1.112 +      strcpy (tmp,pwd->pw_gecos);
   1.113 +				/* dyke out the office and phone poop */
   1.114 +      if (suffix = strchr (tmp,',')) suffix[0] = '\0';
   1.115 +      strcpy (personalname,tmp);/* make a permanent copy of it */
   1.116 +    }
   1.117 +    else personalname[0] = '\0';
   1.118 +  }
   1.119 +#else
   1.120 +  personalname[0] = '\0';
   1.121 +#endif
   1.122 +  curhst = cpystr (mylocalhost ());
   1.123 +  puts ("MTest -- C client test program");
   1.124 +  if (!*personalname) prompt ("Personal name: ",personalname);
   1.125 +				/* user wants protocol telemetry? */
   1.126 +  prompt ("Debug protocol (y/n)?",tmp);
   1.127 +  ucase (tmp);
   1.128 +  debug = (tmp[0] == 'Y') ? T : NIL;
   1.129 +  do {
   1.130 +    prompt ("Mailbox ('?' for help): ",tmp);
   1.131 +    if (!strcmp (tmp,"?")) {
   1.132 +      puts ("Enter INBOX, mailbox name, or IMAP mailbox as {host}mailbox");
   1.133 +      puts ("Known local mailboxes:");
   1.134 +      mail_list (NIL,NIL,"%");
   1.135 +      if (s = sm_read (&sdb)) {
   1.136 +	puts ("Local subscribed mailboxes:");
   1.137 +	do (mm_lsub (NIL,NIL,s,NIL));
   1.138 +	while (s = sm_read (&sdb));
   1.139 +      }
   1.140 +      puts ("or just hit return to quit");
   1.141 +    }
   1.142 +    else if (tmp[0]) stream = mail_open (stream,tmp,debug ? OP_DEBUG : NIL);
   1.143 +  } while (!stream && tmp[0]);
   1.144 +  mm (stream,debug);		/* run user interface if opened */
   1.145 +#if MACOS
   1.146 +				/* clean up resolver */
   1.147 +  if (resolveropen) CloseResolver ();
   1.148 +#endif
   1.149 +  return NIL;
   1.150 +}
   1.151 +
   1.152 +/* MM command loop
   1.153 + * Accepts: MAIL stream
   1.154 + */
   1.155 +
   1.156 +void mm (MAILSTREAM *stream,long debug)
   1.157 +{
   1.158 +  void *sdb = NIL;
   1.159 +  char cmd[MAILTMPLEN];
   1.160 +  char *s,*arg;
   1.161 +  unsigned long i;
   1.162 +  unsigned long last = 0;
   1.163 +  BODY *body;
   1.164 +  status (stream);		/* first report message status */
   1.165 +  while (stream) {
   1.166 +    prompt ("MTest>",cmd);	/* prompt user, get command */
   1.167 +				/* get argument */
   1.168 +    if (arg = strchr (cmd,' ')) *arg++ = '\0';
   1.169 +    switch (*ucase (cmd)) {	/* dispatch based on command */
   1.170 +    case 'B':			/* Body command */
   1.171 +      if (arg) last = atoi (arg);
   1.172 +      else if (!last) {
   1.173 +	puts ("?Missing message number");
   1.174 +	break;
   1.175 +      }
   1.176 +      if (last && (last <= stream->nmsgs)) {
   1.177 +	mail_fetchstructure (stream,last,&body);
   1.178 +	if (body) display_body (body,NIL,(long) 0);
   1.179 +	else puts ("%No body information available");
   1.180 +      }
   1.181 +      else puts ("?Bad message number");
   1.182 +      break;
   1.183 +    case 'C':			/* Check command */
   1.184 +      mail_check (stream);
   1.185 +      status (stream);
   1.186 +      break;
   1.187 +    case 'D':			/* Delete command */
   1.188 +      if (arg) last = atoi (arg);
   1.189 +      else {
   1.190 +	if (last == 0) {
   1.191 +	  puts ("?Missing message number");
   1.192 +	  break;
   1.193 +	}
   1.194 +	arg = cmd;
   1.195 +	sprintf (arg,"%lu",last);
   1.196 +      }
   1.197 +      if (last && (last <= stream->nmsgs))
   1.198 +	mail_setflag (stream,arg,"\\DELETED");
   1.199 +      else puts ("?Bad message number");
   1.200 +      break;
   1.201 +    case 'E':			/* Expunge command */
   1.202 +      mail_expunge (stream);
   1.203 +      last = 0;
   1.204 +      break;
   1.205 +    case 'F':			/* Find command */
   1.206 +      if (!arg) {
   1.207 +	arg = "%";
   1.208 +	if (s = sm_read (&sdb)) {
   1.209 +	  puts ("Local network subscribed mailboxes:");
   1.210 +	  do if (*s == '{') (mm_lsub (NIL,NIL,s,NIL));
   1.211 +	  while (s = sm_read (&sdb));
   1.212 +	}
   1.213 +      }
   1.214 +      puts ("Subscribed mailboxes:");
   1.215 +      mail_lsub (((arg[0] == '{') && (*stream->mailbox == '{')) ? stream : NIL,
   1.216 +		 NIL,arg);
   1.217 +      puts ("Known mailboxes:");
   1.218 +      mail_list (((arg[0] == '{') && (*stream->mailbox == '{')) ? stream : NIL,
   1.219 +		 NIL,arg);
   1.220 +      break;
   1.221 +    case 'G':
   1.222 +      mail_gc (stream,GC_ENV|GC_TEXTS|GC_ELT);
   1.223 +      break;
   1.224 +    case 'H':			/* Headers command */
   1.225 +      if (arg) {
   1.226 +	if (!(last = atoi (arg))) {
   1.227 +	  mail_search (stream,arg);
   1.228 +	  for (i = 1; i <= stream->nmsgs; ++i)
   1.229 +	    if (mail_elt (stream,i)->searched) header (stream,i);
   1.230 +	  break;
   1.231 +	}
   1.232 +      }
   1.233 +      else if (last == 0) {
   1.234 +	puts ("?Missing message number");
   1.235 +	break;
   1.236 +      }
   1.237 +      if (last && (last <= stream->nmsgs)) header (stream,last);
   1.238 +      else puts ("?Bad message number");
   1.239 +      break;
   1.240 +    case 'L':			/* Literal command */
   1.241 +      if (arg) last = atoi (arg);
   1.242 +      else if (!last) {
   1.243 +	puts ("?Missing message number");
   1.244 +	break;
   1.245 +      }
   1.246 +      if (last && (last <= stream->nmsgs))
   1.247 +	puts (mail_fetch_message (stream,last,NIL,NIL));
   1.248 +      else puts ("?Bad message number");
   1.249 +      break;
   1.250 +    case 'M':
   1.251 +      mail_status (NIL,arg ? arg : stream->mailbox,
   1.252 +		   SA_MESSAGES|SA_RECENT|SA_UNSEEN|SA_UIDNEXT|SA_UIDVALIDITY);
   1.253 +      break;
   1.254 +    case 'N':			/* New mailbox command */
   1.255 +      if (!arg) {
   1.256 +	puts ("?Missing mailbox");
   1.257 +	break;
   1.258 +      }
   1.259 +				/* get the new mailbox */
   1.260 +      while (!(stream = mail_open (stream,arg,debug))) {
   1.261 +	prompt ("Mailbox: ",arg);
   1.262 +	if (!arg[0]) break;
   1.263 +      }
   1.264 +      last = 0;
   1.265 +      status (stream);
   1.266 +      break;
   1.267 +    case 'O':			/* Overview command */
   1.268 +      if (!arg) {
   1.269 +	puts ("?Missing UID");
   1.270 +	break;
   1.271 +      }
   1.272 +      mail_fetch_overview (stream,arg,overview_header);
   1.273 +      break;
   1.274 +    case 'P':			/* Ping command */
   1.275 +      mail_ping (stream);
   1.276 +      status (stream);
   1.277 +      break;
   1.278 +    case 'Q':			/* Quit command */
   1.279 +      mail_close (stream);
   1.280 +      stream = NIL;
   1.281 +      break;
   1.282 +    case 'S':			/* Send command */
   1.283 +      smtptest (debug);
   1.284 +      break;
   1.285 +    case '\0':			/* null command (type next message) */
   1.286 +      if (!last || (last++ >= stream->nmsgs)) {
   1.287 +	puts ("%No next message");
   1.288 +	break;
   1.289 +      }
   1.290 +    case 'T':			/* Type command */
   1.291 +      if (arg) last = atoi (arg);
   1.292 +      else if (!last) {
   1.293 +	puts ("?Missing message number");
   1.294 +	break;
   1.295 +      }
   1.296 +      if (last && (last <= stream->nmsgs)) {
   1.297 +	STRINGLIST *lines = mail_newstringlist ();
   1.298 +	STRINGLIST *cur = lines;
   1.299 +	cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
   1.300 +					   cpystr ("Date")));
   1.301 +	cur = cur->next = mail_newstringlist ();
   1.302 +	cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
   1.303 +					   cpystr ("From")));
   1.304 +	cur = cur->next = mail_newstringlist ();
   1.305 +	cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
   1.306 +					   cpystr (">From")));
   1.307 +	cur = cur->next = mail_newstringlist ();
   1.308 +	cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
   1.309 +					   cpystr ("Subject")));
   1.310 +	cur = cur->next = mail_newstringlist ();
   1.311 +	cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
   1.312 +					   cpystr ("To")));
   1.313 +	cur = cur->next = mail_newstringlist ();
   1.314 +	cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
   1.315 +					   cpystr ("cc")));
   1.316 +	cur = cur->next = mail_newstringlist ();
   1.317 +	cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
   1.318 +					   cpystr ("Newsgroups")));
   1.319 +	printf ("%s",mail_fetchheader_full (stream,last,lines,NIL,NIL));
   1.320 +	puts (mail_fetchtext (stream,last));
   1.321 +	mail_free_stringlist (&lines);
   1.322 +      }
   1.323 +      else puts ("?Bad message number");
   1.324 +      break;
   1.325 +    case 'U':			/* Undelete command */
   1.326 +      if (arg) last = atoi (arg);
   1.327 +      else {
   1.328 +	if (!last) {
   1.329 +	  puts ("?Missing message number");
   1.330 +	  break;
   1.331 +	}
   1.332 +	arg = cmd;
   1.333 +	sprintf (arg,"%lu",last);
   1.334 +      }
   1.335 +      if (last > 0 && last <= stream->nmsgs)
   1.336 +	mail_clearflag (stream,arg,"\\DELETED");
   1.337 +      else puts ("?Bad message number");
   1.338 +      break;
   1.339 +    case 'X':			/* Xit command */
   1.340 +      mail_expunge (stream);
   1.341 +      mail_close (stream);
   1.342 +      stream = NIL;
   1.343 +      break;
   1.344 +    case '+':
   1.345 +      mail_debug (stream); debug = T;
   1.346 +      break;
   1.347 +    case '-':
   1.348 +      mail_nodebug (stream); debug = NIL;
   1.349 +      break;
   1.350 +    case '?':			/* ? command */
   1.351 +      puts ("Body, Check, Delete, Expunge, Find, GC, Headers, Literal,");
   1.352 +      puts (" MailboxStatus, New Mailbox, Overview, Ping, Quit, Send, Type,");
   1.353 +      puts ("Undelete, Xit, +, -, or <RETURN> for next message");
   1.354 +      break;
   1.355 +    default:			/* bogus command */
   1.356 +      printf ("?Unrecognized command: %s\n",cmd);
   1.357 +      break;
   1.358 +    }
   1.359 +  }
   1.360 +}
   1.361 +
   1.362 +/* MM display header
   1.363 + * Accepts: IMAP2 stream
   1.364 + *	    message number
   1.365 + */
   1.366 +
   1.367 +void overview_header (MAILSTREAM *stream,unsigned long uid,OVERVIEW *ov,
   1.368 +		      unsigned long msgno)
   1.369 +{
   1.370 +  if (ov) {
   1.371 +    unsigned long i;
   1.372 +    char *t,tmp[MAILTMPLEN];
   1.373 +    ADDRESS *adr;
   1.374 +    MESSAGECACHE *elt = mail_elt (stream,msgno);
   1.375 +    MESSAGECACHE selt;
   1.376 +    tmp[0] = elt->recent ? (elt->seen ? 'R': 'N') : ' ';
   1.377 +    tmp[1] = (elt->recent | elt->seen) ? ' ' : 'U';
   1.378 +    tmp[2] = elt->flagged ? 'F' : ' ';
   1.379 +    tmp[3] = elt->answered ? 'A' : ' ';
   1.380 +    tmp[4] = elt->deleted ? 'D' : ' ';
   1.381 +    mail_parse_date (&selt,ov->date);
   1.382 +    sprintf (tmp+5,"%4lu) ",elt->msgno);
   1.383 +    mail_date (tmp+11,&selt);
   1.384 +    tmp[17] = ' ';
   1.385 +    tmp[18] = '\0';
   1.386 +    memset (tmp+18,' ',(size_t) 20);
   1.387 +    tmp[38] = '\0';		/* tie off with null */
   1.388 +				/* get first from address from envelope */
   1.389 +    for (adr = ov->from; adr && !adr->host; adr = adr->next);
   1.390 +    if (adr) {			/* if a personal name exists use it */
   1.391 +      if (!(t = adr->personal))
   1.392 +	sprintf (t = tmp+400,"%s@%s",adr->mailbox,adr->host);
   1.393 +      memcpy (tmp+18,t,(size_t) min (20,(long) strlen (t)));
   1.394 +    }
   1.395 +    strcat (tmp," ");
   1.396 +    if (i = elt->user_flags) {
   1.397 +      strcat (tmp,"{");
   1.398 +      while (i) {
   1.399 +	strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
   1.400 +	if (i) strcat (tmp," ");
   1.401 +      }
   1.402 +      strcat (tmp,"} ");
   1.403 +    }
   1.404 +    sprintf (tmp + strlen (tmp),"%.25s (%lu chars)",
   1.405 +	     ov->subject ? ov->subject : " ",ov->optional.octets);
   1.406 +    puts (tmp);
   1.407 +  }
   1.408 +  else printf ("%%No overview for UID %lu\n",uid);
   1.409 +}
   1.410 +
   1.411 +/* MM display header
   1.412 + * Accepts: IMAP2 stream
   1.413 + *	    message number
   1.414 + */
   1.415 +
   1.416 +void header (MAILSTREAM *stream,long msgno)
   1.417 +{
   1.418 +  unsigned long i;
   1.419 +  char tmp[MAILTMPLEN];
   1.420 +  char *t;
   1.421 +  MESSAGECACHE *cache = mail_elt (stream,msgno);
   1.422 +  mail_fetchstructure (stream,msgno,NIL);
   1.423 +  tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
   1.424 +  tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
   1.425 +  tmp[2] = cache->flagged ? 'F' : ' ';
   1.426 +  tmp[3] = cache->answered ? 'A' : ' ';
   1.427 +  tmp[4] = cache->deleted ? 'D' : ' ';
   1.428 +  sprintf (tmp+5,"%4lu) ",cache->msgno);
   1.429 +  mail_date (tmp+11,cache);
   1.430 +  tmp[17] = ' ';
   1.431 +  tmp[18] = '\0';
   1.432 +  mail_fetchfrom (tmp+18,stream,msgno,(long) 20);
   1.433 +  strcat (tmp," ");
   1.434 +  if (i = cache->user_flags) {
   1.435 +    strcat (tmp,"{");
   1.436 +    while (i) {
   1.437 +      strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
   1.438 +      if (i) strcat (tmp," ");
   1.439 +    }
   1.440 +    strcat (tmp,"} ");
   1.441 +  }
   1.442 +  mail_fetchsubject (t = tmp + strlen (tmp),stream,msgno,(long) 25);
   1.443 +  sprintf (t += strlen (t)," (%lu chars)",cache->rfc822_size);
   1.444 +  puts (tmp);
   1.445 +}
   1.446 +
   1.447 +/* MM display body
   1.448 + * Accepts: BODY structure pointer
   1.449 + *	    prefix string
   1.450 + *	    index
   1.451 + */
   1.452 +
   1.453 +void display_body (BODY *body,char *pfx,long i)
   1.454 +{
   1.455 +  char tmp[MAILTMPLEN];
   1.456 +  char *s = tmp;
   1.457 +  PARAMETER *par;
   1.458 +  PART *part;			/* multipart doesn't have a row to itself */
   1.459 +  if (body->type == TYPEMULTIPART) {
   1.460 +				/* if not first time, extend prefix */
   1.461 +    if (pfx) sprintf (tmp,"%s%ld.",pfx,++i);
   1.462 +    else tmp[0] = '\0';
   1.463 +    for (i = 0,part = body->nested.part; part; part = part->next)
   1.464 +      display_body (&part->body,tmp,i++);
   1.465 +  }
   1.466 +  else {			/* non-multipart, output oneline descriptor */
   1.467 +    if (!pfx) pfx = "";		/* dummy prefix if top level */
   1.468 +    sprintf (s," %s%ld %s",pfx,++i,body_types[body->type]);
   1.469 +    if (body->subtype) sprintf (s += strlen (s),"/%s",body->subtype);
   1.470 +    if (body->description) sprintf (s += strlen (s)," (%s)",body->description);
   1.471 +    if (par = body->parameter) do
   1.472 +      sprintf (s += strlen (s),";%s=%s",par->attribute,par->value);
   1.473 +    while (par = par->next);
   1.474 +    if (body->id) sprintf (s += strlen (s),", id = %s",body->id);
   1.475 +    switch (body->type) {	/* bytes or lines depending upon body type */
   1.476 +    case TYPEMESSAGE:		/* encapsulated message */
   1.477 +    case TYPETEXT:		/* plain text */
   1.478 +      sprintf (s += strlen (s)," (%lu lines)",body->size.lines);
   1.479 +      break;
   1.480 +    default:
   1.481 +      sprintf (s += strlen (s)," (%lu bytes)",body->size.bytes);
   1.482 +      break;
   1.483 +    }
   1.484 +    puts (tmp);			/* output this line */
   1.485 +				/* encapsulated message? */
   1.486 +    if ((body->type == TYPEMESSAGE) && !strcmp (body->subtype,"RFC822") &&
   1.487 +	(body = body->nested.msg->body)) {
   1.488 +      if (body->type == TYPEMULTIPART) display_body (body,pfx,i-1);
   1.489 +      else {			/* build encapsulation prefix */
   1.490 +	sprintf (tmp,"%s%ld.",pfx,i);
   1.491 +	display_body (body,tmp,(long) 0);
   1.492 +      }
   1.493 +    }
   1.494 +  }
   1.495 +}
   1.496 +
   1.497 +/* MM status report
   1.498 + * Accepts: MAIL stream
   1.499 + */
   1.500 +
   1.501 +void status (MAILSTREAM *stream)
   1.502 +{
   1.503 +  unsigned long i;
   1.504 +  char *s,date[MAILTMPLEN];
   1.505 +  THREADER *thr;
   1.506 +  AUTHENTICATOR *auth;
   1.507 +  rfc822_date (date);
   1.508 +  puts (date);
   1.509 +  if (stream) {
   1.510 +    if (stream->mailbox)
   1.511 +      printf (" %s mailbox: %s, %lu messages, %lu recent\n",
   1.512 +	      stream->dtb->name,stream->mailbox,stream->nmsgs,stream->recent);
   1.513 +    else puts ("%No mailbox is open on this stream");
   1.514 +    if (stream->user_flags[0]) {
   1.515 +      printf ("Keywords: %s",stream->user_flags[0]);
   1.516 +      for (i = 1; i < NUSERFLAGS && stream->user_flags[i]; ++i)
   1.517 +	printf (", %s",stream->user_flags[i]);
   1.518 +      puts ("");
   1.519 +    }
   1.520 +    if (!strcmp (stream->dtb->name,"imap")) {
   1.521 +      if (LEVELIMAP4rev1 (stream)) s = "IMAP4rev1 (RFC 3501)";
   1.522 +      else if (LEVEL1730 (stream)) s = "IMAP4 (RFC 1730)";
   1.523 +      else if (LEVELIMAP2bis (stream)) s = "IMAP2bis";
   1.524 +      else if (LEVEL1176 (stream)) s = "IMAP2 (RFC 1176)";
   1.525 +      else s = "IMAP2 (RFC 1064)";
   1.526 +      printf ("%s server %s\n",s,imap_host (stream));
   1.527 +      if (LEVELIMAP4 (stream)) {
   1.528 +	if (i = imap_cap (stream)->auth) {
   1.529 +	  s = "";
   1.530 +	  printf ("Mutually-supported SASL mechanisms:");
   1.531 +	  while (auth = mail_lookup_auth (find_rightmost_bit (&i) + 1)) {
   1.532 +	    printf (" %s",auth->name);
   1.533 +	    if (!strcmp (auth->name,"PLAIN"))
   1.534 +	      s = "\n  [LOGIN will not be listed here if PLAIN is supported]";
   1.535 +	  }
   1.536 +	  puts (s);
   1.537 +	}
   1.538 +	printf ("Supported standard extensions:\n");
   1.539 +	if (LEVELACL (stream)) puts (" Access Control lists (RFC 2086)");
   1.540 +	if (LEVELQUOTA (stream)) puts (" Quotas (RFC 2087)");
   1.541 +	if (LEVELLITERALPLUS (stream))
   1.542 +	  puts (" Non-synchronizing literals (RFC 2088)");
   1.543 +	if (LEVELIDLE (stream)) puts (" IDLE unsolicited update (RFC 2177)");
   1.544 +	if (LEVELMBX_REF (stream)) puts (" Mailbox referrals (RFC 2193)");
   1.545 +	if (LEVELLOG_REF (stream)) puts (" Login referrals (RFC 2221)");
   1.546 +	if (LEVELANONYMOUS (stream)) puts (" Anonymous access (RFC 2245)");
   1.547 +	if (LEVELNAMESPACE (stream)) puts (" Multiple namespaces (RFC 2342)");
   1.548 +	if (LEVELUIDPLUS (stream)) puts (" Extended UID behavior (RFC 2359)");
   1.549 +	if (LEVELSTARTTLS (stream))
   1.550 +	  puts (" Transport Layer Security (RFC 2595)");
   1.551 +	if (LEVELLOGINDISABLED (stream))
   1.552 +	  puts (" LOGIN command disabled (RFC 2595)");
   1.553 +	if (LEVELID (stream))
   1.554 +	  puts (" Implementation identity negotiation (RFC 2971)");
   1.555 +	if (LEVELCHILDREN (stream))
   1.556 +	  puts (" LIST children announcement (RFC 3348)");
   1.557 +	if (LEVELMULTIAPPEND (stream))
   1.558 +	  puts (" Atomic multiple APPEND (RFC 3502)");
   1.559 +	if (LEVELBINARY (stream))
   1.560 +	  puts (" Binary body content (RFC 3516)");
   1.561 +	if (LEVELUNSELECT (stream)) puts (" Mailbox unselect (RFC 3691)");
   1.562 +	if (LEVELURLAUTH (stream))
   1.563 +	  puts (" URL authenticated fetch (RFC 4467)");
   1.564 +	if (LEVELCATENATE (stream)) puts (" Catenation (RFC 4469)");
   1.565 +	if (LEVELCONDSTORE (stream)) puts (" Conditional STORE (RFC 4551)");
   1.566 +	if (LEVELESEARCH (stream)) puts (" Extended SEARCH (RFC 4731)");
   1.567 +	puts ("Supported draft extensions:");
   1.568 +	if (LEVELSASLIR (stream)) puts (" SASL initial client response");
   1.569 +	if (LEVELSORT (stream)) puts (" Server-based sorting");
   1.570 +	if (LEVELTHREAD (stream)) {
   1.571 +	  printf (" Server-based threading:");
   1.572 +	  for (thr = imap_cap (stream)->threader; thr; thr = thr->next)
   1.573 +	    printf (" %s",thr->name);
   1.574 +	  putchar ('\n');
   1.575 +	}
   1.576 +	if (LEVELSCAN (stream)) puts (" Mailbox text scan");
   1.577 +	if (i = imap_cap (stream)->extlevel) {
   1.578 +	  printf ("Supported BODYSTRUCTURE extensions:");
   1.579 +	  switch (i) {
   1.580 +	  case BODYEXTLOC: printf (" location");
   1.581 +	  case BODYEXTLANG: printf (" language");
   1.582 +	  case BODYEXTDSP: printf (" disposition");
   1.583 +	  case BODYEXTMD5: printf (" MD5\n");
   1.584 +	  }
   1.585 +	}
   1.586 +      }
   1.587 +      else putchar ('\n');
   1.588 +    }
   1.589 +  }
   1.590 +}
   1.591 +
   1.592 +
   1.593 +/* Prompt user for input
   1.594 + * Accepts: pointer to prompt message
   1.595 + *          pointer to input buffer
   1.596 + */
   1.597 +
   1.598 +void prompt (char *msg,char *txt)
   1.599 +{
   1.600 +  printf ("%s",msg);
   1.601 +  gets (txt);
   1.602 +}
   1.603 +
   1.604 +/* Interfaces to C-client */
   1.605 +
   1.606 +
   1.607 +void mm_searched (MAILSTREAM *stream,unsigned long number)
   1.608 +{
   1.609 +}
   1.610 +
   1.611 +
   1.612 +void mm_exists (MAILSTREAM *stream,unsigned long number)
   1.613 +{
   1.614 +}
   1.615 +
   1.616 +
   1.617 +void mm_expunged (MAILSTREAM *stream,unsigned long number)
   1.618 +{
   1.619 +}
   1.620 +
   1.621 +
   1.622 +void mm_flags (MAILSTREAM *stream,unsigned long number)
   1.623 +{
   1.624 +}
   1.625 +
   1.626 +
   1.627 +void mm_notify (MAILSTREAM *stream,char *string,long errflg)
   1.628 +{
   1.629 +  mm_log (string,errflg);
   1.630 +}
   1.631 +
   1.632 +
   1.633 +void mm_list (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
   1.634 +{
   1.635 +  putchar (' ');
   1.636 +  if (delimiter) putchar (delimiter);
   1.637 +  else fputs ("NIL",stdout);
   1.638 +  putchar (' ');
   1.639 +  fputs (mailbox,stdout);
   1.640 +  if (attributes & LATT_NOINFERIORS) fputs (", no inferiors",stdout);
   1.641 +  if (attributes & LATT_NOSELECT) fputs (", no select",stdout);
   1.642 +  if (attributes & LATT_MARKED) fputs (", marked",stdout);
   1.643 +  if (attributes & LATT_UNMARKED) fputs (", unmarked",stdout);
   1.644 +  putchar ('\n');
   1.645 +}
   1.646 +
   1.647 +
   1.648 +void mm_lsub (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
   1.649 +{
   1.650 +  putchar (' ');
   1.651 +  if (delimiter) putchar (delimiter);
   1.652 +  else fputs ("NIL",stdout);
   1.653 +  putchar (' ');
   1.654 +  fputs (mailbox,stdout);
   1.655 +  if (attributes & LATT_NOINFERIORS) fputs (", no inferiors",stdout);
   1.656 +  if (attributes & LATT_NOSELECT) fputs (", no select",stdout);
   1.657 +  if (attributes & LATT_MARKED) fputs (", marked",stdout);
   1.658 +  if (attributes & LATT_UNMARKED) fputs (", unmarked",stdout);
   1.659 +  putchar ('\n');
   1.660 +}
   1.661 +
   1.662 +
   1.663 +void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
   1.664 +{
   1.665 +  printf (" Mailbox %s",mailbox);
   1.666 +  if (status->flags & SA_MESSAGES) printf (", %lu messages",status->messages);
   1.667 +  if (status->flags & SA_RECENT) printf (", %lu recent",status->recent);
   1.668 +  if (status->flags & SA_UNSEEN) printf (", %lu unseen",status->unseen);
   1.669 +  if (status->flags & SA_UIDVALIDITY) printf (", %lu UID validity",
   1.670 +					      status->uidvalidity);
   1.671 +  if (status->flags & SA_UIDNEXT) printf (", %lu next UID",status->uidnext);
   1.672 +  printf ("\n");
   1.673 +}
   1.674 +
   1.675 +
   1.676 +void mm_log (char *string,long errflg)
   1.677 +{
   1.678 +  switch ((short) errflg) {
   1.679 +  case NIL:
   1.680 +    printf ("[%s]\n",string);
   1.681 +    break;
   1.682 +  case PARSE:
   1.683 +  case WARN:
   1.684 +    printf ("%%%s\n",string);
   1.685 +    break;
   1.686 +  case ERROR:
   1.687 +    printf ("?%s\n",string);
   1.688 +    break;
   1.689 +  }
   1.690 +}
   1.691 +
   1.692 +
   1.693 +void mm_dlog (char *string)
   1.694 +{
   1.695 +  puts (string);
   1.696 +}
   1.697 +
   1.698 +
   1.699 +void mm_login (NETMBX *mb,char *user,char *pwd,long trial)
   1.700 +{
   1.701 +  char *s,tmp[MAILTMPLEN];
   1.702 +  if (curhst) fs_give ((void **) &curhst);
   1.703 +  curhst = (char *) fs_get (1+strlen (mb->host));
   1.704 +  strcpy (curhst,mb->host);
   1.705 +  sprintf (s = tmp,"{%s/%s",mb->host,mb->service);
   1.706 +  if (*mb->user) sprintf (tmp+strlen (tmp),"/user=%s",strcpy (user,mb->user));
   1.707 +  if (*mb->authuser) sprintf (tmp+strlen (tmp),"/authuser=%s",mb->authuser);
   1.708 +  if (*mb->user) strcat (s = tmp,"} password:");
   1.709 +  else {
   1.710 +    printf ("%s} username: ",tmp);
   1.711 +    fgets (user,NETMAXUSER-1,stdin);
   1.712 +    user[NETMAXUSER-1] = '\0';
   1.713 +    if (s = strchr (user,'\n')) *s = '\0';
   1.714 +    s = "password: ";
   1.715 +  }
   1.716 +  if (curusr) fs_give ((void **) &curusr);
   1.717 +  curusr = cpystr (user);
   1.718 +  strcpy (pwd,getpass (s));
   1.719 +}
   1.720 +
   1.721 +
   1.722 +void mm_critical (MAILSTREAM *stream)
   1.723 +{
   1.724 +}
   1.725 +
   1.726 +
   1.727 +void mm_nocritical (MAILSTREAM *stream)
   1.728 +{
   1.729 +}
   1.730 +
   1.731 +
   1.732 +long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
   1.733 +{
   1.734 +#if UNIXLIKE
   1.735 +  kill (getpid (),SIGSTOP);
   1.736 +#else
   1.737 +  abort ();
   1.738 +#endif
   1.739 +  return NIL;
   1.740 +}
   1.741 +
   1.742 +
   1.743 +void mm_fatal (char *string)
   1.744 +{
   1.745 +  printf ("?%s\n",string);
   1.746 +}
   1.747 +
   1.748 +/* SMTP tester */
   1.749 +
   1.750 +void smtptest (long debug)
   1.751 +{
   1.752 +  SENDSTREAM *stream = NIL;
   1.753 +  char line[MAILTMPLEN];
   1.754 +  char *text = (char *) fs_get (8*MAILTMPLEN);
   1.755 +  ENVELOPE *msg = mail_newenvelope ();
   1.756 +  BODY *body = mail_newbody ();
   1.757 +  msg->from = mail_newaddr ();
   1.758 +  msg->from->personal = cpystr (personalname);
   1.759 +  msg->from->mailbox = cpystr (curusr);
   1.760 +  msg->from->host = cpystr (curhst);
   1.761 +  msg->return_path = mail_newaddr ();
   1.762 +  msg->return_path->mailbox = cpystr (curusr);
   1.763 +  msg->return_path->host = cpystr (curhst);
   1.764 +  prompt ("To: ",line);
   1.765 +  rfc822_parse_adrlist (&msg->to,line,curhst);
   1.766 +  if (msg->to) {
   1.767 +    prompt ("cc: ",line);
   1.768 +    rfc822_parse_adrlist (&msg->cc,line,curhst);
   1.769 +  }
   1.770 +  else {
   1.771 +    prompt ("Newsgroups: ",line);
   1.772 +    if (*line) msg->newsgroups = cpystr (line);
   1.773 +    else {
   1.774 +      mail_free_body (&body);
   1.775 +      mail_free_envelope (&msg);
   1.776 +      fs_give ((void **) &text);
   1.777 +      return;
   1.778 +    }
   1.779 +  }
   1.780 +  prompt ("Subject: ",line);
   1.781 +  msg->subject = cpystr (line);
   1.782 +  puts (" Msg (end with a line with only a '.'):");
   1.783 +  body->type = TYPETEXT;
   1.784 +  *text = '\0';
   1.785 +  while (gets (line)) {
   1.786 +    if (line[0] == '.') {
   1.787 +      if (line[1] == '\0') break;
   1.788 +      else strcat (text,".");
   1.789 +    }
   1.790 +    strcat (text,line);
   1.791 +    strcat (text,"\015\012");
   1.792 +  }
   1.793 +  body->contents.text.data = (unsigned char *) text;
   1.794 +  body->contents.text.size = strlen (text);
   1.795 +  rfc822_date (line);
   1.796 +  msg->date = (char *) fs_get (1+strlen (line));
   1.797 +  strcpy (msg->date,line);
   1.798 +  if (msg->to) {
   1.799 +    puts ("Sending...");
   1.800 +    if (stream = smtp_open (hostlist,debug)) {
   1.801 +      if (smtp_mail (stream,"MAIL",msg,body)) puts ("[Ok]");
   1.802 +      else printf ("[Failed - %s]\n",stream->reply);
   1.803 +    }
   1.804 +  }
   1.805 +  else {
   1.806 +    puts ("Posting...");
   1.807 +    if (stream = nntp_open (newslist,debug)) {
   1.808 +      if (nntp_mail (stream,msg,body)) puts ("[Ok]");
   1.809 +      else printf ("[Failed - %s]\n",stream->reply);
   1.810 +    }
   1.811 +  }
   1.812 +  if (stream) smtp_close (stream);
   1.813 +  else puts ("[Can't open connection to any server]");
   1.814 +  mail_free_envelope (&msg);
   1.815 +  mail_free_body (&body);
   1.816 +}

UW-IMAP'd extensions by yuuji