17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*f6db9f27Scf46844 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #include <ctype.h> 367c478bd9Sstevel@tonic-gate #include <sys/types.h> 377c478bd9Sstevel@tonic-gate #include <sys/stat.h> 387c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 397c478bd9Sstevel@tonic-gate #include <errno.h> 407c478bd9Sstevel@tonic-gate #include <dirent.h> 417c478bd9Sstevel@tonic-gate #include <pwd.h> 427c478bd9Sstevel@tonic-gate #include <locale.h> 437c478bd9Sstevel@tonic-gate #include <limits.h> 44*f6db9f27Scf46844 #include <unistd.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #define BUFSIZE (LINE_MAX*2) /* This should agree with what's in ex.h */ 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate #include "ex_tune.h" 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #define FTYPE(A) (A.st_mode) 517c478bd9Sstevel@tonic-gate #define FMODE(A) (A.st_mode) 527c478bd9Sstevel@tonic-gate #define IDENTICAL(A, B) (A.st_dev == B.st_dev && A.st_ino == B.st_ino) 537c478bd9Sstevel@tonic-gate #define ISBLK(A) ((A.st_mode & S_IFMT) == S_IFBLK) 547c478bd9Sstevel@tonic-gate #define ISCHR(A) ((A.st_mode & S_IFMT) == S_IFCHR) 557c478bd9Sstevel@tonic-gate #define ISDIR(A) ((A.st_mode & S_IFMT) == S_IFDIR) 567c478bd9Sstevel@tonic-gate #define ISFIFO(A) ((A.st_mode & S_IFMT) == S_IFIFO) 577c478bd9Sstevel@tonic-gate #define ISREG(A) ((A.st_mode & S_IFMT) == S_IFREG) 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * Expreserve - preserve a file in usrpath(preserve) 617c478bd9Sstevel@tonic-gate * 627c478bd9Sstevel@tonic-gate * This routine is very naive - it doesn't remove anything from 637c478bd9Sstevel@tonic-gate * usrpath(preserve)... this may mean that we * stuff there... 647c478bd9Sstevel@tonic-gate * the danger in doing anything with usrpath(preserve) 657c478bd9Sstevel@tonic-gate * is that the clock may be messed up and we may get confused. 667c478bd9Sstevel@tonic-gate * 677c478bd9Sstevel@tonic-gate * We are called in two ways - first from the editor with no arguments 687c478bd9Sstevel@tonic-gate * and the standard input open on the temp file. Second with an argument 697c478bd9Sstevel@tonic-gate * to preserve the entire contents of /var/tmp (root only). 707c478bd9Sstevel@tonic-gate * 717c478bd9Sstevel@tonic-gate * BUG: should do something about preserving Rx... (register contents) 727c478bd9Sstevel@tonic-gate * temporaries. 737c478bd9Sstevel@tonic-gate */ 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate struct header { 767c478bd9Sstevel@tonic-gate time_t Time; /* Time temp file last updated */ 777c478bd9Sstevel@tonic-gate int Uid; /* This user's identity */ 787c478bd9Sstevel@tonic-gate #ifndef VMUNIX 797c478bd9Sstevel@tonic-gate short Flines; /* Number of lines in file */ 807c478bd9Sstevel@tonic-gate #else 817c478bd9Sstevel@tonic-gate int Flines; 827c478bd9Sstevel@tonic-gate #endif 837c478bd9Sstevel@tonic-gate unsigned char Savedfile[FNSIZE]; /* The current file name */ 847c478bd9Sstevel@tonic-gate short Blocks[LBLKS]; /* Blocks where line pointers stashed */ 857c478bd9Sstevel@tonic-gate short encrypted; /* Encrypted temp file flag */ 867c478bd9Sstevel@tonic-gate } H; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate #define eq(a, b) strcmp(a, b) == 0 897c478bd9Sstevel@tonic-gate 90*f6db9f27Scf46844 void notify(int, unsigned char *, int, int); 91*f6db9f27Scf46844 void mkdigits(unsigned char *); 92*f6db9f27Scf46844 93*f6db9f27Scf46844 int 947c478bd9Sstevel@tonic-gate main(argc) 957c478bd9Sstevel@tonic-gate int argc; 967c478bd9Sstevel@tonic-gate { 97*f6db9f27Scf46844 DIR *tf; 987c478bd9Sstevel@tonic-gate struct dirent64 *direntry; 997c478bd9Sstevel@tonic-gate unsigned char *filname; 1007c478bd9Sstevel@tonic-gate struct stat64 stbuf; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 1037c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 1047c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 1057c478bd9Sstevel@tonic-gate #endif 1067c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1077c478bd9Sstevel@tonic-gate /* 1087c478bd9Sstevel@tonic-gate * If only one argument, then preserve the standard input. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate if (argc == 1) { 111*f6db9f27Scf46844 if (copyout((unsigned char *) 0)) 112*f6db9f27Scf46844 return (1); 113*f6db9f27Scf46844 return (0); 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* 1177c478bd9Sstevel@tonic-gate * If not super user, then can only preserve standard input. 1187c478bd9Sstevel@tonic-gate */ 1197c478bd9Sstevel@tonic-gate if (getuid()) { 1207c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("NOT super user\n")); 121*f6db9f27Scf46844 return (1); 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * ... else preserve all the stuff in /var/tmp, removing 1267c478bd9Sstevel@tonic-gate * it as we go. 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate if (chdir(TMPDIR) < 0) { 1297c478bd9Sstevel@tonic-gate perror(TMPDIR); 130*f6db9f27Scf46844 return (1); 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate if ((tf = opendir(".")) == NULL) 1347c478bd9Sstevel@tonic-gate { 1357c478bd9Sstevel@tonic-gate perror(TMPDIR); 136*f6db9f27Scf46844 return (1); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate while ((direntry = readdir64(tf)) != NULL) 1397c478bd9Sstevel@tonic-gate { 1407c478bd9Sstevel@tonic-gate filname = (unsigned char *)direntry->d_name; 1417c478bd9Sstevel@tonic-gate /* 1427c478bd9Sstevel@tonic-gate * Ex temporaries must begin with Ex; 1437c478bd9Sstevel@tonic-gate * we check that the 12th character of the name is null 1447c478bd9Sstevel@tonic-gate * so we won't have to worry about non-null terminated names 1457c478bd9Sstevel@tonic-gate * later on. 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate if (filname[0] != 'E' || filname[1] != 'x' || filname[12]) 1487c478bd9Sstevel@tonic-gate continue; 1497c478bd9Sstevel@tonic-gate if (stat64((char *)filname, &stbuf)) 1507c478bd9Sstevel@tonic-gate continue; 1517c478bd9Sstevel@tonic-gate if (!ISREG(stbuf)) 1527c478bd9Sstevel@tonic-gate continue; 1537c478bd9Sstevel@tonic-gate /* 1547c478bd9Sstevel@tonic-gate * Save the file. 1557c478bd9Sstevel@tonic-gate */ 1567c478bd9Sstevel@tonic-gate (void) copyout(filname); 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate closedir(tf); 159*f6db9f27Scf46844 return (0); 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate unsigned char mydir[] = USRPRESERVE; 1637c478bd9Sstevel@tonic-gate unsigned char pattern[] = "/Exaa`XXXXXXXXXX"; 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * Copy file name into usrpath(preserve)/... 1677c478bd9Sstevel@tonic-gate * If name is (char *) 0, then do the standard input. 1687c478bd9Sstevel@tonic-gate * We make some checks on the input to make sure it is 1697c478bd9Sstevel@tonic-gate * really an editor temporary, generate a name for the 1707c478bd9Sstevel@tonic-gate * file (this is the slowest thing since we must stat 1717c478bd9Sstevel@tonic-gate * to find a unique name), and finally copy the file. 1727c478bd9Sstevel@tonic-gate */ 173*f6db9f27Scf46844 int 174*f6db9f27Scf46844 copyout(unsigned char *name) 1757c478bd9Sstevel@tonic-gate { 1767c478bd9Sstevel@tonic-gate int i; 1777c478bd9Sstevel@tonic-gate static int reenter; 1787c478bd9Sstevel@tonic-gate unsigned char buf[BUFSIZE]; 1797c478bd9Sstevel@tonic-gate unsigned char savdir[PATH_MAX+1]; 1807c478bd9Sstevel@tonic-gate unsigned char savfil[PATH_MAX+1]; 1817c478bd9Sstevel@tonic-gate struct passwd *pp; 1827c478bd9Sstevel@tonic-gate struct stat64 stbuf; 1837c478bd9Sstevel@tonic-gate int savfild; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate /* 1867c478bd9Sstevel@tonic-gate * The first time we put in the digits of our 1877c478bd9Sstevel@tonic-gate * process number at the end of the pattern. 1887c478bd9Sstevel@tonic-gate */ 1897c478bd9Sstevel@tonic-gate if (reenter == 0) { 1907c478bd9Sstevel@tonic-gate mkdigits(pattern); 1917c478bd9Sstevel@tonic-gate reenter++; 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 1957c478bd9Sstevel@tonic-gate * If a file name was given, make it the standard 1967c478bd9Sstevel@tonic-gate * input if possible. 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate if (name != 0) { 1997c478bd9Sstevel@tonic-gate (void) close(0); 2007c478bd9Sstevel@tonic-gate /* 2017c478bd9Sstevel@tonic-gate * Need read/write access for arcane reasons 2027c478bd9Sstevel@tonic-gate * (see below). 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate if (open(name, O_RDWR) < 0) 2057c478bd9Sstevel@tonic-gate return (-1); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * Get the header block. 2107c478bd9Sstevel@tonic-gate */ 2117c478bd9Sstevel@tonic-gate (void) lseek(0, 0l, 0); 2127c478bd9Sstevel@tonic-gate if (read(0, (char *)&H, sizeof (H)) != sizeof (H)) { 2137c478bd9Sstevel@tonic-gate format: 2147c478bd9Sstevel@tonic-gate if (name == 0) 2157c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Buffer format error\t")); 2167c478bd9Sstevel@tonic-gate else { 2177c478bd9Sstevel@tonic-gate /* 2187c478bd9Sstevel@tonic-gate * avoid having a bunch of NULL Ex* files 2197c478bd9Sstevel@tonic-gate * hanging around 2207c478bd9Sstevel@tonic-gate */ 2217c478bd9Sstevel@tonic-gate struct stat64 stbuf; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate if (stat64((char *)name, &stbuf) == 0) 2247c478bd9Sstevel@tonic-gate if (stbuf.st_size == 0) 225*f6db9f27Scf46844 (void) unlink((char *)name); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate return (-1); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate /* 2317c478bd9Sstevel@tonic-gate * Consistency checks so we don't copy out garbage. 2327c478bd9Sstevel@tonic-gate */ 2337c478bd9Sstevel@tonic-gate if (H.Flines < 0) { 2347c478bd9Sstevel@tonic-gate #ifdef DEBUG 2357c478bd9Sstevel@tonic-gate fprintf(stderr, "Negative number of lines\n"); 2367c478bd9Sstevel@tonic-gate #endif 2377c478bd9Sstevel@tonic-gate goto format; 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate if (H.Blocks[0] != HBLKS || H.Blocks[1] != HBLKS+1) { 2407c478bd9Sstevel@tonic-gate #ifdef DEBUG 2417c478bd9Sstevel@tonic-gate fprintf(stderr, "Blocks %d %d\n", H.Blocks[0], H.Blocks[1]); 2427c478bd9Sstevel@tonic-gate #endif 2437c478bd9Sstevel@tonic-gate goto format; 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate if (name == 0 && H.Uid != getuid()) { 2467c478bd9Sstevel@tonic-gate #ifdef DEBUG 2477c478bd9Sstevel@tonic-gate fprintf(stderr, "Wrong user-id\n"); 2487c478bd9Sstevel@tonic-gate #endif 2497c478bd9Sstevel@tonic-gate goto format; 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate if (lseek(0, 0l, 0)) { 2527c478bd9Sstevel@tonic-gate #ifdef DEBUG 2537c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Negative number of lines\n")); 2547c478bd9Sstevel@tonic-gate #endif 2557c478bd9Sstevel@tonic-gate goto format; 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* 2597c478bd9Sstevel@tonic-gate * If no name was assigned to the file, then give it the name 2607c478bd9Sstevel@tonic-gate * LOST, by putting this in the header. 2617c478bd9Sstevel@tonic-gate */ 2627c478bd9Sstevel@tonic-gate if (H.Savedfile[0] == 0) { 2637c478bd9Sstevel@tonic-gate (void) strcpy(H.Savedfile, "LOST"); 2647c478bd9Sstevel@tonic-gate (void) write(0, (char *) &H, sizeof (H)); 2657c478bd9Sstevel@tonic-gate H.Savedfile[0] = 0; 2667c478bd9Sstevel@tonic-gate (void) lseek(0, 0l, 0); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* 2707c478bd9Sstevel@tonic-gate * See if preservation directory for user exists. 2717c478bd9Sstevel@tonic-gate */ 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate strcpy(savdir, mydir); 2747c478bd9Sstevel@tonic-gate pp = getpwuid(H.Uid); 2757c478bd9Sstevel@tonic-gate if (pp) 2767c478bd9Sstevel@tonic-gate strcat(savdir, pp->pw_name); 2777c478bd9Sstevel@tonic-gate else { 2787c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Unable to get uid for user.\n")); 2797c478bd9Sstevel@tonic-gate return (-1); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate if (lstat64((char *)savdir, &stbuf) < 0 || !S_ISDIR(stbuf.st_mode)) { 2827c478bd9Sstevel@tonic-gate /* It doesn't exist or it isn't a directory, safe to unlink */ 283*f6db9f27Scf46844 (void) unlink((char *)savdir); 2847c478bd9Sstevel@tonic-gate if (mkdir((char *)savdir, 0700) < 0) { 2857c478bd9Sstevel@tonic-gate fprintf(stderr, 2867c478bd9Sstevel@tonic-gate gettext("Unable to create directory \"%s\"\n"), 2877c478bd9Sstevel@tonic-gate savdir); 2887c478bd9Sstevel@tonic-gate perror(""); 2897c478bd9Sstevel@tonic-gate return (-1); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate (void) chmod((char *)savdir, 0700); 292*f6db9f27Scf46844 (void) chown((char *)savdir, H.Uid, 2); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * File is good. Get a name and create a file for the copy. 2977c478bd9Sstevel@tonic-gate */ 2987c478bd9Sstevel@tonic-gate (void) close(1); 2997c478bd9Sstevel@tonic-gate if ((savfild = mknext(savdir, pattern)) < 0) { 3007c478bd9Sstevel@tonic-gate if (name == 0) 3017c478bd9Sstevel@tonic-gate perror((char *)savfil); 3027c478bd9Sstevel@tonic-gate return (1); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate strcpy(savfil, savdir); 3057c478bd9Sstevel@tonic-gate strcat(savfil, pattern); 3067c478bd9Sstevel@tonic-gate /* 3077c478bd9Sstevel@tonic-gate * Make target owned by user. 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate (void) fchown(savfild, H.Uid, 2); 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate /* 3137c478bd9Sstevel@tonic-gate * Copy the file. 3147c478bd9Sstevel@tonic-gate */ 3157c478bd9Sstevel@tonic-gate for (;;) { 3167c478bd9Sstevel@tonic-gate i = read(0, buf, BUFSIZE); 3177c478bd9Sstevel@tonic-gate if (i < 0) { 3187c478bd9Sstevel@tonic-gate if (name) 3197c478bd9Sstevel@tonic-gate perror(gettext("Buffer read error")); 320*f6db9f27Scf46844 (void) unlink((char *)savfil); 3217c478bd9Sstevel@tonic-gate return (-1); 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate if (i == 0) { 3247c478bd9Sstevel@tonic-gate if (name) 325*f6db9f27Scf46844 (void) unlink((char *)name); 3267c478bd9Sstevel@tonic-gate notify(H.Uid, H.Savedfile, (int) name, H.encrypted); 3277c478bd9Sstevel@tonic-gate return (0); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate if (write(savfild, buf, i) != i) { 3307c478bd9Sstevel@tonic-gate if (name == 0) 3317c478bd9Sstevel@tonic-gate perror((char *)savfil); 332*f6db9f27Scf46844 (void) unlink((char *)savfil); 3337c478bd9Sstevel@tonic-gate return (-1); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate /* 3397c478bd9Sstevel@tonic-gate * Blast the last 5 characters of cp to be the process number. 3407c478bd9Sstevel@tonic-gate */ 341*f6db9f27Scf46844 void 342*f6db9f27Scf46844 mkdigits(unsigned char *cp) 3437c478bd9Sstevel@tonic-gate { 344*f6db9f27Scf46844 pid_t i; 345*f6db9f27Scf46844 int j; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate for (i = getpid(), j = 10, cp += strlen(cp); j > 0; i /= 10, j--) 3487c478bd9Sstevel@tonic-gate *--cp = i % 10 | '0'; 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate /* 3527c478bd9Sstevel@tonic-gate * Make the name in cp be unique by clobbering up to 3537c478bd9Sstevel@tonic-gate * three alphabetic characters into a sequence of the form 'aab', 'aac', etc. 3547c478bd9Sstevel@tonic-gate * Mktemp gets weird names too quickly to be useful here. 3557c478bd9Sstevel@tonic-gate */ 356*f6db9f27Scf46844 int 357*f6db9f27Scf46844 mknext(unsigned char *dir, unsigned char *cp) 3587c478bd9Sstevel@tonic-gate { 3597c478bd9Sstevel@tonic-gate unsigned char *dcp; 3607c478bd9Sstevel@tonic-gate struct stat stb; 3617c478bd9Sstevel@tonic-gate unsigned char path[PATH_MAX+1]; 3627c478bd9Sstevel@tonic-gate int fd; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate strcpy(path, dir); 3657c478bd9Sstevel@tonic-gate strcat(path, cp); 3667c478bd9Sstevel@tonic-gate dcp = path + strlen(path) - 1; 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate while (isdigit(*dcp)) 3697c478bd9Sstevel@tonic-gate dcp--; 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate do { 3727c478bd9Sstevel@tonic-gate if (dcp[0] == 'z') { 3737c478bd9Sstevel@tonic-gate dcp[0] = 'a'; 3747c478bd9Sstevel@tonic-gate if (dcp[-1] == 'z') { 3757c478bd9Sstevel@tonic-gate dcp[-1] = 'a'; 3767c478bd9Sstevel@tonic-gate if (dcp[-2] == 'z') { 3777c478bd9Sstevel@tonic-gate fprintf(stderr, 3787c478bd9Sstevel@tonic-gate gettext("Can't find a name\t")); 3797c478bd9Sstevel@tonic-gate return (-1); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate dcp[-2]++; 3827c478bd9Sstevel@tonic-gate } else 3837c478bd9Sstevel@tonic-gate dcp[-1]++; 3847c478bd9Sstevel@tonic-gate } else 3857c478bd9Sstevel@tonic-gate dcp[0]++; 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate } while (((fd = open(path, O_CREAT|O_EXCL|O_WRONLY, 0600)) < 0) && 3887c478bd9Sstevel@tonic-gate errno == EEXIST); 3897c478bd9Sstevel@tonic-gate /* copy out patern */ 3907c478bd9Sstevel@tonic-gate strcpy(cp, path + strlen(dir)); 3917c478bd9Sstevel@tonic-gate return (fd); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate /* 3957c478bd9Sstevel@tonic-gate * Notify user uid that his file fname has been saved. 3967c478bd9Sstevel@tonic-gate */ 397*f6db9f27Scf46844 void 398*f6db9f27Scf46844 notify(int uid, unsigned char *fname, int flag, int cryflag) 3997c478bd9Sstevel@tonic-gate { 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate #define MAXHOSTNAMELEN 256 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate struct passwd *pp = getpwuid(uid); 404*f6db9f27Scf46844 FILE *mf; 4057c478bd9Sstevel@tonic-gate unsigned char cmd[BUFSIZE]; 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate char hostname[MAXHOSTNAMELEN]; 4087c478bd9Sstevel@tonic-gate int namelen = MAXHOSTNAMELEN ; 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate if (gethostname((char *)hostname, namelen) == -1) 4117c478bd9Sstevel@tonic-gate return; 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate if (pp == NULL) 4147c478bd9Sstevel@tonic-gate return; 4157c478bd9Sstevel@tonic-gate sprintf((char *)cmd, "/usr/bin/mail %s", pp->pw_name); 4167c478bd9Sstevel@tonic-gate mf = popen((char *)cmd, "w"); 4177c478bd9Sstevel@tonic-gate if (mf == NULL) 4187c478bd9Sstevel@tonic-gate return; 4197c478bd9Sstevel@tonic-gate setbuf(mf, (char *)cmd); 4207c478bd9Sstevel@tonic-gate if (fname[0] == 0) { 4217c478bd9Sstevel@tonic-gate fprintf(mf, flag ? 4227c478bd9Sstevel@tonic-gate "A copy of an editor buffer of yours was saved on %s when the system went down.\n" : 4237c478bd9Sstevel@tonic-gate "A copy of an editor buffer of yours was saved on %s when the editor was killed\nor was unable to save your changes.\n", hostname); 4247c478bd9Sstevel@tonic-gate fprintf(mf, 4257c478bd9Sstevel@tonic-gate "No name was associated with this buffer so it has been named \"LOST\".\n"); 4267c478bd9Sstevel@tonic-gate } else 4277c478bd9Sstevel@tonic-gate fprintf(mf, flag ? 4287c478bd9Sstevel@tonic-gate "A copy of an editor buffer of your file \"%s\"%s was saved on %s\nwhen the system \ 4297c478bd9Sstevel@tonic-gate went down.\n" : 4307c478bd9Sstevel@tonic-gate "A copy of an editor buffer of your file \"%s\"%s was saved on %s\nwhen the editor \ 4317c478bd9Sstevel@tonic-gate was killed or was unable to save your changes.\n", fname, (cryflag) ? "[ENCRYPTED]" : "", hostname); 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * "the editor was killed" is perhaps still not an ideal 4347c478bd9Sstevel@tonic-gate * error message. Usually, either it was forceably terminated 4357c478bd9Sstevel@tonic-gate * or the phone was hung up, but we don't know which. 4367c478bd9Sstevel@tonic-gate */ 4377c478bd9Sstevel@tonic-gate fprintf(mf, 4387c478bd9Sstevel@tonic-gate "This buffer can be retrieved using the \"recover\" command of the editor.\n"); 4397c478bd9Sstevel@tonic-gate fprintf(mf, 4407c478bd9Sstevel@tonic-gate "An easy way to do this is to give the command \"vi -r %s\".\n", 4417c478bd9Sstevel@tonic-gate (fname[0] == 0) ? "LOST" : (char *) fname); 4427c478bd9Sstevel@tonic-gate fprintf(mf, "This works for \"edit\" and \"ex\" also.\n"); 4437c478bd9Sstevel@tonic-gate (void) pclose(mf); 4447c478bd9Sstevel@tonic-gate } 445