1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char *sccsid = "@(#)edit.c 5.4 (Berkeley) 05/18/87"; 9 #endif not lint 10 11 #include "rcv.h" 12 #include <stdio.h> 13 #include <sys/stat.h> 14 #include <sys/wait.h> 15 16 /* 17 * Mail -- a mail program 18 * 19 * Perform message editing functions. 20 */ 21 22 /* 23 * Edit a message list. 24 */ 25 26 editor(msgvec) 27 int *msgvec; 28 { 29 char *edname; 30 31 if ((edname = value("EDITOR")) == NOSTR) 32 edname = EDITOR; 33 return(edit1(msgvec, edname)); 34 } 35 36 /* 37 * Invoke the visual editor on a message list. 38 */ 39 40 visual(msgvec) 41 int *msgvec; 42 { 43 char *edname; 44 45 if ((edname = value("VISUAL")) == NOSTR) 46 edname = VISUAL; 47 return(edit1(msgvec, edname)); 48 } 49 50 /* 51 * Edit a message by writing the message into a funnily-named file 52 * (which should not exist) and forking an editor on it. 53 * We get the editor from the stuff above. 54 */ 55 56 edit1(msgvec, ed) 57 int *msgvec; 58 char *ed; 59 { 60 register int c; 61 int *ip, pid, mesg; 62 int (*sigint)(), (*sigquit)(); 63 FILE *ibuf, *obuf; 64 char edname[15]; 65 register struct message *mp; 66 extern char tempEdit[]; 67 off_t fsize(), size; 68 struct stat statb; 69 long modtime; 70 union wait status; 71 72 /* 73 * Set signals; locate editor. 74 */ 75 76 sigint = signal(SIGINT, SIG_IGN); 77 sigquit = signal(SIGQUIT, SIG_IGN); 78 79 /* 80 * Deal with each message to be edited . . . 81 */ 82 83 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 84 mesg = *ip; 85 mp = &message[mesg-1]; 86 mp->m_flag |= MODIFY; 87 touch(mesg); 88 dot = mp; 89 90 /* 91 * Make up a name for the edit file of the 92 * form "Message%d" and make sure it doesn't 93 * already exist. 94 */ 95 (void) sprintf(edname, "Message%d", mesg); 96 if (!access(edname, 2)) { 97 printf("%s: file exists\n", edname); 98 goto out; 99 } 100 101 /* 102 * Copy the message into the edit file. 103 */ 104 (void) close(creat(edname, 0600)); 105 if ((obuf = fopen(edname, "w")) == NULL) { 106 perror(edname); 107 goto out; 108 } 109 if (send(mp, obuf, 0) < 0) { 110 perror(edname); 111 (void) fclose(obuf); 112 (void) remove(edname); 113 goto out; 114 } 115 (void) fflush(obuf); 116 if (ferror(obuf)) { 117 (void) remove(edname); 118 (void) fclose(obuf); 119 goto out; 120 } 121 (void) fclose(obuf); 122 123 /* 124 * If we are in read only mode, make the 125 * temporary message file readonly as well. 126 */ 127 128 if (readonly) 129 (void) chmod(edname, 0400); 130 131 /* 132 * Fork/execl the editor on the edit file. 133 */ 134 135 if (stat(edname, &statb) < 0) 136 modtime = 0; 137 modtime = statb.st_mtime; 138 pid = vfork(); 139 if (pid == -1) { 140 perror("fork"); 141 (void) remove(edname); 142 goto out; 143 } 144 if (pid == 0) { 145 if (sigint != SIG_IGN) 146 (void) signal(SIGINT, SIG_DFL); 147 if (sigquit != SIG_IGN) 148 (void) signal(SIGQUIT, SIG_DFL); 149 execl(ed, ed, edname, 0); 150 perror(ed); 151 _exit(1); 152 } 153 while (wait(&status) != pid) 154 ; 155 156 /* 157 * If in read only mode, just remove the editor 158 * temporary and return. 159 */ 160 161 if (readonly) { 162 (void) remove(edname); 163 continue; 164 } 165 166 /* 167 * Now copy the message to the end of the 168 * temp file. 169 */ 170 171 if (stat(edname, &statb) < 0) { 172 perror(edname); 173 goto out; 174 } 175 if (modtime == statb.st_mtime) { 176 (void) remove(edname); 177 goto out; 178 } 179 if ((ibuf = fopen(edname, "r")) == NULL) { 180 perror(edname); 181 (void) remove(edname); 182 goto out; 183 } 184 (void) remove(edname); 185 (void) fseek(otf, (long) 0, 2); 186 size = ftell(otf); 187 mp->m_block = blockof(size); 188 mp->m_offset = offsetof(size); 189 mp->m_size = fsize(ibuf); 190 mp->m_lines = 0; 191 while ((c = getc(ibuf)) != EOF) { 192 if (c == '\n') 193 mp->m_lines++; 194 (void) putc(c, otf); 195 if (ferror(otf)) 196 break; 197 } 198 if (ferror(otf)) 199 perror("/tmp"); 200 (void) fclose(ibuf); 201 } 202 203 /* 204 * Restore signals and return. 205 */ 206 207 out: 208 (void) signal(SIGINT, sigint); 209 (void) signal(SIGQUIT, sigquit); 210 return 0; 211 } 212