10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
59694SScott.Rotondo@Sun.COM * Common Development and Distribution License (the "License").
69694SScott.Rotondo@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*13093SRoger.Faulkner@Oracle.COM
220Sstevel@tonic-gate /*
23*13093SRoger.Faulkner@Oracle.COM * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24*13093SRoger.Faulkner@Oracle.COM */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
270Sstevel@tonic-gate /* All Rights Reserved */
280Sstevel@tonic-gate
290Sstevel@tonic-gate
300Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
31802Scf46844
320Sstevel@tonic-gate #include <stdio.h> /* BUFSIZ: stdio = 1024, VMUNIX = 1024 */
330Sstevel@tonic-gate #ifndef TRACE
340Sstevel@tonic-gate #undef NULL
350Sstevel@tonic-gate #endif
360Sstevel@tonic-gate
370Sstevel@tonic-gate #include "ex.h"
380Sstevel@tonic-gate #include "ex_temp.h"
390Sstevel@tonic-gate #include "ex_tty.h"
400Sstevel@tonic-gate #include "ex_tune.h"
410Sstevel@tonic-gate #include <pwd.h>
420Sstevel@tonic-gate #include <locale.h>
430Sstevel@tonic-gate #include <dirent.h>
44634Sdp #include <unistd.h>
45634Sdp #include <errno.h>
46634Sdp
470Sstevel@tonic-gate #define DIRSIZ MAXNAMLEN
480Sstevel@tonic-gate
490Sstevel@tonic-gate short tfile = -1; /* ditto */
500Sstevel@tonic-gate
510Sstevel@tonic-gate /*
520Sstevel@tonic-gate *
530Sstevel@tonic-gate * This program searches through the specified directory and then
540Sstevel@tonic-gate * the directory usrpath(preserve) looking for an instance of the specified
550Sstevel@tonic-gate * file from a crashed editor or a crashed system.
560Sstevel@tonic-gate * If this file is found, it is unscrambled and written to
570Sstevel@tonic-gate * the standard output.
580Sstevel@tonic-gate *
590Sstevel@tonic-gate * If this program terminates without a "broken pipe" diagnostic
600Sstevel@tonic-gate * (i.e. the editor doesn't die right away) then the buffer we are
610Sstevel@tonic-gate * writing from is removed when we finish. This is potentially a mistake
620Sstevel@tonic-gate * as there is not enough handshaking to guarantee that the file has actually
630Sstevel@tonic-gate * been recovered, but should suffice for most cases.
640Sstevel@tonic-gate */
650Sstevel@tonic-gate
660Sstevel@tonic-gate /*
670Sstevel@tonic-gate * This directory definition also appears (obviously) in expreserve.c.
680Sstevel@tonic-gate * Change both if you change either.
690Sstevel@tonic-gate */
700Sstevel@tonic-gate unsigned char mydir[PATH_MAX+1];
710Sstevel@tonic-gate
720Sstevel@tonic-gate /*
730Sstevel@tonic-gate * Limit on the number of printed entries
740Sstevel@tonic-gate * when an, e.g. ``ex -r'' command is given.
750Sstevel@tonic-gate */
760Sstevel@tonic-gate #define NENTRY 50
770Sstevel@tonic-gate
780Sstevel@tonic-gate unsigned char nb[BUFSIZE];
790Sstevel@tonic-gate int vercnt; /* Count number of versions of file found */
80802Scf46844 void rputfile(void);
81802Scf46844 void rsyserror(void);
82802Scf46844 void searchdir(unsigned char *);
83802Scf46844 void scrapbad(void);
84802Scf46844 void findtmp(unsigned char *);
85802Scf46844 void listfiles(unsigned char *);
86634Sdp
87634Sdp int
main(int argc,char * argv[])88802Scf46844 main(int argc, char *argv[])
890Sstevel@tonic-gate {
900Sstevel@tonic-gate unsigned char string[50];
91802Scf46844 unsigned char *cp;
92802Scf46844 int c, b, i;
93802Scf46844 int rflg = 0, errflg = 0;
940Sstevel@tonic-gate int label;
950Sstevel@tonic-gate line *tmpadr;
960Sstevel@tonic-gate extern unsigned char *mypass();
970Sstevel@tonic-gate struct passwd *pp = getpwuid(getuid());
980Sstevel@tonic-gate unsigned char rmcmd[PATH_MAX+1];
990Sstevel@tonic-gate
1000Sstevel@tonic-gate (void)setlocale(LC_ALL, "");
1010Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
1020Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
1030Sstevel@tonic-gate #endif
1040Sstevel@tonic-gate (void)textdomain(TEXT_DOMAIN);
1050Sstevel@tonic-gate cp = string;
1060Sstevel@tonic-gate strcpy(mydir, USRPRESERVE);
1070Sstevel@tonic-gate if (pp == NULL) {
1080Sstevel@tonic-gate fprintf(stderr, gettext("Unable to get user's id\n"));
1090Sstevel@tonic-gate exit(-1);
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate strcat(mydir, pp->pw_name);
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate /*
1140Sstevel@tonic-gate * Initialize as though the editor had just started.
1150Sstevel@tonic-gate */
1160Sstevel@tonic-gate fendcore = (line *) sbrk(0);
1170Sstevel@tonic-gate dot = zero = dol = fendcore;
1180Sstevel@tonic-gate one = zero + 1;
1190Sstevel@tonic-gate endcore = fendcore - 2;
1200Sstevel@tonic-gate iblock = oblock = -1;
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate while ((c=getopt(argc, (char **)argv, "rx")) != EOF)
1230Sstevel@tonic-gate switch (c) {
1240Sstevel@tonic-gate case 'r':
1250Sstevel@tonic-gate rflg++;
1260Sstevel@tonic-gate break;
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate case 'x':
1290Sstevel@tonic-gate xflag++;
1300Sstevel@tonic-gate break;
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate case '?':
1330Sstevel@tonic-gate errflg++;
1340Sstevel@tonic-gate break;
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate argc -= optind;
1370Sstevel@tonic-gate argv = &argv[optind];
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate if (errflg)
1400Sstevel@tonic-gate exit(2);
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate * If given only a -r argument, then list the saved files.
1440Sstevel@tonic-gate * (NOTE: single -r argument is scheduled to be replaced by -L).
1450Sstevel@tonic-gate */
1460Sstevel@tonic-gate if (rflg && argc == 0) {
1470Sstevel@tonic-gate fprintf(stderr,"%s:\n", mydir);
1480Sstevel@tonic-gate listfiles(mydir);
1490Sstevel@tonic-gate fprintf(stderr,"%s:\n", TMPDIR);
150802Scf46844 listfiles((unsigned char *)TMPDIR);
1510Sstevel@tonic-gate exit(0);
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate if (argc != 2)
1550Sstevel@tonic-gate error(gettext(" Wrong number of arguments to exrecover"), 0);
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate CP(file, argv[1]);
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate /*
1600Sstevel@tonic-gate * Search for this file.
1610Sstevel@tonic-gate */
162802Scf46844 findtmp((unsigned char *)argv[0]);
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate /*
1650Sstevel@tonic-gate * Got (one of the versions of) it, write it back to the editor.
1660Sstevel@tonic-gate */
1670Sstevel@tonic-gate (void)cftime((char *)cp, "%a %h %d %T", &H.Time);
1680Sstevel@tonic-gate fprintf(stderr, vercnt > 1 ?
1690Sstevel@tonic-gate gettext(" [Dated: %s, newest of %d saved]") :
1700Sstevel@tonic-gate gettext(" [Dated: %s]"), cp, vercnt);
1710Sstevel@tonic-gate fprintf(stderr, "\r\n");
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate if(H.encrypted) {
1740Sstevel@tonic-gate if(xflag) {
1750Sstevel@tonic-gate kflag = run_setkey(perm, (unsigned char *)getenv("CrYpTkEy"));
1760Sstevel@tonic-gate } else
1770Sstevel@tonic-gate kflag = run_setkey(perm, mypass("Enter key:"));
1780Sstevel@tonic-gate if(kflag == -1) {
1790Sstevel@tonic-gate kflag = 0;
1800Sstevel@tonic-gate xflag = 0;
1810Sstevel@tonic-gate fprintf(stderr,gettext("Encryption facility not available\n"));
1820Sstevel@tonic-gate exit(-1);
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate xtflag = 1;
1850Sstevel@tonic-gate if (makekey(tperm) != 0) {
1860Sstevel@tonic-gate xtflag = 0;
1870Sstevel@tonic-gate fprintf(stderr,gettext("Warning--Cannot encrypt temporary buffer\n"));
1880Sstevel@tonic-gate exit(-1);
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate fprintf(stderr,gettext("\r\n [Hit return to continue]"));
1920Sstevel@tonic-gate fflush(stderr);
1930Sstevel@tonic-gate setbuf(stdin, (char *)NULL);
1940Sstevel@tonic-gate while((c = getchar()) != '\n' && c != '\r');
1950Sstevel@tonic-gate H.Flines++;
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate /*
1980Sstevel@tonic-gate * Allocate space for the line pointers from the temp file.
1990Sstevel@tonic-gate */
2000Sstevel@tonic-gate if ((int) sbrk((int) (H.Flines * sizeof (line))) == -1)
2010Sstevel@tonic-gate error(gettext(" Not enough core for lines"), 0);
2020Sstevel@tonic-gate #ifdef DEBUG
2030Sstevel@tonic-gate fprintf(stderr, "%d lines\n", H.Flines);
2040Sstevel@tonic-gate #endif
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate /*
2070Sstevel@tonic-gate * Now go get the blocks of seek pointers which are scattered
2080Sstevel@tonic-gate * throughout the temp file, reconstructing the incore
2090Sstevel@tonic-gate * line pointers at point of crash.
2100Sstevel@tonic-gate */
2110Sstevel@tonic-gate b = 0;
2120Sstevel@tonic-gate while (H.Flines > 0) {
2130Sstevel@tonic-gate (void)lseek(tfile, (long) blocks[b] * BUFSIZE, 0);
2140Sstevel@tonic-gate i = H.Flines < BUFSIZE / sizeof (line) ?
2150Sstevel@tonic-gate H.Flines * sizeof (line) : BUFSIZE;
2160Sstevel@tonic-gate if (read(tfile, (char *) dot, i) != i) {
2170Sstevel@tonic-gate perror((char *)nb);
2180Sstevel@tonic-gate exit(1);
2190Sstevel@tonic-gate }
2200Sstevel@tonic-gate dot += i / sizeof (line);
2210Sstevel@tonic-gate H.Flines -= i / sizeof (line);
2220Sstevel@tonic-gate b++;
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate dot--; dol = dot;
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate /*
2270Sstevel@tonic-gate * Due to sandbagging some lines may really not be there.
2280Sstevel@tonic-gate * Find and discard such. This shouldn't happen often.
2290Sstevel@tonic-gate */
2300Sstevel@tonic-gate scrapbad();
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate /*
2340Sstevel@tonic-gate * Now if there were any lines in the recovered file
2350Sstevel@tonic-gate * write them to the standard output.
2360Sstevel@tonic-gate */
2370Sstevel@tonic-gate if (dol > zero) {
2380Sstevel@tonic-gate addr1 = one; addr2 = dol; io = 1;
239802Scf46844 rputfile();
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate /*
2420Sstevel@tonic-gate * Trash the saved buffer.
2430Sstevel@tonic-gate * Hopefully the system won't crash before the editor
2440Sstevel@tonic-gate * syncs the new recovered buffer; i.e. for an instant here
2450Sstevel@tonic-gate * you may lose if the system crashes because this file
2460Sstevel@tonic-gate * is gone, but the editor hasn't completed reading the recovered
2470Sstevel@tonic-gate * file from the pipe from us to it.
2480Sstevel@tonic-gate *
2490Sstevel@tonic-gate * This doesn't work if we are coming from an non-absolute path
2500Sstevel@tonic-gate * name since we may have chdir'ed but what the hay, noone really
2510Sstevel@tonic-gate * ever edits with temporaries in "." anyways.
2520Sstevel@tonic-gate */
2530Sstevel@tonic-gate if (nb[0] == '/') {
254634Sdp (void)unlink((const char *)nb);
2550Sstevel@tonic-gate sprintf((char *)rmcmd, "rmdir %s 2> /dev/null", (char *)mydir);
2560Sstevel@tonic-gate system((char *)rmcmd);
2570Sstevel@tonic-gate }
258802Scf46844 return (0);
2590Sstevel@tonic-gate }
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate /*
2620Sstevel@tonic-gate * Print an error message (notably not in error
2630Sstevel@tonic-gate * message file). If terminal is in RAW mode, then
2640Sstevel@tonic-gate * we should be writing output for "vi", so don't print
2650Sstevel@tonic-gate * a newline which would mess up the screen.
2660Sstevel@tonic-gate */
2670Sstevel@tonic-gate /*VARARGS2*/
268802Scf46844 void
error(str,inf)2690Sstevel@tonic-gate error(str, inf)
2700Sstevel@tonic-gate unsigned char *str;
2710Sstevel@tonic-gate int inf;
2720Sstevel@tonic-gate {
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate struct termio termio;
2750Sstevel@tonic-gate if (inf)
2760Sstevel@tonic-gate fprintf(stderr, (char *)str, inf);
2770Sstevel@tonic-gate else
2780Sstevel@tonic-gate fprintf(stderr, (char *)str);
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate ioctl(2, TCGETA, &termio);
2810Sstevel@tonic-gate if (termio.c_lflag & ICANON)
2820Sstevel@tonic-gate fprintf(stderr, "\n");
2830Sstevel@tonic-gate exit(1);
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate /*
2870Sstevel@tonic-gate * Here we save the information about files, when
2880Sstevel@tonic-gate * you ask us what files we have saved for you.
2890Sstevel@tonic-gate * We buffer file name, number of lines, and the time
2900Sstevel@tonic-gate * at which the file was saved.
2910Sstevel@tonic-gate */
2920Sstevel@tonic-gate struct svfile {
2930Sstevel@tonic-gate unsigned char sf_name[FNSIZE + 1];
2940Sstevel@tonic-gate int sf_lines;
2950Sstevel@tonic-gate unsigned char sf_entry[DIRSIZ + 1];
2960Sstevel@tonic-gate time_t sf_time;
2970Sstevel@tonic-gate short sf_encrypted;
2980Sstevel@tonic-gate };
299802Scf46844 void enter(struct svfile *, unsigned char *, int);
3000Sstevel@tonic-gate
301802Scf46844 void
listfiles(unsigned char * dirname)302802Scf46844 listfiles(unsigned char *dirname)
3030Sstevel@tonic-gate {
304802Scf46844 DIR *dir;
3050Sstevel@tonic-gate struct dirent64 *direntry;
3060Sstevel@tonic-gate int ecount, qucmp();
307802Scf46844 int f;
3080Sstevel@tonic-gate unsigned char cp[50];
3090Sstevel@tonic-gate unsigned char cp2[50];
3100Sstevel@tonic-gate unsigned char *filname;
3110Sstevel@tonic-gate struct svfile *fp, svbuf[NENTRY];
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate /*
3140Sstevel@tonic-gate * Open usrpath(preserve), and go there to make things quick.
3150Sstevel@tonic-gate */
3160Sstevel@tonic-gate if ((dir = opendir((char *)dirname)) == NULL)
3170Sstevel@tonic-gate {
3180Sstevel@tonic-gate fprintf(stderr,gettext("No files saved.\n"));
3190Sstevel@tonic-gate return;
3200Sstevel@tonic-gate }
321634Sdp if (chdir((const char *)dirname) < 0) {
3220Sstevel@tonic-gate perror((char *)dirname);
3230Sstevel@tonic-gate return;
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate /*
3270Sstevel@tonic-gate * Look at the candidate files in usrpath(preserve).
3280Sstevel@tonic-gate */
3290Sstevel@tonic-gate fp = &svbuf[0];
3300Sstevel@tonic-gate ecount = 0;
3310Sstevel@tonic-gate while ((direntry = readdir64(dir)) != NULL)
3320Sstevel@tonic-gate {
3330Sstevel@tonic-gate filname = (unsigned char *)direntry->d_name;
3340Sstevel@tonic-gate if (filname[0] != 'E')
3350Sstevel@tonic-gate continue;
3360Sstevel@tonic-gate #ifdef DEBUG
3370Sstevel@tonic-gate fprintf(stderr, "considering %s\n", filname);
3380Sstevel@tonic-gate #endif
3390Sstevel@tonic-gate /*
3400Sstevel@tonic-gate * Name begins with E; open it and
3410Sstevel@tonic-gate * make sure the uid in the header is our uid.
3420Sstevel@tonic-gate * If not, then don't bother with this file, it can't
3430Sstevel@tonic-gate * be ours.
3440Sstevel@tonic-gate */
3450Sstevel@tonic-gate f = open(filname, 0);
3460Sstevel@tonic-gate if (f < 0) {
3470Sstevel@tonic-gate #ifdef DEBUG
3480Sstevel@tonic-gate fprintf(stderr, "open failed\n");
3490Sstevel@tonic-gate #endif
3500Sstevel@tonic-gate continue;
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate if (read(f, (char *) &H, sizeof H) != sizeof H) {
3530Sstevel@tonic-gate #ifdef DEBUG
3540Sstevel@tonic-gate fprintf(stderr, "could not read header\n");
3550Sstevel@tonic-gate #endif
3560Sstevel@tonic-gate (void)close(f);
3570Sstevel@tonic-gate continue;
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate (void)close(f);
3600Sstevel@tonic-gate if (getuid() != H.Uid) {
3610Sstevel@tonic-gate #ifdef DEBUG
3620Sstevel@tonic-gate fprintf(stderr, "uid wrong\n");
3630Sstevel@tonic-gate #endif
3640Sstevel@tonic-gate continue;
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate /*
3680Sstevel@tonic-gate * Saved the day!
3690Sstevel@tonic-gate */
3700Sstevel@tonic-gate enter(fp++, filname, ecount);
3710Sstevel@tonic-gate ecount++;
3720Sstevel@tonic-gate #ifdef DEBUG
3730Sstevel@tonic-gate fprintf(stderr, "entered file %s\n", filname);
3740Sstevel@tonic-gate #endif
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate (void)closedir(dir);
3770Sstevel@tonic-gate /*
3780Sstevel@tonic-gate * If any files were saved, then sort them and print
3790Sstevel@tonic-gate * them out.
3800Sstevel@tonic-gate */
3810Sstevel@tonic-gate if (ecount == 0) {
3820Sstevel@tonic-gate fprintf(stderr, gettext("No files saved.\n"));
3830Sstevel@tonic-gate return;
3840Sstevel@tonic-gate }
3850Sstevel@tonic-gate qsort(&svbuf[0], ecount, sizeof svbuf[0], qucmp);
3860Sstevel@tonic-gate for (fp = &svbuf[0]; fp < &svbuf[ecount]; fp++) {
3870Sstevel@tonic-gate (void)cftime((char *)cp, "%a %b %d", &fp->sf_time);
3880Sstevel@tonic-gate (void)cftime((char *)cp2, "%R", &fp->sf_time);
3890Sstevel@tonic-gate fprintf(stderr,
3900Sstevel@tonic-gate gettext("On %s at %s, saved %d lines of file \"%s\" "),
3910Sstevel@tonic-gate cp, cp2, fp->sf_lines, fp->sf_name);
3920Sstevel@tonic-gate fprintf(stderr, "%s\n",
3930Sstevel@tonic-gate (fp->sf_encrypted) ? gettext("[ENCRYPTED]") : "");
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate /*
3980Sstevel@tonic-gate * Enter a new file into the saved file information.
3990Sstevel@tonic-gate */
400802Scf46844 void
enter(struct svfile * fp,unsigned char * fname,int count)401802Scf46844 enter(struct svfile *fp, unsigned char *fname, int count)
4020Sstevel@tonic-gate {
403802Scf46844 unsigned char *cp, *cp2;
404802Scf46844 struct svfile *f, *fl;
4050Sstevel@tonic-gate time_t curtime;
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate f = 0;
4080Sstevel@tonic-gate if (count >= NENTRY) {
4090Sstevel@tonic-gate /*
4100Sstevel@tonic-gate * Trash the oldest as the most useless.
4110Sstevel@tonic-gate */
4120Sstevel@tonic-gate fl = fp - count + NENTRY - 1;
4130Sstevel@tonic-gate curtime = fl->sf_time;
4140Sstevel@tonic-gate for (f = fl; --f > fp-count; )
4150Sstevel@tonic-gate if (f->sf_time < curtime)
4160Sstevel@tonic-gate curtime = f->sf_time;
4170Sstevel@tonic-gate for (f = fl; --f > fp-count; )
4180Sstevel@tonic-gate if (f->sf_time == curtime)
4190Sstevel@tonic-gate break;
4200Sstevel@tonic-gate fp = f;
4210Sstevel@tonic-gate }
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate /*
4240Sstevel@tonic-gate * Gotcha.
4250Sstevel@tonic-gate */
4260Sstevel@tonic-gate fp->sf_time = H.Time;
4270Sstevel@tonic-gate fp->sf_lines = H.Flines;
4280Sstevel@tonic-gate fp->sf_encrypted = H.encrypted;
4290Sstevel@tonic-gate for (cp2 = fp->sf_name, cp = savedfile; *cp;)
4300Sstevel@tonic-gate *cp2++ = *cp++;
4310Sstevel@tonic-gate *cp2++ = 0;
4320Sstevel@tonic-gate for (cp2 = fp->sf_entry, cp = fname; *cp && cp-fname < 14;)
4330Sstevel@tonic-gate *cp2++ = *cp++;
4340Sstevel@tonic-gate *cp2++ = 0;
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate /*
4380Sstevel@tonic-gate * Do the qsort compare to sort the entries first by file name,
4390Sstevel@tonic-gate * then by modify time.
4400Sstevel@tonic-gate */
441802Scf46844 int
qucmp(struct svfile * p1,struct svfile * p2)442802Scf46844 qucmp(struct svfile *p1, struct svfile *p2)
4430Sstevel@tonic-gate {
444802Scf46844 int t;
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate if (t = strcmp(p1->sf_name, p2->sf_name))
4470Sstevel@tonic-gate return(t);
4480Sstevel@tonic-gate if (p1->sf_time > p2->sf_time)
4490Sstevel@tonic-gate return(-1);
4500Sstevel@tonic-gate return(p1->sf_time < p2->sf_time);
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate /*
4540Sstevel@tonic-gate * Scratch for search.
4550Sstevel@tonic-gate */
4560Sstevel@tonic-gate unsigned char bestnb[BUFSIZE]; /* Name of the best one */
4570Sstevel@tonic-gate long besttime = 0; /* Time at which the best file was saved */
4580Sstevel@tonic-gate int bestfd; /* Keep best file open so it dont vanish */
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate /*
4610Sstevel@tonic-gate * Look for a file, both in the users directory option value
4620Sstevel@tonic-gate * (i.e. usually /tmp) and in usrpath(preserve).
4630Sstevel@tonic-gate * Want to find the newest so we search on and on.
4640Sstevel@tonic-gate */
465802Scf46844 void
findtmp(unsigned char * dir)466802Scf46844 findtmp(unsigned char *dir)
4670Sstevel@tonic-gate {
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate /*
4700Sstevel@tonic-gate * No name or file so far.
4710Sstevel@tonic-gate */
4720Sstevel@tonic-gate bestnb[0] = 0;
4730Sstevel@tonic-gate bestfd = -1;
4740Sstevel@tonic-gate
4750Sstevel@tonic-gate /*
4760Sstevel@tonic-gate * Search usrpath(preserve) and, if we can get there, /tmp
4770Sstevel@tonic-gate * (actually the user's "directory" option).
4780Sstevel@tonic-gate */
4790Sstevel@tonic-gate searchdir(dir);
480634Sdp if (chdir((const char *)mydir) == 0)
4810Sstevel@tonic-gate searchdir(mydir);
4820Sstevel@tonic-gate if (bestfd != -1) {
4830Sstevel@tonic-gate /*
4840Sstevel@tonic-gate * Gotcha.
4850Sstevel@tonic-gate * Put the file (which is already open) in the file
4860Sstevel@tonic-gate * used by the temp file routines, and save its
4870Sstevel@tonic-gate * name for later unlinking.
4880Sstevel@tonic-gate */
4890Sstevel@tonic-gate tfile = bestfd;
4900Sstevel@tonic-gate CP(nb, bestnb);
4910Sstevel@tonic-gate (void)lseek(tfile, 0l, 0);
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate /*
4940Sstevel@tonic-gate * Gotta be able to read the header or fall through
4950Sstevel@tonic-gate * to lossage.
4960Sstevel@tonic-gate */
4970Sstevel@tonic-gate if (read(tfile, (char *) &H, sizeof H) == sizeof H)
4980Sstevel@tonic-gate return;
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate /*
5020Sstevel@tonic-gate * Extreme lossage...
5030Sstevel@tonic-gate */
504802Scf46844 error((unsigned char *)gettext(" File not found"), 0);
5050Sstevel@tonic-gate }
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate /*
5080Sstevel@tonic-gate * Search for the file in directory dirname.
5090Sstevel@tonic-gate *
5100Sstevel@tonic-gate * Don't chdir here, because the users directory
5110Sstevel@tonic-gate * may be ".", and we would move away before we searched it.
5120Sstevel@tonic-gate * Note that we actually chdir elsewhere (because it is too slow
5130Sstevel@tonic-gate * to look around in usrpath(preserve) without chdir'ing there) so we
5140Sstevel@tonic-gate * can't win, because we don't know the name of '.' and if the path
5150Sstevel@tonic-gate * name of the file we want to unlink is relative, rather than absolute
5160Sstevel@tonic-gate * we won't be able to find it again.
5170Sstevel@tonic-gate */
518802Scf46844 void
searchdir(unsigned char * dirname)519802Scf46844 searchdir(unsigned char *dirname)
5200Sstevel@tonic-gate {
5210Sstevel@tonic-gate struct dirent64 *direntry;
522802Scf46844 DIR *dir;
5230Sstevel@tonic-gate unsigned char dbuf[BUFSIZE];
5240Sstevel@tonic-gate unsigned char *filname;
5250Sstevel@tonic-gate if ((dir = opendir((char *)dirname)) == NULL)
5260Sstevel@tonic-gate return;
5270Sstevel@tonic-gate while ((direntry = readdir64(dir)) != NULL)
5280Sstevel@tonic-gate {
5290Sstevel@tonic-gate filname = (unsigned char *)direntry->d_name;
5300Sstevel@tonic-gate if (filname[0] != 'E' || filname[1] != 'x')
5310Sstevel@tonic-gate continue;
5320Sstevel@tonic-gate /*
5330Sstevel@tonic-gate * Got a file in the directory starting with Ex...
5340Sstevel@tonic-gate * Save a consed up name for the file to unlink
5350Sstevel@tonic-gate * later, and check that this is really a file
5360Sstevel@tonic-gate * we are looking for.
5370Sstevel@tonic-gate */
5380Sstevel@tonic-gate (void)strcat(strcat(strcpy(nb, dirname), "/"), filname);
5390Sstevel@tonic-gate if (yeah(nb)) {
5400Sstevel@tonic-gate /*
5410Sstevel@tonic-gate * Well, it is the file we are looking for.
5420Sstevel@tonic-gate * Is it more recent than any version we found before?
5430Sstevel@tonic-gate */
5440Sstevel@tonic-gate if (H.Time > besttime) {
5450Sstevel@tonic-gate /*
5460Sstevel@tonic-gate * A winner.
5470Sstevel@tonic-gate */
5480Sstevel@tonic-gate (void)close(bestfd);
5490Sstevel@tonic-gate bestfd = dup(tfile);
5500Sstevel@tonic-gate besttime = H.Time;
5510Sstevel@tonic-gate CP(bestnb, nb);
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate /*
5540Sstevel@tonic-gate * Count versions and tell user
5550Sstevel@tonic-gate */
5560Sstevel@tonic-gate vercnt++;
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate (void)close(tfile);
5590Sstevel@tonic-gate }
5600Sstevel@tonic-gate (void)closedir(dir);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate /*
5640Sstevel@tonic-gate * Given a candidate file to be recovered, see
5650Sstevel@tonic-gate * if it's really an editor temporary and of this
5660Sstevel@tonic-gate * user and the file specified.
5670Sstevel@tonic-gate */
568802Scf46844 int
yeah(unsigned char * name)569802Scf46844 yeah(unsigned char *name)
5700Sstevel@tonic-gate {
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate tfile = open(name, 2);
5730Sstevel@tonic-gate if (tfile < 0)
5740Sstevel@tonic-gate return (0);
5750Sstevel@tonic-gate if (read(tfile, (char *) &H, sizeof H) != sizeof H) {
5760Sstevel@tonic-gate nope:
5770Sstevel@tonic-gate (void)close(tfile);
5780Sstevel@tonic-gate return (0);
5790Sstevel@tonic-gate }
5800Sstevel@tonic-gate if (!eq(savedfile, file))
5810Sstevel@tonic-gate goto nope;
5820Sstevel@tonic-gate if (getuid() != H.Uid)
5830Sstevel@tonic-gate goto nope;
5840Sstevel@tonic-gate /*
5850Sstevel@tonic-gate * Old code: puts a word LOST in the header block, so that lost lines
5860Sstevel@tonic-gate * can be made to point at it.
5870Sstevel@tonic-gate */
5880Sstevel@tonic-gate (void)lseek(tfile, (long)(BUFSIZE*HBLKS-8), 0);
5890Sstevel@tonic-gate (void)write(tfile, "LOST", 5);
5900Sstevel@tonic-gate return (1);
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate /*
5940Sstevel@tonic-gate * Find the true end of the scratch file, and ``LOSE''
5950Sstevel@tonic-gate * lines which point into thin air. This lossage occurs
5960Sstevel@tonic-gate * due to the sandbagging of i/o which can cause blocks to
5970Sstevel@tonic-gate * be written in a non-obvious order, different from the order
5980Sstevel@tonic-gate * in which the editor tried to write them.
5990Sstevel@tonic-gate *
6000Sstevel@tonic-gate * Lines which are lost are replaced with the text LOST so
6010Sstevel@tonic-gate * they are easy to find. We work hard at pretty formatting here
6020Sstevel@tonic-gate * as lines tend to be lost in blocks.
6030Sstevel@tonic-gate *
6040Sstevel@tonic-gate * This only seems to happen on very heavily loaded systems, and
6050Sstevel@tonic-gate * not very often.
6060Sstevel@tonic-gate */
607802Scf46844 void
scrapbad(void)608802Scf46844 scrapbad(void)
6090Sstevel@tonic-gate {
610802Scf46844 line *ip;
6110Sstevel@tonic-gate struct stat64 stbuf;
6120Sstevel@tonic-gate off_t size, maxt;
6130Sstevel@tonic-gate int bno, cnt, bad, was;
6140Sstevel@tonic-gate unsigned char bk[BUFSIZE];
6150Sstevel@tonic-gate
6160Sstevel@tonic-gate (void)fstat64(tfile, &stbuf);
6170Sstevel@tonic-gate size = (off_t)stbuf.st_size;
6180Sstevel@tonic-gate maxt = (size >> SHFT) | (BNDRY-1);
6190Sstevel@tonic-gate bno = (maxt >> OFFBTS) & BLKMSK;
6200Sstevel@tonic-gate #ifdef DEBUG
6210Sstevel@tonic-gate fprintf(stderr, "size %ld, maxt %o, bno %d\n", size, maxt, bno);
6220Sstevel@tonic-gate #endif
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate /*
6250Sstevel@tonic-gate * Look for a null separating two lines in the temp file;
6260Sstevel@tonic-gate * if last line was split across blocks, then it is lost
6270Sstevel@tonic-gate * if the last block is.
6280Sstevel@tonic-gate */
6290Sstevel@tonic-gate while (bno > 0) {
6300Sstevel@tonic-gate (void)lseek(tfile, (long) BUFSIZE * bno, 0);
6310Sstevel@tonic-gate cnt = read(tfile, (char *) bk, BUFSIZE);
6320Sstevel@tonic-gate if(xtflag)
6330Sstevel@tonic-gate if (run_crypt(0L, bk, CRSIZE, tperm) == -1)
634802Scf46844 rsyserror();
6350Sstevel@tonic-gate #ifdef DEBUG
6360Sstevel@tonic-gate fprintf(stderr,"UNENCRYPTED: BLK %d\n",bno);
6370Sstevel@tonic-gate #endif
6380Sstevel@tonic-gate while (cnt > 0)
6390Sstevel@tonic-gate if (bk[--cnt] == 0)
6400Sstevel@tonic-gate goto null;
6410Sstevel@tonic-gate bno--;
6420Sstevel@tonic-gate }
6430Sstevel@tonic-gate null:
6440Sstevel@tonic-gate
6450Sstevel@tonic-gate /*
6460Sstevel@tonic-gate * Magically calculate the largest valid pointer in the temp file,
6470Sstevel@tonic-gate * consing it up from the block number and the count.
6480Sstevel@tonic-gate */
6490Sstevel@tonic-gate maxt = ((bno << OFFBTS) | (cnt >> SHFT)) & ~1;
6500Sstevel@tonic-gate #ifdef DEBUG
6510Sstevel@tonic-gate fprintf(stderr, "bno %d, cnt %d, maxt %o\n", bno, cnt, maxt);
6520Sstevel@tonic-gate #endif
6530Sstevel@tonic-gate
6540Sstevel@tonic-gate /*
6550Sstevel@tonic-gate * Now cycle through the line pointers,
6560Sstevel@tonic-gate * trashing the Lusers.
6570Sstevel@tonic-gate */
6580Sstevel@tonic-gate was = bad = 0;
6590Sstevel@tonic-gate for (ip = one; ip <= dol; ip++)
6600Sstevel@tonic-gate if (*ip > maxt) {
6610Sstevel@tonic-gate #ifdef DEBUG
6620Sstevel@tonic-gate fprintf(stderr, "%d bad, %o > %o\n", ip - zero, *ip, maxt);
6630Sstevel@tonic-gate #endif
6640Sstevel@tonic-gate if (was == 0)
6650Sstevel@tonic-gate was = ip - zero;
6660Sstevel@tonic-gate *ip = ((HBLKS*BUFSIZE)-8) >> SHFT;
6670Sstevel@tonic-gate } else if (was) {
6680Sstevel@tonic-gate if (bad == 0)
6690Sstevel@tonic-gate fprintf(stderr, gettext(" [Lost line(s):"));
6700Sstevel@tonic-gate fprintf(stderr, " %d", was);
6710Sstevel@tonic-gate if ((ip - 1) - zero > was)
6720Sstevel@tonic-gate fprintf(stderr, "-%d", (ip - 1) - zero);
6730Sstevel@tonic-gate bad++;
6740Sstevel@tonic-gate was = 0;
6750Sstevel@tonic-gate }
6760Sstevel@tonic-gate if (was != 0) {
6770Sstevel@tonic-gate if (bad == 0)
6780Sstevel@tonic-gate fprintf(stderr, " [Lost line(s):");
6790Sstevel@tonic-gate fprintf(stderr, " %d", was);
6800Sstevel@tonic-gate if (dol - zero != was)
6810Sstevel@tonic-gate fprintf(stderr, "-%d", dol - zero);
6820Sstevel@tonic-gate bad++;
6830Sstevel@tonic-gate }
6840Sstevel@tonic-gate if (bad)
6850Sstevel@tonic-gate fprintf(stderr, "]");
6860Sstevel@tonic-gate }
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate int cntch, cntln, cntodd, cntnull;
6890Sstevel@tonic-gate /*
6900Sstevel@tonic-gate * Following routines stolen mercilessly from ex.
6910Sstevel@tonic-gate */
692802Scf46844 void
rputfile(void)693802Scf46844 rputfile(void)
6940Sstevel@tonic-gate {
6950Sstevel@tonic-gate line *a1;
696802Scf46844 unsigned char *fp, *lp;
697802Scf46844 int nib;
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate a1 = addr1;
7000Sstevel@tonic-gate clrstats();
7010Sstevel@tonic-gate cntln = addr2 - a1 + 1;
7020Sstevel@tonic-gate if (cntln == 0)
7030Sstevel@tonic-gate return;
7040Sstevel@tonic-gate nib = BUFSIZE;
7050Sstevel@tonic-gate fp = genbuf;
7060Sstevel@tonic-gate do {
7070Sstevel@tonic-gate #ifdef DEBUG
7080Sstevel@tonic-gate fprintf(stderr,"GETTING A LINE \n");
7090Sstevel@tonic-gate #endif
710*13093SRoger.Faulkner@Oracle.COM getaline(*a1++);
7110Sstevel@tonic-gate lp = linebuf;
7120Sstevel@tonic-gate #ifdef DEBUG
7130Sstevel@tonic-gate fprintf(stderr,"LINE:%s\n",linebuf);
7140Sstevel@tonic-gate #endif
7150Sstevel@tonic-gate for (;;) {
7160Sstevel@tonic-gate if (--nib < 0) {
7170Sstevel@tonic-gate nib = fp - genbuf;
7180Sstevel@tonic-gate if (write(io, genbuf, nib) != nib)
7190Sstevel@tonic-gate wrerror();
7200Sstevel@tonic-gate cntch += nib;
7210Sstevel@tonic-gate nib = BUFSIZE;
7220Sstevel@tonic-gate fp = genbuf;
7230Sstevel@tonic-gate }
7240Sstevel@tonic-gate if ((*fp++ = *lp++) == 0) {
7250Sstevel@tonic-gate fp[-1] = '\n';
7260Sstevel@tonic-gate break;
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate }
7290Sstevel@tonic-gate } while (a1 <= addr2);
7300Sstevel@tonic-gate nib = fp - genbuf;
7310Sstevel@tonic-gate if (write(io, genbuf, nib) != nib)
7320Sstevel@tonic-gate wrerror();
7330Sstevel@tonic-gate cntch += nib;
7340Sstevel@tonic-gate }
7350Sstevel@tonic-gate
736802Scf46844 void
wrerror(void)737802Scf46844 wrerror(void)
7380Sstevel@tonic-gate {
7390Sstevel@tonic-gate
740802Scf46844 rsyserror();
7410Sstevel@tonic-gate }
7420Sstevel@tonic-gate
743802Scf46844 void
clrstats(void)744802Scf46844 clrstats(void)
7450Sstevel@tonic-gate {
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate ninbuf = 0;
7480Sstevel@tonic-gate cntch = 0;
7490Sstevel@tonic-gate cntln = 0;
7500Sstevel@tonic-gate cntnull = 0;
7510Sstevel@tonic-gate cntodd = 0;
7520Sstevel@tonic-gate }
7530Sstevel@tonic-gate
7540Sstevel@tonic-gate #define READ 0
7550Sstevel@tonic-gate #define WRITE 1
7560Sstevel@tonic-gate
757802Scf46844 void
getaline(line tl)758*13093SRoger.Faulkner@Oracle.COM getaline(line tl)
7590Sstevel@tonic-gate {
760802Scf46844 unsigned char *bp, *lp;
761802Scf46844 int nl;
7620Sstevel@tonic-gate
7630Sstevel@tonic-gate lp = linebuf;
7640Sstevel@tonic-gate bp = getblock(tl);
7650Sstevel@tonic-gate nl = nleft;
7660Sstevel@tonic-gate tl &= ~OFFMSK;
7670Sstevel@tonic-gate while (*lp++ = *bp++)
7680Sstevel@tonic-gate if (--nl == 0) {
7690Sstevel@tonic-gate bp = getblock(tl += INCRMT);
7700Sstevel@tonic-gate nl = nleft;
7710Sstevel@tonic-gate }
7720Sstevel@tonic-gate }
7730Sstevel@tonic-gate
7740Sstevel@tonic-gate int read();
7750Sstevel@tonic-gate int write();
7760Sstevel@tonic-gate
7770Sstevel@tonic-gate unsigned char *
getblock(atl)7780Sstevel@tonic-gate getblock(atl)
7790Sstevel@tonic-gate line atl;
7800Sstevel@tonic-gate {
781802Scf46844 int bno, off;
782802Scf46844 unsigned char *p1, *p2;
783802Scf46844 int n;
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate bno = (atl >> OFFBTS) & BLKMSK;
7860Sstevel@tonic-gate #ifdef DEBUG
7870Sstevel@tonic-gate fprintf(stderr,"GETBLOCK: BLK %d\n",bno);
7880Sstevel@tonic-gate #endif
7890Sstevel@tonic-gate off = (atl << SHFT) & LBTMSK;
7900Sstevel@tonic-gate if (bno >= NMBLKS)
791802Scf46844 error((unsigned char *)gettext(" Tmp file too large"));
7920Sstevel@tonic-gate nleft = BUFSIZE - off;
7930Sstevel@tonic-gate if (bno == iblock)
7940Sstevel@tonic-gate return (ibuff + off);
7950Sstevel@tonic-gate iblock = bno;
7960Sstevel@tonic-gate blkio(bno, ibuff, read);
7970Sstevel@tonic-gate if(xtflag)
7980Sstevel@tonic-gate if (run_crypt(0L, ibuff, CRSIZE, tperm) == -1)
799802Scf46844 rsyserror();
8000Sstevel@tonic-gate #ifdef DEBUG
8010Sstevel@tonic-gate fprintf(stderr,"UNENCRYPTED: BLK %d\n",bno);
8020Sstevel@tonic-gate #endif
8030Sstevel@tonic-gate return (ibuff + off);
8040Sstevel@tonic-gate }
8050Sstevel@tonic-gate
806802Scf46844 void
blkio(short b,unsigned char * buf,int (* iofcn)())807802Scf46844 blkio(short b, unsigned char *buf, int (*iofcn)())
8080Sstevel@tonic-gate {
8090Sstevel@tonic-gate
8100Sstevel@tonic-gate int rc;
8110Sstevel@tonic-gate lseek(tfile, (long) (unsigned) b * BUFSIZE, 0);
8120Sstevel@tonic-gate if ((rc =(*iofcn)(tfile, buf, BUFSIZE)) != BUFSIZE) {
8130Sstevel@tonic-gate (void)fprintf(stderr,gettext("Failed on BLK: %d with %d/%d\n"),b,rc,BUFSIZE);
8140Sstevel@tonic-gate perror("");
815802Scf46844 rsyserror();
8160Sstevel@tonic-gate }
8170Sstevel@tonic-gate }
8180Sstevel@tonic-gate
819802Scf46844 void
rsyserror(void)820802Scf46844 rsyserror(void)
8210Sstevel@tonic-gate {
822634Sdp int save_err = errno;
8230Sstevel@tonic-gate
8240Sstevel@tonic-gate dirtcnt = 0;
8250Sstevel@tonic-gate write(2, " ", 1);
826634Sdp error(strerror(save_err));
8270Sstevel@tonic-gate exit(1);
8280Sstevel@tonic-gate }
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate static int intrupt;
8310Sstevel@tonic-gate
8329694SScott.Rotondo@Sun.COM static void catch();
8339694SScott.Rotondo@Sun.COM
8340Sstevel@tonic-gate unsigned char *
mypass(prompt)8350Sstevel@tonic-gate mypass(prompt)
8360Sstevel@tonic-gate unsigned char *prompt;
8370Sstevel@tonic-gate {
8380Sstevel@tonic-gate struct termio ttyb;
8390Sstevel@tonic-gate unsigned short flags;
840802Scf46844 unsigned char *p;
841802Scf46844 int c;
8420Sstevel@tonic-gate static unsigned char pbuf[9];
8430Sstevel@tonic-gate void (*sig)();
8440Sstevel@tonic-gate
8450Sstevel@tonic-gate setbuf(stdin, (char*)NULL);
8460Sstevel@tonic-gate sig = signal(SIGINT, catch);
8470Sstevel@tonic-gate intrupt = 0;
8480Sstevel@tonic-gate (void) ioctl(fileno(stdin), TCGETA, &ttyb);
8490Sstevel@tonic-gate flags = ttyb.c_lflag;
8500Sstevel@tonic-gate ttyb.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
8510Sstevel@tonic-gate (void) ioctl(fileno(stdin), TCSETAF, &ttyb);
8520Sstevel@tonic-gate (void) fputs((char *)prompt, stderr);
8530Sstevel@tonic-gate for(p=pbuf; !intrupt && (c = getc(stdin)) != '\n' && c!= '\r' && c != EOF; ) {
8540Sstevel@tonic-gate if(p < &pbuf[8])
8550Sstevel@tonic-gate *p++ = c;
8560Sstevel@tonic-gate }
8570Sstevel@tonic-gate *p = '\0';
8580Sstevel@tonic-gate (void) putc('\n', stderr);
8590Sstevel@tonic-gate ttyb.c_lflag = flags;
8600Sstevel@tonic-gate (void) ioctl(fileno(stdin), TCSETA, &ttyb);
8610Sstevel@tonic-gate (void) signal(SIGINT, sig);
8620Sstevel@tonic-gate if(intrupt)
8630Sstevel@tonic-gate (void) kill(getpid(), SIGINT);
8640Sstevel@tonic-gate return(pbuf);
8650Sstevel@tonic-gate }
8660Sstevel@tonic-gate
8670Sstevel@tonic-gate static void
catch()8680Sstevel@tonic-gate catch()
8690Sstevel@tonic-gate {
8700Sstevel@tonic-gate ++intrupt;
8710Sstevel@tonic-gate }
872