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