1 /* @(#)quitcmds.c 1.64 09/07/13 Copyright 1984-1989, 1994-2009 J. Schilling */ 2 #include <schily/mconfig.h> 3 #ifndef lint 4 static UConst char sccsid[] = 5 "@(#)quitcmds.c 1.64 09/07/13 Copyright 1984-1989, 1994-2009 J. Schilling"; 6 #endif 7 /* 8 * Commands that deal with exiting the editor in a clean state 9 * 10 * Copyright (c) 1984-1989, 1994-2009 J. Schilling 11 */ 12 /* 13 * The contents of this file are subject to the terms of the 14 * Common Development and Distribution License, Version 1.0 only 15 * (the "License"). You may not use this file except in compliance 16 * with the License. 17 * 18 * See the file CDDL.Schily.txt in this distribution for details. 19 * A copy of the CDDL is also available via the Internet at 20 * http://www.opensource.org/licenses/cddl1.txt 21 * 22 * When distributing Covered Code, include this CDDL HEADER in each 23 * file and include the License file CDDL.Schily.txt from this distribution. 24 */ 25 26 #include "ved.h" 27 #include <schily/unistd.h> 28 #include <schily/fcntl.h> 29 #include <schily/dirent.h> 30 #include <schily/signal.h> 31 #include <schily/errno.h> 32 33 EXPORT BOOL bakbuf __PR((ewin_t *wp, BOOL force)); 34 EXPORT BOOL writebuf __PR((ewin_t *wp, BOOL force)); 35 EXPORT void vbackup __PR((ewin_t *wp)); 36 EXPORT void vquit __PR((ewin_t *wp)); 37 EXPORT void eexit __PR((ewin_t *wp)); 38 EXPORT void vsusp __PR((ewin_t *wp)); 39 LOCAL void suspendme __PR((ewin_t *wp)); 40 #ifndef JOS 41 LOCAL int suspend __PR((int p)); 42 #endif initnum()43 44 45 /* 46 * Write back the content of the current file buffer, 47 * create a backup file if 'nobak' is not set. 48 */ 49 EXPORT BOOL 50 bakbuf(wp, force) 51 ewin_t *wp; 52 BOOL force; 53 { 54 Uchar backup[FNAMESIZE+4]; /* += strlen(".bak"); */ 55 register Uchar *t; 56 register Uchar *s; 57 int oldmodes; 58 BOOL backpresent = TRUE; 59 60 if (wrtcheck(wp, TRUE) == FALSE) { 61 if (!force) 62 return (FALSE); 63 } 64 if (modcheck(wp) == FALSE) { 65 if (!force) 66 return (FALSE); 67 sleep(1); 68 } 69 70 oldmodes = getfmodes(wp->curfile); 71 strcpy(C backup, C wp->curfile); 72 s = t = backup; vmult(wp)73 while (*t) { /* find rightmost '/' */ 74 if (*t++ == '/') 75 s = t; 76 } 77 78 #ifdef FOUND_DIRSIZE 79 if (t - s >= DIRSIZE) /* If ".bak" would not fit, trucate */ 80 t = s + DIRSIZE - 4; 81 #endif 82 83 strcpy(C t, ".bak"); /* add the the ".bak" extension */ 84 if (rename(C wp->curfile, C backup) < 0) { /* rename old curfile to backup */ 85 backpresent = FALSE; 86 if (geterrno() != ENOENT) 87 writemsg(wp, "Can't make *.bak file"); 88 } 89 90 if (!writebuf(wp, force)) { /* if writeback failed ... */ 91 if (backpresent) /* rename backup to orig file name */ 92 rename(C backup, C wp->curfile); vsmult(wp)93 return (FALSE); 94 } 95 if (oldmodes >= 0) 96 chmod(C wp->curfile, oldmodes); 97 if (nobak) 98 unlink(C backup); 99 return (TRUE); 100 } 101 102 /* 103 * Write back the content of the current file buffer, 104 * do not reate a backup file, write into the currently edited file. 105 */ 106 EXPORT BOOL 107 writebuf(wp, force) 108 ewin_t *wp; 109 BOOL force; 110 { 111 FILE *outfile; 112 BOOL ret = TRUE; 113 #ifdef HAVE_FSYNC 114 int err; 115 int cnt; 116 #endif 117 118 if ((!force || ReadOnly > 1) && wrtcheck(wp, TRUE) == FALSE) 119 return (FALSE); 120 121 if (modcheck(wp) == FALSE) { 122 if (!force) vnum(wp)123 return (FALSE); 124 sleep(1); 125 } 126 /* 127 * create outfile 128 */ 129 if ((outfile = opensyserr(wp, wp->curfile, "ctwub")) == NULL) { 130 return (FALSE); 131 } 132 lockfd(fdown(outfile)); 133 134 /* 135 * If writeback failed for some reason, return FALSE. 136 * Be very serious that the file could actually written back correctly. 137 */ 138 if (wp->eof != 0 && !savefile(wp, (epos_t)0, wp->eof, outfile, "FILE")) 139 ret = FALSE; 140 if (fflush(outfile) != 0) 141 ret = FALSE; 142 #ifdef HAVE_FSYNC 143 err = 0; 144 cnt = 0; 145 do { 146 if (fsync(fdown(outfile)) != 0) 147 err = geterrno(); 148 149 if (err == EINVAL) 150 err = 0; enumbad(wp)151 } while (err == EINTR && ++cnt < 10); 152 if (err != 0) 153 ret = FALSE; 154 #endif 155 if (fclose(outfile) != 0) 156 ret = FALSE; 157 enumoverflow(wp)158 if (ret == FALSE) 159 write_errno(wp, "CAN'T PUT %s", wp->curfile); 160 return (ret); 161 } 162 163 /* 164 * Do a backup write of the current file, enumnegative(wp)165 * create a backup file if required. 166 */ 167 EXPORT void 168 vbackup(wp) 169 ewin_t *wp; 170 { 171 int c; 172 173 switch (c = getcmdchar(wp, NULL, "BACKUP?(Y/W/N/F/!) ")) { 174 175 default: 176 abortmsg(wp); 177 /* FALLTHROUGH */ 178 case 0: /* aborted */ 179 case 'n': 180 case 'N': 181 return; 182 case 'w': 183 case 'W': 184 case '!': 185 if (!writebuf(wp, c == '!')) 186 return; 187 goto go_on; 188 case 'y': 189 case 'Y': 190 case 'f': 191 case 'F': 192 if (!bakbuf(wp, c == 'f' || c == 'F')) 193 return; 194 go_on: 195 newprot(wp); 196 wp->modflg = 0; 197 wp->curftime = gftime(C wp->curfile); 198 defaultinfo(wp, UC NULL); 199 } 200 } 201 202 /* 203 * Quit the editor, ask if the current buffer should be saved. 204 */ 205 EXPORT void 206 vquit(wp) 207 ewin_t *wp; 208 { 209 int c; 210 211 vedstopstats(); 212 213 if (wp->modflg) 214 writeerr(wp, "FILE MODIFIED!"); 215 216 switch (c = getcmdchar(wp, NULL, "QUITTING. PUT EDITS?(Y/W/N/F/!) ")) { 217 218 default: 219 abortmsg(wp); 220 /* FALLTHROUGH */ 221 case 0: 222 return; /* aborted */ 223 case 'w': 224 case 'W': 225 case '!': 226 if (!writebuf(wp, c == '!')) 227 return; 228 goto ex_it; 229 case 'y': 230 case 'Y': 231 case 'f': 232 case 'F': 233 if (!bakbuf(wp, c == 'f' || c == 'F')) 234 return; 235 /* FALLTHROUGH */ 236 case 'n': 237 case 'N': 238 ex_it: 239 put_vedtmp(wp, TRUE); 240 eexit(wp); 241 exit(0); 242 } 243 } 244 245 /* 246 * Exit the editor, reset the terminal, the tty driver and 247 * delete temporary files. 248 */ 249 EXPORT void 250 eexit(wp) 251 ewin_t *wp; 252 { 253 rsttmodes(wp); 254 tmpcleanup(wp, TRUE); 255 vedstatistics(); 256 } 257 258 /* 259 * Suspend the editor, ask if the current buffer should be saved. 260 */ 261 EXPORT void 262 vsuspend(wp) 263 ewin_t *wp; 264 { 265 #if defined(SIGSTOP) || defined(JOS) 266 int c; 267 268 if (wp->modflg) 269 writeerr(wp, "FILE MODIFIED!"); 270 271 switch (c = getcmdchar(wp, NULL, "SUSPENDING. PUT EDITS?(Y/W/N/F/!) ")) { 272 273 default: 274 abortmsg(wp); 275 /* FALLTHROUGH */ 276 case 0: 277 return; /* aborted */ 278 case 'w': 279 case 'W': 280 case '!': 281 if (!writebuf(wp, c == '!')) 282 return; 283 goto go_on; 284 case 'y': 285 case 'Y': 286 case 'f': 287 case 'F': 288 if (!bakbuf(wp, c == 'f' || c == 'F')) 289 return; 290 go_on: 291 wp->modflg = 0; 292 wp->curftime = gftime(C wp->curfile); 293 defaultinfo(wp, UC NULL); 294 newprot(wp); 295 /* FALLTHROUGH */ 296 case 'n': 297 case 'N': 298 suspendme(wp); 299 } 300 #else 301 writeerr(wp, "NOT IMPLEMENTED!"); 302 #endif 303 } 304 305 /* 306 * Suspend the editor, reset the terminal, the tty driver, 307 * do not delete temporary files. 308 * Reset terminal and tty state on continue. 309 */ 310 #if defined(SIGSTOP) || defined(JOS) 311 LOCAL void 312 suspendme(wp) 313 ewin_t *wp; 314 { 315 rsttmodes(wp); 316 suspend(0); 317 settmodes(wp); 318 vredisp(wp); 319 } 320 #endif 321 322 /* 323 * Suspend a process 324 */ 325 #ifndef JOS 326 LOCAL int 327 suspend(p) 328 int p; 329 { 330 #ifdef SIGSTOP 331 return (kill(p, SIGSTOP)); 332 #else 333 raisecond("suspend not implemented", 0L); 334 #endif 335 } 336 #endif 337