install correct aliases file
[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
470c33f3 19static char sccsid[] = "@(#)edit.c 5.10 (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{
d33aa50d 62 int (*sigcont)() = signal(SIGCONT, SIG_DFL);
de0c3def 63 register int c;
d33aa50d 64 int i;
064d7d97 65 FILE *fp;
064d7d97 66 register struct message *mp;
d33aa50d 67 off_t size;
de0c3def 68
de0c3def
KS
69 /*
70 * Deal with each message to be edited . . .
71 */
064d7d97 72 for (i = 0; msgvec[i] && i < msgCount; i++) {
d33aa50d 73 int (*sigint)();
d33aa50d
EW
74
75 if (i > 0) {
76 char buf[100];
77 char *p;
78
470c33f3 79 printf("Edit message %d [ynq]? ", msgvec[i]);
d33aa50d
EW
80 if (fgets(buf, sizeof buf, stdin) == 0)
81 break;
470c33f3 82 for (p = buf; *p == ' ' || *p == '\t'; p++)
d33aa50d
EW
83 ;
84 if (*p == 'q')
85 break;
86 if (*p == 'n')
87 continue;
de0c3def 88 }
470c33f3
EW
89 dot = mp = &message[msgvec[i] - 1];
90 touch(mp);
d33aa50d
EW
91 sigint = signal(SIGINT, SIG_IGN);
92 fp = run_editor(setinput(mp), mp->m_size, type, readonly);
93 if (fp != NULL) {
94 (void) fseek(otf, (long) 0, 2);
95 size = ftell(otf);
96 mp->m_block = blockof(size);
97 mp->m_offset = offsetof(size);
98 mp->m_size = fsize(fp);
99 mp->m_lines = 0;
100 mp->m_flag |= MODIFY;
101 rewind(fp);
102 while ((c = getc(fp)) != EOF) {
103 if (c == '\n')
104 mp->m_lines++;
105 if (putc(c, otf) == EOF)
106 break;
107 }
de0c3def 108 if (ferror(otf))
d33aa50d
EW
109 perror("/tmp");
110 (void) fclose(fp);
de0c3def 111 }
d33aa50d
EW
112 (void) signal(SIGINT, sigint);
113 }
114 (void) signal(SIGCONT, sigcont);
115 return 0;
116}
117
118/*
119 * Run an editor on the file at "fpp" of "size" bytes,
120 * and return a new file pointer.
121 * Signals must be handled by the caller.
122 * "Type" is 'e' for EDITOR, 'v' for VISUAL.
123 */
124FILE *
125run_editor(fp, size, type, readonly)
126 register FILE *fp;
127 off_t size;
128 char type;
129{
130 register FILE *nf = NULL;
131 register int t;
132 time_t modtime;
133 char *edit;
134 struct stat statb;
135 extern char tempEdit[];
136
137 if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) {
138 perror(tempEdit);
139 goto out;
140 }
141 if ((nf = fdopen(t, "w")) == NULL) {
142 perror(tempEdit);
143 (void) unlink(tempEdit);
144 goto out;
145 }
146 if (size >= 0)
147 while (--size >= 0 && (t = getc(fp)) != EOF)
148 (void) putc(t, nf);
149 else
150 while ((t = getc(fp)) != EOF)
151 (void) putc(t, nf);
152 (void) fflush(nf);
153 if (fstat(fileno(nf), &statb) < 0)
154 modtime = 0;
155 else
156 modtime = statb.st_mtime;
157 if (ferror(nf) || fclose(nf) < 0) {
158 perror(tempEdit);
159 (void) unlink(tempEdit);
160 nf = NULL;
161 goto out;
162 }
163 nf = NULL;
164 if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
165 edit = type == 'e' ? EDITOR : VISUAL;
166 if (run_command(edit, 0, -1, -1, tempEdit, NOSTR) < 0) {
167 (void) unlink(tempEdit);
168 goto out;
169 }
170 /*
171 * If in read only mode or file unchanged, just remove the editor
172 * temporary and return.
173 */
174 if (readonly) {
175 (void) unlink(tempEdit);
176 goto out;
177 }
178 if (stat(tempEdit, &statb) < 0) {
179 perror(tempEdit);
180 goto out;
181 }
182 if (modtime == statb.st_mtime) {
183 (void) unlink(tempEdit);
184 goto out;
de0c3def 185 }
de0c3def 186 /*
d33aa50d 187 * Now switch to new file.
de0c3def 188 */
d33aa50d
EW
189 if ((nf = fopen(tempEdit, "a+")) == NULL) {
190 perror(tempEdit);
191 (void) unlink(tempEdit);
192 goto out;
193 }
194 (void) unlink(tempEdit);
de0c3def 195out:
d33aa50d 196 return nf;
de0c3def 197}