1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1996 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 /* 32 * University Copyright- Copyright (c) 1982, 1986, 1988 33 * The Regents of the University of California 34 * All Rights Reserved 35 * 36 * University Acknowledgment- Portions of this document are derived from 37 * software developed by the University of California, Berkeley, and its 38 * contributors. 39 */ 40 41 #pragma ident "%Z%%M% %I% %E% SMI" 42 43 #include "rcv.h" 44 #include <locale.h> 45 46 47 /* 48 * mailx -- a modified version of a University of California at Berkeley 49 * mail program 50 * 51 * Perform message editing functions. 52 */ 53 54 static void edit1(int *msgvec, char *ed); 55 56 /* 57 * Edit a message list. 58 */ 59 60 int 61 editor(int *msgvec) 62 { 63 char *edname; 64 65 if ((edname = value("EDITOR")) == NOSTR || *edname == '\0') 66 edname = EDITOR; 67 edit1(msgvec, edname); 68 return(0); 69 } 70 71 /* 72 * Invoke the visual editor on a message list. 73 */ 74 75 int 76 visual(int *msgvec) 77 { 78 char *edname; 79 80 if ((edname = value("VISUAL")) == NOSTR || *edname == '\0') 81 edname = VISUAL; 82 edit1(msgvec, edname); 83 return(0); 84 } 85 86 /* 87 * Edit a message by writing the message into a funnily-named file 88 * (which should not exist) and forking an editor on it. 89 * We get the editor from the stuff above. 90 */ 91 92 static void 93 edit1(int *msgvec, char *ed) 94 { 95 register int c, lastc = '\n'; 96 pid_t pid; 97 int *ip, mesg, blank = 1; 98 long ms, lines; 99 void (*sigint)(int), (*sigquit)(int); 100 FILE *ibuf, *obuf; 101 struct message *mp; 102 off_t size; 103 struct stat statb; 104 long modtime; 105 int fd = -1; 106 107 /* 108 * Set signals; locate editor. 109 */ 110 111 sigint = sigset(SIGINT, SIG_IGN); 112 sigquit = sigset(SIGQUIT, SIG_IGN); 113 ed = safeexpand(ed); 114 115 /* 116 * Deal with each message to be edited . . . 117 */ 118 119 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 120 mesg = *ip; 121 touch(mesg); 122 mp = &message[mesg-1]; 123 dot = mp; 124 if (mp->m_text) { 125 if (!access(tempZedit, 2)) { 126 printf(gettext("%s: file exists\n"), tempZedit); 127 goto out; 128 } 129 130 /* 131 * Copy the message into the edit file. 132 */ 133 134 if ((fd = open(tempZedit, O_RDWR|O_CREAT| 135 O_EXCL, 0600)) < 0 || 136 (obuf = fdopen(fd, "w")) == NULL) { 137 perror(tempZedit); 138 goto out; 139 } 140 if (msend(mp, obuf, 0, fputs) < 0) { 141 perror(tempZedit); 142 fclose(obuf); 143 removefile(tempZedit); 144 goto out; 145 } 146 fflush(obuf); 147 if (fferror(obuf)) { 148 perror(tempZedit); 149 fclose(obuf); 150 removefile(tempZedit); 151 goto out; 152 } 153 fclose(obuf); 154 155 /* 156 * If we are in read only mode, make the 157 * temporary message file readonly as well. 158 */ 159 160 if (readonly) 161 chmod(tempZedit, 0400); 162 163 /* 164 * Fork/execl the editor on the edit file. 165 */ 166 167 if (stat(tempZedit, &statb) < 0) 168 modtime = 0; 169 else 170 modtime = statb.st_mtime; 171 pid = vfork(); 172 if (pid == (pid_t)-1) { 173 perror("fork"); 174 removefile(tempZedit); 175 goto out; 176 } 177 if (pid == 0) { 178 sigchild(); 179 if (sigint != SIG_IGN) 180 sigset(SIGINT, SIG_DFL); 181 if (sigquit != SIG_IGN) 182 sigset(SIGQUIT, SIG_DFL); 183 execlp(ed, ed, tempZedit, (char *)0); 184 perror(ed); 185 _exit(1); 186 } 187 while (wait(&mesg) != pid) 188 ; 189 190 /* 191 * If in read only mode, just remove the editor 192 * temporary and return. 193 */ 194 195 if (readonly) { 196 removefile(tempZedit); 197 continue; 198 } 199 200 /* 201 * Now copy the message to the end of the 202 * temp file. 203 */ 204 205 if (stat(tempZedit, &statb) < 0) { 206 perror(tempZedit); 207 continue; 208 } 209 if (modtime == statb.st_mtime) { 210 removefile(tempZedit); 211 continue; 212 } 213 if ((ibuf = fopen(tempZedit, "r")) == NULL) { 214 perror(tempZedit); 215 removefile(tempZedit); 216 continue; 217 } 218 removefile(tempZedit); 219 fseek(otf, (long) 0, 2); 220 size = fsize(otf); 221 mp->m_flag |= MODIFY; 222 mp->m_offset = size; 223 ms = 0L; 224 lines = 0; 225 while ((c = getc(ibuf)) != EOF) { 226 if (c == '\n') { 227 lines++; 228 blank = lastc == '\n'; 229 } 230 lastc = c; 231 putc(c, otf); 232 if (ferror(otf)) 233 break; 234 ms++; 235 } 236 if (!blank) { 237 putc('\n', otf); 238 ms++; 239 lines++; 240 } 241 mp->m_size = ms; 242 mp->m_lines = lines; 243 fflush(otf); 244 if (fferror(otf)) 245 perror("/tmp"); 246 fclose(ibuf); 247 setclen(mp); 248 } else { 249 printf("\n%s\n", gettext( 250 "*** Message content is not printable: pipe to command or save to a file ***")); 251 } 252 } 253 254 /* 255 * Restore signals and return. 256 */ 257 258 out: 259 sigset(SIGINT, sigint); 260 sigset(SIGQUIT, sigquit); 261 } 262