xref: /illumos-gate/usr/src/cmd/mailx/cmd4.c (revision 88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
42 
43 #include "rcv.h"
44 #include <locale.h>
45 
46 /*
47  * mailx -- a modified version of a University of California at Berkeley
48  *	mail program
49  *
50  * More commands..
51  */
52 
53 static char *stripquotes(char *str);
54 
55 /*
56  * pipe messages to cmd.
57  */
58 
59 int
60 dopipe(char str[])
61 {
62 	register int *ip, mesg;
63 	register struct message *mp;
64 	char *cp, *cmd;
65 	int f, *msgvec, nowait=0;
66 	void (*sigint)(int), (*sigpipe)(int);
67 	long lc, cc, t;
68 	register pid_t pid;
69 	int page, s, pivec[2];
70 	char *Shell;
71 	FILE *pio = NULL;
72 	extern jmp_buf pipestop;
73 	extern void brokpipe(int);
74 
75 	msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
76 	if ((cmd = stripquotes(snarf(str, &f, 0))) == NOSTR) {
77 		if (f == -1) {
78 			printf(gettext("pipe command error\n"));
79 			return(1);
80 		}
81 		if ( (cmd = value("cmd")) == NOSTR) {
82 			printf(gettext("\"cmd\" not set, ignored.\n"));
83 			return(1);
84 		}
85 	}
86 	if (!f) {
87 		*msgvec = first(0, MMNORM);
88 		if (*msgvec == NULL) {
89 			printf(gettext("No messages to pipe.\n"));
90 			return(1);
91 		}
92 		msgvec[1] = NULL;
93 	}
94 	if (f && getmsglist(str, msgvec, 0) < 0)
95 		return(1);
96 	if (*(cp=cmd+strlen(cmd)-1)=='&') {
97 		*cp=0;
98 		nowait++;
99 	}
100 	printf(gettext("Pipe to: \"%s\"\n"), cmd);
101 	flush();
102 
103 	if (setjmp(pipestop))
104 		goto err;
105 					/*  setup pipe */
106 	if (pipe(pivec) < 0) {
107 		perror("pipe");
108 		return(0);
109 	}
110 
111 	if ((pid = vfork()) == 0) {
112 		close(pivec[1]);	/* child */
113 		close(0);
114 		dup(pivec[0]);
115 		close(pivec[0]);
116 		if ((Shell = value("SHELL")) == NOSTR || *Shell=='\0')
117 			Shell = SHELL;
118 		execlp(Shell, Shell, "-c", cmd, 0);
119 		perror(Shell);
120 		_exit(1);
121 	}
122 	if (pid == (pid_t)-1) {		/* error */
123 		perror("fork");
124 		close(pivec[0]);
125 		close(pivec[1]);
126 		return(0);
127 	}
128 
129 	close(pivec[0]);		/* parent */
130 	pio=fdopen(pivec[1],"w");
131 	sigint = sigset(SIGINT, SIG_IGN);
132 	sigpipe = sigset(SIGPIPE, brokpipe);
133 
134 					/* send all messages to cmd */
135 	page = (value("page")!=NOSTR);
136 	lc = cc = 0;
137 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
138 		mesg = *ip;
139 		touch(mesg);
140 		mp = &message[mesg-1];
141 		dot = mp;
142 		if ((t = msend(mp, pio,
143 		    (value("alwaysignore") != NOSTR ||
144 		     value("pipeignore") != NOSTR)
145 		     ? M_IGNORE : 0, fputs)) < 0) {
146 			perror(cmd);
147 			sigset(SIGPIPE, sigpipe);
148 			sigset(SIGINT, sigint);
149 			fclose(pio);
150 			return(1);
151 		}
152 		lc += t;
153 		cc += mp->m_size;
154 		if (page) putc('\f', pio);
155 	}
156 
157 	fflush(pio);
158 	if (ferror(pio))
159 	      perror(cmd);
160 	fclose(pio);
161 	pio = NULL;
162 
163 					/* wait */
164 	if (!nowait) {
165 		while (wait(&s) != pid);
166 		s &= 0377;
167 		if (s != 0)
168 			goto err;
169 	}
170 
171 	printf("\"%s\" %ld/%ld\n", cmd, lc, cc);
172 	sigset(SIGPIPE, sigpipe);
173 	sigset(SIGINT, sigint);
174 	return(0);
175 
176 err:
177 	printf(gettext("Pipe to \"%s\" failed\n"), cmd);
178 	if (pio)
179 		fclose(pio);
180 	sigset(SIGPIPE, sigpipe);
181 	sigset(SIGINT, sigint);
182 	return(0);
183 }
184 
185 /*
186  * Load the named message from the named file.
187  */
188 int
189 loadmsg(char str[])
190 {
191 	char *file;
192 	int f, *msgvec;
193 	register int c, lastc = '\n';
194 	int blank;
195 	int lines;
196 	long ms;
197 	FILE *ibuf;
198 	struct message *mp;
199 	off_t size;
200 
201 	msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
202 	if ((file = snarf(str, &f, 1)) == NOSTR)
203 		return(1);
204 	if (f==-1)
205 		return(1);
206 	if (!f) {
207 		*msgvec = first(0, MMNORM);
208 		if (*msgvec == NULL) {
209 			printf(gettext("No message to load into.\n"));
210 			return(1);
211 		}
212 		msgvec[1] = NULL;
213 	}
214 	if (f && getmsglist(str, msgvec, 0) < 0)
215 		return(1);
216 	if (msgvec[1] != NULL) {
217 		printf(gettext("Can only load into a single message.\n"));
218 		return(1);
219 	}
220 	if ((file = expand(file)) == NOSTR)
221 		return(1);
222 	printf("\"%s\" ", file);
223 	fflush(stdout);
224 	if ((ibuf = fopen(file, "r")) == NULL) {
225 		perror("");
226 		return(1);
227 	}
228 	mp = &message[*msgvec-1];
229 	dot = mp;
230 	mp->m_flag |= MODIFY;
231 	mp->m_flag &= ~MSAVED;		/* should probably turn off more */
232 	fseek(otf, (long) 0, 2);
233 	size = fsize(otf);
234 	mp->m_offset = size;
235 	ms = 0L;
236 	lines = 0;
237 	while ((c = getc(ibuf)) != EOF) {
238 		if (c == '\n') {
239 			lines++;
240 			blank = lastc == '\n';
241 		}
242 		lastc = c;
243 		putc(c, otf);
244 		if (ferror(otf))
245 			break;
246 		ms++;
247 	}
248 	if (!blank) {
249 		putc('\n', otf);
250 		ms++;
251 		lines++;
252 	}
253 	mp->m_size = ms;
254 	mp->m_lines = lines;
255 	if (fferror(otf))
256 		perror("/tmp");
257 	fclose(ibuf);
258 	setclen(mp);
259 	printf(gettext("[Loaded] %d/%ld\n"), lines, ms);
260 	return(0);
261 }
262 
263 /*
264  * Display the named field.
265  */
266 int
267 field(char str[])
268 {
269 	register int *ip;
270 	register struct message *mp;
271 	register char *cp, *fld;
272 	int f, *msgvec;
273 
274 	msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
275 	if ((fld = stripquotes(snarf(str, &f, 0))) == NOSTR) {
276 		if (f == -1)
277 			printf(gettext("Bad field\n"));
278 		else
279 			printf(gettext("No field specified\n"));
280 		return(1);
281 	}
282 	if (!f) {
283 		*msgvec = first(0, MMNORM);
284 		if (*msgvec == NULL) {
285 			printf(gettext("No messages to display.\n"));
286 			return(1);
287 		}
288 		msgvec[1] = NULL;
289 	}
290 	if (f && getmsglist(str, msgvec, 0) < 0)
291 		return(1);
292 
293 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
294 		mp = &message[*ip - 1];
295 		dot = mp;
296 		if ((cp = hfield(fld, mp, addone)) != NULL)
297 			printf("%s\n", cp);
298 	}
299 	return(0);
300 }
301 
302 /*
303  *  Remove the quotes from around the string passed in (if any).  Return
304  *  the beginning of the result.
305  */
306 
307 static char *
308 stripquotes(char *str)
309 {
310 	register int lastch;
311 	if (str == NOSTR) {
312 		return(NOSTR);
313 	}
314 	lastch = strlen(str)-1;
315 	if (any(*str, "\"'") && str[lastch] == *str) {
316 		str[lastch] = '\0';
317 		++str;
318 	}
319 	return(str);
320 }
321