122451Sdist /* 222451Sdist * Copyright (c) 1980 Regents of the University of California. 333499Sbostic * All rights reserved. 433499Sbostic * 533499Sbostic * Redistribution and use in source and binary forms are permitted 634905Sbostic * provided that the above copyright notice and this paragraph are 734905Sbostic * duplicated in all such forms and that any documentation, 834905Sbostic * advertising materials, and other materials related to such 934905Sbostic * distribution and use acknowledge that the software was developed 1034905Sbostic * by the University of California, Berkeley. The name of the 1134905Sbostic * University may not be used to endorse or promote products derived 1234905Sbostic * from this software without specific prior written permission. 1334905Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434905Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534905Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1622451Sdist */ 1722451Sdist 1834905Sbostic #ifndef lint 19*37870Sbostic static char sccsid[] = "@(#)edit.c 5.12 (Berkeley) 05/11/89"; 2034905Sbostic #endif /* not lint */ 211228Skas 221228Skas #include "rcv.h" 231228Skas #include <sys/stat.h> 241228Skas 251228Skas /* 261228Skas * Mail -- a mail program 271228Skas * 281228Skas * Perform message editing functions. 291228Skas */ 301228Skas 311228Skas /* 321228Skas * Edit a message list. 331228Skas */ 341228Skas 351228Skas editor(msgvec) 361228Skas int *msgvec; 371228Skas { 381228Skas 3934963Sedward return edit1(msgvec, 'e'); 401228Skas } 411228Skas 421228Skas /* 431228Skas * Invoke the visual editor on a message list. 441228Skas */ 451228Skas 461228Skas visual(msgvec) 471228Skas int *msgvec; 481228Skas { 491228Skas 5034963Sedward return edit1(msgvec, 'v'); 511228Skas } 521228Skas 531228Skas /* 541228Skas * Edit a message by writing the message into a funnily-named file 551228Skas * (which should not exist) and forking an editor on it. 561228Skas * We get the editor from the stuff above. 571228Skas */ 5834963Sedward edit1(msgvec, type) 591228Skas int *msgvec; 6034963Sedward char type; 611228Skas { 621228Skas register int c; 6334963Sedward int i; 6434879Sedward FILE *fp; 6531142Sedward register struct message *mp; 6634963Sedward off_t size; 671228Skas 681228Skas /* 691228Skas * Deal with each message to be edited . . . 701228Skas */ 7134879Sedward for (i = 0; msgvec[i] && i < msgCount; i++) { 7234963Sedward int (*sigint)(); 7334963Sedward 7434963Sedward if (i > 0) { 7534963Sedward char buf[100]; 7634963Sedward char *p; 7734963Sedward 7834987Sedward printf("Edit message %d [ynq]? ", msgvec[i]); 7934963Sedward if (fgets(buf, sizeof buf, stdin) == 0) 8034963Sedward break; 8134987Sedward for (p = buf; *p == ' ' || *p == '\t'; p++) 8234963Sedward ; 8334963Sedward if (*p == 'q') 8434963Sedward break; 8534963Sedward if (*p == 'n') 8634963Sedward continue; 871228Skas } 8834987Sedward dot = mp = &message[msgvec[i] - 1]; 8934987Sedward touch(mp); 9034963Sedward sigint = signal(SIGINT, SIG_IGN); 9134963Sedward fp = run_editor(setinput(mp), mp->m_size, type, readonly); 9234963Sedward if (fp != NULL) { 9334963Sedward (void) fseek(otf, (long) 0, 2); 9434963Sedward size = ftell(otf); 9534963Sedward mp->m_block = blockof(size); 9634963Sedward mp->m_offset = offsetof(size); 9734963Sedward mp->m_size = fsize(fp); 9834963Sedward mp->m_lines = 0; 9934963Sedward mp->m_flag |= MODIFY; 10034963Sedward rewind(fp); 10134963Sedward while ((c = getc(fp)) != EOF) { 10234963Sedward if (c == '\n') 10334963Sedward mp->m_lines++; 10434963Sedward if (putc(c, otf) == EOF) 10534963Sedward break; 10634963Sedward } 10734963Sedward if (ferror(otf)) 10834963Sedward perror("/tmp"); 10934879Sedward (void) fclose(fp); 1101228Skas } 11134963Sedward (void) signal(SIGINT, sigint); 1121228Skas } 11334963Sedward return 0; 11434963Sedward } 11534963Sedward 11634963Sedward /* 11734963Sedward * Run an editor on the file at "fpp" of "size" bytes, 11834963Sedward * and return a new file pointer. 11934963Sedward * Signals must be handled by the caller. 120*37870Sbostic * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI. 12134963Sedward */ 12234963Sedward FILE * 12334963Sedward run_editor(fp, size, type, readonly) 12434963Sedward register FILE *fp; 12534963Sedward off_t size; 12634963Sedward char type; 12734963Sedward { 12834963Sedward register FILE *nf = NULL; 12934963Sedward register int t; 13034963Sedward time_t modtime; 13134963Sedward char *edit; 13234963Sedward struct stat statb; 13334963Sedward extern char tempEdit[]; 13434963Sedward 13534963Sedward if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) { 13634963Sedward perror(tempEdit); 13734963Sedward goto out; 13834963Sedward } 13934963Sedward if ((nf = fdopen(t, "w")) == NULL) { 14034963Sedward perror(tempEdit); 14134963Sedward (void) unlink(tempEdit); 14234963Sedward goto out; 14334963Sedward } 14434963Sedward if (size >= 0) 14534963Sedward while (--size >= 0 && (t = getc(fp)) != EOF) 14634963Sedward (void) putc(t, nf); 14734963Sedward else 14834963Sedward while ((t = getc(fp)) != EOF) 14934963Sedward (void) putc(t, nf); 15034963Sedward (void) fflush(nf); 15134963Sedward if (fstat(fileno(nf), &statb) < 0) 15234963Sedward modtime = 0; 15334963Sedward else 15434963Sedward modtime = statb.st_mtime; 15534963Sedward if (ferror(nf) || fclose(nf) < 0) { 15634963Sedward perror(tempEdit); 15734963Sedward (void) unlink(tempEdit); 15834963Sedward nf = NULL; 15934963Sedward goto out; 16034963Sedward } 16134963Sedward nf = NULL; 16234963Sedward if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR) 163*37870Sbostic edit = type == 'e' ? _PATH_EX : _PATH_VI; 16434963Sedward if (run_command(edit, 0, -1, -1, tempEdit, NOSTR) < 0) { 16534963Sedward (void) unlink(tempEdit); 16634963Sedward goto out; 16734963Sedward } 1681228Skas /* 16934963Sedward * If in read only mode or file unchanged, just remove the editor 17034963Sedward * temporary and return. 1711228Skas */ 17234963Sedward if (readonly) { 17334963Sedward (void) unlink(tempEdit); 17434963Sedward goto out; 17534963Sedward } 17634963Sedward if (stat(tempEdit, &statb) < 0) { 17734963Sedward perror(tempEdit); 17834963Sedward goto out; 17934963Sedward } 18034963Sedward if (modtime == statb.st_mtime) { 18134963Sedward (void) unlink(tempEdit); 18234963Sedward goto out; 18334963Sedward } 18434963Sedward /* 18534963Sedward * Now switch to new file. 18634963Sedward */ 18734963Sedward if ((nf = fopen(tempEdit, "a+")) == NULL) { 18834963Sedward perror(tempEdit); 18934963Sedward (void) unlink(tempEdit); 19034963Sedward goto out; 19134963Sedward } 19234963Sedward (void) unlink(tempEdit); 1931228Skas out: 19434963Sedward return nf; 1951228Skas } 196