1 | /* tmp.c */
|
---|
2 |
|
---|
3 | /* Author:
|
---|
4 | * Steve Kirkendall
|
---|
5 | * 14407 SW Teal Blvd. #C
|
---|
6 | * Beaverton, OR 97005
|
---|
7 | * kirkenda@cs.pdx.edu
|
---|
8 | */
|
---|
9 |
|
---|
10 |
|
---|
11 | /* This file contains functions which create & readback a TMPFILE */
|
---|
12 |
|
---|
13 |
|
---|
14 | #include "config.h"
|
---|
15 | #include "vi.h"
|
---|
16 | #if TOS
|
---|
17 | # include <stat.h>
|
---|
18 | #else
|
---|
19 | # if OSK
|
---|
20 | # include "osk.h"
|
---|
21 | # else
|
---|
22 | # if AMIGA
|
---|
23 | # include "amistat.h"
|
---|
24 | # else
|
---|
25 | # include <sys/stat.h>
|
---|
26 | # endif
|
---|
27 | # endif
|
---|
28 | #endif
|
---|
29 | #if TURBOC
|
---|
30 | # include <process.h>
|
---|
31 | #endif
|
---|
32 |
|
---|
33 | #ifndef NO_MODELINES
|
---|
34 | static void do_modelines(l, stop)
|
---|
35 | long l; /* line number to start at */
|
---|
36 | long stop; /* line number to stop at */
|
---|
37 | {
|
---|
38 | char *str; /* used to scan through the line */
|
---|
39 | char *start; /* points to the start of the line */
|
---|
40 | char buf[80];
|
---|
41 |
|
---|
42 | /* if modelines are disabled, then do nothing */
|
---|
43 | if (!*o_modelines)
|
---|
44 | {
|
---|
45 | return;
|
---|
46 | }
|
---|
47 |
|
---|
48 | /* for each line... */
|
---|
49 | for (; l <= stop; l++)
|
---|
50 | {
|
---|
51 | /* for each position in the line.. */
|
---|
52 | for (str = fetchline(l); *str; str++)
|
---|
53 | {
|
---|
54 | /* if it is the start of a modeline command... */
|
---|
55 | if ((str[0] == 'e' && str[1] == 'x'
|
---|
56 | || str[0] == 'v' && str[1] == 'i')
|
---|
57 | && str[2] == ':')
|
---|
58 | {
|
---|
59 | start = str += 3;
|
---|
60 |
|
---|
61 | /* find the end */
|
---|
62 | for (str = start + strlen(start); *--str != ':'; )
|
---|
63 | {
|
---|
64 | }
|
---|
65 |
|
---|
66 | /* if it is a well-formed modeline, execute it */
|
---|
67 | if (str > start && str - start < sizeof buf)
|
---|
68 | {
|
---|
69 | strncpy(buf, start, (int)(str - start));
|
---|
70 | exstring(buf, str - start, '\\');
|
---|
71 | break;
|
---|
72 | }
|
---|
73 | }
|
---|
74 | }
|
---|
75 | }
|
---|
76 | }
|
---|
77 | #endif
|
---|
78 |
|
---|
79 |
|
---|
80 | /* The FAIL() macro prints an error message and then exits. */
|
---|
81 | #define FAIL(why,arg) mode = MODE_EX; msg(why, arg); endwin(); exit(9)
|
---|
82 |
|
---|
83 | /* This is the name of the temp file */
|
---|
84 | static char tmpname[80];
|
---|
85 |
|
---|
86 | /* This function creates the temp file and copies the original file into it.
|
---|
87 | * Returns if successful, or stops execution if it fails.
|
---|
88 | */
|
---|
89 | int tmpstart(filename)
|
---|
90 | char *filename; /* name of the original file */
|
---|
91 | {
|
---|
92 | int origfd; /* fd used for reading the original file */
|
---|
93 | struct stat statb; /* stat buffer, used to examine inode */
|
---|
94 | REG BLK *this; /* pointer to the current block buffer */
|
---|
95 | REG BLK *next; /* pointer to the next block buffer */
|
---|
96 | int inbuf; /* number of characters in a buffer */
|
---|
97 | int nread; /* number of bytes read */
|
---|
98 | REG int j, k;
|
---|
99 | int i;
|
---|
100 | long nbytes;
|
---|
101 |
|
---|
102 | /* switching to a different file certainly counts as a change */
|
---|
103 | changes++;
|
---|
104 | redraw(MARK_UNSET, FALSE);
|
---|
105 |
|
---|
106 | /* open the original file for reading */
|
---|
107 | *origname = '\0';
|
---|
108 | if (filename && *filename)
|
---|
109 | {
|
---|
110 | strcpy(origname, filename);
|
---|
111 | origfd = open(origname, O_RDONLY);
|
---|
112 | if (origfd < 0 && errno != ENOENT)
|
---|
113 | {
|
---|
114 | msg("Can't open \"%s\"", origname);
|
---|
115 | return tmpstart("");
|
---|
116 | }
|
---|
117 | if (origfd >= 0)
|
---|
118 | {
|
---|
119 | if (stat(origname, &statb) < 0)
|
---|
120 | {
|
---|
121 | FAIL("Can't stat \"%s\"", origname);
|
---|
122 | }
|
---|
123 | #if TOS
|
---|
124 | if (origfd >= 0 && (statb.st_mode & S_IJDIR))
|
---|
125 | #else
|
---|
126 | # if OSK
|
---|
127 | if (origfd >= 0 && (statb.st_mode & S_IFDIR))
|
---|
128 | # else
|
---|
129 | if (origfd >= 0 && (statb.st_mode & S_IFMT) != S_IFREG)
|
---|
130 | # endif
|
---|
131 | #endif
|
---|
132 | {
|
---|
133 | msg("\"%s\" is not a regular file", origname);
|
---|
134 | return tmpstart("");
|
---|
135 | }
|
---|
136 | }
|
---|
137 | else
|
---|
138 | {
|
---|
139 | stat(".", &statb);
|
---|
140 | }
|
---|
141 | if (origfd >= 0)
|
---|
142 | {
|
---|
143 | origtime = statb.st_mtime;
|
---|
144 | #if OSK
|
---|
145 | if (*o_readonly || !(statb.st_mode &
|
---|
146 | ((getuid() >> 16) == 0 ? S_IOWRITE | S_IWRITE :
|
---|
147 | ((statb.st_gid != (getuid() >> 16) ? S_IOWRITE : S_IWRITE)))))
|
---|
148 | #endif
|
---|
149 | #if AMIGA || MSDOS || (TOS && defined(__GNUC__))
|
---|
150 | if (*o_readonly || !(statb.st_mode & S_IWRITE))
|
---|
151 | #endif
|
---|
152 | #if TOS && !defined(__GNUC__)
|
---|
153 | if (*o_readonly || (statb.st_mode & S_IJRON))
|
---|
154 | #endif
|
---|
155 | #if ANY_UNIX
|
---|
156 | if (*o_readonly || !(statb.st_mode &
|
---|
157 | ((geteuid() == 0) ? 0222 :
|
---|
158 | ((statb.st_uid != geteuid() ? 0022 : 0200)))))
|
---|
159 | #endif
|
---|
160 | #if VMS
|
---|
161 | if (*o_readonly)
|
---|
162 | #endif
|
---|
163 | {
|
---|
164 | setflag(file, READONLY);
|
---|
165 | }
|
---|
166 | }
|
---|
167 | else
|
---|
168 | {
|
---|
169 | origtime = 0L;
|
---|
170 | }
|
---|
171 | }
|
---|
172 | else
|
---|
173 | {
|
---|
174 | setflag(file, NOFILE);
|
---|
175 | origfd = -1;
|
---|
176 | origtime = 0L;
|
---|
177 | stat(".", &statb);
|
---|
178 | }
|
---|
179 |
|
---|
180 | /* make a name for the tmp file */
|
---|
181 | tmpnum++;
|
---|
182 | #if MSDOS || TOS
|
---|
183 | /* MS-Dos doesn't allow multiple slashes, but supports drives
|
---|
184 | * with current directories.
|
---|
185 | * This relies on TMPNAME beginning with "%s\\"!!!!
|
---|
186 | */
|
---|
187 | strcpy(tmpname, o_directory);
|
---|
188 | if ((i = strlen(tmpname)) && !strchr(":/\\", tmpname[i-1]))
|
---|
189 | tmpname[i++]=SLASH;
|
---|
190 | sprintf(tmpname+i, TMPNAME+3, getpid(), tmpnum);
|
---|
191 | #else
|
---|
192 | sprintf(tmpname, TMPNAME, o_directory, getpid(), tmpnum);
|
---|
193 | #endif
|
---|
194 |
|
---|
195 | /* make sure nobody else is editing the same file */
|
---|
196 | if (access(tmpname, 0) == 0)
|
---|
197 | {
|
---|
198 | FAIL("Temp file \"%s\" already exists?", tmpname);
|
---|
199 | }
|
---|
200 |
|
---|
201 | /* create the temp file */
|
---|
202 | #if ANY_UNIX
|
---|
203 | close(creat(tmpname, 0600)); /* only we can read it */
|
---|
204 | #else
|
---|
205 | close(creat(tmpname, FILEPERMS)); /* anybody body can read it, alas */
|
---|
206 | #endif
|
---|
207 | tmpfd = open(tmpname, O_RDWR | O_BINARY);
|
---|
208 | if (tmpfd < 0)
|
---|
209 | {
|
---|
210 | FAIL("Can't create temp file... Does directory \"%s\" exist?", o_directory);
|
---|
211 | return 1;
|
---|
212 | }
|
---|
213 |
|
---|
214 | /* allocate space for the header in the file */
|
---|
215 | write(tmpfd, hdr.c, (unsigned)BLKSIZE);
|
---|
216 | write(tmpfd, tmpblk.c, (unsigned)BLKSIZE);
|
---|
217 |
|
---|
218 | #ifndef NO_RECYCLE
|
---|
219 | /* initialize the block allocator */
|
---|
220 | /* This must already be done here, before the first attempt
|
---|
221 | * to write to the new file! GB */
|
---|
222 | garbage();
|
---|
223 | #endif
|
---|
224 |
|
---|
225 | /* initialize lnum[] */
|
---|
226 | for (i = 1; i < MAXBLKS; i++)
|
---|
227 | {
|
---|
228 | lnum[i] = INFINITY;
|
---|
229 | }
|
---|
230 | lnum[0] = 0;
|
---|
231 |
|
---|
232 | /* if there is no original file, then create a 1-line file */
|
---|
233 | if (origfd < 0)
|
---|
234 | {
|
---|
235 | hdr.n[0] = 0; /* invalid inode# denotes new file */
|
---|
236 |
|
---|
237 | this = blkget(1); /* get the new text block */
|
---|
238 | strcpy(this->c, "\n"); /* put a line in it */
|
---|
239 |
|
---|
240 | lnum[1] = 1L; /* block 1 ends with line 1 */
|
---|
241 | nlines = 1L; /* there is 1 line in the file */
|
---|
242 | nbytes = 1L;
|
---|
243 |
|
---|
244 | if (*origname)
|
---|
245 | {
|
---|
246 | msg("\"%s\" [NEW FILE] 1 line, 1 char", origname);
|
---|
247 | }
|
---|
248 | else
|
---|
249 | {
|
---|
250 | msg("\"[NO FILE]\" 1 line, 1 char");
|
---|
251 | }
|
---|
252 | }
|
---|
253 | else /* there is an original file -- read it in */
|
---|
254 | {
|
---|
255 | nbytes = nlines = 0;
|
---|
256 |
|
---|
257 | /* preallocate 1 "next" buffer */
|
---|
258 | i = 1;
|
---|
259 | next = blkget(i);
|
---|
260 | inbuf = 0;
|
---|
261 |
|
---|
262 | /* loop, moving blocks from orig to tmp */
|
---|
263 | for (;;)
|
---|
264 | {
|
---|
265 | /* "next" buffer becomes "this" buffer */
|
---|
266 | this = next;
|
---|
267 |
|
---|
268 | /* read [more] text into this block */
|
---|
269 | nread = tread(origfd, &this->c[inbuf], BLKSIZE - 1 - inbuf);
|
---|
270 | if (nread < 0)
|
---|
271 | {
|
---|
272 | close(origfd);
|
---|
273 | close(tmpfd);
|
---|
274 | tmpfd = -1;
|
---|
275 | unlink(tmpname);
|
---|
276 | FAIL("Error reading \"%s\"", origname);
|
---|
277 | }
|
---|
278 |
|
---|
279 | /* convert NUL characters to something else */
|
---|
280 | for (j = k = inbuf; k < inbuf + nread; k++)
|
---|
281 | {
|
---|
282 | if (!this->c[k])
|
---|
283 | {
|
---|
284 | setflag(file, HADNUL);
|
---|
285 | this->c[j++] = 0x80;
|
---|
286 | }
|
---|
287 | #ifndef CRUNCH
|
---|
288 | else if (*o_beautify && this->c[k] < ' ' && this->c[k] > 0)
|
---|
289 | {
|
---|
290 | if (this->c[k] == '\t'
|
---|
291 | || this->c[k] == '\n'
|
---|
292 | || this->c[k] == '\f')
|
---|
293 | {
|
---|
294 | this->c[j++] = this->c[k];
|
---|
295 | }
|
---|
296 | else if (this->c[k] == '\b')
|
---|
297 | {
|
---|
298 | /* delete '\b', but complain */
|
---|
299 | setflag(file, HADBS);
|
---|
300 | }
|
---|
301 | /* else silently delete control char */
|
---|
302 | }
|
---|
303 | #endif
|
---|
304 | else
|
---|
305 | {
|
---|
306 | this->c[j++] = this->c[k];
|
---|
307 | }
|
---|
308 | }
|
---|
309 | inbuf = j;
|
---|
310 |
|
---|
311 | /* if the buffer is empty, quit */
|
---|
312 | if (inbuf == 0)
|
---|
313 | {
|
---|
314 | goto FoundEOF;
|
---|
315 | }
|
---|
316 |
|
---|
317 | #if MSDOS || TOS
|
---|
318 | /* BAH! MS text mode read fills inbuf, then compresses eliminating \r
|
---|
319 | but leaving garbage at end of buf. The same is true for TURBOC. GB. */
|
---|
320 |
|
---|
321 | memset(this->c + inbuf, '\0', BLKSIZE - inbuf);
|
---|
322 | #endif
|
---|
323 |
|
---|
324 | /* search backward for last newline */
|
---|
325 | for (k = inbuf; --k >= 0 && this->c[k] != '\n';)
|
---|
326 | {
|
---|
327 | }
|
---|
328 | if (k++ < 0)
|
---|
329 | {
|
---|
330 | if (inbuf >= BLKSIZE - 1)
|
---|
331 | {
|
---|
332 | k = 80;
|
---|
333 | }
|
---|
334 | else
|
---|
335 | {
|
---|
336 | k = inbuf;
|
---|
337 | }
|
---|
338 | }
|
---|
339 |
|
---|
340 | /* allocate next buffer */
|
---|
341 | next = blkget(++i);
|
---|
342 |
|
---|
343 | /* move fragmentary last line to next buffer */
|
---|
344 | inbuf -= k;
|
---|
345 | for (j = 0; k < BLKSIZE; j++, k++)
|
---|
346 | {
|
---|
347 | next->c[j] = this->c[k];
|
---|
348 | this->c[k] = 0;
|
---|
349 | }
|
---|
350 |
|
---|
351 | /* if necessary, add a newline to this buf */
|
---|
352 | for (k = BLKSIZE - inbuf; --k >= 0 && !this->c[k]; )
|
---|
353 | {
|
---|
354 | }
|
---|
355 | if (this->c[k] != '\n')
|
---|
356 | {
|
---|
357 | setflag(file, ADDEDNL);
|
---|
358 | this->c[k + 1] = '\n';
|
---|
359 | }
|
---|
360 |
|
---|
361 | /* count the lines in this block */
|
---|
362 | for (k = 0; k < BLKSIZE && this->c[k]; k++)
|
---|
363 | {
|
---|
364 | if (this->c[k] == '\n')
|
---|
365 | {
|
---|
366 | nlines++;
|
---|
367 | }
|
---|
368 | nbytes++;
|
---|
369 | }
|
---|
370 | lnum[i - 1] = nlines;
|
---|
371 | }
|
---|
372 | FoundEOF:
|
---|
373 |
|
---|
374 | /* if this is a zero-length file, add 1 line */
|
---|
375 | if (nlines == 0)
|
---|
376 | {
|
---|
377 | this = blkget(1); /* get the new text block */
|
---|
378 | strcpy(this->c, "\n"); /* put a line in it */
|
---|
379 |
|
---|
380 | lnum[1] = 1; /* block 1 ends with line 1 */
|
---|
381 | nlines = 1; /* there is 1 line in the file */
|
---|
382 | nbytes = 1;
|
---|
383 | }
|
---|
384 |
|
---|
385 | #if MSDOS || TOS
|
---|
386 | /* each line has an extra CR that we didn't count yet */
|
---|
387 | nbytes += nlines;
|
---|
388 | #endif
|
---|
389 |
|
---|
390 | /* report the number of lines in the file */
|
---|
391 | msg("\"%s\" %s %ld line%s, %ld char%s",
|
---|
392 | origname,
|
---|
393 | (tstflag(file, READONLY) ? "[READONLY]" : ""),
|
---|
394 | nlines,
|
---|
395 | nlines == 1 ? "" : "s",
|
---|
396 | nbytes,
|
---|
397 | nbytes == 1 ? "" : "s");
|
---|
398 | }
|
---|
399 |
|
---|
400 | /* initialize the cursor to start of line 1 */
|
---|
401 | cursor = MARK_FIRST;
|
---|
402 |
|
---|
403 | /* close the original file */
|
---|
404 | close(origfd);
|
---|
405 |
|
---|
406 | /* any other messages? */
|
---|
407 | if (tstflag(file, HADNUL))
|
---|
408 | {
|
---|
409 | msg("This file contained NULs. They've been changed to \\x80 chars");
|
---|
410 | }
|
---|
411 | if (tstflag(file, ADDEDNL))
|
---|
412 | {
|
---|
413 | msg("Newline characters have been inserted to break up long lines");
|
---|
414 | }
|
---|
415 | #ifndef CRUNCH
|
---|
416 | if (tstflag(file, HADBS))
|
---|
417 | {
|
---|
418 | msg("Backspace characters deleted due to ':set beautify'");
|
---|
419 | }
|
---|
420 | #endif
|
---|
421 |
|
---|
422 | storename(origname);
|
---|
423 |
|
---|
424 | #ifndef NO_MODELINES
|
---|
425 | if (nlines > 10)
|
---|
426 | {
|
---|
427 | do_modelines(1L, 5L);
|
---|
428 | do_modelines(nlines - 4L, nlines);
|
---|
429 | }
|
---|
430 | else
|
---|
431 | {
|
---|
432 | do_modelines(1L, nlines);
|
---|
433 | }
|
---|
434 | #endif
|
---|
435 |
|
---|
436 | /* force all blocks out onto the disk, to support file recovery */
|
---|
437 | blksync();
|
---|
438 |
|
---|
439 | return 0;
|
---|
440 | }
|
---|
441 |
|
---|
442 |
|
---|
443 |
|
---|
444 | /* This function copies the temp file back onto an original file.
|
---|
445 | * Returns TRUE if successful, or FALSE if the file could NOT be saved.
|
---|
446 | */
|
---|
447 | int tmpsave(filename, bang)
|
---|
448 | char *filename; /* the name to save it to */
|
---|
449 | int bang; /* forced write? */
|
---|
450 | {
|
---|
451 | int fd; /* fd of the file we're writing to */
|
---|
452 | REG int len; /* length of a text block */
|
---|
453 | REG BLK *this; /* a text block */
|
---|
454 | long bytes; /* byte counter */
|
---|
455 | REG int i;
|
---|
456 |
|
---|
457 | /* if no filename is given, assume the original file name */
|
---|
458 | if (!filename || !*filename)
|
---|
459 | {
|
---|
460 | filename = origname;
|
---|
461 | }
|
---|
462 |
|
---|
463 | /* if still no file name, then fail */
|
---|
464 | if (!*filename)
|
---|
465 | {
|
---|
466 | msg("Don't know a name for this file -- NOT WRITTEN");
|
---|
467 | return FALSE;
|
---|
468 | }
|
---|
469 |
|
---|
470 | /* can't rewrite a READONLY file */
|
---|
471 | #if AMIGA
|
---|
472 | if (!strcmp(filename, origname) && tstflag(file, READONLY) && !bang)
|
---|
473 | #else
|
---|
474 | if (!strcmp(filename, origname) && *o_readonly && !bang)
|
---|
475 | #endif
|
---|
476 | {
|
---|
477 | msg("\"%s\" [READONLY] -- NOT WRITTEN", filename);
|
---|
478 | return FALSE;
|
---|
479 | }
|
---|
480 |
|
---|
481 | /* open the file */
|
---|
482 | if (*filename == '>' && filename[1] == '>')
|
---|
483 | {
|
---|
484 | filename += 2;
|
---|
485 | while (*filename == ' ' || *filename == '\t')
|
---|
486 | {
|
---|
487 | filename++;
|
---|
488 | }
|
---|
489 | #ifdef O_APPEND
|
---|
490 | fd = open(filename, O_WRONLY|O_APPEND);
|
---|
491 | #else
|
---|
492 | fd = open(filename, O_WRONLY);
|
---|
493 | lseek(fd, 0L, 2);
|
---|
494 | #endif
|
---|
495 | }
|
---|
496 | else
|
---|
497 | {
|
---|
498 | /* either the file must not exist, or it must be the original
|
---|
499 | * file, or we must have a bang, or "writeany" must be set.
|
---|
500 | */
|
---|
501 | if (strcmp(filename, origname) && access(filename, 0) == 0 && !bang
|
---|
502 | #ifndef CRUNCH
|
---|
503 | && !*o_writeany
|
---|
504 | #endif
|
---|
505 | )
|
---|
506 | {
|
---|
507 | msg("File already exists - Use :w! to overwrite");
|
---|
508 | return FALSE;
|
---|
509 | }
|
---|
510 | #if VMS
|
---|
511 | /* Create a new VMS version of this file. */
|
---|
512 | {
|
---|
513 | char *strrchr(), *ptr = strrchr(filename,';');
|
---|
514 | if (ptr) *ptr = '\0'; /* Snip off any ;number in the name */
|
---|
515 | }
|
---|
516 | #endif
|
---|
517 | fd = creat(filename, FILEPERMS);
|
---|
518 | }
|
---|
519 | if (fd < 0)
|
---|
520 | {
|
---|
521 | msg("Can't write to \"%s\" -- NOT WRITTEN", filename);
|
---|
522 | return FALSE;
|
---|
523 | }
|
---|
524 |
|
---|
525 | /* write each text block to the file */
|
---|
526 | bytes = 0L;
|
---|
527 | for (i = 1; i < MAXBLKS && (this = blkget(i)) && this->c[0]; i++)
|
---|
528 | {
|
---|
529 | for (len = 0; len < BLKSIZE && this->c[len]; len++)
|
---|
530 | {
|
---|
531 | }
|
---|
532 | if (twrite(fd, this->c, len) < len)
|
---|
533 | {
|
---|
534 | msg("Trouble writing to \"%s\"", filename);
|
---|
535 | if (!strcmp(filename, origname))
|
---|
536 | {
|
---|
537 | setflag(file, MODIFIED);
|
---|
538 | }
|
---|
539 | close(fd);
|
---|
540 | return FALSE;
|
---|
541 | }
|
---|
542 | bytes += len;
|
---|
543 | }
|
---|
544 |
|
---|
545 | /* reset the "modified" flag, but not the "undoable" flag */
|
---|
546 | clrflag(file, MODIFIED);
|
---|
547 | significant = FALSE;
|
---|
548 |
|
---|
549 | /* report lines & characters */
|
---|
550 | #if MSDOS || TOS
|
---|
551 | bytes += nlines; /* for the inserted carriage returns */
|
---|
552 | #endif
|
---|
553 | msg("Wrote \"%s\" %ld lines, %ld characters", filename, nlines, bytes);
|
---|
554 |
|
---|
555 | /* close the file */
|
---|
556 | close(fd);
|
---|
557 |
|
---|
558 | return TRUE;
|
---|
559 | }
|
---|
560 |
|
---|
561 |
|
---|
562 | /* This function deletes the temporary file. If the file has been modified
|
---|
563 | * and "bang" is FALSE, then it returns FALSE without doing anything; else
|
---|
564 | * it returns TRUE.
|
---|
565 | *
|
---|
566 | * If the "autowrite" option is set, then instead of returning FALSE when
|
---|
567 | * the file has been modified and "bang" is false, it will call tmpend().
|
---|
568 | */
|
---|
569 | int tmpabort(bang)
|
---|
570 | int bang;
|
---|
571 | {
|
---|
572 | /* if there is no file, return successfully */
|
---|
573 | if (tmpfd < 0)
|
---|
574 | {
|
---|
575 | return TRUE;
|
---|
576 | }
|
---|
577 |
|
---|
578 | /* see if we must return FALSE -- can't quit */
|
---|
579 | if (!bang && tstflag(file, MODIFIED))
|
---|
580 | {
|
---|
581 | /* if "autowrite" is set, then act like tmpend() */
|
---|
582 | if (*o_autowrite)
|
---|
583 | return tmpend(bang);
|
---|
584 | else
|
---|
585 | return FALSE;
|
---|
586 | }
|
---|
587 |
|
---|
588 | /* delete the tmp file */
|
---|
589 | cutswitch();
|
---|
590 | strcpy(prevorig, origname);
|
---|
591 | prevline = markline(cursor);
|
---|
592 | *origname = '\0';
|
---|
593 | origtime = 0L;
|
---|
594 | blkinit();
|
---|
595 | nlines = 0;
|
---|
596 | initflags();
|
---|
597 | return TRUE;
|
---|
598 | }
|
---|
599 |
|
---|
600 | /* This function saves the file if it has been modified, and then deletes
|
---|
601 | * the temporary file. Returns TRUE if successful, or FALSE if the file
|
---|
602 | * needs to be saved but can't be. When it returns FALSE, it will not have
|
---|
603 | * deleted the tmp file, either.
|
---|
604 | */
|
---|
605 | int tmpend(bang)
|
---|
606 | int bang;
|
---|
607 | {
|
---|
608 | /* save the file if it has been modified */
|
---|
609 | if (tstflag(file, MODIFIED) && !tmpsave((char *)0, FALSE) && !bang)
|
---|
610 | {
|
---|
611 | return FALSE;
|
---|
612 | }
|
---|
613 |
|
---|
614 | /* delete the tmp file */
|
---|
615 | tmpabort(TRUE);
|
---|
616 |
|
---|
617 | return TRUE;
|
---|
618 | }
|
---|
619 |
|
---|
620 |
|
---|
621 | /* If the tmp file has been changed, then this function will force those
|
---|
622 | * changes to be written to the disk, so that the tmp file will survive a
|
---|
623 | * system crash or power failure.
|
---|
624 | */
|
---|
625 | #if AMIGA || MSDOS || TOS
|
---|
626 | sync()
|
---|
627 | {
|
---|
628 | /* MS-DOS and TOS don't flush their buffers until the file is closed,
|
---|
629 | * so here we close the tmp file and then immediately reopen it.
|
---|
630 | */
|
---|
631 | close(tmpfd);
|
---|
632 | tmpfd = open(tmpname, O_RDWR | O_BINARY);
|
---|
633 | return 0;
|
---|
634 | }
|
---|
635 | #endif
|
---|
636 |
|
---|
637 |
|
---|
638 | /* This function stores the file's name in the second block of the temp file.
|
---|
639 | * SLEAZE ALERT! SLEAZE ALERT! The "tmpblk" buffer is probably being used
|
---|
640 | * to store the arguments to a command, so we can't use it here. Instead,
|
---|
641 | * we'll borrow the buffer that is used for "shift-U".
|
---|
642 | */
|
---|
643 | storename(name)
|
---|
644 | char *name; /* the name of the file - normally origname */
|
---|
645 | {
|
---|
646 | #ifndef CRUNCH
|
---|
647 | int len;
|
---|
648 | char *ptr;
|
---|
649 | #endif
|
---|
650 |
|
---|
651 | /* we're going to clobber the U_text buffer, so reset U_line */
|
---|
652 | U_line = 0L;
|
---|
653 |
|
---|
654 | if (!name)
|
---|
655 | {
|
---|
656 | strncpy(U_text, "", BLKSIZE);
|
---|
657 | U_text[1] = 127;
|
---|
658 | }
|
---|
659 | #ifndef CRUNCH
|
---|
660 | else if (*name != SLASH)
|
---|
661 | {
|
---|
662 | /* get the directory name */
|
---|
663 | ptr = getcwd(U_text, BLKSIZE);
|
---|
664 | if (ptr != U_text)
|
---|
665 | {
|
---|
666 | strcpy(U_text, ptr);
|
---|
667 | }
|
---|
668 |
|
---|
669 | /* append a slash to the directory name */
|
---|
670 | len = strlen(U_text);
|
---|
671 | U_text[len++] = SLASH;
|
---|
672 |
|
---|
673 | /* append the filename, padded with heaps o' NULs */
|
---|
674 | strncpy(U_text + len, *name ? name : "foo", BLKSIZE - len);
|
---|
675 | }
|
---|
676 | #endif
|
---|
677 | else
|
---|
678 | {
|
---|
679 | /* copy the filename into U_text */
|
---|
680 | strncpy(U_text, *name ? name : "foo", BLKSIZE);
|
---|
681 | }
|
---|
682 |
|
---|
683 | if (tmpfd >= 0)
|
---|
684 | {
|
---|
685 | /* write the name out to second block of the temp file */
|
---|
686 | lseek(tmpfd, (long)BLKSIZE, 0);
|
---|
687 | write(tmpfd, U_text, (unsigned)BLKSIZE);
|
---|
688 | }
|
---|
689 | return 0;
|
---|
690 | }
|
---|
691 |
|
---|
692 |
|
---|
693 |
|
---|
694 | /* This function handles deadly signals. It restores sanity to the terminal
|
---|
695 | * preserves the current temp file, and deletes any old temp files.
|
---|
696 | */
|
---|
697 | int deathtrap(sig)
|
---|
698 | int sig; /* the deadly signal that we caught */
|
---|
699 | {
|
---|
700 | char *why;
|
---|
701 |
|
---|
702 | /* restore the terminal's sanity */
|
---|
703 | endwin();
|
---|
704 |
|
---|
705 | #ifdef CRUNCH
|
---|
706 | why = "-Elvis died";
|
---|
707 | #else
|
---|
708 | /* give a more specific description of how Elvis died */
|
---|
709 | switch (sig)
|
---|
710 | {
|
---|
711 | # ifdef SIGHUP
|
---|
712 | case SIGHUP: why = "-the modem lost its carrier"; break;
|
---|
713 | # endif
|
---|
714 | # ifndef DEBUG
|
---|
715 | # ifdef SIGILL
|
---|
716 | case SIGILL: why = "-Elvis hit an illegal instruction"; break;
|
---|
717 | # endif
|
---|
718 | # ifdef SIGBUS
|
---|
719 | case SIGBUS: why = "-Elvis had a bus error"; break;
|
---|
720 | # endif
|
---|
721 | # if defined(SIGSEGV) && !defined(TOS)
|
---|
722 | case SIGSEGV: why = "-Elvis had a segmentation violation"; break;
|
---|
723 | # endif
|
---|
724 | # ifdef SIGSYS
|
---|
725 | case SIGSYS: why = "-Elvis munged a system call"; break;
|
---|
726 | # endif
|
---|
727 | # endif /* !DEBUG */
|
---|
728 | # ifdef SIGPIPE
|
---|
729 | case SIGPIPE: why = "-the pipe reader died"; break;
|
---|
730 | # endif
|
---|
731 | # ifdef SIGTERM
|
---|
732 | case SIGTERM: why = "-Elvis was terminated"; break;
|
---|
733 | # endif
|
---|
734 | # if !MINIX
|
---|
735 | # ifdef SIGUSR1
|
---|
736 | case SIGUSR1: why = "-Elvis was killed via SIGUSR1"; break;
|
---|
737 | # endif
|
---|
738 | # ifdef SIGUSR2
|
---|
739 | case SIGUSR2: why = "-Elvis was killed via SIGUSR2"; break;
|
---|
740 | # endif
|
---|
741 | # endif
|
---|
742 | default: why = "-Elvis died"; break;
|
---|
743 | }
|
---|
744 | #endif
|
---|
745 |
|
---|
746 | /* if we had a temp file going, then preserve it */
|
---|
747 | if (tmpnum > 0 && tmpfd >= 0)
|
---|
748 | {
|
---|
749 | close(tmpfd);
|
---|
750 | sprintf(tmpblk.c, "%s \"%s\" %s", PRESERVE, why, tmpname);
|
---|
751 | system(tmpblk.c);
|
---|
752 | }
|
---|
753 |
|
---|
754 | /* delete any old temp files */
|
---|
755 | cutend();
|
---|
756 |
|
---|
757 | /* exit with the proper exit status */
|
---|
758 | exit(sig);
|
---|
759 | }
|
---|