1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 /* Copyright (c) 1981 Regents of the University of California */ 32 33 #pragma ident "%Z%%M% %I% %E% SMI" 34 35 #include <stdio.h> /* BUFSIZ: stdio = 1024, VMUNIX = 1024 */ 36 #ifndef TRACE 37 #undef NULL 38 #endif 39 40 #include "ex.h" 41 #include "ex_temp.h" 42 #include "ex_tty.h" 43 #include "ex_tune.h" 44 #include <pwd.h> 45 #include <locale.h> 46 #include <dirent.h> 47 #include <unistd.h> 48 #include <errno.h> 49 50 #define DIRSIZ MAXNAMLEN 51 52 short tfile = -1; /* ditto */ 53 54 /* 55 * 56 * This program searches through the specified directory and then 57 * the directory usrpath(preserve) looking for an instance of the specified 58 * file from a crashed editor or a crashed system. 59 * If this file is found, it is unscrambled and written to 60 * the standard output. 61 * 62 * If this program terminates without a "broken pipe" diagnostic 63 * (i.e. the editor doesn't die right away) then the buffer we are 64 * writing from is removed when we finish. This is potentially a mistake 65 * as there is not enough handshaking to guarantee that the file has actually 66 * been recovered, but should suffice for most cases. 67 */ 68 69 /* 70 * This directory definition also appears (obviously) in expreserve.c. 71 * Change both if you change either. 72 */ 73 unsigned char mydir[PATH_MAX+1]; 74 75 /* 76 * Limit on the number of printed entries 77 * when an, e.g. ``ex -r'' command is given. 78 */ 79 #define NENTRY 50 80 81 unsigned char nb[BUFSIZE]; 82 int vercnt; /* Count number of versions of file found */ 83 void rputfile(void); 84 void rsyserror(void); 85 void searchdir(unsigned char *); 86 void scrapbad(void); 87 void findtmp(unsigned char *); 88 void listfiles(unsigned char *); 89 90 int 91 main(int argc, char *argv[]) 92 { 93 unsigned char string[50]; 94 unsigned char *cp; 95 int c, b, i; 96 int rflg = 0, errflg = 0; 97 int label; 98 line *tmpadr; 99 extern unsigned char *mypass(); 100 struct passwd *pp = getpwuid(getuid()); 101 unsigned char rmcmd[PATH_MAX+1]; 102 103 (void)setlocale(LC_ALL, ""); 104 #if !defined(TEXT_DOMAIN) 105 #define TEXT_DOMAIN "SYS_TEST" 106 #endif 107 (void)textdomain(TEXT_DOMAIN); 108 cp = string; 109 strcpy(mydir, USRPRESERVE); 110 if (pp == NULL) { 111 fprintf(stderr, gettext("Unable to get user's id\n")); 112 exit(-1); 113 } 114 strcat(mydir, pp->pw_name); 115 116 /* 117 * Initialize as though the editor had just started. 118 */ 119 fendcore = (line *) sbrk(0); 120 dot = zero = dol = fendcore; 121 one = zero + 1; 122 endcore = fendcore - 2; 123 iblock = oblock = -1; 124 125 while ((c=getopt(argc, (char **)argv, "rx")) != EOF) 126 switch (c) { 127 case 'r': 128 rflg++; 129 break; 130 131 case 'x': 132 xflag++; 133 break; 134 135 case '?': 136 errflg++; 137 break; 138 } 139 argc -= optind; 140 argv = &argv[optind]; 141 142 if (errflg) 143 exit(2); 144 145 /* 146 * If given only a -r argument, then list the saved files. 147 * (NOTE: single -r argument is scheduled to be replaced by -L). 148 */ 149 if (rflg && argc == 0) { 150 fprintf(stderr,"%s:\n", mydir); 151 listfiles(mydir); 152 fprintf(stderr,"%s:\n", TMPDIR); 153 listfiles((unsigned char *)TMPDIR); 154 exit(0); 155 } 156 157 if (argc != 2) 158 error(gettext(" Wrong number of arguments to exrecover"), 0); 159 160 CP(file, argv[1]); 161 162 /* 163 * Search for this file. 164 */ 165 findtmp((unsigned char *)argv[0]); 166 167 /* 168 * Got (one of the versions of) it, write it back to the editor. 169 */ 170 (void)cftime((char *)cp, "%a %h %d %T", &H.Time); 171 fprintf(stderr, vercnt > 1 ? 172 gettext(" [Dated: %s, newest of %d saved]") : 173 gettext(" [Dated: %s]"), cp, vercnt); 174 fprintf(stderr, "\r\n"); 175 176 if(H.encrypted) { 177 if(xflag) { 178 kflag = run_setkey(perm, (unsigned char *)getenv("CrYpTkEy")); 179 } else 180 kflag = run_setkey(perm, mypass("Enter key:")); 181 if(kflag == -1) { 182 kflag = 0; 183 xflag = 0; 184 fprintf(stderr,gettext("Encryption facility not available\n")); 185 exit(-1); 186 } 187 xtflag = 1; 188 if (makekey(tperm) != 0) { 189 xtflag = 0; 190 fprintf(stderr,gettext("Warning--Cannot encrypt temporary buffer\n")); 191 exit(-1); 192 } 193 } 194 fprintf(stderr,gettext("\r\n [Hit return to continue]")); 195 fflush(stderr); 196 setbuf(stdin, (char *)NULL); 197 while((c = getchar()) != '\n' && c != '\r'); 198 H.Flines++; 199 200 /* 201 * Allocate space for the line pointers from the temp file. 202 */ 203 if ((int) sbrk((int) (H.Flines * sizeof (line))) == -1) 204 error(gettext(" Not enough core for lines"), 0); 205 #ifdef DEBUG 206 fprintf(stderr, "%d lines\n", H.Flines); 207 #endif 208 209 /* 210 * Now go get the blocks of seek pointers which are scattered 211 * throughout the temp file, reconstructing the incore 212 * line pointers at point of crash. 213 */ 214 b = 0; 215 while (H.Flines > 0) { 216 (void)lseek(tfile, (long) blocks[b] * BUFSIZE, 0); 217 i = H.Flines < BUFSIZE / sizeof (line) ? 218 H.Flines * sizeof (line) : BUFSIZE; 219 if (read(tfile, (char *) dot, i) != i) { 220 perror((char *)nb); 221 exit(1); 222 } 223 dot += i / sizeof (line); 224 H.Flines -= i / sizeof (line); 225 b++; 226 } 227 dot--; dol = dot; 228 229 /* 230 * Due to sandbagging some lines may really not be there. 231 * Find and discard such. This shouldn't happen often. 232 */ 233 scrapbad(); 234 235 236 /* 237 * Now if there were any lines in the recovered file 238 * write them to the standard output. 239 */ 240 if (dol > zero) { 241 addr1 = one; addr2 = dol; io = 1; 242 rputfile(); 243 } 244 /* 245 * Trash the saved buffer. 246 * Hopefully the system won't crash before the editor 247 * syncs the new recovered buffer; i.e. for an instant here 248 * you may lose if the system crashes because this file 249 * is gone, but the editor hasn't completed reading the recovered 250 * file from the pipe from us to it. 251 * 252 * This doesn't work if we are coming from an non-absolute path 253 * name since we may have chdir'ed but what the hay, noone really 254 * ever edits with temporaries in "." anyways. 255 */ 256 if (nb[0] == '/') { 257 (void)unlink((const char *)nb); 258 sprintf((char *)rmcmd, "rmdir %s 2> /dev/null", (char *)mydir); 259 system((char *)rmcmd); 260 } 261 return (0); 262 } 263 264 /* 265 * Print an error message (notably not in error 266 * message file). If terminal is in RAW mode, then 267 * we should be writing output for "vi", so don't print 268 * a newline which would mess up the screen. 269 */ 270 /*VARARGS2*/ 271 void 272 error(str, inf) 273 unsigned char *str; 274 int inf; 275 { 276 277 struct termio termio; 278 if (inf) 279 fprintf(stderr, (char *)str, inf); 280 else 281 fprintf(stderr, (char *)str); 282 283 ioctl(2, TCGETA, &termio); 284 if (termio.c_lflag & ICANON) 285 fprintf(stderr, "\n"); 286 exit(1); 287 } 288 289 /* 290 * Here we save the information about files, when 291 * you ask us what files we have saved for you. 292 * We buffer file name, number of lines, and the time 293 * at which the file was saved. 294 */ 295 struct svfile { 296 unsigned char sf_name[FNSIZE + 1]; 297 int sf_lines; 298 unsigned char sf_entry[DIRSIZ + 1]; 299 time_t sf_time; 300 short sf_encrypted; 301 }; 302 void enter(struct svfile *, unsigned char *, int); 303 304 void 305 listfiles(unsigned char *dirname) 306 { 307 DIR *dir; 308 struct dirent64 *direntry; 309 int ecount, qucmp(); 310 int f; 311 unsigned char cp[50]; 312 unsigned char cp2[50]; 313 unsigned char *filname; 314 struct svfile *fp, svbuf[NENTRY]; 315 316 /* 317 * Open usrpath(preserve), and go there to make things quick. 318 */ 319 if ((dir = opendir((char *)dirname)) == NULL) 320 { 321 fprintf(stderr,gettext("No files saved.\n")); 322 return; 323 } 324 if (chdir((const char *)dirname) < 0) { 325 perror((char *)dirname); 326 return; 327 } 328 329 /* 330 * Look at the candidate files in usrpath(preserve). 331 */ 332 fp = &svbuf[0]; 333 ecount = 0; 334 while ((direntry = readdir64(dir)) != NULL) 335 { 336 filname = (unsigned char *)direntry->d_name; 337 if (filname[0] != 'E') 338 continue; 339 #ifdef DEBUG 340 fprintf(stderr, "considering %s\n", filname); 341 #endif 342 /* 343 * Name begins with E; open it and 344 * make sure the uid in the header is our uid. 345 * If not, then don't bother with this file, it can't 346 * be ours. 347 */ 348 f = open(filname, 0); 349 if (f < 0) { 350 #ifdef DEBUG 351 fprintf(stderr, "open failed\n"); 352 #endif 353 continue; 354 } 355 if (read(f, (char *) &H, sizeof H) != sizeof H) { 356 #ifdef DEBUG 357 fprintf(stderr, "could not read header\n"); 358 #endif 359 (void)close(f); 360 continue; 361 } 362 (void)close(f); 363 if (getuid() != H.Uid) { 364 #ifdef DEBUG 365 fprintf(stderr, "uid wrong\n"); 366 #endif 367 continue; 368 } 369 370 /* 371 * Saved the day! 372 */ 373 enter(fp++, filname, ecount); 374 ecount++; 375 #ifdef DEBUG 376 fprintf(stderr, "entered file %s\n", filname); 377 #endif 378 } 379 (void)closedir(dir); 380 /* 381 * If any files were saved, then sort them and print 382 * them out. 383 */ 384 if (ecount == 0) { 385 fprintf(stderr, gettext("No files saved.\n")); 386 return; 387 } 388 qsort(&svbuf[0], ecount, sizeof svbuf[0], qucmp); 389 for (fp = &svbuf[0]; fp < &svbuf[ecount]; fp++) { 390 (void)cftime((char *)cp, "%a %b %d", &fp->sf_time); 391 (void)cftime((char *)cp2, "%R", &fp->sf_time); 392 fprintf(stderr, 393 gettext("On %s at %s, saved %d lines of file \"%s\" "), 394 cp, cp2, fp->sf_lines, fp->sf_name); 395 fprintf(stderr, "%s\n", 396 (fp->sf_encrypted) ? gettext("[ENCRYPTED]") : ""); 397 } 398 } 399 400 /* 401 * Enter a new file into the saved file information. 402 */ 403 void 404 enter(struct svfile *fp, unsigned char *fname, int count) 405 { 406 unsigned char *cp, *cp2; 407 struct svfile *f, *fl; 408 time_t curtime; 409 410 f = 0; 411 if (count >= NENTRY) { 412 /* 413 * Trash the oldest as the most useless. 414 */ 415 fl = fp - count + NENTRY - 1; 416 curtime = fl->sf_time; 417 for (f = fl; --f > fp-count; ) 418 if (f->sf_time < curtime) 419 curtime = f->sf_time; 420 for (f = fl; --f > fp-count; ) 421 if (f->sf_time == curtime) 422 break; 423 fp = f; 424 } 425 426 /* 427 * Gotcha. 428 */ 429 fp->sf_time = H.Time; 430 fp->sf_lines = H.Flines; 431 fp->sf_encrypted = H.encrypted; 432 for (cp2 = fp->sf_name, cp = savedfile; *cp;) 433 *cp2++ = *cp++; 434 *cp2++ = 0; 435 for (cp2 = fp->sf_entry, cp = fname; *cp && cp-fname < 14;) 436 *cp2++ = *cp++; 437 *cp2++ = 0; 438 } 439 440 /* 441 * Do the qsort compare to sort the entries first by file name, 442 * then by modify time. 443 */ 444 int 445 qucmp(struct svfile *p1, struct svfile *p2) 446 { 447 int t; 448 449 if (t = strcmp(p1->sf_name, p2->sf_name)) 450 return(t); 451 if (p1->sf_time > p2->sf_time) 452 return(-1); 453 return(p1->sf_time < p2->sf_time); 454 } 455 456 /* 457 * Scratch for search. 458 */ 459 unsigned char bestnb[BUFSIZE]; /* Name of the best one */ 460 long besttime = 0; /* Time at which the best file was saved */ 461 int bestfd; /* Keep best file open so it dont vanish */ 462 463 /* 464 * Look for a file, both in the users directory option value 465 * (i.e. usually /tmp) and in usrpath(preserve). 466 * Want to find the newest so we search on and on. 467 */ 468 void 469 findtmp(unsigned char *dir) 470 { 471 472 /* 473 * No name or file so far. 474 */ 475 bestnb[0] = 0; 476 bestfd = -1; 477 478 /* 479 * Search usrpath(preserve) and, if we can get there, /tmp 480 * (actually the user's "directory" option). 481 */ 482 searchdir(dir); 483 if (chdir((const char *)mydir) == 0) 484 searchdir(mydir); 485 if (bestfd != -1) { 486 /* 487 * Gotcha. 488 * Put the file (which is already open) in the file 489 * used by the temp file routines, and save its 490 * name for later unlinking. 491 */ 492 tfile = bestfd; 493 CP(nb, bestnb); 494 (void)lseek(tfile, 0l, 0); 495 496 /* 497 * Gotta be able to read the header or fall through 498 * to lossage. 499 */ 500 if (read(tfile, (char *) &H, sizeof H) == sizeof H) 501 return; 502 } 503 504 /* 505 * Extreme lossage... 506 */ 507 error((unsigned char *)gettext(" File not found"), 0); 508 } 509 510 /* 511 * Search for the file in directory dirname. 512 * 513 * Don't chdir here, because the users directory 514 * may be ".", and we would move away before we searched it. 515 * Note that we actually chdir elsewhere (because it is too slow 516 * to look around in usrpath(preserve) without chdir'ing there) so we 517 * can't win, because we don't know the name of '.' and if the path 518 * name of the file we want to unlink is relative, rather than absolute 519 * we won't be able to find it again. 520 */ 521 void 522 searchdir(unsigned char *dirname) 523 { 524 struct dirent64 *direntry; 525 DIR *dir; 526 unsigned char dbuf[BUFSIZE]; 527 unsigned char *filname; 528 if ((dir = opendir((char *)dirname)) == NULL) 529 return; 530 while ((direntry = readdir64(dir)) != NULL) 531 { 532 filname = (unsigned char *)direntry->d_name; 533 if (filname[0] != 'E' || filname[1] != 'x') 534 continue; 535 /* 536 * Got a file in the directory starting with Ex... 537 * Save a consed up name for the file to unlink 538 * later, and check that this is really a file 539 * we are looking for. 540 */ 541 (void)strcat(strcat(strcpy(nb, dirname), "/"), filname); 542 if (yeah(nb)) { 543 /* 544 * Well, it is the file we are looking for. 545 * Is it more recent than any version we found before? 546 */ 547 if (H.Time > besttime) { 548 /* 549 * A winner. 550 */ 551 (void)close(bestfd); 552 bestfd = dup(tfile); 553 besttime = H.Time; 554 CP(bestnb, nb); 555 } 556 /* 557 * Count versions and tell user 558 */ 559 vercnt++; 560 } 561 (void)close(tfile); 562 } 563 (void)closedir(dir); 564 } 565 566 /* 567 * Given a candidate file to be recovered, see 568 * if it's really an editor temporary and of this 569 * user and the file specified. 570 */ 571 int 572 yeah(unsigned char *name) 573 { 574 575 tfile = open(name, 2); 576 if (tfile < 0) 577 return (0); 578 if (read(tfile, (char *) &H, sizeof H) != sizeof H) { 579 nope: 580 (void)close(tfile); 581 return (0); 582 } 583 if (!eq(savedfile, file)) 584 goto nope; 585 if (getuid() != H.Uid) 586 goto nope; 587 /* 588 * Old code: puts a word LOST in the header block, so that lost lines 589 * can be made to point at it. 590 */ 591 (void)lseek(tfile, (long)(BUFSIZE*HBLKS-8), 0); 592 (void)write(tfile, "LOST", 5); 593 return (1); 594 } 595 596 /* 597 * Find the true end of the scratch file, and ``LOSE'' 598 * lines which point into thin air. This lossage occurs 599 * due to the sandbagging of i/o which can cause blocks to 600 * be written in a non-obvious order, different from the order 601 * in which the editor tried to write them. 602 * 603 * Lines which are lost are replaced with the text LOST so 604 * they are easy to find. We work hard at pretty formatting here 605 * as lines tend to be lost in blocks. 606 * 607 * This only seems to happen on very heavily loaded systems, and 608 * not very often. 609 */ 610 void 611 scrapbad(void) 612 { 613 line *ip; 614 struct stat64 stbuf; 615 off_t size, maxt; 616 int bno, cnt, bad, was; 617 unsigned char bk[BUFSIZE]; 618 619 (void)fstat64(tfile, &stbuf); 620 size = (off_t)stbuf.st_size; 621 maxt = (size >> SHFT) | (BNDRY-1); 622 bno = (maxt >> OFFBTS) & BLKMSK; 623 #ifdef DEBUG 624 fprintf(stderr, "size %ld, maxt %o, bno %d\n", size, maxt, bno); 625 #endif 626 627 /* 628 * Look for a null separating two lines in the temp file; 629 * if last line was split across blocks, then it is lost 630 * if the last block is. 631 */ 632 while (bno > 0) { 633 (void)lseek(tfile, (long) BUFSIZE * bno, 0); 634 cnt = read(tfile, (char *) bk, BUFSIZE); 635 if(xtflag) 636 if (run_crypt(0L, bk, CRSIZE, tperm) == -1) 637 rsyserror(); 638 #ifdef DEBUG 639 fprintf(stderr,"UNENCRYPTED: BLK %d\n",bno); 640 #endif 641 while (cnt > 0) 642 if (bk[--cnt] == 0) 643 goto null; 644 bno--; 645 } 646 null: 647 648 /* 649 * Magically calculate the largest valid pointer in the temp file, 650 * consing it up from the block number and the count. 651 */ 652 maxt = ((bno << OFFBTS) | (cnt >> SHFT)) & ~1; 653 #ifdef DEBUG 654 fprintf(stderr, "bno %d, cnt %d, maxt %o\n", bno, cnt, maxt); 655 #endif 656 657 /* 658 * Now cycle through the line pointers, 659 * trashing the Lusers. 660 */ 661 was = bad = 0; 662 for (ip = one; ip <= dol; ip++) 663 if (*ip > maxt) { 664 #ifdef DEBUG 665 fprintf(stderr, "%d bad, %o > %o\n", ip - zero, *ip, maxt); 666 #endif 667 if (was == 0) 668 was = ip - zero; 669 *ip = ((HBLKS*BUFSIZE)-8) >> SHFT; 670 } else if (was) { 671 if (bad == 0) 672 fprintf(stderr, gettext(" [Lost line(s):")); 673 fprintf(stderr, " %d", was); 674 if ((ip - 1) - zero > was) 675 fprintf(stderr, "-%d", (ip - 1) - zero); 676 bad++; 677 was = 0; 678 } 679 if (was != 0) { 680 if (bad == 0) 681 fprintf(stderr, " [Lost line(s):"); 682 fprintf(stderr, " %d", was); 683 if (dol - zero != was) 684 fprintf(stderr, "-%d", dol - zero); 685 bad++; 686 } 687 if (bad) 688 fprintf(stderr, "]"); 689 } 690 691 int cntch, cntln, cntodd, cntnull; 692 /* 693 * Following routines stolen mercilessly from ex. 694 */ 695 void 696 rputfile(void) 697 { 698 line *a1; 699 unsigned char *fp, *lp; 700 int nib; 701 702 a1 = addr1; 703 clrstats(); 704 cntln = addr2 - a1 + 1; 705 if (cntln == 0) 706 return; 707 nib = BUFSIZE; 708 fp = genbuf; 709 do { 710 #ifdef DEBUG 711 fprintf(stderr,"GETTING A LINE \n"); 712 #endif 713 getline(*a1++); 714 lp = linebuf; 715 #ifdef DEBUG 716 fprintf(stderr,"LINE:%s\n",linebuf); 717 #endif 718 for (;;) { 719 if (--nib < 0) { 720 nib = fp - genbuf; 721 if (write(io, genbuf, nib) != nib) 722 wrerror(); 723 cntch += nib; 724 nib = BUFSIZE; 725 fp = genbuf; 726 } 727 if ((*fp++ = *lp++) == 0) { 728 fp[-1] = '\n'; 729 break; 730 } 731 } 732 } while (a1 <= addr2); 733 nib = fp - genbuf; 734 if (write(io, genbuf, nib) != nib) 735 wrerror(); 736 cntch += nib; 737 } 738 739 void 740 wrerror(void) 741 { 742 743 rsyserror(); 744 } 745 746 void 747 clrstats(void) 748 { 749 750 ninbuf = 0; 751 cntch = 0; 752 cntln = 0; 753 cntnull = 0; 754 cntodd = 0; 755 } 756 757 #define READ 0 758 #define WRITE 1 759 760 void 761 getline(line tl) 762 { 763 unsigned char *bp, *lp; 764 int nl; 765 766 lp = linebuf; 767 bp = getblock(tl); 768 nl = nleft; 769 tl &= ~OFFMSK; 770 while (*lp++ = *bp++) 771 if (--nl == 0) { 772 bp = getblock(tl += INCRMT); 773 nl = nleft; 774 } 775 } 776 777 int read(); 778 int write(); 779 780 unsigned char * 781 getblock(atl) 782 line atl; 783 { 784 int bno, off; 785 unsigned char *p1, *p2; 786 int n; 787 788 bno = (atl >> OFFBTS) & BLKMSK; 789 #ifdef DEBUG 790 fprintf(stderr,"GETBLOCK: BLK %d\n",bno); 791 #endif 792 off = (atl << SHFT) & LBTMSK; 793 if (bno >= NMBLKS) 794 error((unsigned char *)gettext(" Tmp file too large")); 795 nleft = BUFSIZE - off; 796 if (bno == iblock) 797 return (ibuff + off); 798 iblock = bno; 799 blkio(bno, ibuff, read); 800 if(xtflag) 801 if (run_crypt(0L, ibuff, CRSIZE, tperm) == -1) 802 rsyserror(); 803 #ifdef DEBUG 804 fprintf(stderr,"UNENCRYPTED: BLK %d\n",bno); 805 #endif 806 return (ibuff + off); 807 } 808 809 void 810 blkio(short b, unsigned char *buf, int (*iofcn)()) 811 { 812 813 int rc; 814 lseek(tfile, (long) (unsigned) b * BUFSIZE, 0); 815 if ((rc =(*iofcn)(tfile, buf, BUFSIZE)) != BUFSIZE) { 816 (void)fprintf(stderr,gettext("Failed on BLK: %d with %d/%d\n"),b,rc,BUFSIZE); 817 perror(""); 818 rsyserror(); 819 } 820 } 821 822 void 823 rsyserror(void) 824 { 825 int save_err = errno; 826 827 dirtcnt = 0; 828 write(2, " ", 1); 829 error(strerror(save_err)); 830 exit(1); 831 } 832 833 static int intrupt; 834 835 unsigned char * 836 mypass(prompt) 837 unsigned char *prompt; 838 { 839 struct termio ttyb; 840 unsigned short flags; 841 unsigned char *p; 842 int c; 843 static unsigned char pbuf[9]; 844 void (*sig)(); 845 static void catch(); 846 847 setbuf(stdin, (char*)NULL); 848 sig = signal(SIGINT, catch); 849 intrupt = 0; 850 (void) ioctl(fileno(stdin), TCGETA, &ttyb); 851 flags = ttyb.c_lflag; 852 ttyb.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); 853 (void) ioctl(fileno(stdin), TCSETAF, &ttyb); 854 (void) fputs((char *)prompt, stderr); 855 for(p=pbuf; !intrupt && (c = getc(stdin)) != '\n' && c!= '\r' && c != EOF; ) { 856 if(p < &pbuf[8]) 857 *p++ = c; 858 } 859 *p = '\0'; 860 (void) putc('\n', stderr); 861 ttyb.c_lflag = flags; 862 (void) ioctl(fileno(stdin), TCSETA, &ttyb); 863 (void) signal(SIGINT, sig); 864 if(intrupt) 865 (void) kill(getpid(), SIGINT); 866 return(pbuf); 867 } 868 869 static void 870 catch() 871 { 872 ++intrupt; 873 } 874