Commit | Line | Data |
---|---|---|
9552e6b8 | 1 | /* |
a12ff486 KB |
2 | * Copyright (c) 1980, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
0c5f72fb | 4 | * |
f15db449 | 5 | * %sccs.include.redist.c% |
9552e6b8 DF |
6 | */ |
7 | ||
acfc7e9b | 8 | #ifndef lint |
a12ff486 | 9 | static char sccsid[] = "@(#)edit.c 8.1 (Berkeley) %G%"; |
acfc7e9b | 10 | #endif /* not lint */ |
de0c3def KS |
11 | |
12 | #include "rcv.h" | |
a0d23834 KB |
13 | #include <fcntl.h> |
14 | #include "extern.h" | |
de0c3def KS |
15 | |
16 | /* | |
17 | * Mail -- a mail program | |
18 | * | |
19 | * Perform message editing functions. | |
20 | */ | |
21 | ||
de0c3def KS |
22 | /* |
23 | * Edit a message list. | |
24 | */ | |
a0d23834 | 25 | int |
de0c3def KS |
26 | editor(msgvec) |
27 | int *msgvec; | |
28 | { | |
de0c3def | 29 | |
d33aa50d | 30 | return edit1(msgvec, 'e'); |
de0c3def KS |
31 | } |
32 | ||
33 | /* | |
34 | * Invoke the visual editor on a message list. | |
35 | */ | |
a0d23834 | 36 | int |
de0c3def KS |
37 | visual(msgvec) |
38 | int *msgvec; | |
39 | { | |
de0c3def | 40 | |
d33aa50d | 41 | return edit1(msgvec, 'v'); |
de0c3def KS |
42 | } |
43 | ||
44 | /* | |
45 | * Edit a message by writing the message into a funnily-named file | |
46 | * (which should not exist) and forking an editor on it. | |
47 | * We get the editor from the stuff above. | |
48 | */ | |
a0d23834 | 49 | int |
d33aa50d | 50 | edit1(msgvec, type) |
de0c3def | 51 | int *msgvec; |
a0d23834 | 52 | int type; |
de0c3def | 53 | { |
de0c3def | 54 | register int c; |
d33aa50d | 55 | int i; |
064d7d97 | 56 | FILE *fp; |
064d7d97 | 57 | register struct message *mp; |
d33aa50d | 58 | off_t size; |
de0c3def | 59 | |
de0c3def KS |
60 | /* |
61 | * Deal with each message to be edited . . . | |
62 | */ | |
064d7d97 | 63 | for (i = 0; msgvec[i] && i < msgCount; i++) { |
e62a1467 | 64 | sig_t sigint; |
d33aa50d EW |
65 | |
66 | if (i > 0) { | |
67 | char buf[100]; | |
68 | char *p; | |
69 | ||
470c33f3 | 70 | printf("Edit message %d [ynq]? ", msgvec[i]); |
d33aa50d EW |
71 | if (fgets(buf, sizeof buf, stdin) == 0) |
72 | break; | |
470c33f3 | 73 | for (p = buf; *p == ' ' || *p == '\t'; p++) |
d33aa50d EW |
74 | ; |
75 | if (*p == 'q') | |
76 | break; | |
77 | if (*p == 'n') | |
78 | continue; | |
de0c3def | 79 | } |
470c33f3 EW |
80 | dot = mp = &message[msgvec[i] - 1]; |
81 | touch(mp); | |
d33aa50d EW |
82 | sigint = signal(SIGINT, SIG_IGN); |
83 | fp = run_editor(setinput(mp), mp->m_size, type, readonly); | |
84 | if (fp != NULL) { | |
a0d23834 | 85 | (void) fseek(otf, 0L, 2); |
d33aa50d EW |
86 | size = ftell(otf); |
87 | mp->m_block = blockof(size); | |
88 | mp->m_offset = offsetof(size); | |
89 | mp->m_size = fsize(fp); | |
90 | mp->m_lines = 0; | |
91 | mp->m_flag |= MODIFY; | |
92 | rewind(fp); | |
93 | while ((c = getc(fp)) != EOF) { | |
94 | if (c == '\n') | |
95 | mp->m_lines++; | |
96 | if (putc(c, otf) == EOF) | |
97 | break; | |
98 | } | |
de0c3def | 99 | if (ferror(otf)) |
d33aa50d | 100 | perror("/tmp"); |
07b0d286 | 101 | (void) Fclose(fp); |
de0c3def | 102 | } |
d33aa50d EW |
103 | (void) signal(SIGINT, sigint); |
104 | } | |
d33aa50d EW |
105 | return 0; |
106 | } | |
107 | ||
108 | /* | |
109 | * Run an editor on the file at "fpp" of "size" bytes, | |
110 | * and return a new file pointer. | |
111 | * Signals must be handled by the caller. | |
435e8dff | 112 | * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI. |
d33aa50d EW |
113 | */ |
114 | FILE * | |
115 | run_editor(fp, size, type, readonly) | |
116 | register FILE *fp; | |
117 | off_t size; | |
a0d23834 | 118 | int type, readonly; |
d33aa50d EW |
119 | { |
120 | register FILE *nf = NULL; | |
121 | register int t; | |
122 | time_t modtime; | |
123 | char *edit; | |
124 | struct stat statb; | |
125 | extern char tempEdit[]; | |
126 | ||
127 | if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) { | |
128 | perror(tempEdit); | |
129 | goto out; | |
130 | } | |
07b0d286 | 131 | if ((nf = Fdopen(t, "w")) == NULL) { |
d33aa50d EW |
132 | perror(tempEdit); |
133 | (void) unlink(tempEdit); | |
134 | goto out; | |
135 | } | |
136 | if (size >= 0) | |
137 | while (--size >= 0 && (t = getc(fp)) != EOF) | |
138 | (void) putc(t, nf); | |
139 | else | |
140 | while ((t = getc(fp)) != EOF) | |
141 | (void) putc(t, nf); | |
142 | (void) fflush(nf); | |
143 | if (fstat(fileno(nf), &statb) < 0) | |
144 | modtime = 0; | |
145 | else | |
146 | modtime = statb.st_mtime; | |
07b0d286 EW |
147 | if (ferror(nf)) { |
148 | (void) Fclose(nf); | |
149 | perror(tempEdit); | |
150 | (void) unlink(tempEdit); | |
151 | nf = NULL; | |
152 | goto out; | |
153 | } | |
154 | if (Fclose(nf) < 0) { | |
d33aa50d EW |
155 | perror(tempEdit); |
156 | (void) unlink(tempEdit); | |
157 | nf = NULL; | |
158 | goto out; | |
159 | } | |
160 | nf = NULL; | |
161 | if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR) | |
435e8dff | 162 | edit = type == 'e' ? _PATH_EX : _PATH_VI; |
a0d23834 | 163 | if (run_command(edit, 0, -1, -1, tempEdit, NOSTR, NOSTR) < 0) { |
d33aa50d EW |
164 | (void) unlink(tempEdit); |
165 | goto out; | |
166 | } | |
167 | /* | |
168 | * If in read only mode or file unchanged, just remove the editor | |
169 | * temporary and return. | |
170 | */ | |
171 | if (readonly) { | |
172 | (void) unlink(tempEdit); | |
173 | goto out; | |
174 | } | |
175 | if (stat(tempEdit, &statb) < 0) { | |
176 | perror(tempEdit); | |
177 | goto out; | |
178 | } | |
179 | if (modtime == statb.st_mtime) { | |
180 | (void) unlink(tempEdit); | |
181 | goto out; | |
de0c3def | 182 | } |
de0c3def | 183 | /* |
d33aa50d | 184 | * Now switch to new file. |
de0c3def | 185 | */ |
07b0d286 | 186 | if ((nf = Fopen(tempEdit, "a+")) == NULL) { |
d33aa50d EW |
187 | perror(tempEdit); |
188 | (void) unlink(tempEdit); | |
189 | goto out; | |
190 | } | |
191 | (void) unlink(tempEdit); | |
de0c3def | 192 | out: |
d33aa50d | 193 | return nf; |
de0c3def | 194 | } |