imapext-2007

view src/mtest/mtest.c @ 10:cd53ed0e4bb2

For FreeBSD13, use fgets() instead of gets() which causes link error. Note that other ancient insecure function calls are left as they were because mtest is not for daily use.
author HIROSE Yuuji <yuuji@gentei.org>
date Sun, 07 May 2023 12:46:12 +0900
parents ada5e610ab86
children
line source
1 /* ========================================================================
2 * Copyright 1988-2007 University of Washington
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *
11 * ========================================================================
12 */
14 /*
15 * Program: Mail library test program
16 *
17 * Author: Mark Crispin
18 * Networks and Distributed Computing
19 * Computing & Communications
20 * University of Washington
21 * Administration Building, AG-44
22 * Seattle, WA 98195
23 * Internet: MRC@CAC.Washington.EDU
24 *
25 * Date: 8 July 1988
26 * Last Edited: 5 November 2007
27 *
28 * This original version of this file is
29 * Copyright 1988 Stanford University
30 * and was developed in the Symbolic Systems Resources Group of the Knowledge
31 * Systems Laboratory at Stanford University in 1987-88, and was funded by the
32 * Biomedical Research Technology Program of the NationalInstitutes of Health
33 * under grant number RR-00785.
34 */
36 #include <stdio.h>
37 #include <ctype.h>
38 #include <signal.h>
39 #include "c-client.h"
40 #include "imap4r1.h"
42 /* Excellent reasons to hate ifdefs, and why my real code never uses them */
44 #ifndef unix
45 # define unix 0
46 #endif
48 #if unix
49 # define UNIXLIKE 1
50 # define MACOS 0
51 # include <pwd.h>
52 #else
53 # define UNIXLIKE 0
54 # ifdef noErr
55 # define MACOS 1
56 # include <Memory.h>
57 # else
58 # define MACOS 0
59 # endif
60 #endif
62 char *curhst = NIL; /* currently connected host */
63 char *curusr = NIL; /* current login user */
64 char personalname[MAILTMPLEN]; /* user's personal name */
66 static char *hostlist[] = { /* SMTP server host list */
67 "mailhost",
68 "localhost",
69 NIL
70 };
72 static char *newslist[] = { /* Netnews server host list */
73 "news",
74 NIL
75 };
77 int main (void);
78 void mm (MAILSTREAM *stream,long debug);
79 void overview_header (MAILSTREAM *stream,unsigned long uid,OVERVIEW *ov,
80 unsigned long msgno);
81 void header (MAILSTREAM *stream,long msgno);
82 void display_body (BODY *body,char *pfx,long i);
83 void status (MAILSTREAM *stream);
84 void prompt (char *msg,char *txt);
85 void smtptest (long debug);
87 /* Main program - initialization */
89 int main ()
90 {
91 MAILSTREAM *stream = NIL;
92 void *sdb = NIL;
93 char *s,tmp[MAILTMPLEN];
94 long debug;
95 #include "linkage.c"
96 #if MACOS
97 {
98 size_t *base = (size_t *) 0x000908;
99 /* increase stack size on a Mac */
100 SetApplLimit ((Ptr) (*base - (size_t) 65535L));
101 }
102 #endif
103 curusr = cpystr (((s = myusername ()) && *s) ? s : "somebody");
104 #if UNIXLIKE
105 {
106 char *suffix;
107 struct passwd *pwd = getpwnam (curusr);
108 if (pwd) {
109 strcpy (tmp,pwd->pw_gecos);
110 /* dyke out the office and phone poop */
111 if (suffix = strchr (tmp,',')) suffix[0] = '\0';
112 strcpy (personalname,tmp);/* make a permanent copy of it */
113 }
114 else personalname[0] = '\0';
115 }
116 #else
117 personalname[0] = '\0';
118 #endif
119 curhst = cpystr (mylocalhost ());
120 puts ("MTest -- C client test program");
121 if (!*personalname) prompt ("Personal name: ",personalname);
122 /* user wants protocol telemetry? */
123 prompt ("Debug protocol (y/n)?",tmp);
124 ucase (tmp);
125 debug = (tmp[0] == 'Y') ? T : NIL;
126 do {
127 prompt ("Mailbox ('?' for help): ",tmp);
128 if (!strcmp (tmp,"?")) {
129 puts ("Enter INBOX, mailbox name, or IMAP mailbox as {host}mailbox");
130 puts ("Known local mailboxes:");
131 mail_list (NIL,NIL,"%");
132 if (s = sm_read (&sdb)) {
133 puts ("Local subscribed mailboxes:");
134 do (mm_lsub (NIL,NIL,s,NIL));
135 while (s = sm_read (&sdb));
136 }
137 puts ("or just hit return to quit");
138 }
139 else if (tmp[0]) stream = mail_open (stream,tmp,debug ? OP_DEBUG : NIL);
140 } while (!stream && tmp[0]);
141 mm (stream,debug); /* run user interface if opened */
142 #if MACOS
143 /* clean up resolver */
144 if (resolveropen) CloseResolver ();
145 #endif
146 return NIL;
147 }
149 /* MM command loop
150 * Accepts: MAIL stream
151 */
153 void mm (MAILSTREAM *stream,long debug)
154 {
155 void *sdb = NIL;
156 char cmd[MAILTMPLEN];
157 char *s,*arg;
158 unsigned long i;
159 unsigned long last = 0;
160 BODY *body;
161 status (stream); /* first report message status */
162 while (stream) {
163 prompt ("MTest>",cmd); /* prompt user, get command */
164 /* get argument */
165 if (arg = strchr (cmd,' ')) *arg++ = '\0';
166 switch (*ucase (cmd)) { /* dispatch based on command */
167 case 'B': /* Body command */
168 if (arg) last = atoi (arg);
169 else if (!last) {
170 puts ("?Missing message number");
171 break;
172 }
173 if (last && (last <= stream->nmsgs)) {
174 mail_fetchstructure (stream,last,&body);
175 if (body) display_body (body,NIL,(long) 0);
176 else puts ("%No body information available");
177 }
178 else puts ("?Bad message number");
179 break;
180 case 'C': /* Check command */
181 mail_check (stream);
182 status (stream);
183 break;
184 case 'D': /* Delete command */
185 if (arg) last = atoi (arg);
186 else {
187 if (last == 0) {
188 puts ("?Missing message number");
189 break;
190 }
191 arg = cmd;
192 sprintf (arg,"%lu",last);
193 }
194 if (last && (last <= stream->nmsgs))
195 mail_setflag (stream,arg,"\\DELETED");
196 else puts ("?Bad message number");
197 break;
198 case 'E': /* Expunge command */
199 mail_expunge (stream);
200 last = 0;
201 break;
202 case 'F': /* Find command */
203 if (!arg) {
204 arg = "%";
205 if (s = sm_read (&sdb)) {
206 puts ("Local network subscribed mailboxes:");
207 do if (*s == '{') (mm_lsub (NIL,NIL,s,NIL));
208 while (s = sm_read (&sdb));
209 }
210 }
211 puts ("Subscribed mailboxes:");
212 mail_lsub (((arg[0] == '{') && (*stream->mailbox == '{')) ? stream : NIL,
213 NIL,arg);
214 puts ("Known mailboxes:");
215 mail_list (((arg[0] == '{') && (*stream->mailbox == '{')) ? stream : NIL,
216 NIL,arg);
217 break;
218 case 'G':
219 mail_gc (stream,GC_ENV|GC_TEXTS|GC_ELT);
220 break;
221 case 'H': /* Headers command */
222 if (arg) {
223 if (!(last = atoi (arg))) {
224 mail_search (stream,arg);
225 for (i = 1; i <= stream->nmsgs; ++i)
226 if (mail_elt (stream,i)->searched) header (stream,i);
227 break;
228 }
229 }
230 else if (last == 0) {
231 puts ("?Missing message number");
232 break;
233 }
234 if (last && (last <= stream->nmsgs)) header (stream,last);
235 else puts ("?Bad message number");
236 break;
237 case 'L': /* Literal command */
238 if (arg) last = atoi (arg);
239 else if (!last) {
240 puts ("?Missing message number");
241 break;
242 }
243 if (last && (last <= stream->nmsgs))
244 puts (mail_fetch_message (stream,last,NIL,NIL));
245 else puts ("?Bad message number");
246 break;
247 case 'M':
248 mail_status (NIL,arg ? arg : stream->mailbox,
249 SA_MESSAGES|SA_RECENT|SA_UNSEEN|SA_UIDNEXT|SA_UIDVALIDITY);
250 break;
251 case 'N': /* New mailbox command */
252 if (!arg) {
253 puts ("?Missing mailbox");
254 break;
255 }
256 /* get the new mailbox */
257 while (!(stream = mail_open (stream,arg,debug))) {
258 prompt ("Mailbox: ",arg);
259 if (!arg[0]) break;
260 }
261 last = 0;
262 status (stream);
263 break;
264 case 'O': /* Overview command */
265 if (!arg) {
266 puts ("?Missing UID");
267 break;
268 }
269 mail_fetch_overview (stream,arg,overview_header);
270 break;
271 case 'P': /* Ping command */
272 mail_ping (stream);
273 status (stream);
274 break;
275 case 'Q': /* Quit command */
276 mail_close (stream);
277 stream = NIL;
278 break;
279 case 'S': /* Send command */
280 smtptest (debug);
281 break;
282 case '\0': /* null command (type next message) */
283 if (!last || (last++ >= stream->nmsgs)) {
284 puts ("%No next message");
285 break;
286 }
287 case 'T': /* Type command */
288 if (arg) last = atoi (arg);
289 else if (!last) {
290 puts ("?Missing message number");
291 break;
292 }
293 if (last && (last <= stream->nmsgs)) {
294 STRINGLIST *lines = mail_newstringlist ();
295 STRINGLIST *cur = lines;
296 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
297 cpystr ("Date")));
298 cur = cur->next = mail_newstringlist ();
299 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
300 cpystr ("From")));
301 cur = cur->next = mail_newstringlist ();
302 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
303 cpystr (">From")));
304 cur = cur->next = mail_newstringlist ();
305 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
306 cpystr ("Subject")));
307 cur = cur->next = mail_newstringlist ();
308 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
309 cpystr ("To")));
310 cur = cur->next = mail_newstringlist ();
311 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
312 cpystr ("cc")));
313 cur = cur->next = mail_newstringlist ();
314 cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
315 cpystr ("Newsgroups")));
316 printf ("%s",mail_fetchheader_full (stream,last,lines,NIL,NIL));
317 puts (mail_fetchtext (stream,last));
318 mail_free_stringlist (&lines);
319 }
320 else puts ("?Bad message number");
321 break;
322 case 'U': /* Undelete command */
323 if (arg) last = atoi (arg);
324 else {
325 if (!last) {
326 puts ("?Missing message number");
327 break;
328 }
329 arg = cmd;
330 sprintf (arg,"%lu",last);
331 }
332 if (last > 0 && last <= stream->nmsgs)
333 mail_clearflag (stream,arg,"\\DELETED");
334 else puts ("?Bad message number");
335 break;
336 case 'X': /* Xit command */
337 mail_expunge (stream);
338 mail_close (stream);
339 stream = NIL;
340 break;
341 case '+':
342 mail_debug (stream); debug = T;
343 break;
344 case '-':
345 mail_nodebug (stream); debug = NIL;
346 break;
347 case '?': /* ? command */
348 puts ("Body, Check, Delete, Expunge, Find, GC, Headers, Literal,");
349 puts (" MailboxStatus, New Mailbox, Overview, Ping, Quit, Send, Type,");
350 puts ("Undelete, Xit, +, -, or <RETURN> for next message");
351 break;
352 default: /* bogus command */
353 printf ("?Unrecognized command: %s\n",cmd);
354 break;
355 }
356 }
357 }
359 /* MM display header
360 * Accepts: IMAP2 stream
361 * message number
362 */
364 void overview_header (MAILSTREAM *stream,unsigned long uid,OVERVIEW *ov,
365 unsigned long msgno)
366 {
367 if (ov) {
368 unsigned long i;
369 char *t,tmp[MAILTMPLEN];
370 ADDRESS *adr;
371 MESSAGECACHE *elt = mail_elt (stream,msgno);
372 MESSAGECACHE selt;
373 tmp[0] = elt->recent ? (elt->seen ? 'R': 'N') : ' ';
374 tmp[1] = (elt->recent | elt->seen) ? ' ' : 'U';
375 tmp[2] = elt->flagged ? 'F' : ' ';
376 tmp[3] = elt->answered ? 'A' : ' ';
377 tmp[4] = elt->deleted ? 'D' : ' ';
378 mail_parse_date (&selt,ov->date);
379 sprintf (tmp+5,"%4lu) ",elt->msgno);
380 mail_date (tmp+11,&selt);
381 tmp[17] = ' ';
382 tmp[18] = '\0';
383 memset (tmp+18,' ',(size_t) 20);
384 tmp[38] = '\0'; /* tie off with null */
385 /* get first from address from envelope */
386 for (adr = ov->from; adr && !adr->host; adr = adr->next);
387 if (adr) { /* if a personal name exists use it */
388 if (!(t = adr->personal))
389 sprintf (t = tmp+400,"%s@%s",adr->mailbox,adr->host);
390 memcpy (tmp+18,t,(size_t) min (20,(long) strlen (t)));
391 }
392 strcat (tmp," ");
393 if (i = elt->user_flags) {
394 strcat (tmp,"{");
395 while (i) {
396 strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
397 if (i) strcat (tmp," ");
398 }
399 strcat (tmp,"} ");
400 }
401 sprintf (tmp + strlen (tmp),"%.25s (%lu chars)",
402 ov->subject ? ov->subject : " ",ov->optional.octets);
403 puts (tmp);
404 }
405 else printf ("%%No overview for UID %lu\n",uid);
406 }
408 /* MM display header
409 * Accepts: IMAP2 stream
410 * message number
411 */
413 void header (MAILSTREAM *stream,long msgno)
414 {
415 unsigned long i;
416 char tmp[MAILTMPLEN];
417 char *t;
418 MESSAGECACHE *cache = mail_elt (stream,msgno);
419 mail_fetchstructure (stream,msgno,NIL);
420 tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
421 tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
422 tmp[2] = cache->flagged ? 'F' : ' ';
423 tmp[3] = cache->answered ? 'A' : ' ';
424 tmp[4] = cache->deleted ? 'D' : ' ';
425 sprintf (tmp+5,"%4lu) ",cache->msgno);
426 mail_date (tmp+11,cache);
427 tmp[17] = ' ';
428 tmp[18] = '\0';
429 mail_fetchfrom (tmp+18,stream,msgno,(long) 20);
430 strcat (tmp," ");
431 if (i = cache->user_flags) {
432 strcat (tmp,"{");
433 while (i) {
434 strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
435 if (i) strcat (tmp," ");
436 }
437 strcat (tmp,"} ");
438 }
439 mail_fetchsubject (t = tmp + strlen (tmp),stream,msgno,(long) 25);
440 sprintf (t += strlen (t)," (%lu chars)",cache->rfc822_size);
441 puts (tmp);
442 }
444 /* MM display body
445 * Accepts: BODY structure pointer
446 * prefix string
447 * index
448 */
450 void display_body (BODY *body,char *pfx,long i)
451 {
452 char tmp[MAILTMPLEN];
453 char *s = tmp;
454 PARAMETER *par;
455 PART *part; /* multipart doesn't have a row to itself */
456 if (body->type == TYPEMULTIPART) {
457 /* if not first time, extend prefix */
458 if (pfx) sprintf (tmp,"%s%ld.",pfx,++i);
459 else tmp[0] = '\0';
460 for (i = 0,part = body->nested.part; part; part = part->next)
461 display_body (&part->body,tmp,i++);
462 }
463 else { /* non-multipart, output oneline descriptor */
464 if (!pfx) pfx = ""; /* dummy prefix if top level */
465 sprintf (s," %s%ld %s",pfx,++i,body_types[body->type]);
466 if (body->subtype) sprintf (s += strlen (s),"/%s",body->subtype);
467 if (body->description) sprintf (s += strlen (s)," (%s)",body->description);
468 if (par = body->parameter) do
469 sprintf (s += strlen (s),";%s=%s",par->attribute,par->value);
470 while (par = par->next);
471 if (body->id) sprintf (s += strlen (s),", id = %s",body->id);
472 switch (body->type) { /* bytes or lines depending upon body type */
473 case TYPEMESSAGE: /* encapsulated message */
474 case TYPETEXT: /* plain text */
475 sprintf (s += strlen (s)," (%lu lines)",body->size.lines);
476 break;
477 default:
478 sprintf (s += strlen (s)," (%lu bytes)",body->size.bytes);
479 break;
480 }
481 puts (tmp); /* output this line */
482 /* encapsulated message? */
483 if ((body->type == TYPEMESSAGE) && !strcmp (body->subtype,"RFC822") &&
484 (body = body->nested.msg->body)) {
485 if (body->type == TYPEMULTIPART) display_body (body,pfx,i-1);
486 else { /* build encapsulation prefix */
487 sprintf (tmp,"%s%ld.",pfx,i);
488 display_body (body,tmp,(long) 0);
489 }
490 }
491 }
492 }
494 /* MM status report
495 * Accepts: MAIL stream
496 */
498 void status (MAILSTREAM *stream)
499 {
500 unsigned long i;
501 char *s,date[MAILTMPLEN];
502 THREADER *thr;
503 AUTHENTICATOR *auth;
504 rfc822_date (date);
505 puts (date);
506 if (stream) {
507 if (stream->mailbox)
508 printf (" %s mailbox: %s, %lu messages, %lu recent\n",
509 stream->dtb->name,stream->mailbox,stream->nmsgs,stream->recent);
510 else puts ("%No mailbox is open on this stream");
511 if (stream->user_flags[0]) {
512 printf ("Keywords: %s",stream->user_flags[0]);
513 for (i = 1; i < NUSERFLAGS && stream->user_flags[i]; ++i)
514 printf (", %s",stream->user_flags[i]);
515 puts ("");
516 }
517 if (!strcmp (stream->dtb->name,"imap")) {
518 if (LEVELIMAP4rev1 (stream)) s = "IMAP4rev1 (RFC 3501)";
519 else if (LEVEL1730 (stream)) s = "IMAP4 (RFC 1730)";
520 else if (LEVELIMAP2bis (stream)) s = "IMAP2bis";
521 else if (LEVEL1176 (stream)) s = "IMAP2 (RFC 1176)";
522 else s = "IMAP2 (RFC 1064)";
523 printf ("%s server %s\n",s,imap_host (stream));
524 if (LEVELIMAP4 (stream)) {
525 if (i = imap_cap (stream)->auth) {
526 s = "";
527 printf ("Mutually-supported SASL mechanisms:");
528 while (auth = mail_lookup_auth (find_rightmost_bit (&i) + 1)) {
529 printf (" %s",auth->name);
530 if (!strcmp (auth->name,"PLAIN"))
531 s = "\n [LOGIN will not be listed here if PLAIN is supported]";
532 }
533 puts (s);
534 }
535 printf ("Supported standard extensions:\n");
536 if (LEVELACL (stream)) puts (" Access Control lists (RFC 2086)");
537 if (LEVELQUOTA (stream)) puts (" Quotas (RFC 2087)");
538 if (LEVELLITERALPLUS (stream))
539 puts (" Non-synchronizing literals (RFC 2088)");
540 if (LEVELIDLE (stream)) puts (" IDLE unsolicited update (RFC 2177)");
541 if (LEVELMBX_REF (stream)) puts (" Mailbox referrals (RFC 2193)");
542 if (LEVELLOG_REF (stream)) puts (" Login referrals (RFC 2221)");
543 if (LEVELANONYMOUS (stream)) puts (" Anonymous access (RFC 2245)");
544 if (LEVELNAMESPACE (stream)) puts (" Multiple namespaces (RFC 2342)");
545 if (LEVELUIDPLUS (stream)) puts (" Extended UID behavior (RFC 2359)");
546 if (LEVELSTARTTLS (stream))
547 puts (" Transport Layer Security (RFC 2595)");
548 if (LEVELLOGINDISABLED (stream))
549 puts (" LOGIN command disabled (RFC 2595)");
550 if (LEVELID (stream))
551 puts (" Implementation identity negotiation (RFC 2971)");
552 if (LEVELCHILDREN (stream))
553 puts (" LIST children announcement (RFC 3348)");
554 if (LEVELMULTIAPPEND (stream))
555 puts (" Atomic multiple APPEND (RFC 3502)");
556 if (LEVELBINARY (stream))
557 puts (" Binary body content (RFC 3516)");
558 if (LEVELUNSELECT (stream)) puts (" Mailbox unselect (RFC 3691)");
559 if (LEVELURLAUTH (stream))
560 puts (" URL authenticated fetch (RFC 4467)");
561 if (LEVELCATENATE (stream)) puts (" Catenation (RFC 4469)");
562 if (LEVELCONDSTORE (stream)) puts (" Conditional STORE (RFC 4551)");
563 if (LEVELESEARCH (stream)) puts (" Extended SEARCH (RFC 4731)");
564 puts ("Supported draft extensions:");
565 if (LEVELSASLIR (stream)) puts (" SASL initial client response");
566 if (LEVELSORT (stream)) puts (" Server-based sorting");
567 if (LEVELTHREAD (stream)) {
568 printf (" Server-based threading:");
569 for (thr = imap_cap (stream)->threader; thr; thr = thr->next)
570 printf (" %s",thr->name);
571 putchar ('\n');
572 }
573 if (LEVELSCAN (stream)) puts (" Mailbox text scan");
574 if (i = imap_cap (stream)->extlevel) {
575 printf ("Supported BODYSTRUCTURE extensions:");
576 switch (i) {
577 case BODYEXTLOC: printf (" location");
578 case BODYEXTLANG: printf (" language");
579 case BODYEXTDSP: printf (" disposition");
580 case BODYEXTMD5: printf (" MD5\n");
581 }
582 }
583 }
584 else putchar ('\n');
585 }
586 }
587 }
590 /* Prompt user for input
591 * Accepts: pointer to prompt message
592 * pointer to input buffer
593 */
595 void prompt (char *msg,char *txt)
596 {
597 printf ("%s",msg);
598 fgets (txt,MAILTMPLEN-1,stdin);
599 }
601 /* Interfaces to C-client */
604 void mm_searched (MAILSTREAM *stream,unsigned long number)
605 {
606 }
609 void mm_exists (MAILSTREAM *stream,unsigned long number)
610 {
611 }
614 void mm_expunged (MAILSTREAM *stream,unsigned long number)
615 {
616 }
619 void mm_flags (MAILSTREAM *stream,unsigned long number)
620 {
621 }
624 void mm_notify (MAILSTREAM *stream,char *string,long errflg)
625 {
626 mm_log (string,errflg);
627 }
630 void mm_list (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
631 {
632 putchar (' ');
633 if (delimiter) putchar (delimiter);
634 else fputs ("NIL",stdout);
635 putchar (' ');
636 fputs (mailbox,stdout);
637 if (attributes & LATT_NOINFERIORS) fputs (", no inferiors",stdout);
638 if (attributes & LATT_NOSELECT) fputs (", no select",stdout);
639 if (attributes & LATT_MARKED) fputs (", marked",stdout);
640 if (attributes & LATT_UNMARKED) fputs (", unmarked",stdout);
641 putchar ('\n');
642 }
645 void mm_lsub (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
646 {
647 putchar (' ');
648 if (delimiter) putchar (delimiter);
649 else fputs ("NIL",stdout);
650 putchar (' ');
651 fputs (mailbox,stdout);
652 if (attributes & LATT_NOINFERIORS) fputs (", no inferiors",stdout);
653 if (attributes & LATT_NOSELECT) fputs (", no select",stdout);
654 if (attributes & LATT_MARKED) fputs (", marked",stdout);
655 if (attributes & LATT_UNMARKED) fputs (", unmarked",stdout);
656 putchar ('\n');
657 }
660 void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
661 {
662 printf (" Mailbox %s",mailbox);
663 if (status->flags & SA_MESSAGES) printf (", %lu messages",status->messages);
664 if (status->flags & SA_RECENT) printf (", %lu recent",status->recent);
665 if (status->flags & SA_UNSEEN) printf (", %lu unseen",status->unseen);
666 if (status->flags & SA_UIDVALIDITY) printf (", %lu UID validity",
667 status->uidvalidity);
668 if (status->flags & SA_UIDNEXT) printf (", %lu next UID",status->uidnext);
669 printf ("\n");
670 }
673 void mm_log (char *string,long errflg)
674 {
675 switch ((short) errflg) {
676 case NIL:
677 printf ("[%s]\n",string);
678 break;
679 case PARSE:
680 case WARN:
681 printf ("%%%s\n",string);
682 break;
683 case ERROR:
684 printf ("?%s\n",string);
685 break;
686 }
687 }
690 void mm_dlog (char *string)
691 {
692 puts (string);
693 }
696 void mm_login (NETMBX *mb,char *user,char *pwd,long trial)
697 {
698 char *s,tmp[MAILTMPLEN];
699 if (curhst) fs_give ((void **) &curhst);
700 curhst = (char *) fs_get (1+strlen (mb->host));
701 strcpy (curhst,mb->host);
702 sprintf (s = tmp,"{%s/%s",mb->host,mb->service);
703 if (*mb->user) sprintf (tmp+strlen (tmp),"/user=%s",strcpy (user,mb->user));
704 if (*mb->authuser) sprintf (tmp+strlen (tmp),"/authuser=%s",mb->authuser);
705 if (*mb->user) strcat (s = tmp,"} password:");
706 else {
707 printf ("%s} username: ",tmp);
708 fgets (user,NETMAXUSER-1,stdin);
709 user[NETMAXUSER-1] = '\0';
710 if (s = strchr (user,'\n')) *s = '\0';
711 s = "password: ";
712 }
713 if (curusr) fs_give ((void **) &curusr);
714 curusr = cpystr (user);
715 strcpy (pwd,getpass (s));
716 }
719 void mm_critical (MAILSTREAM *stream)
720 {
721 }
724 void mm_nocritical (MAILSTREAM *stream)
725 {
726 }
729 long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
730 {
731 #if UNIXLIKE
732 kill (getpid (),SIGSTOP);
733 #else
734 abort ();
735 #endif
736 return NIL;
737 }
740 void mm_fatal (char *string)
741 {
742 printf ("?%s\n",string);
743 }
745 /* SMTP tester */
747 void smtptest (long debug)
748 {
749 SENDSTREAM *stream = NIL;
750 char line[MAILTMPLEN];
751 char *text = (char *) fs_get (8*MAILTMPLEN);
752 ENVELOPE *msg = mail_newenvelope ();
753 BODY *body = mail_newbody ();
754 msg->from = mail_newaddr ();
755 msg->from->personal = cpystr (personalname);
756 msg->from->mailbox = cpystr (curusr);
757 msg->from->host = cpystr (curhst);
758 msg->return_path = mail_newaddr ();
759 msg->return_path->mailbox = cpystr (curusr);
760 msg->return_path->host = cpystr (curhst);
761 prompt ("To: ",line);
762 rfc822_parse_adrlist (&msg->to,line,curhst);
763 if (msg->to) {
764 prompt ("cc: ",line);
765 rfc822_parse_adrlist (&msg->cc,line,curhst);
766 }
767 else {
768 prompt ("Newsgroups: ",line);
769 if (*line) msg->newsgroups = cpystr (line);
770 else {
771 mail_free_body (&body);
772 mail_free_envelope (&msg);
773 fs_give ((void **) &text);
774 return;
775 }
776 }
777 prompt ("Subject: ",line);
778 msg->subject = cpystr (line);
779 puts (" Msg (end with a line with only a '.'):");
780 body->type = TYPETEXT;
781 *text = '\0';
782 while (fgets (line,MAILTMPLEN-1,stdin)) {
783 if (line[0] == '.') {
784 if (line[1] == '\0') break;
785 else strcat (text,".");
786 }
787 strcat (text,line);
788 strcat (text,"\015\012");
789 }
790 body->contents.text.data = (unsigned char *) text;
791 body->contents.text.size = strlen (text);
792 rfc822_date (line);
793 msg->date = (char *) fs_get (1+strlen (line));
794 strcpy (msg->date,line);
795 if (msg->to) {
796 puts ("Sending...");
797 if (stream = smtp_open (hostlist,debug)) {
798 if (smtp_mail (stream,"MAIL",msg,body)) puts ("[Ok]");
799 else printf ("[Failed - %s]\n",stream->reply);
800 }
801 }
802 else {
803 puts ("Posting...");
804 if (stream = nntp_open (newslist,debug)) {
805 if (nntp_mail (stream,msg,body)) puts ("[Ok]");
806 else printf ("[Failed - %s]\n",stream->reply);
807 }
808 }
809 if (stream) smtp_close (stream);
810 else puts ("[Can't open connection to any server]");
811 mail_free_envelope (&msg);
812 mail_free_body (&body);
813 }

UW-IMAP'd extensions by yuuji