1772
|
1 /* recvmail.c This routine allows a user to read his/her mail.
|
|
2 Copyright (C) 1990, 1993 Rick Adams and Bob Billson
|
|
3
|
|
4 This file is part of the OS-9 UUCP package, UUCPbb.
|
|
5
|
|
6 This program is free software; you can redistribute it and/or modify
|
|
7 it under the terms of the GNU General Public License as published by
|
|
8 the Free Software Foundation; either version 2 of the License, or
|
|
9 (at your option) any later version.
|
|
10
|
|
11 This program is distributed in the hope that it will be useful,
|
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 GNU General Public License for more details.
|
|
15
|
|
16 You should have received a copy of the GNU General Public License
|
|
17 along with this program; if not, write to the Free Software
|
|
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
19
|
|
20 The author of UUCPbb, Bob Billson, can be contacted at:
|
|
21 bob@kc2wz.bubble.org or uunet!kc2wz!bob or by snail mail:
|
|
22 21 Bates Way, Westfield, NJ 07090
|
|
23 */
|
|
24
|
|
25 /* Rewritten to support new spooled mail format. Mail is kept as separate
|
|
26 files in the directory pointed to by the parameter 'maildir' in the
|
|
27 /DD/SYS/UUCP/Parameters file. Each file is named 'mYYMMDDHHMMSS', where
|
|
28 'YYMMDDHHMMSS' is the date/time RMAIL processed the message --REB */
|
|
29
|
|
30 #include "uucp.h"
|
|
31 #include "mail.h"
|
|
32 #include <ctype.h>
|
|
33 #include <modes.h>
|
|
34 #include <direct.h> /* Added - BAS */
|
|
35 #include <sgstat.h>
|
|
36 #ifndef _OSK
|
|
37 #include <os9.h>
|
|
38 #include "dir_6809.h"
|
|
39 #else
|
|
40 #include <dir.h>
|
|
41 #endif
|
|
42
|
|
43 #define WORDSIZE 40
|
|
44
|
|
45
|
|
46 char dspmail(), getresponse();
|
|
47 void givehelp();
|
|
48
|
|
49
|
|
50 int recvmail (fifo)
|
|
51 flag fifo;
|
|
52 {
|
|
53 flag dothis, direction;
|
|
54 int numltrs, ltrsleft;
|
|
55 register MAILPTR envelop;
|
|
56 MAILPTR firstenvelop = NULL;
|
|
57 struct mailbag *whatnow(), *reverselist(), *gathermail();
|
|
58
|
|
59 /* Check waiting for mail. Exit if there is none. When we return our
|
|
60 current data directory will be our mailbox directory. */
|
|
61
|
|
62 if ((numltrs = ltrsleft = checkmail (FALSE, user)) == 0)
|
|
63 exit (0);
|
|
64
|
|
65 firstenvelop = gathermail (numltrs);
|
|
66
|
|
67 if (!fifo)
|
|
68 firstenvelop = reverselist (firstenvelop);
|
|
69
|
|
70 /* Open each letter and read it. Then decide if we want to: save,
|
|
71 delete, undelete, redisplay, move to the next or previous letter. */
|
|
72
|
|
73 envelop = firstenvelop;
|
|
74 direction = FORWARD;
|
|
75 do
|
|
76 switch (dothis = openenvelop (envelop))
|
|
77 {
|
|
78 case ALLREAD:
|
|
79 markallmail (firstenvelop, TRUE);
|
|
80 break;
|
|
81
|
|
82 case KILLMAIL:
|
|
83 markallmail (firstenvelop, FALSE);
|
|
84 ltrsleft = 0;
|
|
85
|
|
86 case QUIT:
|
|
87 envelop = ENDMAIL;
|
|
88 break;
|
|
89
|
|
90 case UNDELETE:
|
|
91 undeletemail (firstenvelop, <rsleft);
|
|
92 break;
|
|
93
|
|
94 case DELETE:
|
|
95 --ltrsleft;
|
|
96
|
|
97 default:
|
|
98 envelop = whatnow (dothis, envelop, &direction);
|
|
99 break;
|
|
100 }
|
|
101 while (envelop != ENDMAIL);
|
|
102
|
|
103 if (!fifo)
|
|
104 firstenvelop = reverselist (firstenvelop);
|
|
105
|
|
106 if (ltrsleft < numltrs)
|
|
107 fputs ("\b \bremoving deleted mail...", stdout);
|
|
108
|
|
109 fflush (stdout);
|
|
110 #ifndef _OSK
|
|
111 loadpager (FALSE);
|
|
112 #endif
|
|
113
|
|
114 if (rmailin)
|
|
115 munload (rmail, 0);
|
|
116
|
|
117 updatemail_list (firstenvelop, ltrsleft);
|
|
118 free (firstenvelop);
|
|
119 }
|
|
120
|
|
121
|
|
122
|
|
123 /* Create a double-linked list of all the mail. Return a pointer to the start
|
|
124 of the list. */
|
|
125
|
|
126 struct mailbag *gathermail (numltrs)
|
|
127 int numltrs;
|
|
128 {
|
|
129 char mailine[MLINE];
|
|
130 register MAILPTR ep;
|
|
131 FILE *mlptr;
|
|
132 char *p, *p1;
|
|
133 MAILPTR elast, envelops;
|
|
134 int newmail, unreadmail;
|
|
135
|
|
136 if ((mlptr = fopen (mail_list, "r")) == NULL)
|
|
137 fatal ("gathermail: can't open user's mail..list");
|
|
138
|
|
139 /* create a double-linked list of pointers to each line in mail..list */
|
|
140 envelops = (MAILPTR) malloc (numltrs * sizeof (MAILBAG));
|
|
141
|
|
142 if (envelops == NULL)
|
|
143 fatal ("gathermail: can't malloc envelops array");
|
|
144
|
|
145 /* make forward and backward links */
|
|
146 ep = envelops;
|
|
147 elast = envelops + numltrs;
|
|
148 do
|
|
149 {
|
|
150 if (ep < elast - 1)
|
|
151 ep->next = ep + 1; /* next envelop or... */
|
|
152 else
|
|
153 ep->next = ENDMAIL; /* ...end of list */
|
|
154
|
|
155 if (ep != envelops)
|
|
156 ep->prev = ep - 1; /* everything else... */
|
|
157 else
|
|
158 ep->prev = ENDMAIL; /* ...or first envelop */
|
|
159 }
|
|
160 while (++ep < elast);
|
|
161
|
|
162 newmail = unreadmail = 0;
|
|
163 ep = envelops;
|
|
164 while (mfgets (mailine, MLINE, mlptr) != NULL)
|
|
165 {
|
|
166 /* save the individual mail..list line and point to the fields */
|
|
167 ep->mline = p1 = strdup (mailine);
|
|
168
|
|
169 if (ep->mline == NULL)
|
|
170 fatal ("recvmail: can't malloc mail..list line");
|
|
171
|
|
172 /* status */
|
|
173 ep->status = *p1++;
|
|
174
|
|
175 if (ep->status == 'N')
|
|
176 ++newmail;
|
|
177 else if (ep->status == 'U')
|
|
178 ++unreadmail;
|
|
179
|
|
180 /* file name */
|
|
181 p = strchr (p1, '|');
|
|
182 *p = '\0';
|
|
183 ep->letter = p1;
|
|
184 ++ep;
|
|
185 }
|
|
186 fclose (mlptr);
|
|
187
|
|
188 if (newmail || unreadmail)
|
|
189 {
|
|
190 printf ("\nOS-9 Mailx v%s %d message%s",
|
|
191 version, numltrs, numltrs > 0 ? "s" : "");
|
|
192
|
|
193 if (newmail)
|
|
194 printf (" %d new", newmail);
|
|
195
|
|
196 if (unreadmail)
|
|
197 printf (" %d unread", unreadmail + newmail);
|
|
198
|
|
199 fputs ("\n\nhit <ENTER> to continue...", stdout);
|
|
200 fflush (stdout);
|
|
201 getresponse();
|
|
202 cls();
|
|
203 }
|
|
204 return (envelops);
|
|
205 }
|
|
206
|
|
207
|
|
208
|
|
209 /* reverse the order of a double-linked list --REB */
|
|
210
|
|
211 struct mailbag *reverselist (list)
|
|
212 MAILPTR list;
|
|
213 {
|
|
214 register MAILPTR p1;
|
|
215 MAILPTR p2;
|
|
216
|
|
217 p2 = ENDMAIL;
|
|
218 while (list)
|
|
219 {
|
|
220 p1 = list;
|
|
221 list = p1->next;
|
|
222 p1->prev = p1->next;
|
|
223 p1->next = p2;
|
|
224 p2 = p1;
|
|
225 }
|
|
226 return (p2);
|
|
227 }
|
|
228
|
|
229
|
|
230
|
|
231 struct mailbag *whatnow (whichway, envelop, direction)
|
|
232 flag whichway, *direction;
|
|
233 register MAILPTR envelop;
|
|
234 {
|
|
235 MAILPTR tmpmail;
|
|
236
|
|
237 tmpmail = envelop;
|
|
238 switch (whichway)
|
|
239 {
|
|
240 case DELETE: /* toss letter/envelop, update links */
|
|
241 envelop->status = 'D';
|
|
242 whichway = *direction == FORWARD ? NEXT : PREVIOUS;
|
|
243
|
|
244 case NEXT: /* move to next message */
|
|
245 do
|
|
246 if ((envelop = envelop->next) == ENDMAIL)
|
|
247 {
|
|
248 if ( !quitmail() )
|
|
249 envelop = tmpmail;
|
|
250 break;
|
|
251 }
|
|
252 while (envelop->status == 'D' || envelop->status == 'B');
|
|
253
|
|
254 *direction = FORWARD;
|
|
255 break;
|
|
256
|
|
257 case PREVIOUS: /* show last message */
|
|
258 do
|
|
259 if ((envelop = envelop->prev) == ENDMAIL)
|
|
260 {
|
|
261 envelop = tmpmail;
|
|
262 break;
|
|
263 }
|
|
264 while (envelop->status == 'D' || envelop->status == 'B');
|
|
265
|
|
266 *direction = REVERSE;
|
|
267 break;
|
|
268
|
|
269 case BADLETTER: /* damaged letter or header, skip it */
|
|
270 envelop->status = 'B';
|
|
271 envelop = *direction == FORWARD ? envelop->next != ENDMAIL
|
|
272 ? envelop->next : envelop
|
|
273 : envelop->next != ENDMAIL
|
|
274 ? envelop->prev : envelop;
|
|
275 break;
|
|
276
|
|
277 case AGAIN: /* show current message again */
|
|
278 default:
|
|
279 break;
|
|
280 }
|
|
281 return (envelop);
|
|
282 }
|
|
283
|
|
284
|
|
285
|
|
286 /* mark all mail as either all read or all deleted. If KILLMAIL is TRUE, all
|
|
287 mail will be deleted and mail will exit immediately. Therefore, killed
|
|
288 mail cannot be restored with the 'x' or 'u' commands. --REB */
|
|
289
|
|
290 int markallmail (firstenvelop, nokilli)
|
|
291 MAILPTR firstenvelop;
|
|
292 flag nokilli;
|
|
293 {
|
|
294 register MAILPTR envelop;
|
|
295
|
|
296 for (envelop = firstenvelop; envelop; envelop = envelop->next)
|
|
297 envelop->status = nokilli ? 'P' : 'D';
|
|
298 }
|
|
299
|
|
300
|
|
301
|
|
302 /* make mail we deleted in this session readable again */
|
|
303
|
|
304 int undeletemail (firstenvelop, ltrsleft)
|
|
305 MAILPTR firstenvelop;
|
|
306 int *ltrsleft;
|
|
307 {
|
|
308 char line[256];
|
|
309 MAILPTR envelop;
|
|
310 register char *p;
|
|
311 char c;
|
|
312 FILE *fp;
|
|
313 int i;
|
|
314
|
|
315 p = line;
|
|
316 envelop = firstenvelop;
|
|
317 do
|
|
318 if (envelop->status == 'D')
|
|
319 if ((fp = fopen (envelop->letter, "r")) != NULL)
|
|
320 {
|
|
321 /* print header... */
|
|
322 cls();
|
|
323
|
|
324 while (mfgets (p, sizeof (line), fp) != NULL)
|
|
325 {
|
|
326 if (!*p)
|
|
327 break;
|
|
328
|
|
329 puts (p);
|
|
330 }
|
|
331
|
|
332 /* ...and first four lines of message */
|
|
333 putchar ('\n');
|
|
334
|
|
335 for (i = 0; i < 4; ++i)
|
|
336 if (mfgets (p, sizeof (line), fp) == NULL)
|
|
337 break;
|
|
338 else
|
|
339 puts (p);
|
|
340
|
|
341 fclose (fp);
|
|
342 fputs ("\n\nUndelete this or resume reading? Y/n/r...",
|
|
343 stdout);
|
|
344
|
|
345 fflush (stdout);
|
|
346 c = tolower ( getresponse() );
|
|
347 switch (c)
|
|
348 {
|
|
349 case 'r':
|
|
350 return (0);
|
|
351
|
|
352 case 'n':
|
|
353 break;
|
|
354
|
|
355 case 'y':
|
|
356 default:
|
|
357 envelop->status = 'P';
|
|
358 ++(*ltrsleft);
|
|
359 break;
|
|
360 }
|
|
361 }
|
|
362 while ((envelop = envelop->next) != ENDMAIL);
|
|
363
|
|
364 fputs ("\n\nHit ENTER to read mail...", stdout);
|
|
365 fflush (stdout);
|
|
366 getresponse();
|
|
367 return (0);
|
|
368 }
|
|
369
|
|
370
|
|
371
|
|
372 /* returns TRUE if user wants to exit after reading last message --REB */
|
|
373
|
|
374 int quitmail()
|
|
375 {
|
|
376 register char c;
|
|
377 char answer;
|
|
378
|
|
379 putchar ('\n');
|
|
380 ReVOn();
|
|
381 fputs (" Last message...quit? y/N ", stdout);
|
|
382 ReVOff();
|
|
383 c = tolower ( getresponse() );
|
|
384 CurUp();
|
|
385 putchar ('\n');
|
|
386 ErEOLine();
|
|
387 CurUp();
|
|
388 putchar ('\n');
|
|
389
|
|
390 if (c == 'y')
|
|
391 {
|
|
392 putchar (' ');
|
|
393 fflush (stdout);
|
|
394 }
|
|
395 return (c == 'y' ? TRUE : FALSE);
|
|
396 }
|
|
397
|
|
398
|
|
399
|
|
400 int openenvelop (envelop)
|
|
401 MAILPTR envelop;
|
|
402 {
|
|
403 FILE *infile;
|
|
404 flag whichway;
|
|
405 register char c;
|
|
406
|
|
407 if ((infile = fopen (envelop->letter, "r")) == NULL)
|
|
408 {
|
|
409 printf ("\n%s: glue too strong...can't open '%s'\n",
|
|
410 pname, envelop->letter);
|
|
411
|
|
412 /* give 'em a chance to read */
|
|
413 sleep (2);
|
|
414
|
|
415 /* letter disappear on us? remove it from mail..list */
|
|
416 return (errno == 216 ? DELETE : BADLETTER);
|
|
417 }
|
|
418
|
|
419 /* display incoming mail */
|
|
420 if (getmsg (infile))
|
|
421 {
|
|
422 if (usepager)
|
|
423 {
|
|
424 sprintf (temp, "%s %s", pager, envelop->letter);
|
|
425 docmd_na (temp);
|
|
426 whichway = mailcmd (envelop->letter);
|
|
427 }
|
|
428 else
|
|
429 {
|
|
430 c = dspmail (infile, envelop->status);
|
|
431 switch (tolower (c))
|
|
432 {
|
|
433 /* want to see letter again */
|
|
434 case 'a':
|
|
435 whichway = AGAIN;
|
|
436 break;
|
|
437
|
|
438 /* want to see previous letter */
|
|
439 case 'p':
|
|
440 case '-':
|
|
441 whichway = PREVIOUS;
|
|
442 break;
|
|
443
|
|
444 /* go on to next letter */
|
|
445 case 'n':
|
|
446 whichway = NEXT;
|
|
447 break;
|
|
448
|
|
449 /* exit immediately, leaving mail unchanged */
|
|
450 case 'x':
|
|
451 exit (0);
|
|
452
|
|
453 /* we need help */
|
|
454 case 'h':
|
|
455 case '?':
|
|
456 givehelp();
|
|
457 /* fall through */
|
|
458
|
|
459 /* continue with the current letter */
|
|
460 default:
|
|
461 whichway = mailcmd (envelop->letter);
|
|
462 break;
|
|
463 }
|
|
464 }
|
|
465 if (envelop->status != 'D' && envelop->status != 'B')
|
|
466 envelop->status = 'P';
|
|
467 }
|
|
468 else
|
|
469 {
|
|
470 whichway = BADLETTER;
|
|
471 printf ("\n%s: letter %s's header has illegible handwriting\n",
|
|
472 pname, envelop->letter);
|
|
473 sleep (2); /* short pause */
|
|
474 }
|
|
475
|
|
476 /* close the letter file */
|
|
477 fclose (infile);
|
|
478 return (whichway);
|
|
479 }
|
|
480
|
|
481
|
|
482
|
|
483 /* getmsg --get message
|
|
484
|
|
485 Get header info from next mail message in the spooled mail directory.
|
|
486 */
|
|
487
|
|
488 int getmsg (file)
|
|
489 FILE *file;
|
|
490 {
|
|
491 char replyto[100], replynam[100], resentrply[100], resentfrm[100];
|
|
492 char resentnam[100], resentdate[40], resentid[100];
|
|
493 register char *lp;
|
|
494 char *p;
|
|
495 flag header;
|
|
496
|
|
497 *subject = *fromdate = *frommsgid = *fromname = '\0';
|
|
498 *sender = *replynam = *resentrply = *resentfrm = '\0';
|
|
499 *resentdate = *resentid = '\0';
|
|
500 header = TRUE;
|
|
501 lp = line;
|
|
502
|
|
503 /* be sure this are all cleared out -- REB */
|
|
504 memset (address, '\0', sizeof (address));
|
|
505 memset (replyto, '\0', sizeof (replyto));
|
|
506
|
|
507 /* Are we still in the header? If so, look at line */
|
|
508 while (header)
|
|
509 if (mfgets (lp, sizeof (line), file) != NULL)
|
|
510 {
|
|
511 if (*lp == '\0')
|
|
512 {
|
|
513 header = FALSE;
|
|
514 continue;
|
|
515 }
|
|
516
|
|
517 /* Be paranoid and extract From return path this will be
|
|
518 overwritten by From: or Reply-to:, if found. */
|
|
519
|
|
520 if (*lp == '>' && strncmp (lp, ">From ", 6) == 0)
|
|
521 {
|
|
522 strcpy (temp, skipspace (lp+5));
|
|
523 for (p = temp; !isspace (*p) && *p != '\0'; p++)
|
|
524 ;
|
|
525
|
|
526 *p = '\0';
|
|
527 strcpy (address, temp);
|
|
528 }
|
|
529
|
|
530 /* extract From: return path + fromname */
|
|
531 if (*lp == 'F' && strnucmp (lp, Hfrom, 6) == 0)
|
|
532 {
|
|
533 strcpy (address, getval (lp));
|
|
534 strcpy (fromname, getrealname (lp));
|
|
535 }
|
|
536
|
|
537 /* extract Sender: return path */
|
|
538 if (*lp == 'S' && strnucmp (lp, Hsender, 8) == 0)
|
|
539 strcpy (sender, getval (lp));
|
|
540
|
|
541 /* Reply-To, Resent-Reply-To, Resent-From: fields */
|
|
542 if (*lp == 'R')
|
|
543 {
|
|
544 /* extract Reply-To: return path */
|
|
545 if (strnucmp (lp, Hreplyto, 10) == 0)
|
|
546 {
|
|
547 strcpy (replyto, getval (lp));
|
|
548 strcpy (replynam, getrealname (lp));
|
|
549 }
|
|
550
|
|
551 /* extract Resent-From: path */
|
|
552 else if (strnucmp (lp, "Resent-From: ", 13) == 0)
|
|
553 {
|
|
554 strcpy (resentfrm, getval (lp));
|
|
555 strcpy (resentnam, getrealname (lp));
|
|
556 }
|
|
557
|
|
558 /* extract Resent-Reply-To: path */
|
|
559 else if (strnucmp (lp, "Resent-Reply-To: ", 17) == 0)
|
|
560 {
|
|
561 strcpy (resentrply, getval (lp));
|
|
562 strcpy (resentnam, getrealname (lp));
|
|
563 }
|
|
564
|
|
565 /* extract Resent-Date */
|
|
566 else if (strnucmp (lp, "Resent-Date: ", 13) == 0)
|
|
567 strcpy (resentdate, getstring (lp));
|
|
568
|
|
569 /* extract Resent-Message-Id */
|
|
570 else if (strnucmp (lp, "Resent-Message-Id: ", 19) == 0)
|
|
571 strcpy (resentid, getval (lp));
|
|
572 }
|
|
573
|
|
574 /* extract message ID */
|
|
575 if (*lp == 'M' && *resentid == '\0'
|
|
576 && strnucmp (lp, "Message-Id: ", 12) == 0)
|
|
577 {
|
|
578 strcpy (frommsgid, getval (lp));
|
|
579 }
|
|
580
|
|
581 /* extract message time */
|
|
582 if (*lp == 'D' && *resentdate == '\0'
|
|
583 && strnucmp (lp, Hdate, 6) == 0)
|
|
584 {
|
|
585 strncpy (fromdate, getstring (lp), sizeof (fromdate));
|
|
586 }
|
|
587
|
|
588 /* extract subject */
|
|
589 if (*lp == 'S' && strnucmp (lp, Hsubject, 9) == 0 ||
|
|
590 strnucmp (lp, Hsubj, 6) == 0)
|
|
591 {
|
|
592 if (*subject == '\0')
|
|
593 {
|
|
594 strcpy (temp, getstring (lp));
|
|
595
|
|
596 if (strnucmp (temp, "Re:", 3) != 0)
|
|
597 strcpy (subject, "Re: ");
|
|
598
|
|
599 strcat (subject, temp);
|
|
600 }
|
|
601 }
|
|
602 }
|
|
603 else
|
|
604 /* header ended prematurely */
|
|
605 return (FALSE);
|
|
606
|
|
607 /* Resent-Date overrides Date: --REB */
|
|
608 if (*resentdate != '\0')
|
|
609 strncpy (fromdate, resentdate, sizeof (fromdate));
|
|
610
|
|
611 /* be sure fromdate is properly terminated */
|
|
612 fromdate[sizeof (fromdate) - 1] = '\0';
|
|
613
|
|
614 /* Resent-Message-Id: overrides Message-Id: --REB */
|
|
615 if (*resentid != '\0')
|
|
616 {
|
|
617 strncpy (frommsgid, resentid, sizeof (fromdate));
|
|
618 frommsgid[sizeof (frommsgid) - 1] = '\0';
|
|
619 }
|
|
620
|
|
621 /* Resent-Reply-To: supercedes From: in determining return path
|
|
622 -or- Resent-From: supercedes From: in determining return path
|
|
623 -or- Reply-To: supercedes From: in determining return path */
|
|
624
|
|
625 if (*resentrply != '\0')
|
|
626 {
|
|
627 strcpy (address, resentrply);
|
|
628 strcpy (fromname, resentnam);
|
|
629 }
|
|
630 else if (*resentfrm != '\0')
|
|
631 {
|
|
632 strcpy (address, resentfrm);
|
|
633 strcpy (fromname, resentnam);
|
|
634 }
|
|
635 else if (*replyto != '\0')
|
|
636 {
|
|
637 strcpy (address, replyto);
|
|
638 strcpy (fromname, replynam);
|
|
639 }
|
|
640
|
|
641 if (*fromname == '\0')
|
|
642 strcpy (fromname, address);
|
|
643
|
|
644 rewind (file);
|
|
645 return (TRUE);
|
|
646 }
|
|
647
|
|
648
|
|
649
|
|
650 /* dspmail --display mail message */
|
|
651
|
|
652 char dspmail (file, status)
|
|
653 register FILE *file;
|
|
654 char status;
|
|
655 {
|
|
656 static char *returnon = "ahnp-qx?";
|
|
657 static int columns = 79, rows;
|
|
658 static flag firstletter = TRUE;
|
|
659 register char *p;
|
|
660 flag header = TRUE;
|
|
661 int i;
|
|
662 char c, t;
|
|
663
|
|
664 /* Get number of rows from path descriptor. We assume at least an
|
|
665 80 column display is used. */
|
|
666
|
|
667 if (firstletter) /* Changed -- REB */
|
|
668 {
|
|
669 struct sgbuf pd;
|
|
670
|
|
671 rows = (_gs_opt (STDOUT, &pd) != ERROR) ? (int) pd.sg_page : 24;
|
|
672 --rows;
|
|
673 firstletter = FALSE;
|
|
674 }
|
|
675
|
|
676 cls();
|
|
677 i = 0;
|
|
678 c = '\0';
|
|
679 p = line;
|
|
680 while (mfgets (p, sizeof (line), file) != NULL)
|
|
681 {
|
|
682 if (header && *p == '\0')
|
|
683 {
|
|
684 fputs ("Status: ", stdout);
|
|
685 switch (status)
|
|
686 {
|
|
687 case 'N':
|
|
688 puts ("NEW");
|
|
689 break;
|
|
690
|
|
691 case 'U':
|
|
692 puts ("UNREAD");
|
|
693 break;
|
|
694
|
|
695 default:
|
|
696 puts ("READ");
|
|
697 break;
|
|
698 }
|
|
699 header = FALSE;
|
|
700 ++i;
|
|
701 }
|
|
702
|
|
703 if (i >= rows || *p == '\f')
|
|
704 {
|
|
705 ReVOn();
|
|
706 fputs (" --MORE--", stdout);
|
|
707 ReVOff ();
|
|
708 c = tolower ( getresponse() );
|
|
709 CurUp();
|
|
710 putchar('\n');
|
|
711 DelLine();
|
|
712 CurUp();
|
|
713 putchar ('\n');
|
|
714 i = 0;
|
|
715
|
|
716 /* Go to 'mailx>' prompt on <A>gain, <->/<P>revious, <N>ext,
|
|
717 <Q>uit, or e<X>it. Changed --REB */
|
|
718
|
|
719 if (strchr (returnon, c) != NULL)
|
|
720 break;
|
|
721 }
|
|
722 fixline (p);
|
|
723
|
|
724 if (header)
|
|
725 if (!fullheader)
|
|
726 if (strnucmp (p, ">From ", 6) == 0)
|
|
727 goto showit;
|
|
728 else if (strnucmp (p, Hfrom, 6) == 0)
|
|
729 goto showit;
|
|
730 else if (strnucmp (p, "To: ", 4) == 0)
|
|
731 goto showit;
|
|
732 else if (strnucmp (p, Hdate, 6) == 0)
|
|
733 goto showit;
|
|
734 else if (strnucmp (p, Hreplyto, 10) == 0)
|
|
735 goto showit;
|
|
736 else if (strnucmp (p, Hsubject, 9) == 0
|
|
737 || strnucmp (p, Hsubj, 6) == 0)
|
|
738 goto showit;
|
|
739 else if (strnucmp (p, Hcc, 4) == 0)
|
|
740 goto showit;
|
|
741 else if (strnucmp (p, Hsender, 8) == 0)
|
|
742 goto showit;
|
|
743 else if (strnucmp (p, Hx, 2) == 0)
|
|
744 goto showit;
|
|
745 else
|
|
746 continue;
|
|
747 showit: puts (p);
|
|
748 i += (strlen (p) / columns) + 1;
|
|
749 }
|
|
750 fclose (file);
|
|
751
|
|
752 if (c == 'n') /* flush keyboard input */
|
|
753 if ((i = _gs_rdy (0)) > 0)
|
|
754 read (0, temp, i);
|
|
755 return (c);
|
|
756 }
|
|
757
|
|
758
|
|
759
|
|
760 /* Returns PREVIOUS if we want to redisplay the previous message. AGAIN if we
|
|
761 want to redisplay the current message. NEXT if we want to move on to the
|
|
762 next message. DELETE if we deleted the current message. */
|
|
763
|
|
764 int mailcmd (letter)
|
|
765 char *letter;
|
|
766 {
|
|
767 char path[128];
|
|
768 struct fildes fdes;
|
|
769 flag noerror, orig_usesig, orig_cc_prompt, cflag;
|
|
770 int n, f;
|
|
771 register char c;
|
|
772 char *p, *words[WORDSIZE], *tmpAdrs, *tmpSubj;
|
|
773
|
|
774 /* make a copy of the filename in case we reply -- REB */
|
|
775 strcpy (message, letter);
|
|
776
|
|
777 /* run mailx commands for this message */
|
|
778 for (;;)
|
|
779 {
|
|
780 fputs ("\nmailx> ", stdout);
|
|
781 fflush (stdout);
|
|
782 c = tolower ( getresponse() );
|
|
783 switch (c)
|
|
784 {
|
|
785 /* Next message */
|
|
786 case ' ':
|
|
787 case 'n':
|
|
788 case '\n':
|
|
789 return (NEXT);
|
|
790
|
|
791 /* toggle displaying entire or abbreviated header */
|
|
792 case 'z':
|
|
793 fullheader = !fullheader;
|
|
794 backspace (1);
|
|
795 printf ("full header display %s...",
|
|
796 fullheader ? "on" : "off");
|
|
797
|
|
798 fflush (stdout);
|
|
799 #ifndef _OSK
|
|
800 tsleep (60); /* brief pause so */
|
|
801 #else /* everyone can read */
|
|
802 sleep (1); /* the message */
|
|
803 #endif
|
|
804 /* fall through */
|
|
805
|
|
806 /* redisplay the current message */
|
|
807 case 'a':
|
|
808 return (AGAIN);
|
|
809
|
|
810 /* reply command */
|
|
811 case 'r':
|
|
812 /* save current From: */
|
|
813 if ((tmpAdrs = strdup (address)) != NULL)
|
|
814 {
|
|
815 reply = TRUE;
|
|
816 putchar ('\n');
|
|
817 sendmail();
|
|
818 strcpy (address, tmpAdrs);
|
|
819 free (tmpAdrs);
|
|
820 reply = FALSE;
|
|
821 }
|
|
822 else
|
|
823 {
|
|
824 fputs ("mailcmd: can't make copy of From:", stdout);
|
|
825 fflush (stdout);
|
|
826 continue;
|
|
827 }
|
|
828 break;
|
|
829
|
|
830 /* save command -- strip or keep header --REB */
|
|
831 case 's':
|
|
832 case 'w':
|
|
833 /* Set up a flag to tell us later whether or not we need
|
|
834 to reset the uid of the file. We don't want to do this
|
|
835 simple hack for just any file as it would allow anyone
|
|
836 to put a file anywhere in the file system. --BAS 2 */
|
|
837
|
|
838 cflag = FALSE;
|
|
839 p = getinput (path, sizeof (path));
|
|
840
|
|
841 if (*p == '\0')
|
|
842 {
|
|
843 sprintf (fname, "%s/mbox", homedir);
|
|
844 cflag = TRUE;
|
|
845 asetuid (0);
|
|
846 }
|
|
847 else if (*p == '/')
|
|
848 strcpy (fname, p);
|
|
849 else
|
|
850 {
|
|
851 sprintf (fname, "%s/%s", homedir, p);
|
|
852 cflag = TRUE;
|
|
853 asetuid(0);
|
|
854 }
|
|
855 printf ("\nSaving message to %s\n", fname);
|
|
856
|
|
857 /* If you don't check the ownership of the file, then it
|
|
858 is possible to overwrite any file on the same disk as
|
|
859 filename given, if you allow users to make links.
|
|
860 --BAS 2 */
|
|
861
|
|
862 if ((f = open (fname, 1)) > 0)
|
|
863 {
|
|
864 _gs_gfd (f, &fdes, sizeof (fdes));
|
|
865 close (f);
|
|
866
|
|
867 if (myuid != (unsigned)fdes.fd_own)
|
|
868 {
|
|
869 printf ("%s: %s exists and it is not yours\n",
|
|
870 pname, fname);
|
|
871
|
|
872 if (cflag)
|
|
873 asetuid (myuid);
|
|
874 continue;
|
|
875 }
|
|
876 }
|
|
877
|
|
878 /* save message with header */
|
|
879 if (c == 's')
|
|
880 noerror = fileapnd (letter, fname, TRUE);
|
|
881 else
|
|
882 /* save message without header */
|
|
883 noerror = fileapskp (letter, fname, TRUE);
|
|
884
|
|
885 if (noerror == FALSE)
|
|
886 {
|
|
887 printf ("%s: can't save letter to %s...error %d\n",
|
|
888 pname, fname, errno);
|
|
889
|
|
890 asetuid (myuid);
|
|
891 continue;
|
|
892 }
|
|
893
|
|
894 /* If we need to, reset the ownership of the file-BAS 2 */
|
|
895 if (cflag)
|
|
896 {
|
|
897 chown (fname, myuid);
|
|
898 asetuid (myuid);
|
|
899 }
|
|
900
|
|
901 /* delete current message -- REB */
|
|
902 case 'd':
|
|
903 CurUp();
|
|
904 fputs ("\nDelete? y/N ", stdout);
|
|
905 fflush (stdout);
|
|
906 c = tolower ( getresponse() );
|
|
907
|
|
908 if (c == 'y')
|
|
909 return (DELETE);
|
|
910 else
|
|
911 {
|
|
912 CurUp();
|
|
913 putchar ('\n');
|
|
914 ErEOLine();
|
|
915 CurUp();
|
|
916 fflush (stdout);
|
|
917 }
|
|
918 break;
|
|
919
|
|
920 /* redisplay previous message */
|
|
921 case 'p':
|
|
922 case '-':
|
|
923 return (PREVIOUS);
|
|
924
|
|
925 /* forward copy of message to user(s) */
|
|
926 case 'f':
|
|
927 fputs ("orward to: ", stdout);
|
|
928 p = getinput (path, sizeof (path));
|
|
929
|
|
930 if (!*p)
|
|
931 continue;
|
|
932
|
|
933 /* save the current To: */
|
|
934 if ((tmpAdrs = strdup (address)) != NULL)
|
|
935 {
|
|
936 /* clear the old To: */
|
|
937 memset (address, '\0', sizeof (address));
|
|
938 usesig = NOSIG;
|
|
939 forward = TRUE;
|
|
940 n = getargs (words, p, WORDSIZE); /* REB */
|
|
941
|
|
942 if (parse_addr (n, words) != ABORT)
|
|
943 sendmail();
|
|
944
|
|
945 /* restore previous To: */
|
|
946 strcpy (address, tmpAdrs);
|
|
947 free (tmpAdrs);
|
|
948 usesig = USESIG;
|
|
949 forward = FALSE;
|
|
950 }
|
|
951 else
|
|
952 {
|
|
953 fputs ("mailcmd: can't make copy of To:", stdout);
|
|
954 fflush (stdout);
|
|
955 continue;
|
|
956 }
|
|
957 break;
|
|
958
|
|
959 /* mail command...can include command line options d,p and s */
|
|
960 case 'm':
|
|
961 p = getinput (path, sizeof (path));
|
|
962
|
|
963 if (*p == '\0')
|
|
964 continue;
|
|
965
|
|
966 /* save original To: and Subject: */
|
|
967 if ((tmpAdrs = strdup (address)) == NULL)
|
|
968 {
|
|
969 fputs ("mailcmd: cannot save original To:",
|
|
970 stdout);
|
|
971 fflush (stdout);
|
|
972 continue;
|
|
973 }
|
|
974
|
|
975 if ((tmpSubj = strdup (subject)) == NULL)
|
|
976 {
|
|
977 fputs ("mailcmd: cannot save original Subject:",
|
|
978 stdout);
|
|
979 fflush (stdout);
|
|
980 continue;
|
|
981 }
|
|
982
|
|
983 /* clear the address and subject --REB */
|
|
984 memset (address, '\0', sizeof (address));
|
|
985 memset (subject, '\0', sizeof (subject));
|
|
986
|
|
987 /* save original cc_prompt and usesig */
|
|
988 orig_usesig = usesig;
|
|
989 orig_cc_prompt = cc_prompt;
|
|
990 n = getargs (words, p, WORDSIZE);
|
|
991
|
|
992 if (parse_addr (n, words) != ABORT)
|
|
993 sendmail();
|
|
994
|
|
995 /* put back original cc_prompt and usesig */
|
|
996 usesig = orig_usesig;
|
|
997 cc_prompt = orig_cc_prompt;
|
|
998 strcpy (address, tmpAdrs);
|
|
999 free (tmpAdrs);
|
|
1000 strcpy (subject, tmpSubj);
|
|
1001 free (tmpSubj);
|
|
1002 break;
|
|
1003
|
|
1004 /* exit mail after killing deleted mail */
|
|
1005 case 'q':
|
|
1006 return (QUIT);
|
|
1007
|
|
1008 /* exit without touch any mail */
|
|
1009 case 'x':
|
|
1010 interrupt (0);
|
|
1011
|
|
1012 /* make ALL deleted mail readable again */
|
|
1013 case 'u':
|
|
1014 return (UNDELETE);
|
|
1015
|
|
1016 /* fork a shell for the user */
|
|
1017 case '!':
|
|
1018 forkshell();
|
|
1019 fputs ("\b ", stdout);
|
|
1020 CurUp();
|
|
1021 break;
|
|
1022
|
|
1023 /* help command */
|
|
1024 case 'h':
|
|
1025 case '?':
|
|
1026 givehelp();
|
|
1027 break;
|
|
1028
|
|
1029 /* mark all mail read --REB */
|
|
1030 case 'c':
|
|
1031 backspace (1);
|
|
1032 fputs ("marking all mail as read...", stdout);
|
|
1033 fflush (stdout);
|
|
1034 return (ALLREAD);
|
|
1035
|
|
1036 /* delete ALL mail then exit */
|
|
1037 case 'k':
|
|
1038 backspace (1);
|
|
1039 fputs ("delete ALL mail? y/N ", stdout);
|
|
1040 fflush (stdout);
|
|
1041 c = tolower ( getresponse() );
|
|
1042 backspace (23);
|
|
1043
|
|
1044 if (c == 'y')
|
|
1045 {
|
|
1046 fputs ("are you sure? y/N ", stdout);
|
|
1047 fflush (stdout);
|
|
1048 c = tolower ( getresponse() );
|
|
1049 backspace (20);
|
|
1050
|
|
1051 if (c == 'y')
|
|
1052 {
|
|
1053 fputs ("killing all mail...", stdout);
|
|
1054 fflush (stdout);
|
|
1055 return (KILLMAIL);
|
|
1056 }
|
|
1057 }
|
|
1058 CurUp();
|
|
1059 fflush (stdout);
|
|
1060 break;
|
|
1061
|
|
1062 /* toggle file viewer on or off --REB */
|
|
1063 case 'v':
|
|
1064 fputs ("iewer ", stdout);
|
|
1065
|
|
1066 if (*pager != '\0')
|
|
1067 {
|
|
1068 usepager = !usepager;
|
|
1069 printf ("now %s...", usepager ? "on" : "off");
|
|
1070 fflush (stdout);
|
|
1071 #ifndef _OSK
|
|
1072 loadpager (usepager ? TRUE: FALSE);
|
|
1073 #endif
|
|
1074 }
|
|
1075 else
|
|
1076 {
|
|
1077 fputs ("is not defined...", stdout);
|
|
1078 fflush (stdout);
|
|
1079 }
|
|
1080 break;
|
|
1081
|
|
1082 #ifdef FIXME
|
|
1083 /* current message is piped to standard input of a program */
|
|
1084 case '|':
|
|
1085 p = getinput (path, sizeof (path));
|
|
1086
|
|
1087 if (*p == NULL)
|
|
1088 continue;
|
|
1089
|
|
1090 dopipe (letter, p);
|
|
1091 break;
|
|
1092 #endif
|
|
1093 default:
|
|
1094 printf ("\nUnknown command: %c\n", c);
|
|
1095 break;
|
|
1096 }
|
|
1097 }
|
|
1098 }
|
|
1099
|
|
1100
|
|
1101
|
|
1102 /* get a single character response from the user */
|
|
1103
|
|
1104 char getresponse()
|
|
1105 {
|
|
1106 char c;
|
|
1107
|
|
1108 /* wait for valid input */
|
|
1109 echo (OFF);
|
|
1110 do
|
|
1111 {
|
|
1112 while (_gs_rdy (0) <= 0)
|
|
1113 tsleep (4);
|
|
1114
|
|
1115 read (0, &c, 1);
|
|
1116 }
|
|
1117 while (c < '\x20' && c > '\x7f');
|
|
1118
|
|
1119 echo (ON);
|
|
1120 if (c != '\n' && c != ' ')
|
|
1121 {
|
|
1122 putchar (c);
|
|
1123 fflush (stdout);
|
|
1124 }
|
|
1125 return (c);
|
|
1126 }
|
|
1127
|
|
1128
|
|
1129
|
|
1130 /* Open double overlay windows for keyboard user--white on red over black on
|
|
1131 black. Should only be called by CoCo when TERMCAP is not defined. */
|
|
1132
|
|
1133 #ifndef TERMCAP
|
|
1134 int popdoublewindow (x, y, width, height)
|
|
1135 int x, y, width, height;
|
|
1136 {
|
|
1137 char outstr[18];
|
|
1138
|
|
1139 /* turn off the cursor */
|
|
1140 write (1, "\x05\x20", 2);
|
|
1141
|
|
1142 *(outstr + 0) = *(outstr + 9) = 0x1b;
|
|
1143 *(outstr + 1) = *(outstr + 10) = 0x22;
|
|
1144 *(outstr + 2) = *(outstr + 11) = 1;
|
|
1145 *(outstr + 5) = *(outstr + 14) = width;
|
|
1146 *(outstr + 6) = *(outstr + 15) = height;
|
|
1147
|
|
1148 /* bottom window */
|
|
1149 *(outstr + 3) = x + 1; /* offset bottom window */
|
|
1150 *(outstr + 4) = y + 1;
|
|
1151 *(outstr + 7) = 2; /* black on black */
|
|
1152 *(outstr + 8) = 2;
|
|
1153
|
|
1154 /* top window */
|
|
1155 *(outstr + 12) = x;
|
|
1156 *(outstr + 13) = y;
|
|
1157 *(outstr + 16) = 0; /* white on red */
|
|
1158 *(outstr + 17) = 4;
|
|
1159
|
|
1160 write (1, outstr, sizeof (outstr));
|
|
1161 winopen = TRUE;
|
|
1162 }
|
|
1163
|
|
1164
|
|
1165
|
|
1166 /* Close double overlay window */
|
|
1167
|
|
1168 int closedoublewindow()
|
|
1169 {
|
|
1170 write (1, "\x1b\x23\x1b\x23\x08 \n\x09\x05\x21", 11);
|
|
1171 winopen = FALSE;
|
|
1172 }
|
|
1173 #endif
|
|
1174
|
|
1175
|
|
1176 /* backspace-space-backspace to delete part of a line */
|
|
1177
|
|
1178 int backspace (howmany)
|
|
1179 int howmany;
|
|
1180 {
|
|
1181 register int i;
|
|
1182
|
|
1183 for (i = 0; i < howmany; ++i)
|
|
1184 fputs ("\b \b", stdout);
|
|
1185
|
|
1186 fflush (stdout);
|
|
1187 }
|
|
1188
|
|
1189
|
|
1190
|
|
1191 int putdashes (howmany)
|
|
1192 int howmany;
|
|
1193 {
|
|
1194 register int i;
|
|
1195
|
|
1196 putchar (' ');
|
|
1197
|
|
1198 for (i = 0; i < howmany; ++i)
|
|
1199 putchar ('=');
|
|
1200
|
|
1201 fflush (stdout);
|
|
1202 }
|
|
1203
|
|
1204
|
|
1205
|
|
1206 void givehelp()
|
|
1207 {
|
|
1208 register char **hlp;
|
|
1209 static char *helptxt[] = {
|
|
1210 "a\t\t redisplay current message",
|
|
1211 "c\t\t mark all mail as read",
|
|
1212 "d\t\t delete current message",
|
|
1213 "f\t\t forward current message",
|
|
1214 "h, ?\t this message",
|
|
1215 "k\t\t delete ALL mail",
|
|
1216 "m <address> send mail to <address>",
|
|
1217 "n/ENTER/SPACE go to next message",
|
|
1218 "p, -\t show previous message",
|
|
1219 "q\t\t update and exit",
|
|
1220 "r\t\t reply to this message",
|
|
1221 "s [filename] save message to 'filename'",
|
|
1222 "\t\t default is 'mbox'",
|
|
1223 "u\t\t undelete mail",
|
|
1224 "v\t\t toggle using file viewer",
|
|
1225 "w [filename] save message without header to",
|
|
1226 "\t\t 'filename', default is 'mbox'",
|
|
1227 "x\t\t exit with no updating",
|
|
1228 "z\t\t toggle message header display",
|
|
1229 "!\t\t fork a shell",
|
|
1230 #ifdef FIXME
|
|
1231 "|cmd\t run 'cmd' with current message",
|
|
1232 "\t\t as input",
|
|
1233 #endif
|
|
1234 NULL
|
|
1235 };
|
|
1236
|
|
1237 #ifndef TERMCAP
|
|
1238 if (t2flag)
|
|
1239 puts ("\n");
|
|
1240 else
|
|
1241 {
|
|
1242 popdoublewindow (31, 0, 48, 22);
|
|
1243 putdashes (17);
|
|
1244 printf (" Mailx v%s", version);
|
|
1245 putdashes (17);
|
|
1246 putchar (' ');
|
|
1247 }
|
|
1248 #else
|
|
1249 putchar ('\n');
|
|
1250 putdashes (17);
|
|
1251 printf ("Mailx v%s", version);
|
|
1252 putdashes (17);
|
|
1253 putchar ('\n');
|
|
1254 #endif
|
|
1255 for (hlp = helptxt; *hlp; ++hlp)
|
|
1256 printf (" %s\n", strdetab (strcpy (temp, *hlp), 7));
|
|
1257
|
|
1258 #ifndef TERMCAP
|
|
1259 if (t2flag)
|
|
1260 putchar ('\n');
|
|
1261 else
|
|
1262 {
|
|
1263 putdashes (46);
|
|
1264 getresponse();
|
|
1265 closedoublewindow();
|
|
1266 }
|
|
1267 #else
|
|
1268 putdashes (46);
|
|
1269 putchar ('\n');
|
|
1270 #endif
|
|
1271 }
|