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
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
bakbuf(wp,force)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;
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);
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
writebuf(wp,force)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)
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;
151 } while (err == EINTR && ++cnt < 10);
152 if (err != 0)
153 ret = FALSE;
154 #endif
155 if (fclose(outfile) != 0)
156 ret = FALSE;
157
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,
165 * create a backup file if required.
166 */
167 EXPORT void
vbackup(wp)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
vquit(wp)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
eexit(wp)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
vsuspend(wp)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
suspendme(wp)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
suspend(p)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