|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)edit.c 5.15 (Berkeley) 6/25/90";
22: #endif /* not lint */
23:
24: #include "rcv.h"
25: #include <sys/stat.h>
26:
27: /*
28: * Mail -- a mail program
29: *
30: * Perform message editing functions.
31: */
32:
33: /*
34: * Edit a message list.
35: */
36:
37: editor(msgvec)
38: int *msgvec;
39: {
40:
41: return edit1(msgvec, 'e');
42: }
43:
44: /*
45: * Invoke the visual editor on a message list.
46: */
47:
48: visual(msgvec)
49: int *msgvec;
50: {
51:
52: return edit1(msgvec, 'v');
53: }
54:
55: /*
56: * Edit a message by writing the message into a funnily-named file
57: * (which should not exist) and forking an editor on it.
58: * We get the editor from the stuff above.
59: */
60: edit1(msgvec, type)
61: int *msgvec;
62: char type;
63: {
64: register int c;
65: int i;
66: FILE *fp;
67: register struct message *mp;
68: off_t size;
69:
70: /*
71: * Deal with each message to be edited . . .
72: */
73: for (i = 0; msgvec[i] && i < msgCount; i++) {
74: sig_t sigint;
75:
76: if (i > 0) {
77: char buf[100];
78: char *p;
79:
80: printf("Edit message %d [ynq]? ", msgvec[i]);
81: if (fgets(buf, sizeof buf, stdin) == 0)
82: break;
83: for (p = buf; *p == ' ' || *p == '\t'; p++)
84: ;
85: if (*p == 'q')
86: break;
87: if (*p == 'n')
88: continue;
89: }
90: dot = mp = &message[msgvec[i] - 1];
91: touch(mp);
92: sigint = signal(SIGINT, SIG_IGN);
93: fp = run_editor(setinput(mp), mp->m_size, type, readonly);
94: if (fp != NULL) {
95: (void) fseek(otf, (long) 0, 2);
96: size = ftell(otf);
97: mp->m_block = blockof(size);
98: mp->m_offset = offsetof(size);
99: mp->m_size = fsize(fp);
100: mp->m_lines = 0;
101: mp->m_flag |= MODIFY;
102: rewind(fp);
103: while ((c = getc(fp)) != EOF) {
104: if (c == '\n')
105: mp->m_lines++;
106: if (putc(c, otf) == EOF)
107: break;
108: }
109: if (ferror(otf))
110: perror("/tmp");
111: (void) Fclose(fp);
112: }
113: (void) signal(SIGINT, sigint);
114: }
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 _PATH_EX, 'v' for _PATH_VI.
123: */
124: FILE *
125: run_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)) {
158: (void) Fclose(nf);
159: perror(tempEdit);
160: (void) unlink(tempEdit);
161: nf = NULL;
162: goto out;
163: }
164: if (Fclose(nf) < 0) {
165: perror(tempEdit);
166: (void) unlink(tempEdit);
167: nf = NULL;
168: goto out;
169: }
170: nf = NULL;
171: if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
172: edit = type == 'e' ? _PATH_EX : _PATH_VI;
173: if (run_command(edit, 0, -1, -1, tempEdit, NOSTR) < 0) {
174: (void) unlink(tempEdit);
175: goto out;
176: }
177: /*
178: * If in read only mode or file unchanged, just remove the editor
179: * temporary and return.
180: */
181: if (readonly) {
182: (void) unlink(tempEdit);
183: goto out;
184: }
185: if (stat(tempEdit, &statb) < 0) {
186: perror(tempEdit);
187: goto out;
188: }
189: if (modtime == statb.st_mtime) {
190: (void) unlink(tempEdit);
191: goto out;
192: }
193: /*
194: * Now switch to new file.
195: */
196: if ((nf = Fopen(tempEdit, "a+")) == NULL) {
197: perror(tempEdit);
198: (void) unlink(tempEdit);
199: goto out;
200: }
201: (void) unlink(tempEdit);
202: out:
203: return nf;
204: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.