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