Commit | Line | Data |
---|---|---|
6b5f5483 WJ |
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 | close(tmpfd); | |
598 | tmpfd = -1; | |
599 | unlink(tmpname); | |
600 | return TRUE; | |
601 | } | |
602 | ||
603 | /* This function saves the file if it has been modified, and then deletes | |
604 | * the temporary file. Returns TRUE if successful, or FALSE if the file | |
605 | * needs to be saved but can't be. When it returns FALSE, it will not have | |
606 | * deleted the tmp file, either. | |
607 | */ | |
608 | int tmpend(bang) | |
609 | int bang; | |
610 | { | |
611 | /* save the file if it has been modified */ | |
612 | if (tstflag(file, MODIFIED) && !tmpsave((char *)0, FALSE) && !bang) | |
613 | { | |
614 | return FALSE; | |
615 | } | |
616 | ||
617 | /* delete the tmp file */ | |
618 | tmpabort(TRUE); | |
619 | ||
620 | return TRUE; | |
621 | } | |
622 | ||
623 | ||
624 | /* If the tmp file has been changed, then this function will force those | |
625 | * changes to be written to the disk, so that the tmp file will survive a | |
626 | * system crash or power failure. | |
627 | */ | |
628 | #if AMIGA || MSDOS || TOS | |
629 | sync() | |
630 | { | |
631 | /* MS-DOS and TOS don't flush their buffers until the file is closed, | |
632 | * so here we close the tmp file and then immediately reopen it. | |
633 | */ | |
634 | close(tmpfd); | |
635 | tmpfd = open(tmpname, O_RDWR | O_BINARY); | |
636 | return 0; | |
637 | } | |
638 | #endif | |
639 | ||
640 | ||
641 | /* This function stores the file's name in the second block of the temp file. | |
642 | * SLEAZE ALERT! SLEAZE ALERT! The "tmpblk" buffer is probably being used | |
643 | * to store the arguments to a command, so we can't use it here. Instead, | |
644 | * we'll borrow the buffer that is used for "shift-U". | |
645 | */ | |
646 | storename(name) | |
647 | char *name; /* the name of the file - normally origname */ | |
648 | { | |
649 | #ifndef CRUNCH | |
650 | int len; | |
651 | char *ptr; | |
652 | #endif | |
653 | ||
654 | /* we're going to clobber the U_text buffer, so reset U_line */ | |
655 | U_line = 0L; | |
656 | ||
657 | if (!name) | |
658 | { | |
659 | strncpy(U_text, "", BLKSIZE); | |
660 | U_text[1] = 127; | |
661 | } | |
662 | #ifndef CRUNCH | |
663 | else if (*name != SLASH) | |
664 | { | |
665 | /* get the directory name */ | |
666 | ptr = getcwd(U_text, BLKSIZE); | |
667 | if (ptr != U_text) | |
668 | { | |
669 | strcpy(U_text, ptr); | |
670 | } | |
671 | ||
672 | /* append a slash to the directory name */ | |
673 | len = strlen(U_text); | |
674 | U_text[len++] = SLASH; | |
675 | ||
676 | /* append the filename, padded with heaps o' NULs */ | |
677 | strncpy(U_text + len, *name ? name : "foo", BLKSIZE - len); | |
678 | } | |
679 | #endif | |
680 | else | |
681 | { | |
682 | /* copy the filename into U_text */ | |
683 | strncpy(U_text, *name ? name : "foo", BLKSIZE); | |
684 | } | |
685 | ||
686 | if (tmpfd >= 0) | |
687 | { | |
688 | /* write the name out to second block of the temp file */ | |
689 | lseek(tmpfd, (long)BLKSIZE, 0); | |
690 | write(tmpfd, U_text, (unsigned)BLKSIZE); | |
691 | } | |
692 | return 0; | |
693 | } | |
694 | ||
695 | ||
696 | ||
697 | /* This function handles deadly signals. It restores sanity to the terminal | |
698 | * preserves the current temp file, and deletes any old temp files. | |
699 | */ | |
700 | int deathtrap(sig) | |
701 | int sig; /* the deadly signal that we caught */ | |
702 | { | |
703 | char *why; | |
704 | ||
705 | /* restore the terminal's sanity */ | |
706 | endwin(); | |
707 | ||
708 | #ifdef CRUNCH | |
709 | why = "-Elvis died"; | |
710 | #else | |
711 | /* give a more specific description of how Elvis died */ | |
712 | switch (sig) | |
713 | { | |
714 | # ifdef SIGHUP | |
715 | case SIGHUP: why = "-the modem lost its carrier"; break; | |
716 | # endif | |
717 | # ifndef DEBUG | |
718 | # ifdef SIGILL | |
719 | case SIGILL: why = "-Elvis hit an illegal instruction"; break; | |
720 | # endif | |
721 | # ifdef SIGBUS | |
722 | case SIGBUS: why = "-Elvis had a bus error"; break; | |
723 | # endif | |
724 | # if defined(SIGSEGV) && !defined(TOS) | |
725 | case SIGSEGV: why = "-Elvis had a segmentation violation"; break; | |
726 | # endif | |
727 | # ifdef SIGSYS | |
728 | case SIGSYS: why = "-Elvis munged a system call"; break; | |
729 | # endif | |
730 | # endif /* !DEBUG */ | |
731 | # ifdef SIGPIPE | |
732 | case SIGPIPE: why = "-the pipe reader died"; break; | |
733 | # endif | |
734 | # ifdef SIGTERM | |
735 | case SIGTERM: why = "-Elvis was terminated"; break; | |
736 | # endif | |
737 | # if !MINIX | |
738 | # ifdef SIGUSR1 | |
739 | case SIGUSR1: why = "-Elvis was killed via SIGUSR1"; break; | |
740 | # endif | |
741 | # ifdef SIGUSR2 | |
742 | case SIGUSR2: why = "-Elvis was killed via SIGUSR2"; break; | |
743 | # endif | |
744 | # endif | |
745 | default: why = "-Elvis died"; break; | |
746 | } | |
747 | #endif | |
748 | ||
749 | /* if we had a temp file going, then preserve it */ | |
750 | if (tmpnum > 0 && tmpfd >= 0) | |
751 | { | |
752 | close(tmpfd); | |
753 | sprintf(tmpblk.c, "%s \"%s\" %s", PRESERVE, why, tmpname); | |
754 | system(tmpblk.c); | |
755 | } | |
756 | ||
757 | /* delete any old temp files */ | |
758 | cutend(); | |
759 | ||
760 | /* exit with the proper exit status */ | |
761 | exit(sig); | |
762 | } |