home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1988 / 07 / c_chest / c_chest.lst
File List  |  1988-04-25  |  12KB  |  394 lines

  1.               Listing 1 -- shellarc.c, Printed 4/24/1988
  2.    ________________________________________________________________
  3.   1| #include <stdio.h>
  4.   2| #include <ctype.h>
  5.   3| #include <tools/getargs.h>
  6.   4| 
  7.   5| /*------------------------------------------------------------
  8.   6|  * SHELLARC.C   This program manufactures a shell archive.
  9.   7|  *              Usage is:
  10.   8|  *                      shellarc [-ffile] [-q] names...
  11.   9|  *
  12.  10|  * if -f is specified, the rest of the command line is ignored
  13.  11|  * and file names are taken from the indicated file, otherwise
  14.  12|  * filenames are taken from the command line.
  15.  13|  * The output archive looks like this:
  16.  14|  *
  17.  15|  *      cat >file <<"END-OF-FILE--END-OF-FILE--END-OF-FILE"
  18.  16|  *      <contents of file>
  19.  17|  *      "END-OF-FILE--END-OF-FILE--END-OF-FILE"
  20.  18|  *
  21.  19|  * Lines (or command-line arguments) that start with a = are
  22.  20|  * written to the output file in the corresponding place.
  23.  21|  * For example, the list:
  24.  22|  *
  25.  23|  *              file1
  26.  24|  *              = mkdir foo
  27.  25|  *              foo/file2
  28.  26|  *
  29.  27|  * comes out as follows:
  30.  28|  *
  31.  29|  *   cat >file1 <<"END-OF-FILE--END-OF-FILE--END-OF-FILE"
  32.  30|  *   <contents of file1>
  33.  31|  *   "END-OF-FILE--END-OF-FILE--END-OF-FILE"
  34.  32|  *   mkdir foo
  35.  33|  *   cat >foo/file2 <<"END-OF-FILE--END-OF-FILE--END-OF-FILE"
  36.  34|  *   <contents of foo/file2>
  37.  35|  *   "END-OF-FILE--END-OF-FILE--END-OF-FILE"
  38.  36|  *
  39.  37|  * The = sign and any trailing whitespaces is removed.
  40.  38|  *
  41.  39|  * If -q is specified, the quotes are omitted from the 
  42.  40|  * END-OF-FILE... In this case the shell will expand shell
  43.  41|  * varaibles, etc, that are present in the file.
  44.  42|  *------------------------------------------------------------
  45.  43|  */
  46.  44| 
  47.  45| char    **Argv  = NULL ;
  48.  46| int     Argc    = 0 ;
  49.  47| FILE    *Fd     = NULL ;
  50.  48| int     Noquote = 0 ;
  51.  49| void    get_file();
  52.  50| int     Dodot = 0;
  53.  51| 
  54.  52| #define NOQUOTE_MARK "END-OF-FILE--END-OF-FILE--END-OF-FILE"
  55.  53| #define NORM_MARK    "\"END-OF-FILE--END-OF-FILE--END-OF-FILE\""
  56.  54| #define BUFSIZE      1024
  57.  55| 
  58.  56| ARG     Argtab[] =
  59.  57| {
  60.  58| {'f',PROC,   (int *)get_file,"Use <str> as command file"        },
  61.  59| {'q',BOOLEAN,&Noquote,       "Expand shell vars on dearchiving" },
  62.  60| {'.',BOOLEAN,&Dodot,         "precede all file names with a dot"}
  63.  61| };
  64.  62| 
  65.  63| static char *Usage_msg[] =
  66.  64| {
  67.  65| "",
  68.  66| "Shellarc makes a shell archive by concatenating together the",
  69.  67| "files listed on the command line (or in the command file) with",
  70.  68| "interspersed shell directives so that, when the output file is",
  71.  69| "run, it will unpack itself. For example, shellarc \"=mkdir test\"",
  72.  70| "test/file1 test/file2 sends the following to standard output:",
  73.  71| "",
  74.  72| "\tmkdir test",
  75.  73| "\tcat >test/file1 <<\"END-OF-FILE--END-OF-FILE--END-OF-FILE\"",
  76.  74| "\t<contents of test/file1>",
  77.  75| "\t\"END-OF-FILE--END-OF-FILE--END-OF-FILE\"",
  78.  76| "\tcat >test/file2 <<\"END-OF-FILE--END-OF-FILE--END-OF-FILE\"",
  79.  77| "\t<contents of test/file2>",
  80.  78| "\t\"END-OF-FILE--END-OF-FILE--END-OF-FILE\"",
  81.  79| "",
  82.  80| "Arguments that begin with = are just written to the output",
  83.  81| "file in the place coresponding to the position on the command",
  84.  82| "line (with the = stripped. -q removes the quotes from the",
  85.  83| "END-OF-FILE... string. -f causes commands to be taken from the",
  86.  84| "file instead of the command line, one file name or = command",
  87.  85| "per line",
  88.  86| NULL
  89.  87| };
  90.  88| 
  91.  89| /*------------------------------------------------------------*/
  92.  90| 
  93.  91| usage()
  94.  92| {
  95.  93|     char **p;
  96.  94|     for( p = Usage_msg; *p; puts(*p++) )
  97.  95|         ;
  98.  96| 
  99.  97|     exit( 1 );
  100.  98| }
  101.  99| 
  102. 100| /*------------------------------------------------------------*/
  103. 101| 
  104. 102| void    get_file( name )
  105. 103| char    *name;
  106. 104| {
  107. 105|     /* Open a file and exit if you can't */
  108. 106| 
  109. 107|     if( !(Fd = fopen(name,"r") ))
  110. 108|     {
  111. 109|         perror( name );
  112. 110|         exit( 1 );
  113. 111|     }
  114. 112| }
  115. 113| 
  116. 114| /*------------------------------------------------------------*/
  117. 115| 
  118. 116| char    *nextline( buf, n )
  119. 117| char    *buf;
  120. 118| {
  121. 119|     /* Get the next input line of the description file. Get the
  122. 120|      * line either from a file specified with -f on the command
  123. 121|      * line (if Fd is NULL), or from the command line itself (if
  124. 122|      * it's not). Return NULL at ten of file, the buf argument
  125. 123|      * otherwise.
  126. 124|      */
  127. 125| 
  128. 126|     char *rval;
  129. 127| 
  130. 128|     if( Fd )
  131. 129|     {
  132. 130|         if( rval = fgets( buf, n, Fd ) )
  133. 131|             buf[ strlen(buf) - 1 ] = '\0' ; /* Overwrite \n */
  134. 132| 
  135. 133|         return rval;
  136. 134|     }
  137. 135|     else if( --Argc )
  138. 136|     {
  139. 137|         strncpy( buf, *++Argv, n );
  140. 138|         return buf;
  141. 139|     }
  142. 140|     else
  143. 141|         return NULL;
  144. 142| }
  145. 143| 
  146. 144| /*------------------------------------------------------------*/
  147. 145| 
  148. 146| main( argc, argv )
  149. 147| char    **argv;
  150. 148| {
  151. 149|     char        *mark = NORM_MARK ;
  152. 150|     FILE        *ifile;
  153. 151|     static char buf[ BUFSIZE ];
  154. 152|     char        *p;
  155. 153|     char        *dot = "";
  156. 154| 
  157. 155|     reargv( &argc, &argv );
  158. 156| 
  159. 157|     Argc = getargs( argc, argv, Argtab,
  160. 158|                         sizeof(Argtab)/sizeof(ARG), usage );
  161. 159|     Argv = argv;
  162. 160| 
  163. 161|     if( Noquote )
  164. 162|         mark = NOQUOTE_MARK ;
  165. 163| 
  166. 164|     if( Dodot )
  167. 165|         dot = "." ;
  168. 166|            
  169. 167|     printf("#\n");            /* Make this a C-shell script */
  170. 168| 
  171. 169|     while( nextline( buf, BUFSIZE ) )
  172. 170|     {
  173. 171|         if( *buf == '=' )
  174. 172|         {
  175. 173|             for(p = buf + 1; isspace( *p ) ; ++p )
  176. 174|                 ;
  177. 175|             puts( p );
  178. 176|         }
  179. 177|         else
  180. 178|         {
  181. 179|             if( !(ifile = fopen(buf, "r")) )
  182. 180|                 perror( buf );
  183. 181|             else
  184. 182|             {
  185. 183|                 fprintf( stderr, "%s:\n", buf );
  186. 184|                 printf ("echo Unarchiving %s%s\n", dot, buf );
  187. 185|                 printf ("cat >%s%s <<%s\n",   dot, buf, mark );
  188. 186| 
  189. 187|                 while( fgets(buf, BUFSIZE, ifile) )
  190. 188|                     fputs( buf, stdout );
  191. 189| 
  192. 190|                 fclose( ifile );
  193. 191|                 puts( mark );
  194. 192|             }
  195. 193|         }
  196. 194|     }
  197. 195| }
  198.                Listing 2 -- exp-arc.c, Printed 4/24/1988
  199.    ________________________________________________________________
  200.   1| #include <stdio.h>
  201.   2| #include <stdlib.h>
  202.   3| #include <ctype.h>
  203.   4| #include <io.h>         /* prototype for mktemp()            */
  204.   5| 
  205.   6| #define MAXARRAY 256    /* Maximum input line size           */
  206.   7| #define REDIR   0       /* return value from extract_stuff() */
  207.   8| #define NOREDIR 1       /* "                                 */
  208.   9| 
  209.  10| /*------------------------------------------------------------*/
  210.  11| 
  211.  12| char    *do_input( word, echo, tname, inp )
  212.  13| char    *word;          /* Terminal string              */
  213.  14| int     echo;           /* echo file to stdout if true  */
  214.  15| FILE    *inp;           /* input stream                 */
  215.  16| {
  216.  17|     /* Read lines from "inp" up to "word" into a temporary
  217.  18|      * file, then close the temporary file, and return its name.
  218.  19|      */
  219.  20| 
  220.  21|     char *temp_name;
  221.  22|     static char template[ 16 ];
  222.  23| 
  223.  24|     FILE *tfile;        /* FILE pointer to temporary file */
  224.  25|     char buf[256];      /* Input line buffer.             */
  225.  26| 
  226.  27|     strcpy(template,"eaXXXXXX");
  227.  28|     if( (temp_name = mktemp(template)) == NULL )
  228.  29|     {
  229.  30|         fprintf(stderr,"Can't make temporary file name\n");
  230.  31|         exit(1);
  231.  32|     }
  232.  33| 
  233.  34|     if( !(tfile = fopen( temp_name, "w" )) )
  234.  35|     {
  235.  36|         perror( temp_name );
  236.  37|         exit(1);
  237.  38|     }
  238.  39| 
  239.  40|     while( fgets(buf, sizeof(buf), inp) )
  240.  41|     {
  241.  42|         if( strcmp(buf, word) == 0 )
  242.  43|             break;
  243.  44| 
  244.  45|         if( echo )
  245.  46|             fprintf( stderr, "<< %s", buf );
  246.  47| 
  247.  48|         fputs( buf,  tfile );
  248.  49|     }
  249.  50| 
  250.  51|     fclose( tfile );
  251.  52|     return temp_name ;
  252.  53| }
  253.  54| 
  254.  55| /*------------------------------------------------------------*/
  255.  56| 
  256.  57| usage()
  257.  58| {
  258.  59|     fprintf(stderr, "Usage:     exp-arc [-e] archive...\n\n");
  259.  60|     fprintf(stderr, "Expand a UNIX shell archive.\n");
  260.  61|     fprintf(stderr, "-e to print expanded files to stderr\n");
  261.  62|     exit( 1 );
  262.  63| }
  263.  64| 
  264.  65| /*------------------------------------------------------------*/
  265.  66| 
  266.  67| main( argc, argv )
  267.  68| char    **argv;
  268.  69| {
  269.  70|     /* Usage:   exp-arc [-e] archive_file...
  270.  71|      *
  271.  72|      *  Expand a UNIX shell archive.
  272.  73|      *  -e to print files to standard error as they're expanded
  273.  74|      */
  274.  75| 
  275.  76|     int         echo = 0;
  276.  77|     int         i;
  277.  78|     char        *temp_name;
  278.  79|     FILE        *archive;
  279.  80|     char        *word;
  280.  81|     static char command[ MAXARRAY ];
  281.  82| 
  282.  83|     ++argv;
  283.  84|     --argc;
  284.  85| 
  285.  86|     if( argc && argv[0][0] == '-' )
  286.  87|     {
  287.  88|         if( argv[0][1] == 'e' )
  288.  89|             echo = 1;
  289.  90|         else
  290.  91|             usage();
  291.  92| 
  292.  93|         --argc ;
  293.  94|         ++argv ;
  294.  95|     }
  295.  96| 
  296.  97|     if( argc == 0 )
  297.  98|         usage();
  298.  99| 
  299. 100|     for( ; --argc >= 0; ++argv )
  300. 101|     {
  301. 102|         if( !(archive = fopen(*argv, "r")) )
  302. 103|         {
  303. 104|             perror( *argv );
  304. 105|             exit(1);
  305. 106|         }
  306. 107| 
  307. 108|         while((i = extract_stuff(command,&word,archive)) != EOF)
  308. 109|         {
  309. 110|             if( i == NOREDIR )
  310. 111|                 system( command );
  311. 112|             else
  312. 113|             {
  313. 114|                 temp_name=do_input(word,echo,temp_name,archive);
  314. 115| 
  315. 116|                 if( !freopen( temp_name, "r", stdin )  )
  316. 117|                 {
  317. 118|                     perror( temp_name );
  318. 119|                     exit(1);
  319. 120|                 }
  320. 121| 
  321. 122|                 system( command );
  322. 123| 
  323. 124|                 freopen( "con:", "r", stdin );
  324. 125|                 unlink ( temp_name );
  325. 126|             }
  326. 127|         }
  327. 128| 
  328. 129|         fclose( archive );
  329. 130|     }
  330. 131| }
  331. 132| 
  332. 133| /*------------------------------------------------------------*/
  333. 134| 
  334. 135| int     extract_stuff( command, word, inp )
  335. 136| char    *command;
  336. 137| char    **word;
  337. 138| FILE    *inp;
  338. 139| {
  339. 140|     /* Read a line of input. If it takes the form:
  340. 141|      *
  341. 142|      *          cat >file <<pattern
  342. 143|      *
  343. 144|      * put everything up to the << into "command."
  344. 145|      * Modify *word to point at word. That is,
  345. 146|      * given the previous line, command will
  346. 147|      * hold "cat >file" and word will hold
  347. 148|      * "pattern". The space to the right of
  348. 149|      * the 'e' in file will be replaced with a
  349. 150|      * '\0'. Return REDIR in this case.
  350. 151|      * If the "cat," the >, or the << is
  351. 152|      * missing, put the entire line into command
  352. 153|      * and return NOREDIR. Return EOF at end of
  353. 154|      * file.
  354. 155|      */
  355. 156| 
  356. 157|     char        *p, *endp;
  357. 158| 
  358. 159|     if( ! fgets(command,MAXARRAY,inp) )
  359. 160|         return EOF;
  360. 161| 
  361. 162|     for( p = command; isspace(*p) ; ++p )
  362. 163|         ;
  363. 164| 
  364. 165|     if( !(p[0]=='c' && p[1]=='a' && p[2]=='t' ) )
  365. 166|         return NOREDIR;
  366. 167| 
  367. 168|     for( p += 3; isspace(*p) ; ++p )
  368. 169|         ;
  369. 170| 
  370. 171|     if( p[0] != '>' )
  371. 172|         return NOREDIR;
  372. 173|     
  373. 174|     for( ++p; isspace(*p); ++p )
  374. 175|         ;
  375. 176|         
  376. 177|     while( *p && !isspace(*p) )
  377. 178|         ++p;
  378. 179|     endp = p;                   /* Just remember it for now */
  379. 180| 
  380. 181|     for(; isspace(*p); ++p )
  381. 182|         ;
  382. 183|     
  383. 184|     if( !(p[0]=='<' && p[1]=='<') )
  384. 185|         return NOREDIR;
  385. 186| 
  386. 187|     for( p += 2 ; isspace(*p); ++p )
  387. 188|         ;
  388. 189| 
  389. 190|     *endp = '\0';               /* Now terminate it */
  390. 191|     *word = p ;
  391. 192|     return REDIR;
  392. 193| }
  393.  
  394.