1*22451Sdist /* 2*22451Sdist * Copyright (c) 1980 Regents of the University of California. 3*22451Sdist * All rights reserved. The Berkeley software License Agreement 4*22451Sdist * specifies the terms and conditions for redistribution. 5*22451Sdist */ 6*22451Sdist 714529Ssam #ifndef lint 8*22451Sdist static char sccsid[] = "@(#)edit.c 5.1 (Berkeley) 06/06/85"; 9*22451Sdist #endif not lint 101228Skas 111228Skas #include "rcv.h" 121228Skas #include <stdio.h> 131228Skas #include <sys/stat.h> 141228Skas 151228Skas /* 161228Skas * Mail -- a mail program 171228Skas * 181228Skas * Perform message editing functions. 191228Skas */ 201228Skas 211228Skas /* 221228Skas * Edit a message list. 231228Skas */ 241228Skas 251228Skas editor(msgvec) 261228Skas int *msgvec; 271228Skas { 281228Skas char *edname; 291228Skas 301228Skas if ((edname = value("EDITOR")) == NOSTR) 311228Skas edname = EDITOR; 321228Skas return(edit1(msgvec, edname)); 331228Skas } 341228Skas 351228Skas /* 361228Skas * Invoke the visual editor on a message list. 371228Skas */ 381228Skas 391228Skas visual(msgvec) 401228Skas int *msgvec; 411228Skas { 421228Skas char *edname; 431228Skas 441228Skas if ((edname = value("VISUAL")) == NOSTR) 451228Skas edname = VISUAL; 461228Skas return(edit1(msgvec, edname)); 471228Skas } 481228Skas 491228Skas /* 501228Skas * Edit a message by writing the message into a funnily-named file 511228Skas * (which should not exist) and forking an editor on it. 521228Skas * We get the editor from the stuff above. 531228Skas */ 541228Skas 551228Skas edit1(msgvec, ed) 561228Skas int *msgvec; 571228Skas char *ed; 581228Skas { 591228Skas register char *cp, *cp2; 601228Skas register int c; 611228Skas int *ip, pid, mesg, lines; 628745Scarl long ms; 631228Skas int (*sigint)(), (*sigquit)(); 641228Skas FILE *ibuf, *obuf; 651228Skas char edname[15], nbuf[10]; 661228Skas struct message *mp; 671228Skas extern char tempEdit[]; 681228Skas off_t fsize(), size; 691228Skas struct stat statb; 701228Skas long modtime; 711228Skas 721228Skas /* 731228Skas * Set signals; locate editor. 741228Skas */ 751228Skas 763410Skurt sigint = sigset(SIGINT, SIG_IGN); 773410Skurt sigquit = sigset(SIGQUIT, SIG_IGN); 781228Skas 791228Skas /* 801228Skas * Deal with each message to be edited . . . 811228Skas */ 821228Skas 831228Skas for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 841228Skas mesg = *ip; 851228Skas mp = &message[mesg-1]; 861228Skas mp->m_flag |= MODIFY; 871228Skas 881228Skas /* 891228Skas * Make up a name for the edit file of the 901228Skas * form "Message%d" and make sure it doesn't 911228Skas * already exist. 921228Skas */ 931228Skas 941228Skas cp = &nbuf[10]; 951228Skas *--cp = 0; 961228Skas while (mesg) { 971228Skas *--cp = mesg % 10 + '0'; 981228Skas mesg /= 10; 991228Skas } 1001228Skas cp2 = copy("Message", edname); 1011228Skas while (*cp2++ = *cp++) 1021228Skas ; 1031228Skas if (!access(edname, 2)) { 1041228Skas printf("%s: file exists\n", edname); 1051228Skas goto out; 1061228Skas } 1071228Skas 1081228Skas /* 1091228Skas * Copy the message into the edit file. 1101228Skas */ 1111228Skas 1121228Skas close(creat(edname, 0600)); 1131228Skas if ((obuf = fopen(edname, "w")) == NULL) { 1141228Skas perror(edname); 1151228Skas goto out; 1161228Skas } 1177577Skurt if (send(mp, obuf, 0) < 0) { 1181228Skas perror(edname); 1191228Skas fclose(obuf); 1201228Skas remove(edname); 1211228Skas goto out; 1221228Skas } 1231228Skas fflush(obuf); 1241228Skas if (ferror(obuf)) { 1251228Skas remove(edname); 1261228Skas fclose(obuf); 1271228Skas goto out; 1281228Skas } 1291228Skas fclose(obuf); 1301228Skas 1311228Skas /* 1321472Skas * If we are in read only mode, make the 1331472Skas * temporary message file readonly as well. 1341472Skas */ 1351472Skas 1361472Skas if (readonly) 1371472Skas chmod(edname, 0400); 1381472Skas 1391472Skas /* 1401228Skas * Fork/execl the editor on the edit file. 1411228Skas */ 1421228Skas 1431228Skas if (stat(edname, &statb) < 0) 1441228Skas modtime = 0; 1451228Skas modtime = statb.st_mtime; 1461228Skas pid = vfork(); 1471228Skas if (pid == -1) { 1481228Skas perror("fork"); 1491228Skas remove(edname); 1501228Skas goto out; 1511228Skas } 1521228Skas if (pid == 0) { 1537544Skurt sigchild(); 1541228Skas if (sigint != SIG_IGN) 1553410Skurt sigsys(SIGINT, SIG_DFL); 1561228Skas if (sigquit != SIG_IGN) 1573410Skurt sigsys(SIGQUIT, SIG_DFL); 1581228Skas execl(ed, ed, edname, 0); 1591228Skas perror(ed); 1601228Skas _exit(1); 1611228Skas } 1621228Skas while (wait(&mesg) != pid) 1631228Skas ; 1641228Skas 1651228Skas /* 1661472Skas * If in read only mode, just remove the editor 1671472Skas * temporary and return. 1681472Skas */ 1691472Skas 1701472Skas if (readonly) { 1711472Skas remove(edname); 1721472Skas continue; 1731472Skas } 1741472Skas 1751472Skas /* 1761228Skas * Now copy the message to the end of the 1771228Skas * temp file. 1781228Skas */ 1791228Skas 1801228Skas if (stat(edname, &statb) < 0) { 1811228Skas perror(edname); 1821228Skas goto out; 1831228Skas } 1841228Skas if (modtime == statb.st_mtime) { 1851228Skas remove(edname); 1861228Skas goto out; 1871228Skas } 1881228Skas if ((ibuf = fopen(edname, "r")) == NULL) { 1891228Skas perror(edname); 1901228Skas remove(edname); 1911228Skas goto out; 1921228Skas } 1931228Skas remove(edname); 1941228Skas fseek(otf, (long) 0, 2); 1951228Skas size = fsize(otf); 1961228Skas mp->m_block = blockof(size); 1971228Skas mp->m_offset = offsetof(size); 1988745Scarl ms = 0L; 1991228Skas lines = 0; 2001228Skas while ((c = getc(ibuf)) != EOF) { 2011228Skas if (c == '\n') 2021228Skas lines++; 2031228Skas putc(c, otf); 2041228Skas if (ferror(otf)) 2051228Skas break; 2061228Skas ms++; 2071228Skas } 2081228Skas mp->m_size = ms; 2091228Skas mp->m_lines = lines; 2101228Skas if (ferror(otf)) 2111228Skas perror("/tmp"); 2121228Skas fclose(ibuf); 2131228Skas } 2141228Skas 2151228Skas /* 2161228Skas * Restore signals and return. 2171228Skas */ 2181228Skas 2191228Skas out: 2203410Skurt sigset(SIGINT, sigint); 2213410Skurt sigset(SIGQUIT, sigquit); 2221228Skas } 223