home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************
- * can.c 2.0
- *
- * This is a utility to replace rm. I hope you like it
- *
- * written by "the bit butcher"
- *
- * 2.02 changed the error handling to cases and segmented the
- * program into three pieces and now have "can.h"
- * 28 June 1988
- *
- * 2.01 changed the way cross device problems are dealt with
- * copy file from one system to the other
- * before 28 June 1988
- *************************************************************/
-
- #include "can.h"
-
- char CAN[MAXPATHLEN]; /* String containing .trashcan directory*/
- char ANSWER[14]; /* String used for finding interactive response */
- int VERBOSE = 0; /* Set if Verbose is wanted */
- int INTERACTIVE = 0; /* Set if Interactive is wanted */
- long TIME; /* Used to get the current time */
- UTIMBUF TIMES; /* Structure used to change the access time */
-
- main(argc, argv)
- int argc;
- char** argv;
- {
- int c; /* which character in getopt */
- DIR *DIRP; /* Used to list the directory by pointing at .trashcan */
- struct direct *DP; /* Used to point at consecutive entries when listing */
- char FILENAME[MAXPATHLEN]; /* String containing .trashcan/current file*/
- char *ACTNAME; /* Points to filename without any leading directory */
- struct stat BUF; /* Used to point to mode info about files */
- int RECURSIVE = 0; /* Set if Recursive is wanted */
- #ifdef SYSV
- int UID; /* Variable holding user's ID */
- #endif
- #ifdef SUN
- int UID; /* Variable holding user's ID */
- #endif
- #ifdef BSD
- uid_t UID; /* Variable holding user's ID */
- #endif
- char TEMP[MAXPATHLEN]; /* Used for quick access of file names */
- struct passwd *USERINFO; /* Structure used to find out $HOME dir */
- extern int optind; /* used to step through arguments */
- extern char *optarg; /* used to step through arguments */
- int errflag = 0; /* Used to indicate errors in options */
- void recurcan(); /* Say this is a void function */
-
- /* Find out the users ID */
- if((UID= getuid()) == NULL)
- {
- fprintf(stderr, "Invalid Login: Who Are You!?!\n");
- exit(0);
- }
-
- /* Get his home directory from the passwd file */
- USERINFO = getpwuid(UID);
- if(USERINFO->pw_dir == NULL)
- {
- fprintf(stderr, "No Home Directory: check /etc/passwd !!!\n");
- exit(0);
- }
- /* say where the trashcan will be */
- sprintf(CAN, "%s/.trashcan", USERINFO->pw_dir);
-
- /* make sure there is a trashcan */
- if (access(CAN, F_OK) != 0)
- /* if not, make a trashcan */
- if(mkdir(CAN, 004777) != 0)
- {
- perror("can");
- exit(2);
- }
-
- /* could add force (-f) option later, perhaps */
- /* Let's look at the options */
- while((c=getopt(argc, argv, "ivlR:r")) != EOF)
- switch(c)
- {
- case 'l': /* list the contents by stepping through */
- fprintf(stdout, "%s\n", CAN);
- DIRP = opendir(CAN);
- /* Could allow arguments for selective listing */
- for(DP = readdir(DIRP); DP != NULL; DP= readdir(DIRP))
- fprintf(stdout, "%s\n", DP->d_name);
- closedir(DIRP);
- exit(0);
- break;
- case 'v': /* Set the verbose mode */
- VERBOSE++;
- break;
- case 'i': /* Set the interactive mode */
- INTERACTIVE++;
- break;
- case 'R': /* Recover a file */
- if(RECURSIVE) /* if recursive point out illegal option
- combination */
- {
- errflag++;
- break;
- }
- /* get name of file to recover */
- strcpy(TEMP, optarg);
- /* does it have a directory in its name ? (it should not) */
- if((ACTNAME = strrchr(TEMP, '/')) != NULL)
- {
- fprintf(stderr, "can: cannot access %s\n", TEMP);
- fprintf(stderr, " no directory names in Recovery\n");
- continue;
- }
- else
- /* name the actual file in the trashcan to get */
- sprintf(FILENAME, "%s/%s", CAN, TEMP);
- /* does it exist in the trashcan */
- if(access(FILENAME, F_OK) != 0)
- {
- fprintf(stderr, "can: %s does not exist\n", TEMP);
- continue;
- }
- /* interogate just in case */
- if (INTERACTIVE)
- {
- fprintf(stdout, "can recover: %s\? ", TEMP);
- fscanf(stdin, "%s", ANSWER);
- if ((ANSWER[0] != 'y') && (ANSWER[0] != 'Y'))
- continue;
- }
- /* get rid of file if it exists in current directory */
- if (access(TEMP, F_OK) == 0)
- if (unlink(TEMP) != 0)
- {
- perror("can");
- continue;
- }
- /* get a new copy of the file into the working directory */
- if (link(FILENAME, TEMP) != 0)
- {
- perror("can");
- continue;
- }
- /* say it has been recycled */
- fprintf(stdout, "%s: recovered\n", TEMP);
- exit(0);
- break;
- case 'r': /* Let's get recursive */
- RECURSIVE++;
- break;
- default: /* Errors in bad options */
- errflag++;
- break;
- }
-
- /* say if there are some bad options */
- if(errflag)
- {
- fprintf(stderr, "%s\n", USAGE);
- exit(2);
- }
-
- /* get the current time */
- if((TIME =time(0)) == 0)
- {
- perror("can");
- exit(2);
- }
- /* step through the arguments to see what to get rid of */
- for( ; optind < argc; optind++)
- {
- strcpy(TEMP, argv[optind]); /* get the next argument */
- stat(TEMP, &BUF); /* get file info about this file */
- /* Check for the existence of a file that is not a directory */
- if ((access(TEMP, F_OK) == 0) && (!(BUF.st_mode & 0040000)))
- {
- /* interogate */
- if(INTERACTIVE != 0)
- {
- fprintf(stdout, "can %s\? ", TEMP);
- fscanf(stdin, "%s", ANSWER);
- if((ANSWER[0] != 'y') && (ANSWER[0] != 'Y'))
- continue;
- }
- /* strip off directory names so we can trash it properly */
- if((ACTNAME = strrchr(TEMP, '/')) != NULL)
- sprintf(FILENAME, "%s%s", CAN, ACTNAME);
- else
- sprintf(FILENAME, "%s/%s", CAN, TEMP);
- /* if it exists in the trashcan already get rid of it */
- if (access(FILENAME, F_OK) == 0)
- if(unlink(FILENAME) != 0)
- {
- perror("can3");
- continue;
- }
- /* put it in the trashcan */
- if(link(TEMP, FILENAME) != 0)
- {
- switch(errno)
- {
- case EXDEV:
- crossdevcan(TEMP, FILENAME);
- break;
- default:
- perror("can1");
- continue;
- }
- }
- /* get rid of the original */
- if(unlink(TEMP) != 0)
- {
- perror("can4");
- continue;
- }
- /* change the access time */
- TIMES.actime= (time_t)TIME;
- TIMES.modtime= BUF.st_mtime;
- if(utime(FILENAME, &TIMES) != 0)
- {
- perror("can5");
- continue;
- }
- /* tell them what we did if they want to know */
- if(VERBOSE)
- fprintf(stdout, "%s: canned\n", TEMP);
- }
- else
- {
- /* is this a directory? */
- if(BUF.st_mode & 0040000)
- {
- if(RECURSIVE == 0) /* yes, then do recursion if OK */
- fprintf(stderr, "cannot can: %s directory\n", TEMP);
- else
- {
- if(INTERACTIVE != 0)
- {
- fprintf(stdout, "can check %s directory\? ", TEMP);
- fscanf(stdin, "%s", ANSWER);
- if((ANSWER[0] != 'y') && (ANSWER[0] != 'Y'))
- continue;
- }
- recurcan(TEMP);
- }
- }
- else /* the file does not exist */
- perror("can6");
- }
- }
- }
-