home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume3 / can2 / can.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-03  |  6.8 KB  |  253 lines

  1. /*************************************************************
  2. *    can.c    2.0
  3. *
  4. *    This is a utility to replace rm.  I hope you like it
  5. *
  6. *    written by "the bit butcher"
  7. *
  8. *    2.02 changed the error handling to cases and segmented the
  9. *         program into three pieces and now have "can.h"
  10. *            28 June 1988
  11. *
  12. *    2.01 changed the way cross device problems are dealt with
  13. *        copy file from one system to the other
  14. *            before 28 June 1988
  15. *************************************************************/
  16.  
  17. #include "can.h"
  18.  
  19. char CAN[MAXPATHLEN];    /* String containing .trashcan directory*/    
  20. char ANSWER[14];        /* String used for finding interactive response */
  21. int VERBOSE = 0;            /* Set if Verbose is wanted */
  22. int INTERACTIVE = 0;            /* Set if Interactive is wanted */
  23. long TIME;        /* Used to get the current time */
  24. UTIMBUF TIMES;    /* Structure used to change the access time */
  25.  
  26. main(argc, argv)
  27. int argc;
  28. char** argv;
  29. {
  30.     int c;                        /* which character in getopt */
  31.     DIR *DIRP;        /* Used to list the directory by pointing at .trashcan */
  32.     struct direct *DP;    /* Used to point at consecutive entries when listing */
  33.     char FILENAME[MAXPATHLEN];    /* String containing .trashcan/current file*/    
  34.     char *ACTNAME;        /* Points to filename without any leading directory */
  35.     struct stat BUF;    /* Used to point to mode info about files */
  36.     int RECURSIVE = 0;            /* Set if Recursive is wanted */
  37. #ifdef SYSV
  38.     int UID;    /* Variable holding user's ID */
  39. #endif
  40. #ifdef SUN
  41.     int UID;    /* Variable holding user's ID */
  42. #endif
  43. #ifdef BSD
  44.     uid_t UID;    /* Variable holding user's ID */
  45. #endif
  46.     char TEMP[MAXPATHLEN];    /* Used for quick access of file names */
  47.     struct passwd *USERINFO;    /* Structure used to find out $HOME dir */
  48.     extern int optind;    /* used to step through arguments */
  49.     extern char *optarg;    /* used to step through arguments */
  50.     int    errflag = 0;    /* Used to indicate errors in options */
  51.     void recurcan();    /* Say this is a void function */
  52.  
  53.     /* Find out the users ID */
  54.     if((UID= getuid()) == NULL)
  55.     {
  56.         fprintf(stderr, "Invalid Login: Who Are You!?!\n");
  57.         exit(0);
  58.     }
  59.  
  60.     /* Get his home directory from the passwd file */
  61.     USERINFO = getpwuid(UID);
  62.     if(USERINFO->pw_dir == NULL)
  63.     {
  64.         fprintf(stderr, "No Home Directory: check /etc/passwd !!!\n");
  65.         exit(0);
  66.     }
  67.     /*  say where the trashcan will be */
  68.     sprintf(CAN, "%s/.trashcan", USERINFO->pw_dir);
  69.  
  70.     /* make sure there is a trashcan */
  71.     if (access(CAN, F_OK) != 0)
  72.         /* if not, make a trashcan */
  73.         if(mkdir(CAN, 004777) != 0)
  74.         {
  75.             perror("can");
  76.             exit(2);
  77.         }
  78.  
  79.     /* could add force (-f) option later, perhaps */
  80.     /* Let's look at the options */
  81.     while((c=getopt(argc, argv, "ivlR:r")) != EOF)
  82.         switch(c)
  83.         {
  84.             case 'l':    /* list the contents by stepping through */
  85.                 fprintf(stdout, "%s\n", CAN);
  86.                 DIRP = opendir(CAN);
  87.         /* Could allow arguments for selective listing */
  88.                 for(DP = readdir(DIRP); DP != NULL; DP= readdir(DIRP))
  89.                     fprintf(stdout, "%s\n", DP->d_name);
  90.                 closedir(DIRP);
  91.                 exit(0);
  92.                 break;
  93.             case 'v':    /* Set the verbose mode */
  94.                 VERBOSE++;
  95.                 break;
  96.             case 'i':    /* Set the interactive mode */
  97.                 INTERACTIVE++;
  98.                 break;
  99.             case 'R':    /* Recover a file */
  100.                 if(RECURSIVE)    /* if recursive point out illegal option 
  101.                                 combination */
  102.                 {
  103.                     errflag++;
  104.                     break;
  105.                 }
  106.                 /* get name of file to recover */
  107.                 strcpy(TEMP, optarg);
  108.                 /* does it have a directory in its name ? (it should not) */
  109.                 if((ACTNAME = strrchr(TEMP, '/')) != NULL)
  110.                 {
  111.                     fprintf(stderr, "can: cannot access %s\n", TEMP);
  112.                     fprintf(stderr, "    no directory names in Recovery\n");
  113.                     continue;
  114.                 }
  115.                 else
  116.                     /* name the actual file in the trashcan to get */
  117.                     sprintf(FILENAME, "%s/%s", CAN, TEMP);
  118.                 /* does it exist in the trashcan */
  119.                 if(access(FILENAME, F_OK) != 0)
  120.                 {
  121.                     fprintf(stderr, "can: %s does not exist\n", TEMP);
  122.                     continue;
  123.                 }
  124.                 /* interogate just in case */
  125.                 if (INTERACTIVE)
  126.                 {
  127.                     fprintf(stdout, "can recover: %s\? ", TEMP);
  128.                     fscanf(stdin, "%s", ANSWER);
  129.                     if ((ANSWER[0] != 'y') && (ANSWER[0] != 'Y'))
  130.                         continue;
  131.                 }
  132.                 /* get rid of file if it exists in current directory */
  133.                 if (access(TEMP, F_OK) == 0)
  134.                     if (unlink(TEMP) != 0)
  135.                     {
  136.                         perror("can");
  137.                         continue;
  138.                     }
  139.                 /* get a new copy of the file into the working directory */
  140.                 if (link(FILENAME, TEMP) != 0)
  141.                 {
  142.                     perror("can");
  143.                     continue;
  144.                 }
  145.                 /* say it has been recycled */
  146.                 fprintf(stdout, "%s: recovered\n", TEMP);
  147.                 exit(0);
  148.                 break;
  149.             case 'r':    /* Let's get recursive */
  150.                 RECURSIVE++;
  151.                 break;
  152.             default:    /* Errors in bad options */
  153.                 errflag++;
  154.                 break;
  155.         }
  156.  
  157.         /* say if there are some bad options */
  158.         if(errflag)
  159.         {
  160.             fprintf(stderr, "%s\n", USAGE);
  161.             exit(2);
  162.         }
  163.  
  164.         /* get the current time */
  165.         if((TIME =time(0)) == 0)
  166.         {
  167.             perror("can");
  168.             exit(2);
  169.         }
  170.         /* step through the arguments to see what to get rid of */
  171.         for( ; optind < argc; optind++)
  172.         {
  173.             strcpy(TEMP, argv[optind]);    /* get the next argument */
  174.             stat(TEMP, &BUF);    /* get file info about this file */
  175.             /* Check for the existence of a file that is not a directory */
  176.             if ((access(TEMP, F_OK) == 0) && (!(BUF.st_mode & 0040000)))
  177.             {
  178.                 /* interogate */
  179.                 if(INTERACTIVE != 0)
  180.                 {
  181.                     fprintf(stdout, "can %s\? ", TEMP);
  182.                     fscanf(stdin, "%s", ANSWER);
  183.                     if((ANSWER[0] != 'y') && (ANSWER[0] != 'Y'))
  184.                         continue;
  185.                 }
  186.                 /* strip off directory names so we can trash it properly */
  187.                 if((ACTNAME = strrchr(TEMP, '/')) != NULL)
  188.                     sprintf(FILENAME, "%s%s", CAN, ACTNAME);
  189.                 else
  190.                     sprintf(FILENAME, "%s/%s", CAN, TEMP);
  191.                 /* if it exists in the trashcan already get rid of it */
  192.                 if (access(FILENAME, F_OK) == 0)
  193.                     if(unlink(FILENAME) != 0)
  194.                     {
  195.                         perror("can3");
  196.                         continue;
  197.                     }
  198.                 /* put it in the trashcan */
  199.                 if(link(TEMP, FILENAME) != 0)
  200.                 {
  201.                     switch(errno)
  202.                     {
  203.                         case EXDEV:
  204.                             crossdevcan(TEMP, FILENAME);
  205.                             break;
  206.                         default:
  207.                             perror("can1");
  208.                             continue;
  209.                     }
  210.                 }
  211.                 /* get rid of the original */
  212.                 if(unlink(TEMP) != 0)
  213.                 {
  214.                     perror("can4");
  215.                     continue;
  216.                 }
  217.                 /* change the access time */
  218.                 TIMES.actime= (time_t)TIME;
  219.                 TIMES.modtime= BUF.st_mtime;
  220.                 if(utime(FILENAME, &TIMES) != 0)
  221.                 {
  222.                     perror("can5");
  223.                     continue;
  224.                 }
  225.                 /* tell them what we did if they want to know */
  226.                 if(VERBOSE)
  227.                     fprintf(stdout, "%s: canned\n", TEMP);
  228.             }
  229.             else
  230.             {
  231.                 /* is this a directory? */
  232.                 if(BUF.st_mode & 0040000)
  233.                 {
  234.                     if(RECURSIVE == 0) /* yes, then do recursion if OK */
  235.                         fprintf(stderr, "cannot can: %s directory\n", TEMP);
  236.                     else
  237.                     {
  238.                         if(INTERACTIVE != 0)
  239.                         {
  240.                             fprintf(stdout, "can check %s directory\? ", TEMP);
  241.                             fscanf(stdin, "%s", ANSWER);
  242.                             if((ANSWER[0] != 'y') && (ANSWER[0] != 'Y'))
  243.                                 continue;
  244.                         }
  245.                         recurcan(TEMP);
  246.                     }
  247.                 }
  248.                 else    /* the file does not exist */
  249.                     perror("can6");
  250.             }
  251.         }
  252. }
  253.