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 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. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)edit.c 5.13 (Berkeley) 11/24/89"; 20 #endif /* not lint */ 21 22 #include "rcv.h" 23 #include <sys/stat.h> 24 25 /* 26 * Mail -- a mail program 27 * 28 * Perform message editing functions. 29 */ 30 31 /* 32 * Edit a message list. 33 */ 34 35 editor(msgvec) 36 int *msgvec; 37 { 38 39 return edit1(msgvec, 'e'); 40 } 41 42 /* 43 * Invoke the visual editor on a message list. 44 */ 45 46 visual(msgvec) 47 int *msgvec; 48 { 49 50 return edit1(msgvec, 'v'); 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 */ 58 edit1(msgvec, type) 59 int *msgvec; 60 char type; 61 { 62 register int c; 63 int i; 64 FILE *fp; 65 register struct message *mp; 66 off_t size; 67 68 /* 69 * Deal with each message to be edited . . . 70 */ 71 for (i = 0; msgvec[i] && i < msgCount; i++) { 72 sig_t sigint; 73 74 if (i > 0) { 75 char buf[100]; 76 char *p; 77 78 printf("Edit message %d [ynq]? ", msgvec[i]); 79 if (fgets(buf, sizeof buf, stdin) == 0) 80 break; 81 for (p = buf; *p == ' ' || *p == '\t'; p++) 82 ; 83 if (*p == 'q') 84 break; 85 if (*p == 'n') 86 continue; 87 } 88 dot = mp = &message[msgvec[i] - 1]; 89 touch(mp); 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 } 107 if (ferror(otf)) 108 perror("/tmp"); 109 (void) fclose(fp); 110 } 111 (void) signal(SIGINT, sigint); 112 } 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. 120 * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI. 121 */ 122 FILE * 123 run_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) 163 edit = type == 'e' ? _PATH_EX : _PATH_VI; 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; 183 } 184 /* 185 * Now switch to new file. 186 */ 187 if ((nf = fopen(tempEdit, "a+")) == NULL) { 188 perror(tempEdit); 189 (void) unlink(tempEdit); 190 goto out; 191 } 192 (void) unlink(tempEdit); 193 out: 194 return nf; 195 } 196