Annotation of src/usr.bin/mail/edit.c, Revision 1.7.10.1
1.7.10.1! jason 1: /* $OpenBSD: edit.c,v 1.8 2000/06/30 16:00:18 millert Exp $ */
1.2 deraadt 2: /* $NetBSD: edit.c,v 1.5 1996/06/08 19:48:20 christos Exp $ */
3:
1.1 deraadt 4: /*
5: * Copyright (c) 1980, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
1.2 deraadt 38: #if 0
39: static char sccsid[] = "@(#)edit.c 8.1 (Berkeley) 6/6/93";
40: #else
1.7.10.1! jason 41: static char rcsid[] = "$OpenBSD: edit.c,v 1.8 2000/06/30 16:00:18 millert Exp $";
1.2 deraadt 42: #endif
1.1 deraadt 43: #endif /* not lint */
44:
45: #include "rcv.h"
46: #include <fcntl.h>
47: #include "extern.h"
48:
49: /*
50: * Mail -- a mail program
51: *
52: * Perform message editing functions.
53: */
54:
55: /*
56: * Edit a message list.
57: */
58: int
1.2 deraadt 59: editor(v)
60: void *v;
1.1 deraadt 61: {
1.2 deraadt 62: int *msgvec = v;
1.1 deraadt 63:
1.3 millert 64: return(edit1(msgvec, 'e'));
1.1 deraadt 65: }
66:
67: /*
68: * Invoke the visual editor on a message list.
69: */
70: int
1.2 deraadt 71: visual(v)
72: void *v;
1.1 deraadt 73: {
1.2 deraadt 74: int *msgvec = v;
1.1 deraadt 75:
1.3 millert 76: return(edit1(msgvec, 'v'));
1.1 deraadt 77: }
78:
79: /*
80: * Edit a message by writing the message into a funnily-named file
81: * (which should not exist) and forking an editor on it.
82: * We get the editor from the stuff above.
83: */
84: int
85: edit1(msgvec, type)
86: int *msgvec;
87: int type;
88: {
1.7 millert 89: int c, i;
1.1 deraadt 90: FILE *fp;
1.7 millert 91: struct message *mp;
1.1 deraadt 92: off_t size;
93:
94: /*
95: * Deal with each message to be edited . . .
96: */
97: for (i = 0; msgvec[i] && i < msgCount; i++) {
98: sig_t sigint;
99:
100: if (i > 0) {
101: char buf[100];
102: char *p;
103:
104: printf("Edit message %d [ynq]? ", msgvec[i]);
1.3 millert 105: if (fgets(buf, sizeof(buf), stdin) == 0)
1.1 deraadt 106: break;
107: for (p = buf; *p == ' ' || *p == '\t'; p++)
108: ;
109: if (*p == 'q')
110: break;
111: if (*p == 'n')
112: continue;
113: }
114: dot = mp = &message[msgvec[i] - 1];
115: touch(mp);
116: sigint = signal(SIGINT, SIG_IGN);
117: fp = run_editor(setinput(mp), mp->m_size, type, readonly);
118: if (fp != NULL) {
1.4 millert 119: (void)fseek(otf, 0L, 2);
1.1 deraadt 120: size = ftell(otf);
121: mp->m_block = blockof(size);
122: mp->m_offset = offsetof(size);
123: mp->m_size = fsize(fp);
124: mp->m_lines = 0;
125: mp->m_flag |= MODIFY;
126: rewind(fp);
127: while ((c = getc(fp)) != EOF) {
128: if (c == '\n')
129: mp->m_lines++;
130: if (putc(c, otf) == EOF)
131: break;
132: }
133: if (ferror(otf))
1.3 millert 134: warn("/tmp");
135: (void)Fclose(fp);
1.1 deraadt 136: }
1.4 millert 137: (void)signal(SIGINT, sigint);
1.1 deraadt 138: }
1.3 millert 139: return(0);
1.1 deraadt 140: }
141:
142: /*
143: * Run an editor on the file at "fpp" of "size" bytes,
144: * and return a new file pointer.
145: * Signals must be handled by the caller.
146: * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI.
147: */
148: FILE *
149: run_editor(fp, size, type, readonly)
1.7 millert 150: FILE *fp;
1.1 deraadt 151: off_t size;
152: int type, readonly;
153: {
1.7 millert 154: FILE *nf = NULL;
155: int t;
1.1 deraadt 156: time_t modtime;
1.6 millert 157: char *edit, tempname[PATHSIZE];
1.1 deraadt 158: struct stat statb;
159:
1.6 millert 160: (void)snprintf(tempname, sizeof(tempname),
161: "%s/mail.ReXXXXXXXXXX", tmpdir);
162: if ((t = mkstemp(tempname)) == -1 ||
163: (nf = Fdopen(t, "w")) == NULL) {
1.7.10.1! jason 164: warn("%s", tempname);
1.1 deraadt 165: goto out;
166: }
1.6 millert 167: if (readonly && fchmod(t, 0400) == -1) {
1.7.10.1! jason 168: warn("%s", tempname);
1.6 millert 169: (void)rm(tempname);
1.1 deraadt 170: goto out;
171: }
172: if (size >= 0)
173: while (--size >= 0 && (t = getc(fp)) != EOF)
1.4 millert 174: (void)putc(t, nf);
1.1 deraadt 175: else
176: while ((t = getc(fp)) != EOF)
1.4 millert 177: (void)putc(t, nf);
178: (void)fflush(nf);
1.1 deraadt 179: if (fstat(fileno(nf), &statb) < 0)
180: modtime = 0;
181: else
182: modtime = statb.st_mtime;
183: if (ferror(nf)) {
1.4 millert 184: (void)Fclose(nf);
1.7.10.1! jason 185: warn("%s", tempname);
1.6 millert 186: (void)rm(tempname);
1.1 deraadt 187: nf = NULL;
188: goto out;
189: }
190: if (Fclose(nf) < 0) {
1.7.10.1! jason 191: warn("%s", tempname);
1.6 millert 192: (void)rm(tempname);
1.1 deraadt 193: nf = NULL;
194: goto out;
195: }
196: nf = NULL;
1.5 millert 197: if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NULL)
1.1 deraadt 198: edit = type == 'e' ? _PATH_EX : _PATH_VI;
1.6 millert 199: if (run_command(edit, 0, -1, -1, tempname, NULL, NULL) < 0) {
200: (void)rm(tempname);
1.1 deraadt 201: goto out;
202: }
203: /*
204: * If in read only mode or file unchanged, just remove the editor
205: * temporary and return.
206: */
207: if (readonly) {
1.6 millert 208: (void)rm(tempname);
1.1 deraadt 209: goto out;
210: }
1.6 millert 211: if (stat(tempname, &statb) < 0) {
1.7.10.1! jason 212: warn("%s", tempname);
1.1 deraadt 213: goto out;
214: }
215: if (modtime == statb.st_mtime) {
1.6 millert 216: (void)rm(tempname);
1.1 deraadt 217: goto out;
218: }
219: /*
220: * Now switch to new file.
221: */
1.6 millert 222: if ((nf = Fopen(tempname, "a+")) == NULL) {
1.7.10.1! jason 223: warn("%s", tempname);
1.6 millert 224: (void)rm(tempname);
1.1 deraadt 225: goto out;
226: }
1.6 millert 227: (void)rm(tempname);
1.1 deraadt 228: out:
1.3 millert 229: return(nf);
1.1 deraadt 230: }