home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / extra-st / gnu / uuencode.0 / uuencode / uuencode-1.0 / uudecode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-23  |  6.6 KB  |  310 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. /* Reworked to GNU style by Ian Lance Taylor, ian@airs.com, August 93.  */
  35.  
  36. /* AIX requires this to be the first thing in the file.  */
  37. #if defined (_AIX) && !defined (__GNUC__)
  38.  #pragma alloca
  39. #endif
  40.  
  41. /*
  42.  * uudecode [file ...]
  43.  *
  44.  * create the specified file, decoding as you go.
  45.  * used with uuencode.
  46.  */
  47. #include <sys/stat.h>
  48. #include <pwd.h>
  49. #include <stdio.h>
  50. #include "getopt.h"
  51.  
  52. #ifdef    __GNUC__
  53. #undef    alloca
  54. #define    alloca(n)    __builtin_alloca (n)
  55. #else    /* Not GCC.  */
  56. #ifdef    HAVE_ALLOCA_H
  57. #include <alloca.h>
  58. #else    /* Not HAVE_ALLOCA_H.  */
  59. #ifndef    _AIX
  60. extern char *alloca ();
  61. #endif    /* Not AIX.  */
  62. #endif    /* HAVE_ALLOCA_H.  */
  63. #endif    /* GCC.  */
  64.  
  65. /* Get definitions for the file permission bits.  */
  66.  
  67. #ifndef S_IRWXU
  68. #define S_IRWXU 0700
  69. #endif
  70. #ifndef S_IRUSR
  71. #define S_IRUSR 0400
  72. #endif
  73. #ifndef S_IWUSR
  74. #define S_IWUSR 0200
  75. #endif
  76. #ifndef S_IXUSR
  77. #define S_IXUSR 0100
  78. #endif
  79.  
  80. #ifndef S_IRWXG
  81. #define S_IRWXG 0070
  82. #endif
  83. #ifndef S_IRGRP
  84. #define S_IRGRP 0040
  85. #endif
  86. #ifndef S_IWGRP
  87. #define S_IWGRP 0020
  88. #endif
  89. #ifndef S_IXGRP
  90. #define S_IXGRP 0010
  91. #endif
  92.  
  93. #ifndef S_IRWXO
  94. #define S_IRWXO 0007
  95. #endif
  96. #ifndef S_IROTH
  97. #define S_IROTH 0004
  98. #endif
  99. #ifndef S_IWOTH
  100. #define S_IWOTH 0002
  101. #endif
  102. #ifndef S_IXOTH
  103. #define S_IXOTH 0001
  104. #endif
  105.  
  106. static struct option longopts[] =
  107. {
  108.   { "version", 0, 0, 'v' },
  109.   { "help", 0, 0, 'h' },
  110.   { NULL, 0, 0, 0 }
  111. };
  112.  
  113. #if __STDC__
  114. static int decode (char *);
  115. static void usage (FILE *, int);
  116. #else
  117. static int decode ();
  118. static void usage ();
  119. #endif
  120.  
  121. extern char version[];
  122. static char *program_name;
  123.  
  124. int
  125. main (argc, argv)
  126.      int argc;
  127.      char **argv;
  128. {
  129.   int opt;
  130.   int rval;
  131.  
  132.   program_name = argv[0];
  133.  
  134.   while ((opt = getopt_long (argc, argv, "hv", longopts, (int *) NULL))
  135.      != EOF)
  136.     {
  137.       switch (opt)
  138.     {
  139.     case 'h':
  140.       printf ("Decode a file created by uuencode\n");
  141.       usage (stdout, 0);
  142.  
  143.     case 'v':
  144.       printf ("%s\n", version);
  145.       exit (0);
  146.  
  147.     case 0:
  148.       break;
  149.  
  150.     default:
  151.       usage (stderr, 1);
  152.     }
  153.     }
  154.  
  155.   if (optind == argc)
  156.     rval = decode ((char *) "stdin");
  157.   else
  158.     {
  159.       char *filename;
  160.  
  161.       rval = 0;
  162.       do
  163.     {
  164.       if (freopen (argv[optind], "r", stdin) != NULL)
  165.         rval |= decode (argv[optind]);
  166.       else
  167.         {
  168.           fprintf (stderr, "%s:", program_name);
  169.           perror (argv[optind]);
  170.           rval = 1;
  171.         }
  172.       ++optind;
  173.     }
  174.       while (optind < argc);
  175.     }
  176.  
  177.   exit (rval);
  178. }
  179.  
  180. #define    DEC(c)    (((c) - ' ') & 077) /* single character decode */
  181.  
  182. static int
  183. decode (filename)
  184.      char *filename;
  185. {
  186.   struct passwd *pw;
  187.   register int n;
  188.   register char ch, *p;
  189.   int mode, n1;
  190.   char buf[2 * BUFSIZ];
  191.   char *outname;
  192.  
  193.   /* search for header line */
  194.   do
  195.     {
  196.       if (fgets (buf, sizeof (buf), stdin) == NULL)
  197.     {
  198.       fprintf (stderr,
  199.           "%s:%s: no \"begin\" line\n", program_name, filename);
  200.       return 1;
  201.     }
  202.     }
  203.   while (strncmp (buf, "begin ", 6) != 0);
  204.  
  205.   sscanf (buf, "begin %o %s", &mode, buf);
  206.  
  207.   /* handle ~user/file format */
  208.   if (buf[0] != '~')
  209.     outname = buf;
  210.   else
  211.     {
  212.       p = buf + 1;
  213.       while (*p != '/')
  214.     ++p;
  215.       if (*p == '\0')
  216.     {
  217.       fprintf (stderr, "%s:%s: illegal ~user\n", program_name,
  218.            filename);
  219.       return 1;
  220.     }
  221.       *p++ = '\0';
  222.       pw = getpwnam (buf + 1);
  223.       if (pw == NULL)
  224.     {
  225.       fprintf (stderr, "%s:%s: no user %s\n", program_name,
  226.            filename, buf + 1);
  227.       return 1;
  228.     }
  229.       n = strlen (pw->pw_dir);
  230.       n1 = strlen (p);
  231.       outname = (char *) alloca (n + n1 + 2);
  232.       memcpy (outname + n + 1, p, n1 + 1);
  233.       memcpy (outname, pw->pw_dir, n);
  234.       outname[n] = '/';
  235.     }
  236.  
  237.   /* create output file, set mode */
  238.   if (freopen (outname, "w", stdout) == NULL
  239.       || fchmod (fileno (stdout),
  240.          mode & (S_IRWXU | S_IRWXG | S_IRWXO)))
  241.     {
  242.       fprintf (stderr, "%s:%s:", program_name, outname);
  243.       perror (filename);
  244.       return 1;
  245.     }
  246.  
  247.   /* for each input line */
  248.   while (1)
  249.     {
  250.       if (fgets (buf, sizeof(buf), stdin) == NULL)
  251.     {
  252.       fprintf (stderr, "%s:%s: short file.\n", program_name,
  253.            filename);
  254.       return 1;
  255.     }
  256.       p = buf;
  257.       /*
  258.        * `n' is used to avoid writing out all the characters
  259.        * at the end of the file.
  260.        */
  261.       n = DEC (*p);
  262.       if (n <= 0)
  263.     break;
  264.       for (++p; n > 0; p += 4, n -= 3)
  265.     {
  266.       if (n >= 3)
  267.         {
  268.           ch = DEC (p[0]) << 2 | DEC (p[1]) >> 4;
  269.           putchar (ch);
  270.           ch = DEC (p[1]) << 4 | DEC (p[2]) >> 2;
  271.           putchar (ch);
  272.           ch = DEC (p[2]) << 6 | DEC (p[3]);
  273.           putchar (ch);
  274.         }
  275.       else
  276.         {
  277.           if (n >= 1)
  278.         {
  279.           ch = DEC (p[0]) << 2 | DEC (p[1]) >> 4;
  280.           putchar (ch);
  281.         }
  282.           if (n >= 2)
  283.         {
  284.           ch = DEC (p[1]) << 4 | DEC (p[2]) >> 2;
  285.           putchar (ch);
  286.         }
  287.         }
  288.     }
  289.     }
  290.  
  291.   if (fgets (buf, sizeof(buf), stdin) == NULL
  292.       || strcmp (buf, "end\n"))
  293.     {
  294.       fprintf (stderr, "%s:%s: no \"end\" line.\n", program_name,
  295.            filename);
  296.       return 1;
  297.     }
  298.  
  299.   return 0;
  300. }
  301.  
  302. static void
  303. usage (f, status)
  304.      FILE *f;
  305.      int status;
  306. {
  307.   fprintf (f, "usage: %s [file ...]\n", program_name);
  308.   exit (status);
  309. }
  310.