dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / mailx / edit.c
blob4e9f117935bc48ecbd2829a7f4d21f730347b2ee
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 1996 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
32 * University Copyright- Copyright (c) 1982, 1986, 1988
33 * The Regents of the University of California
34 * All Rights Reserved
36 * University Acknowledgment- Portions of this document are derived from
37 * software developed by the University of California, Berkeley, and its
38 * contributors.
41 #pragma ident "%Z%%M% %I% %E% SMI"
43 #include "rcv.h"
44 #include <locale.h>
48 * mailx -- a modified version of a University of California at Berkeley
49 * mail program
51 * Perform message editing functions.
54 static void edit1(int *msgvec, char *ed);
57 * Edit a message list.
60 int
61 editor(int *msgvec)
63 char *edname;
65 if ((edname = value("EDITOR")) == NOSTR || *edname == '\0')
66 edname = EDITOR;
67 edit1(msgvec, edname);
68 return(0);
72 * Invoke the visual editor on a message list.
75 int
76 visual(int *msgvec)
78 char *edname;
80 if ((edname = value("VISUAL")) == NOSTR || *edname == '\0')
81 edname = VISUAL;
82 edit1(msgvec, edname);
83 return(0);
87 * Edit a message by writing the message into a funnily-named file
88 * (which should not exist) and forking an editor on it.
89 * We get the editor from the stuff above.
92 static void
93 edit1(int *msgvec, char *ed)
95 register int c, lastc = '\n';
96 pid_t pid;
97 int *ip, mesg, blank = 1;
98 long ms, lines;
99 void (*sigint)(int), (*sigquit)(int);
100 FILE *ibuf, *obuf;
101 struct message *mp;
102 off_t size;
103 struct stat statb;
104 long modtime;
105 int fd = -1;
108 * Set signals; locate editor.
111 sigint = sigset(SIGINT, SIG_IGN);
112 sigquit = sigset(SIGQUIT, SIG_IGN);
113 ed = safeexpand(ed);
116 * Deal with each message to be edited . . .
119 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
120 mesg = *ip;
121 touch(mesg);
122 mp = &message[mesg-1];
123 dot = mp;
124 if (mp->m_text) {
125 if (!access(tempZedit, 2)) {
126 printf(gettext("%s: file exists\n"), tempZedit);
127 goto out;
131 * Copy the message into the edit file.
134 if ((fd = open(tempZedit, O_RDWR|O_CREAT|
135 O_EXCL, 0600)) < 0 ||
136 (obuf = fdopen(fd, "w")) == NULL) {
137 perror(tempZedit);
138 goto out;
140 if (msend(mp, obuf, 0, fputs) < 0) {
141 perror(tempZedit);
142 fclose(obuf);
143 removefile(tempZedit);
144 goto out;
146 fflush(obuf);
147 if (fferror(obuf)) {
148 perror(tempZedit);
149 fclose(obuf);
150 removefile(tempZedit);
151 goto out;
153 fclose(obuf);
156 * If we are in read only mode, make the
157 * temporary message file readonly as well.
160 if (readonly)
161 chmod(tempZedit, 0400);
164 * Fork/execl the editor on the edit file.
167 if (stat(tempZedit, &statb) < 0)
168 modtime = 0;
169 else
170 modtime = statb.st_mtime;
171 pid = vfork();
172 if (pid == (pid_t)-1) {
173 perror("fork");
174 removefile(tempZedit);
175 goto out;
177 if (pid == 0) {
178 sigchild();
179 if (sigint != SIG_IGN)
180 sigset(SIGINT, SIG_DFL);
181 if (sigquit != SIG_IGN)
182 sigset(SIGQUIT, SIG_DFL);
183 execlp(ed, ed, tempZedit, (char *)0);
184 perror(ed);
185 _exit(1);
187 while (wait(&mesg) != pid)
191 * If in read only mode, just remove the editor
192 * temporary and return.
195 if (readonly) {
196 removefile(tempZedit);
197 continue;
201 * Now copy the message to the end of the
202 * temp file.
205 if (stat(tempZedit, &statb) < 0) {
206 perror(tempZedit);
207 continue;
209 if (modtime == statb.st_mtime) {
210 removefile(tempZedit);
211 continue;
213 if ((ibuf = fopen(tempZedit, "r")) == NULL) {
214 perror(tempZedit);
215 removefile(tempZedit);
216 continue;
218 removefile(tempZedit);
219 fseek(otf, (long) 0, 2);
220 size = fsize(otf);
221 mp->m_flag |= MODIFY;
222 mp->m_offset = size;
223 ms = 0L;
224 lines = 0;
225 while ((c = getc(ibuf)) != EOF) {
226 if (c == '\n') {
227 lines++;
228 blank = lastc == '\n';
230 lastc = c;
231 putc(c, otf);
232 if (ferror(otf))
233 break;
234 ms++;
236 if (!blank) {
237 putc('\n', otf);
238 ms++;
239 lines++;
241 mp->m_size = ms;
242 mp->m_lines = lines;
243 fflush(otf);
244 if (fferror(otf))
245 perror("/tmp");
246 fclose(ibuf);
247 setclen(mp);
248 } else {
249 printf("\n%s\n", gettext(
250 "*** Message content is not printable: pipe to command or save to a file ***"));
255 * Restore signals and return.
258 out:
259 sigset(SIGINT, sigint);
260 sigset(SIGQUIT, sigquit);