home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / WATTCP / PISA_TAR.TAR / tar / oldrtar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-22  |  11.8 KB  |  521 lines

  1. /******************************************************************************
  2.  
  3.     RTAR - remotely execute a TAR command
  4.  
  5.     Copyright (C) 1991, University of Waterloo
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it, but you may not sell it.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but without any warranty; without even the implied warranty of
  12.     merchantability or fitness for a particular purpose.
  13.  
  14.         Giovanni Mercaldo 
  15.         Faculty of Engineering
  16.         University of Pisa 
  17.         
  18. ******************************************************************************/
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <time.h>        /* for randomize */
  22. #include <stdlib.h>
  23. #include <conio.h>        /* for getpass */
  24. #include <sys/types.h>        /* Needed for typedefs in tar.h */
  25.  
  26. /* extern char     *malloc(); */
  27. extern char    *strncpy();
  28. extern char    *optarg;    /* Pointer to argument */
  29. extern int    optind;        /* Global argv index from getopt */
  30.  
  31.  
  32. /*
  33.  * The following causes "tar.h" to produce definitions of all the
  34.  * global variables, rather than just "extern" declarations of them.
  35.  */
  36. #define TAR_EXTERN /**/
  37. #include <tar.h>
  38.  
  39. /*
  40.  * We should use a conversion routine that does reasonable error
  41.  * checking -- atoi doesn't.  For now, punt.  FIXME.
  42.  */
  43. #define intconv    atoi
  44. extern int    getoldopt();
  45. extern void    read_and();
  46. extern void    list_archive();
  47. extern void    extract_archive();
  48. extern void    create_archive();
  49.  
  50. static FILE    *namef;        /* File to read names from */
  51. static char    **n_argv;    /* Argv used by name routines */
  52. static int    n_argc;    /* Argc used by name routines */
  53.             /* They also use "optind" from getopt(). */
  54.  
  55. void    describe();
  56.  
  57. help()
  58. {
  59.     puts("RTAR options filename [host [username [password]]] ");
  60.     puts("The values for cmdstring should be placed inside quotes");
  61.     exit( 3 );
  62. }
  63.  
  64. /*
  65.  * A public domain tar(1) program.
  66.  * 
  67.  * Written by John Gilmore, ihnp4!hoptoad!gnu, starting 25 Aug 85.
  68.  *
  69.  * @(#)tar.c 1.21 10/29/86 Public Domain - gnu
  70.  * 
  71.  * and modified by G.Mercaldo 9-Apr-92
  72.  *
  73.  * Main routine for tar.
  74.  */
  75. main(argc, argv)
  76.     int    argc;
  77.     char    **argv;
  78. {
  79.     hostname = name = pass = NULL;
  80.  
  81.     tar = "tar";        /* Set program name */
  82.  
  83.     options(argc, argv);
  84.  
  85.     if (f_remote) {    
  86.         dbuginit();
  87.         sock_init();
  88.     }
  89.  
  90.     name_init(argc, argv);
  91.  
  92.     if (f_create) {
  93.         if (f_remote) goto errflags; 
  94.         if (f_extract || f_list) goto dupflags;
  95.         create_archive();
  96.     } else if (f_extract) {
  97.         if (f_list) goto dupflags;
  98.         read_and(extract_archive);
  99.     } else if (f_list) {
  100.         read_and(list_archive);
  101.     } else {
  102. dupflags:
  103.         fprintf (stderr,
  104. "tar: you must specify exactly one of the c, t, or x options\n");
  105.         describe();
  106.         exit(EX_ARGSBAD);
  107. errflags:
  108.         fprintf (stderr,
  109. "tar: you can't specify the c option! \n");
  110.         describe();
  111.         exit(EX_ARGSBAD);
  112.     }
  113.     exit(0);
  114. }
  115.  
  116.  
  117. /*
  118.  * Parse the options for tar.
  119.  */
  120. int
  121. options(argc, argv)
  122.     int    argc;
  123.     char    **argv;
  124. {
  125.     register int    c;        /* Option letter */
  126.  
  127.     /* Set default option values */
  128.     blocking = DEFBLOCKING;        /* From Makefile */
  129. #ifdef    DEF_AR_FILE
  130.     ar_file = "null";        /* From Makefile */
  131. #else
  132.     ar_file = "/dev/null";
  133. #endif
  134.  
  135.     /* Parse options */
  136.     while ((c = getoldopt(argc, argv, "a:b:BcdDf:hikmoprqstT:vxXzZ")
  137.         ) != EOF) {
  138.         switch (c) {
  139.  
  140. #ifdef    DUMPTIME
  141.         case 'a':
  142.             time(&dumptime);
  143.             dumptime -= (long)intconv(optarg) * 60L * 60L * 24L;
  144.             break;
  145. #endif
  146.  
  147.         case 'b':
  148.             blocking = intconv(optarg);
  149.             break;
  150.  
  151.         case 'B':
  152.             f_reblock++;        /* For reading 4.2BSD pipes */
  153.             break;
  154.  
  155.         case 'c':
  156.             f_create++;
  157.             break;
  158.  
  159.         case 'd':
  160.             f_debug++;        /* Debugging code */
  161.             break;            /* Yes, even with dbx */
  162.  
  163.         case 'D':
  164.             f_sayblock++;        /* Print block #s for debug */
  165.             break;            /* of bad tar archives */
  166.  
  167.         case 'f':
  168.             ar_file = optarg;
  169.             break;
  170.  
  171.         case 'h':
  172.             f_follow_links++;    /* follow symbolic links */
  173.             break;
  174.  
  175.         case 'i':
  176.             f_ignorez++;        /* Ignore zero records (eofs) */
  177.             /*
  178.              * This can't be the default, because Unix tar
  179.              * writes two records of zeros, then pads out the
  180.              * block with garbage.
  181.              */
  182.             break;
  183.  
  184.         case 'k':            /* Don't overwrite files */
  185.             f_keep++;
  186.             break;
  187.  
  188.         case 'm':
  189.             f_modified++;
  190.             break;
  191.  
  192.         case 'o':            /* Generate old archive */
  193.             f_oldarch++;
  194.             break;
  195.  
  196.         case 'p':
  197.             f_use_protection++;
  198.             (void)umask(0);        /* Turn off kernel "help" */
  199.             break;
  200.  
  201.         case 'q':
  202.             f_use_zcat++;
  203.             f_compress++;
  204.             break;
  205.  
  206.         case 'r':
  207.             f_remote++;
  208.             break;
  209.  
  210.         case 's':
  211.             f_sorted_names++;    /* Names to extr are sorted */
  212.             break;
  213.  
  214.         case 't':
  215.             f_list++;
  216.             break;
  217.  
  218.         case 'T':
  219.             name_file = optarg;
  220.             f_namefile++;
  221.             break;
  222.  
  223.         case 'v':
  224.             f_verbose++;
  225.             break;
  226.  
  227.         case 'x':
  228.             f_extract++;
  229.             break;
  230.  
  231. #ifdef    XBUF
  232.         case 'X':
  233.             f_xbuf++;
  234.             break;
  235. #endif
  236.  
  237.         case 'z':        /* Easy to type */
  238.         case 'Z':        /* Like the filename extension .Z */
  239.             if ( f_use_zcat ) break;
  240.             f_compress++;
  241.             break;
  242.  
  243.         case '?':
  244.             help();
  245.             describe();
  246.             exit(EX_ARGSBAD);
  247.  
  248.         }
  249.     }
  250.  
  251.     blocksize = blocking * RECORDSIZE;
  252. }
  253.  
  254.  
  255. /* FIXME, describe tar options here */
  256. void
  257. describe()
  258. {
  259.  
  260.     fputs("tar: valid options:\n\
  261. -b N    blocking factor N (block size = Nx512 bytes)\n\
  262. -B    reblock as we read (for reading 4.2BSD pipes)\n\
  263. -c    create an archive\n\
  264. -D    dump record number within archive with each message\n\
  265. -f F    read/write archive from file or device F\n\
  266.     REMEMBER! This one MUST be last option given!\n\
  267. -h    don't dump symbolic links; dump the files they point to\n\
  268. -i    ignore blocks of zeros in the archive, which normally mean EOF\n\
  269. -k    keep existing files, don't overwrite them from the archive\n\
  270. -m    don't extract file modified time\n", stderr);
  271.     fputs("\
  272. -o    write an old V7 format archive, rather than ANSI [draft 6] format\n\
  273. -p    do extract all protection information\n\
  274. -q    use remote zcat for .z files\n\
  275. -r    set remote connection\n\
  276. -s    list of names to extract is sorted to match the archive\n\
  277. -t    list a table of contents of an archive\n\
  278. -T F    get names to extract or create from file F\n\
  279. -v    verbosely list what files we process\n\
  280. -x    extract files from an archive\n\
  281. -z or Z    run the archive through compress(1)\n", stderr);
  282. }
  283.  
  284.  
  285. /*
  286.  * Set up to gather file names for tar.
  287.  *
  288.  * They can either come from stdin or from argv.
  289.  */
  290. name_init(argc, argv)
  291.     int    argc;
  292.     char    **argv;
  293. {
  294.  
  295.     if (!(f_remote)) {
  296.     if (f_namefile) {
  297.         if (optind < argc) {
  298.             fprintf(stderr, "tar: too many args with -T option\n");
  299.             exit(EX_ARGSBAD);
  300.         }
  301.         if (!strcmp(name_file, "-")) {
  302.             namef = stdin;
  303.         } else {
  304.             namef = fopen(name_file, "r");
  305.             if (namef == NULL) {
  306.                 fprintf(stderr, "tar: ");
  307.                 perror(name_file);
  308.                 exit(EX_BADFILE);
  309.             }
  310.         }
  311.     } else {
  312.         /* Get file names from argv, after options. */
  313.         n_argc = argc;
  314.         n_argv = argv;
  315.     }
  316.     } else {
  317.         /* char tmp[100] = ""; */
  318.  
  319.         --optind;
  320.         strcpy(cmd,"cat "); 
  321.         if (f_use_zcat) strcpy(cmd,"zcat ");
  322.         strcat (cmd,argv[optind++]);
  323.  
  324.         switch ( argc-optind ) {
  325.                 
  326.             case  3 : hostname = argv[optind++];
  327.                   name = argv[optind++];
  328.                   pass = argv[optind++];
  329.                              break;
  330.             case  2 : hostname = argv[optind++];
  331.                   name = argv[optind++];
  332.                              break;
  333.             case  1 : hostname = argv[optind++];
  334.                              break;
  335.             default : help();
  336.                   exit(EX_ARGSBAD);
  337.             }
  338.      }
  339. }
  340.  
  341. /*
  342.  * Get the next name from argv or the name file.
  343.  *
  344.  * Result is in static storage and can't be relied upon across two calls.
  345.  */
  346. char *
  347. name_next()
  348. {
  349.     static char    buffer[NAMSIZ+2];    /* Holding pattern */
  350.     register char    *p;
  351.     register char    *q;
  352.  
  353.     if (!(f_remote)) {
  354.         if (namef == NULL) {
  355.             /* Names come from argv, after options */
  356.             if (optind < n_argc)
  357.                 return n_argv[optind++];
  358.             return (char *)NULL;
  359.         }
  360.         else p = fgets(buffer, NAMSIZ+1 /*nl*/, namef);
  361.         if (p == NULL) return p;    /* End of file */
  362.         q = p+strlen(p)-1;        /* Find the newline */
  363.         *q-- = '\0';            /* Zap the newline */
  364.         while (*q == '/')  *q-- = '\0';    /* Zap trailing slashes too */
  365.         return p;
  366.     } else return(char *)NULL;
  367. }
  368.  
  369.  
  370. /*
  371.  * Close the name file, if any.
  372.  */
  373. name_close()
  374. {
  375.  
  376.     if (namef != NULL && namef != stdin) fclose(namef);
  377. }
  378.  
  379.  
  380. /*
  381.  * Gather names in a list for scanning.
  382.  * Could hash them later if we really care.
  383.  *
  384.  * If the names are already sorted to match the archive, we just
  385.  * read them one by one.  name_gather reads the first one, and it
  386.  * is called by name_match as appropriate to read the next ones.
  387.  * At EOF, the last name read is just left in the buffer.
  388.  * This option lets users of small machines extract an arbitrary
  389.  * number of files by doing "tar t" and editing down the list of files.
  390.  */
  391. name_gather()
  392. {
  393.     register char *p;
  394.     static struct name namebuf[1];    /* One-name buffer */
  395.  
  396.     if (f_sorted_names) {
  397.         p = name_next();
  398.         if (p) {
  399.             namebuf->length = strlen(p);
  400.             if (namebuf->length >= sizeof namebuf->name) {
  401.                 fprintf(stderr, "Argument name too long: %s\n",
  402.                     p);
  403.                 namebuf->length = (sizeof namebuf->name) - 1;
  404.             }
  405.             strncpy(namebuf->name, p, namebuf->length);
  406.             namebuf->next = (struct name *)NULL;
  407.             namebuf->found = 0;
  408.             namelist = namebuf;
  409.             namelast = namelist;
  410.         }
  411.         return;
  412.     }
  413.  
  414.     /* Non sorted names -- read them all in */
  415.     while (NULL != (p = name_next())) {
  416.         addname(p);
  417.     }
  418. }
  419.  
  420. /*
  421.  * A name from the namelist has been found.
  422.  * If it's just a list, 
  423.  
  424. /*
  425.  * Add a name to the namelist.
  426.  */
  427. addname(name)
  428.     char    *name;            /* pointer to name */
  429. {
  430.     register int    i;        /* Length of string */
  431.     register struct name    *p;    /* Current struct pointer */
  432.  
  433.     i = strlen(name);
  434.     /*NOSTRICT*/
  435.     p = (struct name *)
  436.         malloc((unsigned)(i + sizeof(struct name) - NAMSIZ));
  437.     p->next = (struct name *)NULL;
  438.     p->length = i;
  439.     p->found = 0;
  440.     strncpy(p->name, name, i);
  441.     p->name[i] = '\0';    /* Null term */
  442.     if (namelast) namelast->next = p;
  443.     namelast = p;
  444.     if (!namelist) namelist = p;
  445. }
  446.  
  447.  
  448. /*
  449.  * Match a name from an archive, p, with a name from the namelist.
  450.  *
  451.  * FIXME: Allow regular expressions in the name list.
  452.  */
  453. name_match(p)
  454.     register char *p;
  455. {
  456.     register struct name    *nlp;
  457.     register int        len;
  458.  
  459. again:
  460.     if (0 == (nlp = namelist))    /* Empty namelist is easy */
  461.         return 1;
  462.     len = strlen(p);
  463.     for (; nlp != 0; nlp = nlp->next) {
  464.         if ( nlp->name[0] == p[0]    /* First chars match */
  465.          && nlp->length <= len        /* Archive len >= specified */
  466.          && (p[nlp->length] == '\0' || p[nlp->length] == '/')
  467.                         /* Full match on file/dirname */
  468.          && strncmp(p, nlp->name, nlp->length) == 0) /* Name compare */
  469.         {
  470.             nlp->found = 1;        /* Remember it matched */
  471.             return 1;        /* We got a match */
  472.         }
  473.     }
  474.     /*
  475.      * Filename from archive not found in namelist.
  476.      * If we have the whole namelist here, just return 0.
  477.      * Otherwise, read the next name in and compare it.
  478.      * If this was the last name, namelist->found will remain on.
  479.      * If not, we loop to compare the newly read name.
  480.      */
  481.     if (f_sorted_names && namelist->found) {
  482.         name_gather();        /* Read one more */
  483.         if (!namelist->found) goto again;
  484.     }
  485.     return 0;
  486. }
  487.  
  488.  
  489. /*
  490.  * Print the names of things in the namelist that were not matched.
  491.  */
  492. names_notfound()
  493. {
  494.     register struct name    *nlp;
  495.     register char        *p;
  496.  
  497.     for (nlp = namelist; nlp != 0; nlp = nlp->next) {
  498.         if (!nlp->found) {
  499.             fprintf(stderr, "tar: %s not found in archive\n",
  500.                 nlp->name);
  501.         }
  502.         /*
  503.          * We could free() the list, but the process is about
  504.          * to die anyway, so save some CPU time.  Amigas and
  505.          * other similarly broken software will need to waste
  506.          * the time, though.
  507.          */
  508. #ifndef unix
  509.         if (!f_sorted_names)
  510.             free(nlp);
  511. #endif
  512.     }
  513.     namelist = (struct name *)NULL;
  514.     namelast = (struct name *)NULL;
  515.  
  516.     if (f_sorted_names) {
  517.         while (0 != (p = name_next()))
  518.             fprintf(stderr, "tar: %s not found in archive\n", p);
  519.     }
  520. }
  521.