xref: /illumos-gate/usr/src/cmd/mailx/cmd4.c (revision 99ea293e719ac006d413e4fde6ac0d5cd4dd6c59)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1995 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 /*
32  * University Copyright- Copyright (c) 1982, 1986, 1988
33  * The Regents of the University of California
34  * All Rights Reserved
35  *
36  * University Acknowledgment- Portions of this document are derived from
37  * software developed by the University of California, Berkeley, and its
38  * contributors.
39  */
40 
41 #include "rcv.h"
42 #include <locale.h>
43 
44 /*
45  * mailx -- a modified version of a University of California at Berkeley
46  *	mail program
47  *
48  * More commands..
49  */
50 
51 static char *stripquotes(char *str);
52 
53 /*
54  * pipe messages to cmd.
55  */
56 
57 int
58 dopipe(char str[])
59 {
60 	int *ip, mesg;
61 	struct message *mp;
62 	char *cp, *cmd;
63 	int f, *msgvec, nowait=0;
64 	void (*sigint)(int), (*sigpipe)(int);
65 	long lc, cc, t;
66 	pid_t pid;
67 	int page, s, pivec[2];
68 	char *Shell;
69 	FILE *pio = NULL;
70 	extern jmp_buf pipestop;
71 	extern void brokpipe(int);
72 
73 	msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
74 	if ((cmd = stripquotes(snarf(str, &f, 0))) == NOSTR) {
75 		if (f == -1) {
76 			printf(gettext("pipe command error\n"));
77 			return(1);
78 		}
79 		if ( (cmd = value("cmd")) == NOSTR) {
80 			printf(gettext("\"cmd\" not set, ignored.\n"));
81 			return(1);
82 		}
83 	}
84 	if (!f) {
85 		*msgvec = first(0, MMNORM);
86 		if (*msgvec == 0) {
87 			printf(gettext("No messages to pipe.\n"));
88 			return(1);
89 		}
90 		msgvec[1] = 0;
91 	}
92 	if (f && getmsglist(str, msgvec, 0) < 0)
93 		return(1);
94 	if (*(cp=cmd+strlen(cmd)-1)=='&') {
95 		*cp=0;
96 		nowait++;
97 	}
98 	printf(gettext("Pipe to: \"%s\"\n"), cmd);
99 	flush();
100 
101 	if (setjmp(pipestop))
102 		goto err;
103 					/*  setup pipe */
104 	if (pipe(pivec) < 0) {
105 		perror("pipe");
106 		return(0);
107 	}
108 
109 	if ((pid = vfork()) == 0) {
110 		close(pivec[1]);	/* child */
111 		close(0);
112 		dup(pivec[0]);
113 		close(pivec[0]);
114 		if ((Shell = value("SHELL")) == NOSTR || *Shell=='\0')
115 			Shell = SHELL;
116 		execlp(Shell, Shell, "-c", cmd, 0);
117 		perror(Shell);
118 		_exit(1);
119 	}
120 	if (pid == (pid_t)-1) {		/* error */
121 		perror("fork");
122 		close(pivec[0]);
123 		close(pivec[1]);
124 		return(0);
125 	}
126 
127 	close(pivec[0]);		/* parent */
128 	pio=fdopen(pivec[1],"w");
129 	sigint = sigset(SIGINT, SIG_IGN);
130 	sigpipe = sigset(SIGPIPE, brokpipe);
131 
132 					/* send all messages to cmd */
133 	page = (value("page")!=NOSTR);
134 	lc = cc = 0;
135 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
136 		mesg = *ip;
137 		touch(mesg);
138 		mp = &message[mesg-1];
139 		dot = mp;
140 		if ((t = msend(mp, pio,
141 		    (value("alwaysignore") != NOSTR ||
142 		     value("pipeignore") != NOSTR)
143 		     ? M_IGNORE : 0, fputs)) < 0) {
144 			perror(cmd);
145 			sigset(SIGPIPE, sigpipe);
146 			sigset(SIGINT, sigint);
147 			fclose(pio);
148 			return(1);
149 		}
150 		lc += t;
151 		cc += mp->m_size;
152 		if (page) putc('\f', pio);
153 	}
154 
155 	fflush(pio);
156 	if (ferror(pio))
157 	      perror(cmd);
158 	fclose(pio);
159 	pio = NULL;
160 
161 					/* wait */
162 	if (!nowait) {
163 		while (wait(&s) != pid);
164 		s &= 0377;
165 		if (s != 0)
166 			goto err;
167 	}
168 
169 	printf("\"%s\" %ld/%ld\n", cmd, lc, cc);
170 	sigset(SIGPIPE, sigpipe);
171 	sigset(SIGINT, sigint);
172 	return(0);
173 
174 err:
175 	printf(gettext("Pipe to \"%s\" failed\n"), cmd);
176 	if (pio)
177 		fclose(pio);
178 	sigset(SIGPIPE, sigpipe);
179 	sigset(SIGINT, sigint);
180 	return(0);
181 }
182 
183 /*
184  * Load the named message from the named file.
185  */
186 int
187 loadmsg(char str[])
188 {
189 	char *file;
190 	int f, *msgvec;
191 	int c, lastc = '\n';
192 	int blank;
193 	int lines;
194 	long ms;
195 	FILE *ibuf;
196 	struct message *mp;
197 	off_t size;
198 
199 	msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
200 	if ((file = snarf(str, &f, 1)) == NOSTR)
201 		return(1);
202 	if (f==-1)
203 		return(1);
204 	if (!f) {
205 		*msgvec = first(0, MMNORM);
206 		if (*msgvec == 0) {
207 			printf(gettext("No message to load into.\n"));
208 			return(1);
209 		}
210 		msgvec[1] = 0;
211 	}
212 	if (f && getmsglist(str, msgvec, 0) < 0)
213 		return(1);
214 	if (msgvec[1] != 0) {
215 		printf(gettext("Can only load into a single message.\n"));
216 		return(1);
217 	}
218 	if ((file = expand(file)) == NOSTR)
219 		return(1);
220 	printf("\"%s\" ", file);
221 	fflush(stdout);
222 	if ((ibuf = fopen(file, "r")) == NULL) {
223 		perror("");
224 		return(1);
225 	}
226 	mp = &message[*msgvec-1];
227 	dot = mp;
228 	mp->m_flag |= MODIFY;
229 	mp->m_flag &= ~MSAVED;		/* should probably turn off more */
230 	fseek(otf, (long) 0, 2);
231 	size = fsize(otf);
232 	mp->m_offset = size;
233 	ms = 0L;
234 	lines = 0;
235 	while ((c = getc(ibuf)) != EOF) {
236 		if (c == '\n') {
237 			lines++;
238 			blank = lastc == '\n';
239 		}
240 		lastc = c;
241 		putc(c, otf);
242 		if (ferror(otf))
243 			break;
244 		ms++;
245 	}
246 	if (!blank) {
247 		putc('\n', otf);
248 		ms++;
249 		lines++;
250 	}
251 	mp->m_size = ms;
252 	mp->m_lines = lines;
253 	if (fferror(otf))
254 		perror("/tmp");
255 	fclose(ibuf);
256 	setclen(mp);
257 	printf(gettext("[Loaded] %d/%ld\n"), lines, ms);
258 	return(0);
259 }
260 
261 /*
262  * Display the named field.
263  */
264 int
265 field(char str[])
266 {
267 	int *ip;
268 	struct message *mp;
269 	char *cp, *fld;
270 	int f, *msgvec;
271 
272 	msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
273 	if ((fld = stripquotes(snarf(str, &f, 0))) == NOSTR) {
274 		if (f == -1)
275 			printf(gettext("Bad field\n"));
276 		else
277 			printf(gettext("No field specified\n"));
278 		return(1);
279 	}
280 	if (!f) {
281 		*msgvec = first(0, MMNORM);
282 		if (*msgvec == 0) {
283 			printf(gettext("No messages to display.\n"));
284 			return(1);
285 		}
286 		msgvec[1] = 0;
287 	}
288 	if (f && getmsglist(str, msgvec, 0) < 0)
289 		return(1);
290 
291 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
292 		mp = &message[*ip - 1];
293 		dot = mp;
294 		if ((cp = hfield(fld, mp, addone)) != NULL)
295 			printf("%s\n", cp);
296 	}
297 	return(0);
298 }
299 
300 /*
301  *  Remove the quotes from around the string passed in (if any).  Return
302  *  the beginning of the result.
303  */
304 
305 static char *
306 stripquotes(char *str)
307 {
308 	int lastch;
309 	if (str == NOSTR) {
310 		return(NOSTR);
311 	}
312 	lastch = strlen(str)-1;
313 	if (any(*str, "\"'") && str[lastch] == *str) {
314 		str[lastch] = '\0';
315 		++str;
316 	}
317 	return(str);
318 }
319