11228Skas # 21228Skas 31228Skas #include "rcv.h" 41228Skas #include <stdio.h> 51228Skas #include <sys/stat.h> 61228Skas 71228Skas /* 81228Skas * Mail -- a mail program 91228Skas * 101228Skas * Perform message editing functions. 111228Skas */ 121228Skas 13*1472Skas static char *SccsId = "@(#)edit.c 1.2 10/16/80"; 141228Skas 151228Skas /* 161228Skas * Edit a message list. 171228Skas */ 181228Skas 191228Skas editor(msgvec) 201228Skas int *msgvec; 211228Skas { 221228Skas char *edname; 231228Skas 241228Skas if ((edname = value("EDITOR")) == NOSTR) 251228Skas edname = EDITOR; 261228Skas return(edit1(msgvec, edname)); 271228Skas } 281228Skas 291228Skas /* 301228Skas * Invoke the visual editor on a message list. 311228Skas */ 321228Skas 331228Skas visual(msgvec) 341228Skas int *msgvec; 351228Skas { 361228Skas char *edname; 371228Skas 381228Skas if ((edname = value("VISUAL")) == NOSTR) 391228Skas edname = VISUAL; 401228Skas return(edit1(msgvec, edname)); 411228Skas } 421228Skas 431228Skas /* 441228Skas * Edit a message by writing the message into a funnily-named file 451228Skas * (which should not exist) and forking an editor on it. 461228Skas * We get the editor from the stuff above. 471228Skas */ 481228Skas 491228Skas edit1(msgvec, ed) 501228Skas int *msgvec; 511228Skas char *ed; 521228Skas { 531228Skas register char *cp, *cp2; 541228Skas register int c; 551228Skas int *ip, pid, mesg, lines; 561228Skas unsigned int ms; 571228Skas int (*sigint)(), (*sigquit)(); 581228Skas FILE *ibuf, *obuf; 591228Skas char edname[15], nbuf[10]; 601228Skas struct message *mp; 611228Skas extern char tempEdit[]; 621228Skas off_t fsize(), size; 631228Skas struct stat statb; 641228Skas long modtime; 651228Skas 661228Skas /* 671228Skas * Set signals; locate editor. 681228Skas */ 691228Skas 701228Skas sigint = signal(SIGINT, SIG_IGN); 711228Skas sigquit = signal(SIGQUIT, SIG_IGN); 721228Skas 731228Skas /* 741228Skas * Deal with each message to be edited . . . 751228Skas */ 761228Skas 771228Skas for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 781228Skas mesg = *ip; 791228Skas mp = &message[mesg-1]; 801228Skas mp->m_flag |= MODIFY; 811228Skas 821228Skas /* 831228Skas * Make up a name for the edit file of the 841228Skas * form "Message%d" and make sure it doesn't 851228Skas * already exist. 861228Skas */ 871228Skas 881228Skas cp = &nbuf[10]; 891228Skas *--cp = 0; 901228Skas while (mesg) { 911228Skas *--cp = mesg % 10 + '0'; 921228Skas mesg /= 10; 931228Skas } 941228Skas cp2 = copy("Message", edname); 951228Skas while (*cp2++ = *cp++) 961228Skas ; 971228Skas if (!access(edname, 2)) { 981228Skas printf("%s: file exists\n", edname); 991228Skas goto out; 1001228Skas } 1011228Skas 1021228Skas /* 1031228Skas * Copy the message into the edit file. 1041228Skas */ 1051228Skas 1061228Skas close(creat(edname, 0600)); 1071228Skas if ((obuf = fopen(edname, "w")) == NULL) { 1081228Skas perror(edname); 1091228Skas goto out; 1101228Skas } 1111228Skas if (send(mp, obuf) < 0) { 1121228Skas perror(edname); 1131228Skas fclose(obuf); 1141228Skas remove(edname); 1151228Skas goto out; 1161228Skas } 1171228Skas fflush(obuf); 1181228Skas if (ferror(obuf)) { 1191228Skas remove(edname); 1201228Skas fclose(obuf); 1211228Skas goto out; 1221228Skas } 1231228Skas fclose(obuf); 1241228Skas 1251228Skas /* 126*1472Skas * If we are in read only mode, make the 127*1472Skas * temporary message file readonly as well. 128*1472Skas */ 129*1472Skas 130*1472Skas if (readonly) 131*1472Skas chmod(edname, 0400); 132*1472Skas 133*1472Skas /* 1341228Skas * Fork/execl the editor on the edit file. 1351228Skas */ 1361228Skas 1371228Skas if (stat(edname, &statb) < 0) 1381228Skas modtime = 0; 1391228Skas modtime = statb.st_mtime; 1401228Skas pid = vfork(); 1411228Skas if (pid == -1) { 1421228Skas perror("fork"); 1431228Skas remove(edname); 1441228Skas goto out; 1451228Skas } 1461228Skas if (pid == 0) { 1471228Skas if (sigint != SIG_IGN) 1481228Skas signal(SIGINT, SIG_DFL); 1491228Skas if (sigquit != SIG_IGN) 1501228Skas signal(SIGQUIT, SIG_DFL); 1511228Skas execl(ed, ed, edname, 0); 1521228Skas perror(ed); 1531228Skas _exit(1); 1541228Skas } 1551228Skas while (wait(&mesg) != pid) 1561228Skas ; 1571228Skas 1581228Skas /* 159*1472Skas * If in read only mode, just remove the editor 160*1472Skas * temporary and return. 161*1472Skas */ 162*1472Skas 163*1472Skas if (readonly) { 164*1472Skas remove(edname); 165*1472Skas continue; 166*1472Skas } 167*1472Skas 168*1472Skas /* 1691228Skas * Now copy the message to the end of the 1701228Skas * temp file. 1711228Skas */ 1721228Skas 1731228Skas if (stat(edname, &statb) < 0) { 1741228Skas perror(edname); 1751228Skas goto out; 1761228Skas } 1771228Skas if (modtime == statb.st_mtime) { 1781228Skas remove(edname); 1791228Skas goto out; 1801228Skas } 1811228Skas if ((ibuf = fopen(edname, "r")) == NULL) { 1821228Skas perror(edname); 1831228Skas remove(edname); 1841228Skas goto out; 1851228Skas } 1861228Skas remove(edname); 1871228Skas fseek(otf, (long) 0, 2); 1881228Skas size = fsize(otf); 1891228Skas mp->m_block = blockof(size); 1901228Skas mp->m_offset = offsetof(size); 1911228Skas ms = 0; 1921228Skas lines = 0; 1931228Skas while ((c = getc(ibuf)) != EOF) { 1941228Skas if (c == '\n') 1951228Skas lines++; 1961228Skas putc(c, otf); 1971228Skas if (ferror(otf)) 1981228Skas break; 1991228Skas ms++; 2001228Skas } 2011228Skas mp->m_size = ms; 2021228Skas mp->m_lines = lines; 2031228Skas if (ferror(otf)) 2041228Skas perror("/tmp"); 2051228Skas fclose(ibuf); 2061228Skas } 2071228Skas 2081228Skas /* 2091228Skas * Restore signals and return. 2101228Skas */ 2111228Skas 2121228Skas out: 2131228Skas signal(SIGINT, sigint); 2141228Skas signal(SIGQUIT, sigquit); 2151228Skas } 216