122451Sdist /* 222451Sdist * Copyright (c) 1980 Regents of the University of California. 333499Sbostic * All rights reserved. 433499Sbostic * 5*42741Sbostic * %sccs.include.redist.c% 622451Sdist */ 722451Sdist 834905Sbostic #ifndef lint 9*42741Sbostic static char sccsid[] = "@(#)edit.c 5.14 (Berkeley) 06/01/90"; 1034905Sbostic #endif /* not lint */ 111228Skas 121228Skas #include "rcv.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 2934963Sedward return edit1(msgvec, 'e'); 301228Skas } 311228Skas 321228Skas /* 331228Skas * Invoke the visual editor on a message list. 341228Skas */ 351228Skas 361228Skas visual(msgvec) 371228Skas int *msgvec; 381228Skas { 391228Skas 4034963Sedward return edit1(msgvec, 'v'); 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 */ 4834963Sedward edit1(msgvec, type) 491228Skas int *msgvec; 5034963Sedward char type; 511228Skas { 521228Skas register int c; 5334963Sedward int i; 5434879Sedward FILE *fp; 5531142Sedward register struct message *mp; 5634963Sedward off_t size; 571228Skas 581228Skas /* 591228Skas * Deal with each message to be edited . . . 601228Skas */ 6134879Sedward for (i = 0; msgvec[i] && i < msgCount; i++) { 6239612Sedward sig_t sigint; 6334963Sedward 6434963Sedward if (i > 0) { 6534963Sedward char buf[100]; 6634963Sedward char *p; 6734963Sedward 6834987Sedward printf("Edit message %d [ynq]? ", msgvec[i]); 6934963Sedward if (fgets(buf, sizeof buf, stdin) == 0) 7034963Sedward break; 7134987Sedward for (p = buf; *p == ' ' || *p == '\t'; p++) 7234963Sedward ; 7334963Sedward if (*p == 'q') 7434963Sedward break; 7534963Sedward if (*p == 'n') 7634963Sedward continue; 771228Skas } 7834987Sedward dot = mp = &message[msgvec[i] - 1]; 7934987Sedward touch(mp); 8034963Sedward sigint = signal(SIGINT, SIG_IGN); 8134963Sedward fp = run_editor(setinput(mp), mp->m_size, type, readonly); 8234963Sedward if (fp != NULL) { 8334963Sedward (void) fseek(otf, (long) 0, 2); 8434963Sedward size = ftell(otf); 8534963Sedward mp->m_block = blockof(size); 8634963Sedward mp->m_offset = offsetof(size); 8734963Sedward mp->m_size = fsize(fp); 8834963Sedward mp->m_lines = 0; 8934963Sedward mp->m_flag |= MODIFY; 9034963Sedward rewind(fp); 9134963Sedward while ((c = getc(fp)) != EOF) { 9234963Sedward if (c == '\n') 9334963Sedward mp->m_lines++; 9434963Sedward if (putc(c, otf) == EOF) 9534963Sedward break; 9634963Sedward } 9734963Sedward if (ferror(otf)) 9834963Sedward perror("/tmp"); 9934879Sedward (void) fclose(fp); 1001228Skas } 10134963Sedward (void) signal(SIGINT, sigint); 1021228Skas } 10334963Sedward return 0; 10434963Sedward } 10534963Sedward 10634963Sedward /* 10734963Sedward * Run an editor on the file at "fpp" of "size" bytes, 10834963Sedward * and return a new file pointer. 10934963Sedward * Signals must be handled by the caller. 11037870Sbostic * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI. 11134963Sedward */ 11234963Sedward FILE * 11334963Sedward run_editor(fp, size, type, readonly) 11434963Sedward register FILE *fp; 11534963Sedward off_t size; 11634963Sedward char type; 11734963Sedward { 11834963Sedward register FILE *nf = NULL; 11934963Sedward register int t; 12034963Sedward time_t modtime; 12134963Sedward char *edit; 12234963Sedward struct stat statb; 12334963Sedward extern char tempEdit[]; 12434963Sedward 12534963Sedward if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) { 12634963Sedward perror(tempEdit); 12734963Sedward goto out; 12834963Sedward } 12934963Sedward if ((nf = fdopen(t, "w")) == NULL) { 13034963Sedward perror(tempEdit); 13134963Sedward (void) unlink(tempEdit); 13234963Sedward goto out; 13334963Sedward } 13434963Sedward if (size >= 0) 13534963Sedward while (--size >= 0 && (t = getc(fp)) != EOF) 13634963Sedward (void) putc(t, nf); 13734963Sedward else 13834963Sedward while ((t = getc(fp)) != EOF) 13934963Sedward (void) putc(t, nf); 14034963Sedward (void) fflush(nf); 14134963Sedward if (fstat(fileno(nf), &statb) < 0) 14234963Sedward modtime = 0; 14334963Sedward else 14434963Sedward modtime = statb.st_mtime; 14534963Sedward if (ferror(nf) || fclose(nf) < 0) { 14634963Sedward perror(tempEdit); 14734963Sedward (void) unlink(tempEdit); 14834963Sedward nf = NULL; 14934963Sedward goto out; 15034963Sedward } 15134963Sedward nf = NULL; 15234963Sedward if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR) 15337870Sbostic edit = type == 'e' ? _PATH_EX : _PATH_VI; 15434963Sedward if (run_command(edit, 0, -1, -1, tempEdit, NOSTR) < 0) { 15534963Sedward (void) unlink(tempEdit); 15634963Sedward goto out; 15734963Sedward } 1581228Skas /* 15934963Sedward * If in read only mode or file unchanged, just remove the editor 16034963Sedward * temporary and return. 1611228Skas */ 16234963Sedward if (readonly) { 16334963Sedward (void) unlink(tempEdit); 16434963Sedward goto out; 16534963Sedward } 16634963Sedward if (stat(tempEdit, &statb) < 0) { 16734963Sedward perror(tempEdit); 16834963Sedward goto out; 16934963Sedward } 17034963Sedward if (modtime == statb.st_mtime) { 17134963Sedward (void) unlink(tempEdit); 17234963Sedward goto out; 17334963Sedward } 17434963Sedward /* 17534963Sedward * Now switch to new file. 17634963Sedward */ 17734963Sedward if ((nf = fopen(tempEdit, "a+")) == NULL) { 17834963Sedward perror(tempEdit); 17934963Sedward (void) unlink(tempEdit); 18034963Sedward goto out; 18134963Sedward } 18234963Sedward (void) unlink(tempEdit); 1831228Skas out: 18434963Sedward return nf; 1851228Skas } 186