122451Sdist /* 222451Sdist * Copyright (c) 1980 Regents of the University of California. 3*33499Sbostic * All rights reserved. 4*33499Sbostic * 5*33499Sbostic * Redistribution and use in source and binary forms are permitted 6*33499Sbostic * provided that this notice is preserved and that due credit is given 7*33499Sbostic * to the University of California at Berkeley. The name of the University 8*33499Sbostic * may not be used to endorse or promote products derived from this 9*33499Sbostic * software without specific prior written permission. This software 10*33499Sbostic * is provided ``as is'' without express or implied warranty. 1122451Sdist */ 1222451Sdist 13*33499Sbostic #ifdef notdef 14*33499Sbostic static char sccsid[] = "@(#)edit.c 5.5 (Berkeley) 02/18/88"; 15*33499Sbostic #endif /* notdef */ 161228Skas 171228Skas #include "rcv.h" 181228Skas #include <stdio.h> 191228Skas #include <sys/stat.h> 2031142Sedward #include <sys/wait.h> 211228Skas 221228Skas /* 231228Skas * Mail -- a mail program 241228Skas * 251228Skas * Perform message editing functions. 261228Skas */ 271228Skas 281228Skas /* 291228Skas * Edit a message list. 301228Skas */ 311228Skas 321228Skas editor(msgvec) 331228Skas int *msgvec; 341228Skas { 351228Skas char *edname; 361228Skas 371228Skas if ((edname = value("EDITOR")) == NOSTR) 381228Skas edname = EDITOR; 391228Skas return(edit1(msgvec, edname)); 401228Skas } 411228Skas 421228Skas /* 431228Skas * Invoke the visual editor on a message list. 441228Skas */ 451228Skas 461228Skas visual(msgvec) 471228Skas int *msgvec; 481228Skas { 491228Skas char *edname; 501228Skas 511228Skas if ((edname = value("VISUAL")) == NOSTR) 521228Skas edname = VISUAL; 531228Skas return(edit1(msgvec, edname)); 541228Skas } 551228Skas 561228Skas /* 571228Skas * Edit a message by writing the message into a funnily-named file 581228Skas * (which should not exist) and forking an editor on it. 591228Skas * We get the editor from the stuff above. 601228Skas */ 611228Skas 621228Skas edit1(msgvec, ed) 631228Skas int *msgvec; 641228Skas char *ed; 651228Skas { 661228Skas register int c; 6731142Sedward int *ip, pid, mesg; 681228Skas int (*sigint)(), (*sigquit)(); 691228Skas FILE *ibuf, *obuf; 7031143Sedward char edname[15]; 7131142Sedward register struct message *mp; 721228Skas extern char tempEdit[]; 731228Skas off_t fsize(), size; 741228Skas struct stat statb; 751228Skas long modtime; 7631142Sedward union wait status; 771228Skas 781228Skas /* 791228Skas * Set signals; locate editor. 801228Skas */ 811228Skas 8231142Sedward sigint = signal(SIGINT, SIG_IGN); 8331142Sedward sigquit = signal(SIGQUIT, SIG_IGN); 841228Skas 851228Skas /* 861228Skas * Deal with each message to be edited . . . 871228Skas */ 881228Skas 891228Skas for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 901228Skas mesg = *ip; 911228Skas mp = &message[mesg-1]; 921228Skas mp->m_flag |= MODIFY; 9331142Sedward touch(mesg); 9431142Sedward dot = mp; 951228Skas 961228Skas /* 971228Skas * Make up a name for the edit file of the 981228Skas * form "Message%d" and make sure it doesn't 991228Skas * already exist. 1001228Skas */ 10131143Sedward (void) sprintf(edname, "Message%d", mesg); 1021228Skas if (!access(edname, 2)) { 1031228Skas printf("%s: file exists\n", edname); 1041228Skas goto out; 1051228Skas } 1061228Skas 1071228Skas /* 1081228Skas * Copy the message into the edit file. 1091228Skas */ 11031143Sedward (void) close(creat(edname, 0600)); 1111228Skas if ((obuf = fopen(edname, "w")) == NULL) { 1121228Skas perror(edname); 1131228Skas goto out; 1141228Skas } 1157577Skurt if (send(mp, obuf, 0) < 0) { 1161228Skas perror(edname); 11731143Sedward (void) fclose(obuf); 11831143Sedward (void) remove(edname); 1191228Skas goto out; 1201228Skas } 12131143Sedward (void) fflush(obuf); 1221228Skas if (ferror(obuf)) { 12331143Sedward (void) remove(edname); 12431143Sedward (void) fclose(obuf); 1251228Skas goto out; 1261228Skas } 12731143Sedward (void) fclose(obuf); 1281228Skas 1291228Skas /* 1301472Skas * If we are in read only mode, make the 1311472Skas * temporary message file readonly as well. 1321472Skas */ 1331472Skas 1341472Skas if (readonly) 13531143Sedward (void) chmod(edname, 0400); 1361472Skas 1371472Skas /* 1381228Skas * Fork/execl the editor on the edit file. 1391228Skas */ 1401228Skas 1411228Skas if (stat(edname, &statb) < 0) 1421228Skas modtime = 0; 1431228Skas modtime = statb.st_mtime; 1441228Skas pid = vfork(); 1451228Skas if (pid == -1) { 1461228Skas perror("fork"); 14731143Sedward (void) remove(edname); 1481228Skas goto out; 1491228Skas } 1501228Skas if (pid == 0) { 1511228Skas if (sigint != SIG_IGN) 15231143Sedward (void) signal(SIGINT, SIG_DFL); 1531228Skas if (sigquit != SIG_IGN) 15431143Sedward (void) signal(SIGQUIT, SIG_DFL); 1551228Skas execl(ed, ed, edname, 0); 1561228Skas perror(ed); 1571228Skas _exit(1); 1581228Skas } 15931142Sedward while (wait(&status) != pid) 1601228Skas ; 1611228Skas 1621228Skas /* 1631472Skas * If in read only mode, just remove the editor 1641472Skas * temporary and return. 1651472Skas */ 1661472Skas 1671472Skas if (readonly) { 16831143Sedward (void) remove(edname); 1691472Skas continue; 1701472Skas } 1711472Skas 1721472Skas /* 1731228Skas * Now copy the message to the end of the 1741228Skas * temp file. 1751228Skas */ 1761228Skas 1771228Skas if (stat(edname, &statb) < 0) { 1781228Skas perror(edname); 1791228Skas goto out; 1801228Skas } 1811228Skas if (modtime == statb.st_mtime) { 18231143Sedward (void) remove(edname); 1831228Skas goto out; 1841228Skas } 1851228Skas if ((ibuf = fopen(edname, "r")) == NULL) { 1861228Skas perror(edname); 18731143Sedward (void) remove(edname); 1881228Skas goto out; 1891228Skas } 19031143Sedward (void) remove(edname); 19131143Sedward (void) fseek(otf, (long) 0, 2); 19231142Sedward size = ftell(otf); 1931228Skas mp->m_block = blockof(size); 1941228Skas mp->m_offset = offsetof(size); 19531142Sedward mp->m_size = fsize(ibuf); 19631142Sedward mp->m_lines = 0; 1971228Skas while ((c = getc(ibuf)) != EOF) { 1981228Skas if (c == '\n') 19931142Sedward mp->m_lines++; 20031143Sedward (void) putc(c, otf); 2011228Skas if (ferror(otf)) 2021228Skas break; 2031228Skas } 2041228Skas if (ferror(otf)) 2051228Skas perror("/tmp"); 20631143Sedward (void) fclose(ibuf); 2071228Skas } 2081228Skas 2091228Skas /* 2101228Skas * Restore signals and return. 2111228Skas */ 2121228Skas 2131228Skas out: 21431143Sedward (void) signal(SIGINT, sigint); 21531143Sedward (void) signal(SIGQUIT, sigquit); 21631142Sedward return 0; 2171228Skas } 218