📄 recover.c
字号:
/*************************************************************************** * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * * is provided to you without charge, and with no warranty. You may give * * away copies of JOVE, including sources, provided that this notice is * * included in all the files. * ***************************************************************************//* Recovers JOVE files after a system/editor crash. Usage: recover [-d directory] [-syscrash] The -syscrash option is specified in /etc/rc. It directs recover to move all the jove tmp files from TMP_DIR (/tmp) to REC_DIR (/usr/preserve). recover -syscrash must be invoked in /ect/rc BEFORE /tmp gets cleared out. (about the same place as expreserve gets invoked to save ed/vi/ex files. The -d option lets you specify the directory to search for tmp files when the default isn't the right one. Look in Makefile to change the default directories. */#include <stdio.h> /* Do stdio first so it doesn't override OUR definitions. */#include "jove.h"#include "temp.h"#include "rec.h"#include "rectune.h"#include "wait.h"#ifdef UNIX# include <signal.h># include <sys/file.h># include <pwd.h># include <time.h>#endif#ifdef SYSV# include <sys/utsname.h>#endif#ifndef L_SET# define L_SET 0# define L_INCR 1#endifextern char *ctime proto((const time_t *));private char blk_buf[JBUFSIZ];private int nleft;private FILE *ptrs_fp;private int data_fd;private struct rec_head Header;private long Nchars, Nlines;private char tty[] = "/dev/tty";private int UserID, Verbose = 0;private char *Directory = NULL; /* the directory we're looking in */private struct file_pair { char *file_data, *file_rec;#define INSPECTED 01 int file_flags; struct file_pair *file_next;} *First = NULL;private struct rec_entry *buflist[100]; /* system initializes to 0 */#ifndef F_COMPLETION# define F_COMPLETION /* since scandir.c is surrounded by an ifdef */#endif/* simpler version of one in util.c, needed by scandir.c */UnivPtremalloc(size)size_t size;{ register UnivPtr ptr; if ((ptr = malloc(size)) == NULL) { fprintf(stderr, "couldn't malloc(%d)\n", size); exit(1); } return ptr;} /* simpler version of one in util.c, needed by scandir.c */UnivPtrerealloc(ptr, size)UnivPtr ptr;size_t size;{ if ((ptr = realloc(ptr, size)) == NULL) { fprintf(stderr, "couldn't realloc(%d)\n", size); exit(1); } return ptr;}/* duplicated in util.c, needed by scandir.c */voidnull_ncpy(to, from, n)char *to, *from;size_t n;{ (void) strncpy(to, from, n); to[n] = '\0';}#define complain printf /* kludge! needed by scandir.c */#include "scandir.c" /* to get dirent simulation and jscandir *//* Get a line at `tl' in the tmp file into `buf' which should be LBSIZE long. */private char *getblock proto((daddr atl));voidgetline(tl, buf)daddr tl;char *buf;{ register char *bp, *lp; register int nl; lp = buf; bp = getblock(tl >> 1); nl = nleft; tl = blk_round(tl); while ((*lp++ = *bp++) != '\0') { if (--nl == 0) { tl = forward_block(tl); bp = getblock(tl >> 1); nl = nleft; } }}private char *getblock(atl)daddr atl;{ int bno, off; static int curblock = -1; bno = da_to_bno(atl); off = da_to_off(atl); nleft = JBUFSIZ - off; if (bno != curblock) { lseek(data_fd, (long) bno * JBUFSIZ, L_SET); read(data_fd, (UnivPtr)blk_buf, (size_t)JBUFSIZ); curblock = bno; } return blk_buf + off;}char *copystr(s)char *s;{ char *str; str = malloc((size_t) (strlen(s) + 1)); strcpy(str, s); return str;}private char *CurDir;/* Scan the DIRNAME directory for jove tmp files, and make a linked list out of them. */private int add_name proto((char *));private voidget_files(dirname)char *dirname;{ char **nmptr; CurDir = dirname; First = NULL; jscandir(dirname, &nmptr, add_name, (int (*) proto((UnivConstPtr, UnivConstPtr)))NULL);}private intadd_name(fname)char *fname;{ char dfile[128], rfile[128]; struct file_pair *fp; struct rec_head header; int fd; if (strncmp(fname, "jrec", (size_t)4) != 0) return 0; /* If we get here, we found a "recover" tmp file, so now we look for the corresponding "data" tmp file. First, though, we check to see whether there is anything in the "recover" file. If it's 0 length, there's no point in saving its name. */ (void) sprintf(rfile, "%s/%s", CurDir, fname); (void) sprintf(dfile, "%s/jove%s", CurDir, fname + 4); if ((fd = open(rfile, 0)) != -1) { if ((read(fd, (UnivPtr) &header, sizeof header) != sizeof header)) { close(fd); return 0; } else close(fd); } if (access(dfile, 0) != 0) { fprintf(stderr, "recover: can't find the data file for %s/%s\n", Directory, fname); fprintf(stderr, "so deleting...\n"); (void) unlink(rfile); (void) unlink(dfile); return 0; } /* If we get here, we've found both files, so we put them in the list. */ fp = (struct file_pair *) malloc (sizeof *fp); if (fp == NULL) { fprintf(stderr, "recover: cannot malloc for file_pair.\n"); exit(-1); } fp->file_data = copystr(dfile); fp->file_rec = copystr(rfile); fp->file_flags = 0; fp->file_next = First; First = fp; return 1;}private voidoptions(){ printf("Options are:\n"); printf(" ? list options.\n"); printf(" get get a buffer to a file.\n"); printf(" list list known buffers.\n"); printf(" print print a buffer to terminal.\n"); printf(" quit quit and delete jove tmp files.\n"); printf(" restore restore all buffers.\n");}/* Returns a legitimate buffer # */private void tellme proto((char *, char *)), list proto((void));private struct rec_entry **getsrc(){ char name[128]; int number; for (;;) { tellme("Which buffer ('?' for list)? ", name); if (name[0] == '?') list(); else if (name[0] == '\0') return NULL; else if ((number = atoi(name)) > 0 && number <= Header.Nbuffers) return &buflist[number]; else { int i; for (i = 1; i <= Header.Nbuffers; i++) if (strcmp(buflist[i]->r_bname, name) == 0) return &buflist[i]; printf("%s: unknown buffer.\n", name); } }}/* Get a destination file name. */static char *getdest(){ static char filebuf[256]; tellme("Output file: ", filebuf); if (filebuf[0] == '\0') return NULL; return filebuf;}#include "ctype.h"private char *readword(buf)char *buf;{ int c; char *bp = buf; do ; while (strchr(" \t\n", c = getchar())); do { if (strchr(" \t\n", c)) break; *bp++ = c; } while ((c = getchar()) != EOF); *bp = '\0'; return buf;}private voidtellme(quest, answer)char *quest, *answer;{#ifndef BSD386 /* this is naughty anyway */ if (stdin->_cnt <= 0) { printf("%s", quest); fflush(stdout); }#else printf("%s", quest); fflush(stdout);#endif readword(answer);}/* Print the specified file to standard output. */private jmp_buf int_env;private SIGRESULTcatch(junk)int junk;{ longjmp(int_env, 1); /*NOTREACHED*/}private void get proto((struct rec_entry **src, char *dest));private voidrestore(){ register int i; char tofile[100], answer[30]; int nrecovered = 0; for (i = 1; i <= Header.Nbuffers; i++) { (void) sprintf(tofile, "#%s", buflist[i]->r_bname);tryagain: printf("Restoring %s to %s, okay?", buflist[i]->r_bname, tofile); tellme(" ", answer); switch (answer[0]) { case 'y': break; case 'n': continue; default: tellme("What file should I use instead? ", tofile); goto tryagain; } get(&buflist[i], tofile); nrecovered += 1; } printf("Recovered %d buffers.\n", nrecovered);}private void dump_file proto((int which, FILE *out));private voidget(src, dest)struct rec_entry **src;char *dest;{ FILE *outfile; if (src == NULL || dest == NULL) return; (void) signal(SIGINT, catch); if (setjmp(int_env) == 0) { if (dest == tty) outfile = stdout; else { if ((outfile = fopen(dest, "w")) == NULL) { printf("recover: cannot create %s.\n", dest); (void) signal(SIGINT, SIG_DFL); return; } printf("\"%s\"", dest); } dump_file(src - buflist, outfile); } else printf("\nAborted!\n"); (void) signal(SIGINT, SIG_DFL); if (dest != tty) { fclose(outfile); printf(" %ld lines, %ld characters.\n", Nlines, Nchars); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -