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
dopipe(char str[])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
loadmsg(char str[])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
field(char str[])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 *
stripquotes(char * str)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