1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: newmail.c 1266 2009-07-14 18:39:12Z hubert@u.washington.edu $";
3 #endif
4 
5 /*
6  * ========================================================================
7  * Copyright 2013-2021 Eduardo Chappa
8  * Copyright 2009 University of Washington
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *     http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * ========================================================================
17  */
18 
19 #include "../pith/headers.h"
20 #include "../pith/newmail.h"
21 #include "../pith/conf.h"
22 #include "../pith/flag.h"
23 #include "../pith/mailindx.h"
24 #include "../pith/msgno.h"
25 #include "../pith/bldaddr.h"
26 #include "../pith/stream.h"
27 #include "../pith/sort.h"
28 #include "../pith/status.h"
29 #include "../pith/util.h"
30 #include "../pith/thread.h"
31 #include "../pith/options.h"
32 #include "../pith/folder.h"
33 #include "../pith/ablookup.h"
34 
35 #ifdef _WINDOWS
36 #include "../pico/osdep/mswin.h"
37 #endif
38 
39 
40 /*
41  * Internal prototypes
42  */
43 void new_mail_win_mess(MAILSTREAM *, long);
44 void new_mail_mess(MAILSTREAM *, long, long, int);
45 void newmailfifo(int, char *, char *, char *);
46 
47 
48 /*----------------------------------------------------------------------
49      pith optional function to queue a newmail announcement
50 
51 
52   ----*/
53 void
newmail_status_message(MAILSTREAM * stream,long n,long t_nm_count)54 newmail_status_message(MAILSTREAM *stream, long n, long t_nm_count)
55 {
56 #ifdef _WINDOWS
57     if(mswin_newmailwinon())
58       new_mail_win_mess(stream, t_nm_count);
59 #elif !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
60     if(ps_global->VAR_FIFOPATH)
61       new_mail_win_mess(stream, t_nm_count);
62 #endif
63     if(n){
64       new_mail_mess(stream, sp_mail_since_cmd(stream), n, 0);
65     }
66 }
67 
68 
69 /*
70  * alert for each new message individually.  new_mail_mess lumps
71  * messages together, we call new_mail_mess with 1 message at a time.
72  * This is currently for PC-Pine new mail window, but could probably
73  * be used more generally.
74  *      stream - new mail stream
75  *      number - number of new messages to alert for
76  */
77 void
new_mail_win_mess(MAILSTREAM * stream,long int number)78 new_mail_win_mess(MAILSTREAM *stream, long int number)
79 {
80     int n, i;
81     MESSAGECACHE *mc;
82 
83     if(!stream)
84       return;
85 
86     /*
87      * spare6, or MN_STMP, should be safe to use for now, we
88      * just want to set which messages to alert about before
89      * going to c-client.
90      */
91     for(n = stream->nmsgs, i = 0; n > 1L && i < number; n--){
92 	if(!get_lflag(stream, NULL, n, MN_EXLD)){
93 	    mc = mail_elt(stream, n);
94 	    if(mc)
95 	      mc->spare6 = 1;
96 
97 	    if(++i == number)
98 	      break;
99 	}
100 	else{
101 	    mc = mail_elt(stream, n);
102 	    if(mc)
103 	      mc->spare6 = 0;
104 	}
105     }
106     /*
107      * Here n is the first new message we want to notify about.
108      * spare6 will tell us which ones to use.  We set spare6
109      * in case of new mail or expunge that could happen when
110      * we mail_fetchstructure in new_mail_mess.
111      */
112     for(; n <= stream->nmsgs; n++)
113       if(n > 0L && (mc = mail_elt(stream, n)) && mc->spare6){
114 	  mc->spare6 = 0;
115 	  new_mail_mess(stream, 1, n, 1);
116       }
117 }
118 
119 
120 /*----------------------------------------------------------------------
121      Format and queue a "new mail" message
122 
123   Args: stream     -- mailstream on which a mail has arrived
124         number     -- number of new messages since last command
125         max_num    -- The number of messages now on stream
126 	for_new_mail_win -- for separate new mail window (curr. PC-Pine)
127 
128  Not too much worry here about the length of the message because the
129 status_message code will fit what it can on the screen and truncation on
130 the right is about what we want which is what will happen.
131   ----*/
132 void
new_mail_mess(MAILSTREAM * stream,long int number,long int max_num,int for_new_mail_win)133 new_mail_mess(MAILSTREAM *stream, long int number, long int max_num, int for_new_mail_win)
134 {
135     char      subject[MAILTMPLEN+1], subjtext[MAILTMPLEN+1], from[MAILTMPLEN+1],
136 	     *folder = NULL, intro[MAILTMPLEN+1];
137     ENVELOPE *e = NULL;
138 
139     if(stream)
140       e = pine_mail_fetchstructure(stream, max_num, NULL);
141 
142     if(stream){
143 	if(sp_flagged(stream, SP_INBOX))
144 	  folder = NULL;
145 	else{
146 	    folder = STREAMNAME(stream);
147 	    if(folder[0] == '?' && folder[1] == '\0')
148 	      folder = NULL;
149 	}
150     }
151 
152     format_new_mail_msg(folder, number, e, intro, from, subject, subjtext, sizeof(subject));
153 
154     if(!for_new_mail_win)
155       q_status_message5(SM_ASYNC | SM_DING, 0, 60,
156 		      "%s%s%s%.80s%.80s", intro,
157  		      from && from[0] ? ((number > 1L) ? " Most recent f" : " F") : "",
158  		      from && from[0] ? "rom " : "",
159  		      from && from[0] ? from : "",
160 		      subjtext);
161 #if (!defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)) || defined(_WINDOWS)
162     else {
163 	int is_us = 0;
164 	ADDRESS *tadr;
165 
166 	if(e)
167 	  for(tadr = e->to; tadr; tadr = tadr->next)
168 	    if(address_is_us(tadr, ps_global)){
169 		is_us = 1;
170 		break;
171 	    }
172 #ifdef _WINDOWS
173 	mswin_newmailwin(is_us, from, subject, folder);
174 #else
175 	newmailfifo(is_us, from, subject, folder);
176 #endif
177     }
178 #endif
179 
180     if(pith_opt_icon_text){
181 	if(F_ON(F_ENABLE_XTERM_NEWMAIL, ps_global)
182 	   && F_ON(F_ENABLE_NEWMAIL_SHORT_TEXT, ps_global)){
183 	    long inbox_nm;
184 	    if(!sp_flagged(stream, SP_INBOX)
185 	       && (inbox_nm = sp_mail_since_cmd(sp_inbox_stream()))){
186 		snprintf(tmp_20k_buf, SIZEOF_20KBUF, "[%ld, %ld] %s",
187 			 inbox_nm > 1L ? inbox_nm : 1L,
188 			 number > 1L ? number: 1L,
189 			 ps_global->pine_name);
190 	    }
191 	    else
192 	      snprintf(tmp_20k_buf, SIZEOF_20KBUF, "[%ld] %s", number > 1L ? number: 1L,
193 		       ps_global->pine_name);
194 	}
195 	else
196 	  snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s%s%s%.80s", intro,
197 		   from && from[0] ? ((number > 1L) ? " Most recent f" : " F") : "",
198 		   from && from[0] ? "rom " : "",
199 		   from && from[0] ? from : "");
200 
201 	(*pith_opt_icon_text)(tmp_20k_buf, IT_NEWMAIL);
202     }
203 }
204 
205 
206 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
207 static char *fifoname = NULL;
208 static int   fifoopenerrmsg = 0;
209 static int   fifofd = -1;
210 static int   fifoheader = 0;
211 
212 void
init_newmailfifo(char * fname)213 init_newmailfifo(char *fname)
214 {
215     if(fifoname)
216       close_newmailfifo();
217 
218     if(!(fname && *fname))
219       return;
220 
221     if(!fifoname){
222 	if(mkfifo(fname, 0600) == -1){
223 	    q_status_message2(SM_ORDER,3,3,
224 			      "Can't create NewMail FIFO \"%s\": %s",
225 			      fname, error_description(errno));
226 	    return;
227 	}
228 	else
229 	  q_status_message1(SM_ORDER,0,3, "NewMail FIFO: \"%s\"", fname);
230 
231 	fifoname = cpystr(fname);
232     }
233 }
234 
235 
236 void
close_newmailfifo(void)237 close_newmailfifo(void)
238 {
239     if(fifoname){
240 	if(fifofd >= 0)
241 	  (void) close(fifofd);
242 
243 	if(*fifoname)
244 	  our_unlink(fifoname);
245 
246 	fs_give((void **) &fifoname);
247     }
248 
249     fifoheader = 0;
250     fifoname = NULL;
251     fifofd = -1;
252     fifoopenerrmsg = 0;
253 }
254 
255 
256 void
newmailfifo(int is_us,char * from,char * subject,char * folder)257 newmailfifo(int is_us, char *from, char *subject, char *folder)
258 {
259     char buf[MAX_SCREEN_COLS+1], buf2[MAX_SCREEN_COLS+1];
260     char buf3[MAX_SCREEN_COLS+1], buf4[MAX_SCREEN_COLS+1];
261 
262     if(!(fifoname && *fifoname)){
263 	if(fifoname)
264 	  close_newmailfifo();
265 
266 	return;
267     }
268 
269     if(fifofd < 0){
270 	fifofd = our_open(fifoname, O_WRONLY | O_NONBLOCK | O_BINARY, 0600);
271 	if(fifofd < 0){
272 	    if(!fifoopenerrmsg){
273 		if(errno == ENXIO)
274 		  q_status_message2(SM_ORDER,0,3, "Nothing reading \"%s\": %s",
275 				    fifoname, error_description(errno));
276 		else
277 		  q_status_message2(SM_ORDER,0,3, "Can't open \"%s\": %s",
278 				    fifoname, error_description(errno));
279 
280 		fifoopenerrmsg++;
281 	    }
282 
283 	    return;
284 	}
285     }
286 
287     if(fifofd >= 0){
288 	int width;
289 	int fromlen, subjlen, foldlen;
290 
291 	width = MIN(MAX(20, ps_global->nmw_width), MAX_SCREEN_COLS);
292 
293 	foldlen = .18 * width;
294 	foldlen = MAX(5, foldlen);
295 	fromlen = .28 * width;
296 	subjlen = width - 2 - foldlen - fromlen;
297 
298 	if(!fifoheader){
299 	    time_t now;
300 	    char *tmtxt;
301 
302 	    now = time((time_t *) 0);
303 	    tmtxt = ctime(&now);
304 	    if(!tmtxt)
305 	      tmtxt = "";
306 
307 	    snprintf(buf, sizeof(buf), "New Mail window started at %.*s\n",
308 		   (int) MIN(100, strlen(tmtxt)-1), tmtxt);
309 	    (void) write(fifofd, buf, strlen(buf));
310 
311 	    snprintf(buf, sizeof(buf), "  %-*s%-*s%-*s\n",
312 		    fromlen, "From:",
313 		    subjlen, "Subject:",
314 		    foldlen, "Folder:");
315 	    (void) write(fifofd, buf, strlen(buf));
316 
317 	    snprintf(buf, sizeof(buf), "%-*.*s\n", width, width, repeat_char(width, '-'));
318 	    (void) write(fifofd, buf, strlen(buf));
319 
320 	    fifoheader++;
321 	}
322 
323 	snprintf(buf, sizeof(buf), "%s %-*.*s %-*.*s %-*.*s\n", is_us ? "+" : " ",
324 		fromlen - 1, fromlen - 1,
325 		short_str(from ? from : "", buf2, sizeof(buf2), fromlen-1, EndDots),
326 		subjlen - 1, subjlen - 1,
327 		short_str(subject ? subject : "(no subject)",
328 			  buf3, sizeof(buf3), subjlen-1, EndDots),
329 		foldlen, foldlen,
330 		short_str(folder ? folder : "INBOX", buf4, sizeof(buf4), foldlen, FrontDots));
331 	(void) write(fifofd, buf, strlen(buf));
332     }
333 }
334 #endif
335