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