xref: /original-bsd/usr.bin/mail/cmd1.c (revision 552e81d8)
1 #
2 #include "rcv.h"
3 #include <sys/stat.h>
4 
5 /*
6  * Mail -- a mail program
7  *
8  * User commands.
9  */
10 
11 static char *SccsId = "@(#)cmd1.c	1.1 10/08/80";
12 
13 /*
14  * Print the current active headings.
15  */
16 
17 static int screen;
18 
19 headers(msgvec)
20 	int *msgvec;
21 {
22 	register int n, mesg, flag;
23 	register struct message *mp;
24 
25 	n = msgvec[0];
26 	if (n != 0)
27 		screen = (n-1)/SCREEN;
28 	if (screen < 0)
29 		screen = 0;
30 	mp = &message[screen * SCREEN];
31 	if (mp >= &message[msgCount])
32 		mp = &message[msgCount - SCREEN];
33 	if (mp < &message[0])
34 		mp = &message[0];
35 	flag = 0;
36 	mesg = mp - &message[0];
37 	dot = mp;
38 	for (; mp < &message[msgCount]; mp++) {
39 		mesg++;
40 		if (mp->m_flag & MDELETED)
41 			continue;
42 		if (flag++ >= SCREEN)
43 			break;
44 		printhead(mesg);
45 		sreset();
46 	}
47 	if (flag == 0) {
48 		printf("No more mail.\n");
49 		return(1);
50 	}
51 	return(0);
52 }
53 
54 /*
55  * Scroll to the next/previous screen
56  */
57 
58 scroll(arg)
59 	char arg[];
60 {
61 	register int s;
62 	int cur[1];
63 
64 	cur[0] = 0;
65 	s = screen;
66 	switch (*arg) {
67 	case 0:
68 	case '+':
69 		s++;
70 		if (s*SCREEN > msgCount) {
71 			printf("On last screenful of messages\n");
72 			return(0);
73 		}
74 		screen = s;
75 		break;
76 
77 	case '-':
78 		if (--s < 0) {
79 			printf("On first screenful of messages\n");
80 			return(0);
81 		}
82 		screen = s;
83 		break;
84 
85 	default:
86 		printf("Unrecognized scrolling command \"%s\"\n", arg);
87 		return(1);
88 	}
89 	return(headers(cur));
90 }
91 
92 
93 /*
94  * Print out the headlines for each message
95  * in the passed message list.
96  */
97 
98 from(msgvec)
99 	int *msgvec;
100 {
101 	register int *ip;
102 
103 	for (ip = msgvec; *ip != NULL; ip++) {
104 		printhead(*ip);
105 		sreset();
106 	}
107 	if (--ip >= msgvec)
108 		dot = &message[*ip - 1];
109 	return(0);
110 }
111 
112 /*
113  * Print out the header of a specific message.
114  * This is a slight improvement to the standard one.
115  */
116 
117 printhead(mesg)
118 {
119 	struct message *mp;
120 	FILE *ibuf;
121 	char headline[LINESIZE], wcount[10], *subjline, dispc;
122 	char pbuf[BUFSIZ];
123 	int s;
124 	struct headline hl;
125 	register char *cp;
126 
127 	mp = &message[mesg-1];
128 	ibuf = setinput(mp);
129 	readline(ibuf, headline);
130 	subjline = hfield("subject", mp);
131 	if (subjline == NOSTR)
132 		subjline = hfield("subj", mp);
133 
134 	/*
135 	 * Bletch!
136 	 */
137 
138 	if (subjline != NOSTR && strlen(subjline) > 28)
139 		subjline[29] = '\0';
140 	dispc = ' ';
141 	if (mp->m_flag & MSAVED)
142 		dispc = '*';
143 	if (mp->m_flag & MPRESERVE)
144 		dispc = 'P';
145 	parse(headline, &hl, pbuf);
146 	sprintf(wcount, " %d/%d", mp->m_lines, mp->m_size);
147 	s = strlen(wcount);
148 	cp = wcount + s;
149 	while (s < 7)
150 		s++, *cp++ = ' ';
151 	*cp = '\0';
152 	if (subjline != NOSTR)
153 		printf("%c%3d %-8s %16.16s %s \"%s\"\n", dispc, mesg,
154 		    nameof(mp), hl.l_date, wcount, subjline);
155 	else
156 		printf("%c%3d %-8s %16.16s %s\n", dispc, mesg,
157 		    nameof(mp), hl.l_date, wcount);
158 }
159 
160 /*
161  * Print out the value of dot.
162  */
163 
164 pdot()
165 {
166 	printf("%d\n", dot - &message[0] + 1);
167 	return(0);
168 }
169 
170 /*
171  * Print out all the possible commands.
172  */
173 
174 pcmdlist()
175 {
176 	register struct cmd *cp;
177 	register int cc;
178 	extern struct cmd cmdtab[];
179 
180 	printf("Commands are:\n");
181 	for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
182 		cc += strlen(cp->c_name) + 2;
183 		if (cc > 72) {
184 			printf("\n");
185 			cc = strlen(cp->c_name) + 2;
186 		}
187 		if ((cp+1)->c_name != NOSTR)
188 			printf("%s, ", cp->c_name);
189 		else
190 			printf("%s\n", cp->c_name);
191 	}
192 	return(0);
193 }
194 
195 /*
196  * Type out the messages requested.
197  */
198 
199 type(msgvec)
200 	int *msgvec;
201 {
202 	register *ip;
203 	register struct message *mp;
204 	register int mesg;
205 	int c;
206 	FILE *ibuf;
207 
208 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
209 		mesg = *ip;
210 		touch(mesg);
211 		mp = &message[mesg-1];
212 		dot = mp;
213 		print(mp);
214 	}
215 	return(0);
216 }
217 
218 /*
219  * Print the indicated message on standard output.
220  */
221 
222 print(mp)
223 	register struct message *mp;
224 {
225 
226 	if (value("quiet") == NOSTR)
227 		printf("Message %2d:\n", mp - &message[0] + 1);
228 	touch(mp - &message[0] + 1);
229 	send(mp, stdout);
230 }
231 
232 /*
233  * Print the top so many lines of each desired message.
234  * The number of lines is taken from the variable "toplines"
235  * and defaults to 5.
236  */
237 
238 top(msgvec)
239 	int *msgvec;
240 {
241 	register int *ip;
242 	register struct message *mp;
243 	register int mesg;
244 	int c, topl, lines, lineb;
245 	char *valtop, linebuf[LINESIZE];
246 	FILE *ibuf;
247 
248 	topl = 5;
249 	valtop = value("toplines");
250 	if (valtop != NOSTR) {
251 		topl = atoi(valtop);
252 		if (topl < 0 || topl > 10000)
253 			topl = 5;
254 	}
255 	lineb = 1;
256 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
257 		mesg = *ip;
258 		touch(mesg);
259 		mp = &message[mesg-1];
260 		dot = mp;
261 		if (value("quiet") == NOSTR)
262 			printf("Message %2d:\n", mesg);
263 		ibuf = setinput(mp);
264 		c = mp->m_lines;
265 		if (!lineb)
266 			printf("\n");
267 		for (lines = 0; lines < c && lines <= topl; lines++) {
268 			if (readline(ibuf, linebuf) <= 0)
269 				break;
270 			puts(linebuf);
271 			lineb = blankline(linebuf);
272 		}
273 	}
274 	return(0);
275 }
276 
277 /*
278  * Touch all the given messages so that they will
279  * get mboxed.
280  */
281 
282 stouch(msgvec)
283 	int msgvec[];
284 {
285 	register int *ip;
286 
287 	for (ip = msgvec; *ip != 0; ip++) {
288 		touch(*ip);
289 		dot = &message[*ip-1];
290 		dot->m_flag &= ~MPRESERVE;
291 	}
292 	return(0);
293 }
294