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*34963Sedward static char sccsid[] = "@(#)edit.c 5.8 (Berkeley) 07/07/88"; 2034905Sbostic #endif /* not lint */ 211228Skas 221228Skas #include "rcv.h" 231228Skas #include <stdio.h> 241228Skas #include <sys/stat.h> 2531142Sedward #include <sys/wait.h> 261228Skas 271228Skas /* 281228Skas * Mail -- a mail program 291228Skas * 301228Skas * Perform message editing functions. 311228Skas */ 321228Skas 331228Skas /* 341228Skas * Edit a message list. 351228Skas */ 361228Skas 371228Skas editor(msgvec) 381228Skas int *msgvec; 391228Skas { 401228Skas 41*34963Sedward return edit1(msgvec, 'e'); 421228Skas } 431228Skas 441228Skas /* 451228Skas * Invoke the visual editor on a message list. 461228Skas */ 471228Skas 481228Skas visual(msgvec) 491228Skas int *msgvec; 501228Skas { 511228Skas 52*34963Sedward return edit1(msgvec, 'v'); 531228Skas } 541228Skas 551228Skas /* 561228Skas * Edit a message by writing the message into a funnily-named file 571228Skas * (which should not exist) and forking an editor on it. 581228Skas * We get the editor from the stuff above. 591228Skas */ 60*34963Sedward edit1(msgvec, type) 611228Skas int *msgvec; 62*34963Sedward char type; 631228Skas { 64*34963Sedward int (*sigcont)() = signal(SIGCONT, SIG_DFL); 651228Skas register int c; 66*34963Sedward int i; 6734879Sedward FILE *fp; 6831142Sedward register struct message *mp; 69*34963Sedward off_t size; 701228Skas 711228Skas /* 721228Skas * Deal with each message to be edited . . . 731228Skas */ 7434879Sedward for (i = 0; msgvec[i] && i < msgCount; i++) { 75*34963Sedward int (*sigint)(); 76*34963Sedward int m = msgvec[i]; 77*34963Sedward 78*34963Sedward if (i > 0) { 79*34963Sedward char buf[100]; 80*34963Sedward char *p; 81*34963Sedward 82*34963Sedward printf("Edit message %d [ynq]? ", m); 83*34963Sedward if (fgets(buf, sizeof buf, stdin) == 0) 84*34963Sedward break; 85*34963Sedward for (p = buf; any(*p, " \t"); p++) 86*34963Sedward ; 87*34963Sedward if (*p == 'q') 88*34963Sedward break; 89*34963Sedward if (*p == 'n') 90*34963Sedward continue; 911228Skas } 92*34963Sedward dot = mp = &message[m - 1]; 93*34963Sedward touch(m); 94*34963Sedward sigint = signal(SIGINT, SIG_IGN); 95*34963Sedward fp = run_editor(setinput(mp), mp->m_size, type, readonly); 96*34963Sedward if (fp != NULL) { 97*34963Sedward (void) fseek(otf, (long) 0, 2); 98*34963Sedward size = ftell(otf); 99*34963Sedward mp->m_block = blockof(size); 100*34963Sedward mp->m_offset = offsetof(size); 101*34963Sedward mp->m_size = fsize(fp); 102*34963Sedward mp->m_lines = 0; 103*34963Sedward mp->m_flag |= MODIFY; 104*34963Sedward rewind(fp); 105*34963Sedward while ((c = getc(fp)) != EOF) { 106*34963Sedward if (c == '\n') 107*34963Sedward mp->m_lines++; 108*34963Sedward if (putc(c, otf) == EOF) 109*34963Sedward break; 110*34963Sedward } 111*34963Sedward if (ferror(otf)) 112*34963Sedward perror("/tmp"); 11334879Sedward (void) fclose(fp); 1141228Skas } 115*34963Sedward (void) signal(SIGINT, sigint); 1161228Skas } 117*34963Sedward (void) signal(SIGCONT, sigcont); 118*34963Sedward return 0; 119*34963Sedward } 120*34963Sedward 121*34963Sedward /* 122*34963Sedward * Run an editor on the file at "fpp" of "size" bytes, 123*34963Sedward * and return a new file pointer. 124*34963Sedward * Signals must be handled by the caller. 125*34963Sedward * "Type" is 'e' for EDITOR, 'v' for VISUAL. 126*34963Sedward */ 127*34963Sedward FILE * 128*34963Sedward run_editor(fp, size, type, readonly) 129*34963Sedward register FILE *fp; 130*34963Sedward off_t size; 131*34963Sedward char type; 132*34963Sedward { 133*34963Sedward register FILE *nf = NULL; 134*34963Sedward register int t; 135*34963Sedward time_t modtime; 136*34963Sedward char *edit; 137*34963Sedward struct stat statb; 138*34963Sedward extern char tempEdit[]; 139*34963Sedward 140*34963Sedward if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) { 141*34963Sedward perror(tempEdit); 142*34963Sedward goto out; 143*34963Sedward } 144*34963Sedward if ((nf = fdopen(t, "w")) == NULL) { 145*34963Sedward perror(tempEdit); 146*34963Sedward (void) unlink(tempEdit); 147*34963Sedward goto out; 148*34963Sedward } 149*34963Sedward if (size >= 0) 150*34963Sedward while (--size >= 0 && (t = getc(fp)) != EOF) 151*34963Sedward (void) putc(t, nf); 152*34963Sedward else 153*34963Sedward while ((t = getc(fp)) != EOF) 154*34963Sedward (void) putc(t, nf); 155*34963Sedward (void) fflush(nf); 156*34963Sedward if (fstat(fileno(nf), &statb) < 0) 157*34963Sedward modtime = 0; 158*34963Sedward else 159*34963Sedward modtime = statb.st_mtime; 160*34963Sedward if (ferror(nf) || fclose(nf) < 0) { 161*34963Sedward perror(tempEdit); 162*34963Sedward (void) unlink(tempEdit); 163*34963Sedward nf = NULL; 164*34963Sedward goto out; 165*34963Sedward } 166*34963Sedward nf = NULL; 167*34963Sedward if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR) 168*34963Sedward edit = type == 'e' ? EDITOR : VISUAL; 169*34963Sedward if (run_command(edit, 0, -1, -1, tempEdit, NOSTR) < 0) { 170*34963Sedward (void) unlink(tempEdit); 171*34963Sedward goto out; 172*34963Sedward } 1731228Skas /* 174*34963Sedward * If in read only mode or file unchanged, just remove the editor 175*34963Sedward * temporary and return. 1761228Skas */ 177*34963Sedward if (readonly) { 178*34963Sedward (void) unlink(tempEdit); 179*34963Sedward goto out; 180*34963Sedward } 181*34963Sedward if (stat(tempEdit, &statb) < 0) { 182*34963Sedward perror(tempEdit); 183*34963Sedward goto out; 184*34963Sedward } 185*34963Sedward if (modtime == statb.st_mtime) { 186*34963Sedward (void) unlink(tempEdit); 187*34963Sedward goto out; 188*34963Sedward } 189*34963Sedward /* 190*34963Sedward * Now switch to new file. 191*34963Sedward */ 192*34963Sedward if ((nf = fopen(tempEdit, "a+")) == NULL) { 193*34963Sedward perror(tempEdit); 194*34963Sedward (void) unlink(tempEdit); 195*34963Sedward goto out; 196*34963Sedward } 197*34963Sedward (void) unlink(tempEdit); 1981228Skas out: 199*34963Sedward return nf; 2001228Skas } 201