mtest.c
上传用户:ycwykj01
上传日期:2007-01-04
资源大小:1819k
文件大小:20k
- /*
- * Program: Mail library test program
- *
- * Author: Mark Crispin
- * Networks and Distributed Computing
- * Computing & Communications
- * University of Washington
- * Administration Building, AG-44
- * Seattle, WA 98195
- * Internet: MRC@CAC.Washington.EDU
- *
- * Date: 8 July 1988
- * Last Edited: 28 May 1999
- *
- * Sponsorship: The original version of this work was developed in the
- * Symbolic Systems Resources Group of the Knowledge Systems
- * Laboratory at Stanford University in 1987-88, and was funded
- * by the Biomedical Research Technology Program of the National
- * Institutes of Health under grant number RR-00785.
- *
- * Original version Copyright 1988 by The Leland Stanford Junior University
- * Copyright 1999 by the University of Washington
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notices appear in all copies and that both the
- * above copyright notices and this permission notice appear in supporting
- * documentation, and that the name of the University of Washington or The
- * Leland Stanford Junior University not be used in advertising or publicity
- * pertaining to distribution of the software without specific, written prior
- * permission. This software is made available "as is", and
- * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
- * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
- * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
- * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
- * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
- #include <stdio.h>
- #include <ctype.h>
- #include <signal.h>
- #include "mail.h"
- #include "osdep.h"
- #include "rfc822.h"
- #include "smtp.h"
- #include "nntp.h"
- /* Excellent reasons to hate ifdefs, and why my real code never uses them */
- #ifndef unix
- # define unix 0
- #endif
- #if unix
- # define UNIXLIKE 1
- # define MACOS 0
- # include <pwd.h>
- char *getpass ();
- #else
- # define UNIXLIKE 0
- # ifdef noErr
- # define MACOS 1
- # include <Memory.h>
- # else
- # define MACOS 0
- # endif
- #endif
- #include "misc.h"
- char *curhst = NIL; /* currently connected host */
- char *curusr = NIL; /* current login user */
- char personalname[MAILTMPLEN]; /* user's personal name */
- static char *hostlist[] = { /* SMTP server host list */
- "mailhost",
- "localhost",
- NIL
- };
- static char *newslist[] = { /* Netnews server host list */
- "news",
- NIL
- };
- int main (void);
- void mm (MAILSTREAM *stream,long debug);
- void overview_header (MAILSTREAM *stream,unsigned long uid,OVERVIEW *ov);
- void header (MAILSTREAM *stream,long msgno);
- void display_body (BODY *body,char *pfx,long i);
- void status (MAILSTREAM *stream);
- void prompt (char *msg,char *txt);
- void smtptest (long debug);
- /* Main program - initialization */
- int main ()
- {
- MAILSTREAM *stream = NIL;
- void *sdb = NIL;
- char *s,tmp[MAILTMPLEN];
- long debug;
- #include "linkage.c"
- #if MACOS
- {
- size_t *base = (size_t *) 0x000908;
- /* increase stack size on a Mac */
- SetApplLimit ((Ptr) (*base - (size_t) 65535L));
- }
- #endif
- #if UNIXLIKE
- curusr = cpystr(myusername());/* current user is this name */
- {
- char *suffix;
- struct passwd *pwd = getpwnam (curusr);
- if (pwd) {
- strcpy (tmp,pwd->pw_gecos);
- /* dyke out the office and phone poop */
- if (suffix = strchr (tmp,',')) suffix[0] = ' ';
- strcpy (personalname,tmp);/* make a permanent copy of it */
- }
- else personalname[0] = ' ';
- }
- #else
- curusr = cpystr ("somebody");
- personalname[0] = ' ';
- #endif
- curhst = cpystr (mylocalhost ());
- puts ("MTest -- C client test program");
- if (!*personalname) prompt ("Personal name: ",personalname);
- /* user wants protocol telemetry? */
- prompt ("Debug protocol (y/n)?",tmp);
- ucase (tmp);
- debug = (tmp[0] == 'Y') ? T : NIL;
- do {
- prompt ("Mailbox ('?' for help): ",tmp);
- if (!strcmp (tmp,"?")) {
- puts ("Enter INBOX, mailbox name, or IMAP mailbox as {host}mailbox");
- puts ("Known local mailboxes:");
- mail_list (NIL,NIL,"%");
- if (s = sm_read (&sdb)) {
- puts ("Local subscribed mailboxes:");
- do (mm_lsub (NIL,NIL,s,NIL));
- while (s = sm_read (&sdb));
- }
- puts ("or just hit return to quit");
- }
- else if (tmp[0]) stream = mail_open (stream,tmp,debug ? OP_DEBUG : NIL);
- } while (!stream && tmp[0]);
- mm (stream,debug); /* run user interface if opened */
- #if MACOS
- /* clean up resolver */
- if (resolveropen) CloseResolver ();
- #endif
- return NIL;
- }
- /* MM command loop
- * Accepts: MAIL stream
- */
- void mm (MAILSTREAM *stream,long debug)
- {
- void *sdb = NIL;
- char cmd[MAILTMPLEN];
- char *s,*arg;
- unsigned long i;
- unsigned long last = 0;
- BODY *body;
- status (stream); /* first report message status */
- while (stream) {
- prompt ("MTest>",cmd); /* prompt user, get command */
- /* get argument */
- if (arg = strchr (cmd,' ')) *arg++ = ' ';
- switch (*ucase (cmd)) { /* dispatch based on command */
- case 'B': /* Body command */
- if (arg) last = atoi (arg);
- else if (!last) {
- puts ("?Missing message number");
- break;
- }
- if (last && (last <= stream->nmsgs)) {
- mail_fetchstructure (stream,last,&body);
- if (body) display_body (body,NIL,(long) 0);
- else puts ("%No body information available");
- }
- else puts ("?Bad message number");
- break;
- case 'C': /* Check command */
- mail_check (stream);
- status (stream);
- break;
- case 'D': /* Delete command */
- if (arg) last = atoi (arg);
- else {
- if (last == 0) {
- puts ("?Missing message number");
- break;
- }
- arg = cmd;
- sprintf (arg,"%lu",last);
- }
- if (last && (last <= stream->nmsgs))
- mail_setflag (stream,arg,"\DELETED");
- else puts ("?Bad message number");
- break;
- case 'E': /* Expunge command */
- mail_expunge (stream);
- last = 0;
- break;
- case 'F': /* Find command */
- if (!arg) {
- arg = "%";
- if (s = sm_read (&sdb)) {
- puts ("Local network subscribed mailboxes:");
- do if (*s == '{') (mm_lsub (NIL,NIL,s,NIL));
- while (s = sm_read (&sdb));
- }
- }
- puts ("Subscribed mailboxes:");
- mail_lsub (((arg[0] == '{') && (*stream->mailbox == '{')) ? stream : NIL,
- NIL,arg);
- puts ("Known mailboxes:");
- mail_list (((arg[0] == '{') && (*stream->mailbox == '{')) ? stream : NIL,
- NIL,arg);
- break;
- case 'G':
- mail_gc (stream,GC_ENV|GC_TEXTS|GC_ELT);
- break;
- case 'H': /* Headers command */
- if (arg) {
- if (!(last = atoi (arg))) {
- mail_search (stream,arg);
- for (i = 1; i <= stream->nmsgs; ++i)
- if (mail_elt (stream,i)->searched) header (stream,i);
- break;
- }
- }
- else if (last == 0) {
- puts ("?Missing message number");
- break;
- }
- if (last && (last <= stream->nmsgs)) header (stream,last);
- else puts ("?Bad message number");
- break;
- case 'L': /* Literal command */
- if (arg) last = atoi (arg);
- else if (!last) {
- puts ("?Missing message number");
- break;
- }
- if (last && (last <= stream->nmsgs))
- puts (mail_fetch_message (stream,last,NIL,NIL));
- else puts ("?Bad message number");
- break;
- case 'M':
- mail_status (NIL,arg ? arg : stream->mailbox,
- SA_MESSAGES|SA_RECENT|SA_UNSEEN|SA_UIDNEXT|SA_UIDVALIDITY);
- break;
- case 'N': /* New mailbox command */
- if (!arg) {
- puts ("?Missing mailbox");
- break;
- }
- /* get the new mailbox */
- while (!(stream = mail_open (stream,arg,debug)))
- prompt ("Mailbox: ",arg);
- last = 0;
- status (stream);
- break;
- case 'O': /* Overview command */
- if (!arg) {
- puts ("?Missing UID");
- break;
- }
- mail_fetch_overview (stream,arg,overview_header);
- break;
- case 'Q': /* Quit command */
- mail_close (stream);
- stream = NIL;
- break;
- case 'S': /* Send command */
- smtptest (debug);
- break;
- case ' ': /* null command (type next message) */
- if (!last || (last++ >= stream->nmsgs)) {
- puts ("%No next message");
- break;
- }
- case 'T': /* Type command */
- if (arg) last = atoi (arg);
- else if (!last) {
- puts ("?Missing message number");
- break;
- }
- if (last && (last <= stream->nmsgs)) {
- STRINGLIST *lines = mail_newstringlist ();
- STRINGLIST *cur = lines;
- cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
- cpystr ("Date")));
- cur = cur->next = mail_newstringlist ();
- cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
- cpystr ("From")));
- cur = cur->next = mail_newstringlist ();
- cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
- cpystr (">From")));
- cur = cur->next = mail_newstringlist ();
- cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
- cpystr ("Subject")));
- cur = cur->next = mail_newstringlist ();
- cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
- cpystr ("To")));
- cur = cur->next = mail_newstringlist ();
- cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
- cpystr ("cc")));
- cur = cur->next = mail_newstringlist ();
- cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
- cpystr ("Newsgroups")));
- printf ("%s",mail_fetchheader_full (stream,last,lines,NIL,NIL));
- puts (mail_fetchtext (stream,last));
- mail_free_stringlist (&lines);
- }
- else puts ("?Bad message number");
- break;
- case 'U': /* Undelete command */
- if (arg) last = atoi (arg);
- else {
- if (!last) {
- puts ("?Missing message number");
- break;
- }
- arg = cmd;
- sprintf (arg,"%lu",last);
- }
- if (last > 0 && last <= stream->nmsgs)
- mail_clearflag (stream,arg,"\DELETED");
- else puts ("?Bad message number");
- break;
- case 'X': /* Xit command */
- mail_expunge (stream);
- mail_close (stream);
- stream = NIL;
- break;
- case '+':
- mail_debug (stream); debug = T;
- break;
- case '-':
- mail_nodebug (stream); debug = NIL;
- break;
- case '?': /* ? command */
- puts ("Body, Check, Delete, Expunge, Find, GC, Headers, Literal,");
- puts (" MailboxStatus, New Mailbox, Overview, Quit, Send, Type,");
- puts ("Undelete, Xit, +, -, or <RETURN> for next message");
- break;
- default: /* bogus command */
- printf ("?Unrecognized command: %sn",cmd);
- break;
- }
- }
- }
- /* MM display header
- * Accepts: IMAP2 stream
- * message number
- */
- void overview_header (MAILSTREAM *stream,unsigned long uid,OVERVIEW *ov)
- {
- unsigned long i;
- char *t,tmp[MAILTMPLEN];
- ADDRESS *adr;
- unsigned long msgno = mail_msgno (stream,uid);
- MESSAGECACHE *elt = mail_elt (stream,msgno);
- MESSAGECACHE selt;
- tmp[0] = elt->recent ? (elt->seen ? 'R': 'N') : ' ';
- tmp[1] = (elt->recent | elt->seen) ? ' ' : 'U';
- tmp[2] = elt->flagged ? 'F' : ' ';
- tmp[3] = elt->answered ? 'A' : ' ';
- tmp[4] = elt->deleted ? 'D' : ' ';
- mail_parse_date (&selt,ov->date);
- sprintf (tmp+5,"%4lu) ",elt->msgno);
- mail_date (tmp+11,&selt);
- tmp[17] = ' ';
- tmp[18] = ' ';
- memset (tmp+18,' ',(size_t) 20);
- tmp[38] = ' '; /* tie off with null */
- /* get first from address from envelope */
- for (adr = ov->from; adr && !adr->host; adr = adr->next);
- if (adr) { /* if a personal name exists use it */
- if (!(t = adr->personal))
- sprintf (t = tmp+400,"%s@%s",adr->mailbox,adr->host);
- memcpy (tmp+18,t,(size_t) min (20,(long) strlen (t)));
- }
- strcat (tmp," ");
- if (i = elt->user_flags) {
- strcat (tmp,"{");
- while (i) {
- strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
- if (i) strcat (tmp," ");
- }
- strcat (tmp,"} ");
- }
- sprintf (tmp + strlen (tmp),"%.25s (%lu chars)",
- ov->subject ? ov->subject : " ",ov->optional.octets);
- puts (tmp);
- }
- /* MM display header
- * Accepts: IMAP2 stream
- * message number
- */
- void header (MAILSTREAM *stream,long msgno)
- {
- unsigned long i;
- char tmp[MAILTMPLEN];
- char *t;
- MESSAGECACHE *cache = mail_elt (stream,msgno);
- mail_fetchstructure (stream,msgno,NIL);
- tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
- tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
- tmp[2] = cache->flagged ? 'F' : ' ';
- tmp[3] = cache->answered ? 'A' : ' ';
- tmp[4] = cache->deleted ? 'D' : ' ';
- sprintf (tmp+5,"%4lu) ",cache->msgno);
- mail_date (tmp+11,cache);
- tmp[17] = ' ';
- tmp[18] = ' ';
- mail_fetchfrom (tmp+18,stream,msgno,(long) 20);
- strcat (tmp," ");
- if (i = cache->user_flags) {
- strcat (tmp,"{");
- while (i) {
- strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
- if (i) strcat (tmp," ");
- }
- strcat (tmp,"} ");
- }
- mail_fetchsubject (t = tmp + strlen (tmp),stream,msgno,(long) 25);
- sprintf (t += strlen (t)," (%lu chars)",cache->rfc822_size);
- puts (tmp);
- }
- /* MM display body
- * Accepts: BODY structure pointer
- * prefix string
- * index
- */
- void display_body (BODY *body,char *pfx,long i)
- {
- char tmp[MAILTMPLEN];
- char *s = tmp;
- PARAMETER *par;
- PART *part; /* multipart doesn't have a row to itself */
- if (body->type == TYPEMULTIPART) {
- /* if not first time, extend prefix */
- if (pfx) sprintf (tmp,"%s%ld.",pfx,++i);
- else tmp[0] = ' ';
- for (i = 0,part = body->nested.part; part; part = part->next)
- display_body (&part->body,tmp,i++);
- }
- else { /* non-multipart, output oneline descriptor */
- if (!pfx) pfx = ""; /* dummy prefix if top level */
- sprintf (s," %s%ld %s",pfx,++i,body_types[body->type]);
- if (body->subtype) sprintf (s += strlen (s),"/%s",body->subtype);
- if (body->description) sprintf (s += strlen (s)," (%s)",body->description);
- if (par = body->parameter) do
- sprintf (s += strlen (s),";%s=%s",par->attribute,par->value);
- while (par = par->next);
- if (body->id) sprintf (s += strlen (s),", id = %s",body->id);
- switch (body->type) { /* bytes or lines depending upon body type */
- case TYPEMESSAGE: /* encapsulated message */
- case TYPETEXT: /* plain text */
- sprintf (s += strlen (s)," (%lu lines)",body->size.lines);
- break;
- default:
- sprintf (s += strlen (s)," (%lu bytes)",body->size.bytes);
- break;
- }
- puts (tmp); /* output this line */
- /* encapsulated message? */
- if ((body->type == TYPEMESSAGE) && !strcmp (body->subtype,"RFC822") &&
- (body = body->nested.msg->body)) {
- if (body->type == TYPEMULTIPART) display_body (body,pfx,i-1);
- else { /* build encapsulation prefix */
- sprintf (tmp,"%s%ld.",pfx,i);
- display_body (body,tmp,(long) 0);
- }
- }
- }
- }
- /* MM status report
- * Accepts: MAIL stream
- */
- void status (MAILSTREAM *stream)
- {
- long i;
- char date[MAILTMPLEN];
- rfc822_date (date);
- puts (date);
- if (stream) {
- if (stream->mailbox)
- printf (" %s mailbox: %s, %lu messages, %lu recentn",
- stream->dtb->name,stream->mailbox,stream->nmsgs,stream->recent);
- else puts ("%No mailbox is open on this stream");
- if (stream->user_flags[0]) {
- printf ("Keywords: %s",stream->user_flags[0]);
- for (i = 1; i < NUSERFLAGS && stream->user_flags[i]; ++i)
- printf (", %s",stream->user_flags[i]);
- puts ("");
- }
- }
- }
- /* Prompt user for input
- * Accepts: pointer to prompt message
- * pointer to input buffer
- */
- void prompt (char *msg,char *txt)
- {
- printf ("%s",msg);
- gets (txt);
- }
- /* Interfaces to C-client */
- void mm_searched (MAILSTREAM *stream,unsigned long number)
- {
- }
- void mm_exists (MAILSTREAM *stream,unsigned long number)
- {
- }
- void mm_expunged (MAILSTREAM *stream,unsigned long number)
- {
- }
- void mm_flags (MAILSTREAM *stream,unsigned long number)
- {
- }
- void mm_notify (MAILSTREAM *stream,char *string,long errflg)
- {
- mm_log (string,errflg);
- }
- void mm_list (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
- {
- putchar (' ');
- if (delimiter) putchar (delimiter);
- else fputs ("NIL",stdout);
- putchar (' ');
- fputs (mailbox,stdout);
- if (attributes & LATT_NOINFERIORS) fputs (", no inferiors",stdout);
- if (attributes & LATT_NOSELECT) fputs (", no select",stdout);
- if (attributes & LATT_MARKED) fputs (", marked",stdout);
- if (attributes & LATT_UNMARKED) fputs (", unmarked",stdout);
- putchar ('n');
- }
- void mm_lsub (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
- {
- putchar (' ');
- if (delimiter) putchar (delimiter);
- else fputs ("NIL",stdout);
- putchar (' ');
- fputs (mailbox,stdout);
- if (attributes & LATT_NOINFERIORS) fputs (", no inferiors",stdout);
- if (attributes & LATT_NOSELECT) fputs (", no select",stdout);
- if (attributes & LATT_MARKED) fputs (", marked",stdout);
- if (attributes & LATT_UNMARKED) fputs (", unmarked",stdout);
- putchar ('n');
- }
- void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
- {
- printf (" Mailbox %s",mailbox);
- if (status->flags & SA_MESSAGES) printf (", %lu messages",status->messages);
- if (status->flags & SA_RECENT) printf (", %lu recent",status->recent);
- if (status->flags & SA_UNSEEN) printf (", %lu unseen",status->unseen);
- if (status->flags & SA_UIDVALIDITY) printf (", %lu UID validity",
- status->uidvalidity);
- if (status->flags & SA_UIDNEXT) printf (", %lu next UID",status->uidnext);
- printf ("n");
- }
- void mm_log (char *string,long errflg)
- {
- switch ((short) errflg) {
- case NIL:
- printf ("[%s]n",string);
- break;
- case PARSE:
- case WARN:
- printf ("%%%sn",string);
- break;
- case ERROR:
- printf ("?%sn",string);
- break;
- }
- }
- void mm_dlog (char *string)
- {
- puts (string);
- }
- void mm_login (NETMBX *mb,char *user,char *pwd,long trial)
- {
- char tmp[MAILTMPLEN];
- if (curhst) fs_give ((void **) &curhst);
- curhst = (char *) fs_get (1+strlen (mb->host));
- strcpy (curhst,mb->host);
- if (*mb->user) {
- strcpy (user,mb->user);
- sprintf (tmp,"{%s/%s/user="%s"} password: ",mb->host,mb->service,mb->user);
- }
- else {
- sprintf (tmp,"{%s/%s} username: ",mb->host,mb->service);
- prompt (tmp,user);
- strcpy (tmp,"Password: ");
- }
- if (curusr) fs_give ((void **) &curusr);
- curusr = cpystr (user);
- #if UNIXLIKE
- strcpy (pwd,getpass (tmp));
- #else
- prompt (tmp,pwd);
- #endif
- }
- void mm_critical (MAILSTREAM *stream)
- {
- }
- void mm_nocritical (MAILSTREAM *stream)
- {
- }
- long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
- {
- #if UNIXLIKE
- kill (getpid (),SIGSTOP);
- #else
- abort ();
- #endif
- return NIL;
- }
- void mm_fatal (char *string)
- {
- printf ("?%sn",string);
- }
- /* SMTP tester */
- void smtptest (long debug)
- {
- SENDSTREAM *stream = NIL;
- char line[MAILTMPLEN];
- char *text = (char *) fs_get (8*MAILTMPLEN);
- ENVELOPE *msg = mail_newenvelope ();
- BODY *body = mail_newbody ();
- msg->from = mail_newaddr ();
- msg->from->personal = cpystr (personalname);
- msg->from->mailbox = cpystr (curusr);
- msg->from->host = cpystr (curhst);
- msg->return_path = mail_newaddr ();
- msg->return_path->mailbox = cpystr (curusr);
- msg->return_path->host = cpystr (curhst);
- prompt ("To: ",line);
- rfc822_parse_adrlist (&msg->to,line,curhst);
- if (msg->to) {
- prompt ("cc: ",line);
- rfc822_parse_adrlist (&msg->cc,line,curhst);
- }
- else {
- prompt ("Newsgroups: ",line);
- if (*line) msg->newsgroups = cpystr (line);
- else {
- mail_free_body (&body);
- mail_free_envelope (&msg);
- fs_give ((void **) &text);
- }
- }
- prompt ("Subject: ",line);
- msg->subject = cpystr (line);
- puts (" Msg (end with a line with only a '.'):");
- body->type = TYPETEXT;
- *text = ' ';
- while (gets (line)) {
- if (line[0] == '.') {
- if (line[1] == ' ') break;
- else strcat (text,".");
- }
- strcat (text,line);
- strcat (text,"