xref: /onnv-gate/usr/src/cmd/mailx/cmd1.c (revision 0)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*0Sstevel@tonic-gate 
25*0Sstevel@tonic-gate 
26*0Sstevel@tonic-gate /*
27*0Sstevel@tonic-gate  * Copyright (c) 1985-2001 by Sun Microsystems, Inc.
28*0Sstevel@tonic-gate  * All rights reserved.
29*0Sstevel@tonic-gate  */
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate /*
32*0Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
33*0Sstevel@tonic-gate  * The Regents of the University of California
34*0Sstevel@tonic-gate  * All Rights Reserved
35*0Sstevel@tonic-gate  *
36*0Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
37*0Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
38*0Sstevel@tonic-gate  * contributors.
39*0Sstevel@tonic-gate  */
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate #include "rcv.h"
44*0Sstevel@tonic-gate #include <locale.h>
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate /*
47*0Sstevel@tonic-gate  * mailx -- a modified version of a University of California at Berkeley
48*0Sstevel@tonic-gate  *	mail program
49*0Sstevel@tonic-gate  *
50*0Sstevel@tonic-gate  * User commands.
51*0Sstevel@tonic-gate  */
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate static char	*dispname(char *hdr);
54*0Sstevel@tonic-gate static void	print(register struct message *mp, FILE *obuf, int doign);
55*0Sstevel@tonic-gate static int	type1(int *msgvec, int doign, int page);
56*0Sstevel@tonic-gate static int	topputs(const char *line, FILE *obuf);
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate void	brokpipe(int sig);
59*0Sstevel@tonic-gate jmp_buf	pipestop;
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate /*
62*0Sstevel@tonic-gate  * Print the current active headings.
63*0Sstevel@tonic-gate  * Don't change dot if invoker didn't give an argument.
64*0Sstevel@tonic-gate  */
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate static int curscreen = 0, oldscreensize = 0;
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate int
69*0Sstevel@tonic-gate headers(int *msgvec)
70*0Sstevel@tonic-gate {
71*0Sstevel@tonic-gate 	register int n, mesg, flag;
72*0Sstevel@tonic-gate 	register struct message *mp;
73*0Sstevel@tonic-gate 	int size;
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate 	size = screensize();
76*0Sstevel@tonic-gate 	n = msgvec[0];
77*0Sstevel@tonic-gate 	if (n != 0)
78*0Sstevel@tonic-gate 		curscreen = (n-1)/size;
79*0Sstevel@tonic-gate 	if (curscreen < 0)
80*0Sstevel@tonic-gate 		curscreen = 0;
81*0Sstevel@tonic-gate 	mp = &message[curscreen * size];
82*0Sstevel@tonic-gate 	if (mp >= &message[msgCount])
83*0Sstevel@tonic-gate 		mp = &message[msgCount - size];
84*0Sstevel@tonic-gate 	if (mp < &message[0])
85*0Sstevel@tonic-gate 		mp = &message[0];
86*0Sstevel@tonic-gate 	flag = 0;
87*0Sstevel@tonic-gate 	mesg = mp - &message[0];
88*0Sstevel@tonic-gate 	if (dot != &message[n-1])
89*0Sstevel@tonic-gate 		dot = mp;
90*0Sstevel@tonic-gate 	if (Hflag)
91*0Sstevel@tonic-gate 		mp = message;
92*0Sstevel@tonic-gate 	for (; mp < &message[msgCount]; mp++) {
93*0Sstevel@tonic-gate 		mesg++;
94*0Sstevel@tonic-gate 		if (mp->m_flag & MDELETED)
95*0Sstevel@tonic-gate 			continue;
96*0Sstevel@tonic-gate 		if (flag++ >= size && !Hflag)
97*0Sstevel@tonic-gate 			break;
98*0Sstevel@tonic-gate 		printhead(mesg);
99*0Sstevel@tonic-gate 		sreset();
100*0Sstevel@tonic-gate 	}
101*0Sstevel@tonic-gate 	if (flag == 0) {
102*0Sstevel@tonic-gate 		printf(gettext("No more mail.\n"));
103*0Sstevel@tonic-gate 		return (1);
104*0Sstevel@tonic-gate 	}
105*0Sstevel@tonic-gate 	return (0);
106*0Sstevel@tonic-gate }
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate /*
109*0Sstevel@tonic-gate  * Scroll to the next/previous screen
110*0Sstevel@tonic-gate  */
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate int
113*0Sstevel@tonic-gate scroll(char arg[])
114*0Sstevel@tonic-gate {
115*0Sstevel@tonic-gate 	register int s, size;
116*0Sstevel@tonic-gate 	int cur[1];
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate 	cur[0] = 0;
119*0Sstevel@tonic-gate 	size = screensize();
120*0Sstevel@tonic-gate 	s = curscreen;
121*0Sstevel@tonic-gate 	switch (*arg) {
122*0Sstevel@tonic-gate 	case 0:
123*0Sstevel@tonic-gate 	case '+':
124*0Sstevel@tonic-gate 		s++;
125*0Sstevel@tonic-gate 		if (s * size > msgCount) {
126*0Sstevel@tonic-gate 			printf(gettext("On last screenful of messages\n"));
127*0Sstevel@tonic-gate 			return (0);
128*0Sstevel@tonic-gate 		}
129*0Sstevel@tonic-gate 		curscreen = s;
130*0Sstevel@tonic-gate 		break;
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 	case '-':
133*0Sstevel@tonic-gate 		if (--s < 0) {
134*0Sstevel@tonic-gate 			printf(gettext("On first screenful of messages\n"));
135*0Sstevel@tonic-gate 			return (0);
136*0Sstevel@tonic-gate 		}
137*0Sstevel@tonic-gate 		curscreen = s;
138*0Sstevel@tonic-gate 		break;
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 	default:
141*0Sstevel@tonic-gate 		printf(gettext("Unrecognized scrolling command \"%s\"\n"), arg);
142*0Sstevel@tonic-gate 		return (1);
143*0Sstevel@tonic-gate 	}
144*0Sstevel@tonic-gate 	return (headers(cur));
145*0Sstevel@tonic-gate }
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate /*
148*0Sstevel@tonic-gate  * Compute what the screen size should be.
149*0Sstevel@tonic-gate  * We use the following algorithm:
150*0Sstevel@tonic-gate  *	If user specifies with screen option, use that.
151*0Sstevel@tonic-gate  *	If baud rate < 1200, use  5
152*0Sstevel@tonic-gate  *	If baud rate = 1200, use 10
153*0Sstevel@tonic-gate  *	If baud rate > 1200, use 20
154*0Sstevel@tonic-gate  */
155*0Sstevel@tonic-gate int
156*0Sstevel@tonic-gate screensize(void)
157*0Sstevel@tonic-gate {
158*0Sstevel@tonic-gate 	register char *cp;
159*0Sstevel@tonic-gate 	register int newscreensize, tmp;
160*0Sstevel@tonic-gate #ifdef	TIOCGWINSZ
161*0Sstevel@tonic-gate 	struct winsize ws;
162*0Sstevel@tonic-gate #endif
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	if ((cp = value("screen")) != NOSTR && (tmp = atoi(cp)) > 0)
165*0Sstevel@tonic-gate 		newscreensize = tmp;
166*0Sstevel@tonic-gate 	else if (baud < B1200)
167*0Sstevel@tonic-gate 		newscreensize = 5;
168*0Sstevel@tonic-gate 	else if (baud == B1200)
169*0Sstevel@tonic-gate 		newscreensize = 10;
170*0Sstevel@tonic-gate #ifdef	TIOCGWINSZ
171*0Sstevel@tonic-gate 	else if (ioctl(fileno(stdout), TIOCGWINSZ, &ws) == 0 && ws.ws_row > 4)
172*0Sstevel@tonic-gate 		newscreensize = ws.ws_row - 4;
173*0Sstevel@tonic-gate #endif
174*0Sstevel@tonic-gate 	else
175*0Sstevel@tonic-gate 		newscreensize = 20;
176*0Sstevel@tonic-gate 	/* renormalize the value of curscreen */
177*0Sstevel@tonic-gate 	if (newscreensize != oldscreensize) {
178*0Sstevel@tonic-gate 		curscreen = curscreen * oldscreensize / newscreensize;
179*0Sstevel@tonic-gate 		oldscreensize = newscreensize;
180*0Sstevel@tonic-gate 	}
181*0Sstevel@tonic-gate 	return (newscreensize);
182*0Sstevel@tonic-gate }
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate /*
185*0Sstevel@tonic-gate  * Print out the headlines for each message
186*0Sstevel@tonic-gate  * in the passed message list.
187*0Sstevel@tonic-gate  */
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate int
190*0Sstevel@tonic-gate from(int *msgvec)
191*0Sstevel@tonic-gate {
192*0Sstevel@tonic-gate 	register int *ip;
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate 	for (ip = msgvec; *ip != NULL; ip++) {
195*0Sstevel@tonic-gate 		printhead(*ip);
196*0Sstevel@tonic-gate 		sreset();
197*0Sstevel@tonic-gate 	}
198*0Sstevel@tonic-gate 	if (--ip >= msgvec)
199*0Sstevel@tonic-gate 		dot = &message[*ip - 1];
200*0Sstevel@tonic-gate 	return (0);
201*0Sstevel@tonic-gate }
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate /*
204*0Sstevel@tonic-gate  * Print out the header of a specific message.
205*0Sstevel@tonic-gate  * This is a slight improvement to the standard one.
206*0Sstevel@tonic-gate  */
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate void
209*0Sstevel@tonic-gate printhead(int mesg)
210*0Sstevel@tonic-gate {
211*0Sstevel@tonic-gate 	struct message *mp;
212*0Sstevel@tonic-gate 	FILE *ibuf;
213*0Sstevel@tonic-gate 	char headline[LINESIZE], *subjline, dispc, curind;
214*0Sstevel@tonic-gate 	char *fromline;
215*0Sstevel@tonic-gate 	char pbuf[LINESIZE];
216*0Sstevel@tonic-gate 	char name[LINESIZE];
217*0Sstevel@tonic-gate 	struct headline hl;
218*0Sstevel@tonic-gate 	register char *cp;
219*0Sstevel@tonic-gate 	int showto;
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate 	mp = &message[mesg-1];
222*0Sstevel@tonic-gate 	ibuf = setinput(mp);
223*0Sstevel@tonic-gate 	readline(ibuf, headline);
224*0Sstevel@tonic-gate 	if ((subjline = hfield("subject", mp, addone)) == NOSTR &&
225*0Sstevel@tonic-gate 	    (subjline = hfield("subj", mp, addone)) == NOSTR &&
226*0Sstevel@tonic-gate 	    (subjline = hfield("message-status", mp, addone)) == NOSTR)
227*0Sstevel@tonic-gate 		subjline = "";
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	curind = (!Hflag && dot == mp) ? '>' : ' ';
230*0Sstevel@tonic-gate 	dispc = ' ';
231*0Sstevel@tonic-gate 	showto = 0;
232*0Sstevel@tonic-gate 	if ((mp->m_flag & (MREAD|MNEW)) == (MREAD|MNEW))
233*0Sstevel@tonic-gate 		dispc = 'R';
234*0Sstevel@tonic-gate 	if (!(int)value("bsdcompat") && (mp->m_flag & (MREAD|MNEW)) == MREAD)
235*0Sstevel@tonic-gate 		dispc = 'O';
236*0Sstevel@tonic-gate 	if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
237*0Sstevel@tonic-gate 		dispc = 'N';
238*0Sstevel@tonic-gate 	if ((mp->m_flag & (MREAD|MNEW)) == 0)
239*0Sstevel@tonic-gate 		dispc = 'U';
240*0Sstevel@tonic-gate 	if (mp->m_flag & MSAVED)
241*0Sstevel@tonic-gate 		if ((int)value("bsdcompat"))
242*0Sstevel@tonic-gate 			dispc = '*';
243*0Sstevel@tonic-gate 		else
244*0Sstevel@tonic-gate 			dispc = 'S';
245*0Sstevel@tonic-gate 	if (mp->m_flag & MPRESERVE)
246*0Sstevel@tonic-gate 		if ((int)value("bsdcompat"))
247*0Sstevel@tonic-gate 			dispc = 'P';
248*0Sstevel@tonic-gate 		else
249*0Sstevel@tonic-gate 			dispc = 'H';
250*0Sstevel@tonic-gate 	if (mp->m_flag & MBOX)
251*0Sstevel@tonic-gate 		dispc = 'M';
252*0Sstevel@tonic-gate 	parse(headline, &hl, pbuf);
253*0Sstevel@tonic-gate 	if (hl.l_date == NOSTR)
254*0Sstevel@tonic-gate 		hl.l_date = "<Unknown date>";
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 	/*
257*0Sstevel@tonic-gate 	 * Netnews interface?
258*0Sstevel@tonic-gate 	 */
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 	if (newsflg) {
261*0Sstevel@tonic-gate 		if ((fromline = hfield("newsgroups", mp, addone)) == NOSTR &&
262*0Sstevel@tonic-gate 		    (fromline = hfield("article-id", mp, addone)) == NOSTR)
263*0Sstevel@tonic-gate 			fromline = "<>";
264*0Sstevel@tonic-gate 		else
265*0Sstevel@tonic-gate 			for (cp = fromline; *cp; cp++) { /* limit length */
266*0Sstevel@tonic-gate 				if (any(*cp, " ,\n")) {
267*0Sstevel@tonic-gate 					*cp = '\0';
268*0Sstevel@tonic-gate 					break;
269*0Sstevel@tonic-gate 				}
270*0Sstevel@tonic-gate 			}
271*0Sstevel@tonic-gate 	/*
272*0Sstevel@tonic-gate 	 * else regular.
273*0Sstevel@tonic-gate 	 */
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate 	} else {
276*0Sstevel@tonic-gate 		fromline = nameof(mp);
277*0Sstevel@tonic-gate 		if (value("showto") &&
278*0Sstevel@tonic-gate 		    samebody(myname, skin(fromline), FALSE) &&
279*0Sstevel@tonic-gate 		    (cp = hfield("to", mp, addto))) {
280*0Sstevel@tonic-gate 			showto = 1;
281*0Sstevel@tonic-gate 			yankword(cp, fromline = name, sizeof (name),
282*0Sstevel@tonic-gate 				docomma(cp));
283*0Sstevel@tonic-gate 		}
284*0Sstevel@tonic-gate 		if (value("showname"))
285*0Sstevel@tonic-gate 			fromline = dispname(fromline);
286*0Sstevel@tonic-gate 		else
287*0Sstevel@tonic-gate 			fromline = skin(fromline);
288*0Sstevel@tonic-gate 	}
289*0Sstevel@tonic-gate 	printf("%c%c%3d ", curind, dispc, mesg);
290*0Sstevel@tonic-gate 	if ((int)value("showfull")) {
291*0Sstevel@tonic-gate 		if (showto)
292*0Sstevel@tonic-gate 			printf("To %-15s ", fromline);
293*0Sstevel@tonic-gate 		else
294*0Sstevel@tonic-gate 			printf("%-18s ", fromline);
295*0Sstevel@tonic-gate 	} else {
296*0Sstevel@tonic-gate 		if (showto)
297*0Sstevel@tonic-gate 			printf("To %-15.15s ", fromline);
298*0Sstevel@tonic-gate 		else
299*0Sstevel@tonic-gate 			printf("%-18.18s ", fromline);
300*0Sstevel@tonic-gate 	}
301*0Sstevel@tonic-gate 	if (mp->m_text) {
302*0Sstevel@tonic-gate 		printf("%16.16s %4ld/%-5ld %-.25s\n",
303*0Sstevel@tonic-gate 			hl.l_date, mp->m_lines, mp->m_size, subjline);
304*0Sstevel@tonic-gate 	} else {
305*0Sstevel@tonic-gate 		printf("%16.16s binary/%-5ld %-.25s\n", hl.l_date, mp->m_size,
306*0Sstevel@tonic-gate 		    subjline);
307*0Sstevel@tonic-gate 	}
308*0Sstevel@tonic-gate }
309*0Sstevel@tonic-gate 
310*0Sstevel@tonic-gate /*
311*0Sstevel@tonic-gate  * Return the full name from an RFC-822 header line
312*0Sstevel@tonic-gate  * or the last two (or one) component of the address.
313*0Sstevel@tonic-gate  */
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate static char *
316*0Sstevel@tonic-gate dispname(char *hdr)
317*0Sstevel@tonic-gate {
318*0Sstevel@tonic-gate 	char *cp, *cp2;
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate 	if (hdr == 0)
321*0Sstevel@tonic-gate 		return (0);
322*0Sstevel@tonic-gate 	if (((cp = strchr(hdr, '<')) != 0) && (cp > hdr)) {
323*0Sstevel@tonic-gate 		*cp = 0;
324*0Sstevel@tonic-gate 		if ((*hdr == '"') && ((cp = strrchr(++hdr, '"')) != 0))
325*0Sstevel@tonic-gate 			*cp = 0;
326*0Sstevel@tonic-gate 		return (hdr);
327*0Sstevel@tonic-gate 	} else if ((cp = strchr(hdr, '(')) != 0) {
328*0Sstevel@tonic-gate 		hdr = ++cp;
329*0Sstevel@tonic-gate 		if ((cp = strchr(hdr, '+')) != 0)
330*0Sstevel@tonic-gate 			*cp = 0;
331*0Sstevel@tonic-gate 		if ((cp = strrchr(hdr, ')')) != 0)
332*0Sstevel@tonic-gate 			*cp = 0;
333*0Sstevel@tonic-gate 		return (hdr);
334*0Sstevel@tonic-gate 	}
335*0Sstevel@tonic-gate 	cp = skin(hdr);
336*0Sstevel@tonic-gate 	if ((cp2 = strrchr(cp, '!')) != 0) {
337*0Sstevel@tonic-gate 		while (cp2 >= cp && *--cp2 != '!');
338*0Sstevel@tonic-gate 		cp = ++cp2;
339*0Sstevel@tonic-gate 	}
340*0Sstevel@tonic-gate 	return (cp);
341*0Sstevel@tonic-gate }
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate /*
344*0Sstevel@tonic-gate  * Print out the value of dot.
345*0Sstevel@tonic-gate  */
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate int
348*0Sstevel@tonic-gate pdot(void)
349*0Sstevel@tonic-gate {
350*0Sstevel@tonic-gate 	printf("%d\n", dot - &message[0] + 1);
351*0Sstevel@tonic-gate 	return (0);
352*0Sstevel@tonic-gate }
353*0Sstevel@tonic-gate 
354*0Sstevel@tonic-gate /*
355*0Sstevel@tonic-gate  * Print out all the possible commands.
356*0Sstevel@tonic-gate  */
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate int
359*0Sstevel@tonic-gate pcmdlist(void)
360*0Sstevel@tonic-gate {
361*0Sstevel@tonic-gate 	register const struct cmd *cp;
362*0Sstevel@tonic-gate 	register int cc;
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 	printf("Commands are:\n");
365*0Sstevel@tonic-gate 	for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
366*0Sstevel@tonic-gate 		cc += strlen(cp->c_name) + 2;
367*0Sstevel@tonic-gate 		if (cc > 72) {
368*0Sstevel@tonic-gate 			printf("\n");
369*0Sstevel@tonic-gate 			cc = strlen(cp->c_name) + 2;
370*0Sstevel@tonic-gate 		}
371*0Sstevel@tonic-gate 		if ((cp+1)->c_name != NOSTR)
372*0Sstevel@tonic-gate 			printf("%s, ", cp->c_name);
373*0Sstevel@tonic-gate 		else
374*0Sstevel@tonic-gate 			printf("%s\n", cp->c_name);
375*0Sstevel@tonic-gate 	}
376*0Sstevel@tonic-gate 	return (0);
377*0Sstevel@tonic-gate }
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate /*
380*0Sstevel@tonic-gate  * Paginate messages, honor ignored fields.
381*0Sstevel@tonic-gate  */
382*0Sstevel@tonic-gate int
383*0Sstevel@tonic-gate more(int *msgvec)
384*0Sstevel@tonic-gate {
385*0Sstevel@tonic-gate 	return (type1(msgvec, 1, 1));
386*0Sstevel@tonic-gate }
387*0Sstevel@tonic-gate 
388*0Sstevel@tonic-gate /*
389*0Sstevel@tonic-gate  * Paginate messages, even printing ignored fields.
390*0Sstevel@tonic-gate  */
391*0Sstevel@tonic-gate int
392*0Sstevel@tonic-gate More(int *msgvec)
393*0Sstevel@tonic-gate {
394*0Sstevel@tonic-gate 
395*0Sstevel@tonic-gate 	return (type1(msgvec, 0, 1));
396*0Sstevel@tonic-gate }
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate /*
399*0Sstevel@tonic-gate  * Type out messages, honor ignored fields.
400*0Sstevel@tonic-gate  */
401*0Sstevel@tonic-gate int
402*0Sstevel@tonic-gate type(int *msgvec)
403*0Sstevel@tonic-gate {
404*0Sstevel@tonic-gate 
405*0Sstevel@tonic-gate 	return (type1(msgvec, 1, 0));
406*0Sstevel@tonic-gate }
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate /*
409*0Sstevel@tonic-gate  * Type out messages, even printing ignored fields.
410*0Sstevel@tonic-gate  */
411*0Sstevel@tonic-gate int
412*0Sstevel@tonic-gate Type(int *msgvec)
413*0Sstevel@tonic-gate {
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate 	return (type1(msgvec, 0, 0));
416*0Sstevel@tonic-gate }
417*0Sstevel@tonic-gate 
418*0Sstevel@tonic-gate /*
419*0Sstevel@tonic-gate  * Type out the messages requested.
420*0Sstevel@tonic-gate  */
421*0Sstevel@tonic-gate static int
422*0Sstevel@tonic-gate type1(int *msgvec, int doign, int page)
423*0Sstevel@tonic-gate {
424*0Sstevel@tonic-gate 	register *ip;
425*0Sstevel@tonic-gate 	register struct message *mp;
426*0Sstevel@tonic-gate 	register int mesg;
427*0Sstevel@tonic-gate 	register char *cp;
428*0Sstevel@tonic-gate 	long nlines;
429*0Sstevel@tonic-gate 	FILE *obuf;
430*0Sstevel@tonic-gate 	void (*sigint)(int), (*sigpipe)(int);
431*0Sstevel@tonic-gate 	int setsigs = 0;
432*0Sstevel@tonic-gate 
433*0Sstevel@tonic-gate 	obuf = stdout;
434*0Sstevel@tonic-gate 	if (setjmp(pipestop)) {
435*0Sstevel@tonic-gate 		if (obuf != stdout) {
436*0Sstevel@tonic-gate 			pipef = NULL;
437*0Sstevel@tonic-gate 			npclose(obuf);
438*0Sstevel@tonic-gate 		}
439*0Sstevel@tonic-gate 		goto ret0;
440*0Sstevel@tonic-gate 	}
441*0Sstevel@tonic-gate 	if (intty && outtty && (page || (cp = value("crt")) != NOSTR)) {
442*0Sstevel@tonic-gate 		if (!page) {
443*0Sstevel@tonic-gate 			nlines = 0;
444*0Sstevel@tonic-gate 			for (ip = msgvec, nlines = 0;
445*0Sstevel@tonic-gate 			    *ip && ip-msgvec < msgCount; ip++)
446*0Sstevel@tonic-gate 				nlines += message[*ip - 1].m_lines;
447*0Sstevel@tonic-gate 		}
448*0Sstevel@tonic-gate 		if (page ||
449*0Sstevel@tonic-gate 		    nlines > (*cp == '\0' ? screensize() - 2 : atoi(cp))) {
450*0Sstevel@tonic-gate 			obuf = npopen(MORE, "w");
451*0Sstevel@tonic-gate 			if (obuf == NULL) {
452*0Sstevel@tonic-gate 				perror(MORE);
453*0Sstevel@tonic-gate 				obuf = stdout;
454*0Sstevel@tonic-gate 			} else {
455*0Sstevel@tonic-gate 				pipef = obuf;
456*0Sstevel@tonic-gate 				sigint = sigset(SIGINT, SIG_IGN);
457*0Sstevel@tonic-gate 				sigpipe = sigset(SIGPIPE, brokpipe);
458*0Sstevel@tonic-gate 				setsigs++;
459*0Sstevel@tonic-gate 			}
460*0Sstevel@tonic-gate 		}
461*0Sstevel@tonic-gate 	}
462*0Sstevel@tonic-gate 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
463*0Sstevel@tonic-gate 		mesg = *ip;
464*0Sstevel@tonic-gate 		touch(mesg);
465*0Sstevel@tonic-gate 		mp = &message[mesg-1];
466*0Sstevel@tonic-gate 		dot = mp;
467*0Sstevel@tonic-gate 		print(mp, obuf, doign);
468*0Sstevel@tonic-gate 	}
469*0Sstevel@tonic-gate 	if (obuf != stdout) {
470*0Sstevel@tonic-gate 		pipef = NULL;
471*0Sstevel@tonic-gate 		npclose(obuf);
472*0Sstevel@tonic-gate 	}
473*0Sstevel@tonic-gate ret0:
474*0Sstevel@tonic-gate 	if (setsigs) {
475*0Sstevel@tonic-gate 		sigset(SIGPIPE, sigpipe);
476*0Sstevel@tonic-gate 		sigset(SIGINT, sigint);
477*0Sstevel@tonic-gate 	}
478*0Sstevel@tonic-gate 	return (0);
479*0Sstevel@tonic-gate }
480*0Sstevel@tonic-gate 
481*0Sstevel@tonic-gate /*
482*0Sstevel@tonic-gate  * Respond to a broken pipe signal --
483*0Sstevel@tonic-gate  * probably caused by user quitting more.
484*0Sstevel@tonic-gate  */
485*0Sstevel@tonic-gate void
486*0Sstevel@tonic-gate #ifdef	__cplusplus
487*0Sstevel@tonic-gate brokpipe(int)
488*0Sstevel@tonic-gate #else
489*0Sstevel@tonic-gate /* ARGSUSED */
490*0Sstevel@tonic-gate brokpipe(int s)
491*0Sstevel@tonic-gate #endif
492*0Sstevel@tonic-gate {
493*0Sstevel@tonic-gate #ifdef OLD_BSD_SIGS
494*0Sstevel@tonic-gate 	sigrelse(SIGPIPE);
495*0Sstevel@tonic-gate #endif
496*0Sstevel@tonic-gate 	longjmp(pipestop, 1);
497*0Sstevel@tonic-gate }
498*0Sstevel@tonic-gate 
499*0Sstevel@tonic-gate /*
500*0Sstevel@tonic-gate  * Print the indicated message on standard output.
501*0Sstevel@tonic-gate  */
502*0Sstevel@tonic-gate 
503*0Sstevel@tonic-gate static void
504*0Sstevel@tonic-gate print(register struct message *mp, FILE *obuf, int doign)
505*0Sstevel@tonic-gate {
506*0Sstevel@tonic-gate 
507*0Sstevel@tonic-gate 	if (value("quiet") == NOSTR && (!doign || !isign("message", 0)))
508*0Sstevel@tonic-gate 		fprintf(obuf, "Message %2d:\n", mp - &message[0] + 1);
509*0Sstevel@tonic-gate 	touch(mp - &message[0] + 1);
510*0Sstevel@tonic-gate 	if (mp->m_text) {
511*0Sstevel@tonic-gate 		(void) msend(mp, obuf, doign ? M_IGNORE : 0, fputs);
512*0Sstevel@tonic-gate 	} else {
513*0Sstevel@tonic-gate 		fprintf(obuf, "\n%s\n", gettext(binmsg));
514*0Sstevel@tonic-gate 	}
515*0Sstevel@tonic-gate }
516*0Sstevel@tonic-gate 
517*0Sstevel@tonic-gate /*
518*0Sstevel@tonic-gate  * Print the top so many lines of each desired message.
519*0Sstevel@tonic-gate  * The number of lines is taken from the variable "toplines"
520*0Sstevel@tonic-gate  * and defaults to 5.
521*0Sstevel@tonic-gate  */
522*0Sstevel@tonic-gate 
523*0Sstevel@tonic-gate static	long	top_linecount, top_maxlines, top_lineb;
524*0Sstevel@tonic-gate static	jmp_buf	top_buf;
525*0Sstevel@tonic-gate 
526*0Sstevel@tonic-gate int
527*0Sstevel@tonic-gate top(int *msgvec)
528*0Sstevel@tonic-gate {
529*0Sstevel@tonic-gate 	register int *ip;
530*0Sstevel@tonic-gate 	register struct message *mp;
531*0Sstevel@tonic-gate 	register int mesg;
532*0Sstevel@tonic-gate 	char *valtop;
533*0Sstevel@tonic-gate 
534*0Sstevel@tonic-gate 	top_maxlines = 5;
535*0Sstevel@tonic-gate 	valtop = value("toplines");
536*0Sstevel@tonic-gate 	if (valtop != NOSTR) {
537*0Sstevel@tonic-gate 		top_maxlines = atoi(valtop);
538*0Sstevel@tonic-gate 		if (top_maxlines < 0 || top_maxlines > 10000)
539*0Sstevel@tonic-gate 			top_maxlines = 5;
540*0Sstevel@tonic-gate 	}
541*0Sstevel@tonic-gate 	top_lineb = 1;
542*0Sstevel@tonic-gate 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
543*0Sstevel@tonic-gate 		mesg = *ip;
544*0Sstevel@tonic-gate 		touch(mesg);
545*0Sstevel@tonic-gate 		mp = &message[mesg-1];
546*0Sstevel@tonic-gate 		dot = mp;
547*0Sstevel@tonic-gate 		if (value("quiet") == NOSTR)
548*0Sstevel@tonic-gate 			printf("Message %2d:\n", mesg);
549*0Sstevel@tonic-gate 		if (!top_lineb)
550*0Sstevel@tonic-gate 			printf("\n");
551*0Sstevel@tonic-gate 		top_linecount = 0;
552*0Sstevel@tonic-gate 		if (setjmp(top_buf) == 0) {
553*0Sstevel@tonic-gate 			if (mp->m_text) {
554*0Sstevel@tonic-gate 				(void) msend(mp, stdout, M_IGNORE, topputs);
555*0Sstevel@tonic-gate 			} else {
556*0Sstevel@tonic-gate 				printf("\n%s\n", gettext(binmsg));
557*0Sstevel@tonic-gate 			}
558*0Sstevel@tonic-gate 		}
559*0Sstevel@tonic-gate 	}
560*0Sstevel@tonic-gate 	return (0);
561*0Sstevel@tonic-gate }
562*0Sstevel@tonic-gate 
563*0Sstevel@tonic-gate int
564*0Sstevel@tonic-gate topputs(const char *line, FILE *obuf)
565*0Sstevel@tonic-gate {
566*0Sstevel@tonic-gate 	if (top_linecount++ >= top_maxlines)
567*0Sstevel@tonic-gate 		longjmp(top_buf, 1);
568*0Sstevel@tonic-gate 	top_lineb = blankline(line);
569*0Sstevel@tonic-gate 	return (fputs(line, obuf));
570*0Sstevel@tonic-gate }
571*0Sstevel@tonic-gate 
572*0Sstevel@tonic-gate /*
573*0Sstevel@tonic-gate  * Touch all the given messages so that they will
574*0Sstevel@tonic-gate  * get mboxed.
575*0Sstevel@tonic-gate  */
576*0Sstevel@tonic-gate 
577*0Sstevel@tonic-gate int
578*0Sstevel@tonic-gate stouch(int msgvec[])
579*0Sstevel@tonic-gate {
580*0Sstevel@tonic-gate 	register int *ip;
581*0Sstevel@tonic-gate 
582*0Sstevel@tonic-gate 	for (ip = msgvec; *ip != 0; ip++) {
583*0Sstevel@tonic-gate 		dot = &message[*ip-1];
584*0Sstevel@tonic-gate 		dot->m_flag |= MTOUCH;
585*0Sstevel@tonic-gate 		dot->m_flag &= ~MPRESERVE;
586*0Sstevel@tonic-gate 	}
587*0Sstevel@tonic-gate 	return (0);
588*0Sstevel@tonic-gate }
589*0Sstevel@tonic-gate 
590*0Sstevel@tonic-gate /*
591*0Sstevel@tonic-gate  * Make sure all passed messages get mboxed.
592*0Sstevel@tonic-gate  */
593*0Sstevel@tonic-gate 
594*0Sstevel@tonic-gate int
595*0Sstevel@tonic-gate mboxit(int msgvec[])
596*0Sstevel@tonic-gate {
597*0Sstevel@tonic-gate 	register int *ip;
598*0Sstevel@tonic-gate 
599*0Sstevel@tonic-gate 	for (ip = msgvec; *ip != 0; ip++) {
600*0Sstevel@tonic-gate 		dot = &message[*ip-1];
601*0Sstevel@tonic-gate 		dot->m_flag |= MTOUCH|MBOX;
602*0Sstevel@tonic-gate 		dot->m_flag &= ~MPRESERVE;
603*0Sstevel@tonic-gate 	}
604*0Sstevel@tonic-gate 	return (0);
605*0Sstevel@tonic-gate }
606*0Sstevel@tonic-gate 
607*0Sstevel@tonic-gate /*
608*0Sstevel@tonic-gate  * List the folders the user currently has.
609*0Sstevel@tonic-gate  */
610*0Sstevel@tonic-gate int
611*0Sstevel@tonic-gate folders(char **arglist)
612*0Sstevel@tonic-gate {
613*0Sstevel@tonic-gate 	char dirname[BUFSIZ], cmd[BUFSIZ];
614*0Sstevel@tonic-gate 
615*0Sstevel@tonic-gate 	if (getfold(dirname) < 0) {
616*0Sstevel@tonic-gate 		printf(gettext("No value set for \"folder\"\n"));
617*0Sstevel@tonic-gate 		return (-1);
618*0Sstevel@tonic-gate 	}
619*0Sstevel@tonic-gate 	if (*arglist) {
620*0Sstevel@tonic-gate 		nstrcat(dirname, sizeof (dirname), "/");
621*0Sstevel@tonic-gate 		nstrcat(dirname, sizeof (dirname), *arglist);
622*0Sstevel@tonic-gate 	}
623*0Sstevel@tonic-gate 	snprintf(cmd, sizeof (cmd), "%s %s", LS, dirname);
624*0Sstevel@tonic-gate 	return (system(cmd));
625*0Sstevel@tonic-gate }
626