home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / uuencode-1.0-src.lha / src / amiga / uuencode-1.0 / uudecode.c < prev    next >
C/C++ Source or Header  |  1994-02-24  |  7KB  |  311 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/types.h>
  48. #include <sys/stat.h>
  49. #include <pwd.h>
  50. #include <stdio.h>
  51. #include "getopt.h"
  52.  
  53. #ifdef    __GNUC__
  54. #undef    alloca
  55. #define    alloca(n)    __builtin_alloca (n)
  56. #else    /* Not GCC.  */
  57. #ifdef    HAVE_ALLOCA_H
  58. #include <alloca.h>
  59. #else    /* Not HAVE_ALLOCA_H.  */
  60. #ifndef    _AIX
  61. extern char *alloca ();
  62. #endif    /* Not AIX.  */
  63. #endif    /* HAVE_ALLOCA_H.  */
  64. #endif    /* GCC.  */
  65.  
  66. /* Get definitions for the file permission bits.  */
  67.  
  68. #ifndef S_IRWXU
  69. #define S_IRWXU 0700
  70. #endif
  71. #ifndef S_IRUSR
  72. #define S_IRUSR 0400
  73. #endif
  74. #ifndef S_IWUSR
  75. #define S_IWUSR 0200
  76. #endif
  77. #ifndef S_IXUSR
  78. #define S_IXUSR 0100
  79. #endif
  80.  
  81. #ifndef S_IRWXG
  82. #define S_IRWXG 0070
  83. #endif
  84. #ifndef S_IRGRP
  85. #define S_IRGRP 0040
  86. #endif
  87. #ifndef S_IWGRP
  88. #define S_IWGRP 0020
  89. #endif
  90. #ifndef S_IXGRP
  91. #define S_IXGRP 0010
  92. #endif
  93.  
  94. #ifndef S_IRWXO
  95. #define S_IRWXO 0007
  96. #endif
  97. #ifndef S_IROTH
  98. #define S_IROTH 0004
  99. #endif
  100. #ifndef S_IWOTH
  101. #define S_IWOTH 0002
  102. #endif
  103. #ifndef S_IXOTH
  104. #define S_IXOTH 0001
  105. #endif
  106.  
  107. static struct option longopts[] =
  108. {
  109.   { "version", 0, 0, 'v' },
  110.   { "help", 0, 0, 'h' },
  111.   { NULL, 0, 0, 0 }
  112. };
  113.  
  114. #if __STDC__
  115. static int decode (char *);
  116. static void usage (FILE *, int);
  117. #else
  118. static int decode ();
  119. static void usage ();
  120. #endif
  121.  
  122. extern char version[];
  123. static char *program_name;
  124.  
  125. int
  126. main (argc, argv)
  127.      int argc;
  128.      char **argv;
  129. {
  130.   int opt;
  131.   int rval;
  132.  
  133.   program_name = argv[0];
  134.  
  135.   while ((opt = getopt_long (argc, argv, "hv", longopts, (int *) NULL))
  136.      != EOF)
  137.     {
  138.       switch (opt)
  139.     {
  140.     case 'h':
  141.       printf ("Decode a file created by uuencode\n");
  142.       usage (stdout, 0);
  143.  
  144.     case 'v':
  145.       printf ("%s\n", version);
  146.       exit (0);
  147.  
  148.     case 0:
  149.       break;
  150.  
  151.     default:
  152.       usage (stderr, 1);
  153.     }
  154.     }
  155.  
  156.   if (optind == argc)
  157.     rval = decode ((char *) "stdin");
  158.   else
  159.     {
  160.       char *filename;
  161.  
  162.       rval = 0;
  163.       do
  164.     {
  165.       if (freopen (argv[optind], "r", stdin) != NULL)
  166.         rval |= decode (argv[optind]);
  167.       else
  168.         {
  169.           fprintf (stderr, "%s:", program_name);
  170.           perror (argv[optind]);
  171.           rval = 1;
  172.         }
  173.       ++optind;
  174.     }
  175.       while (optind < argc);
  176.     }
  177.  
  178.   exit (rval);
  179. }
  180.  
  181. #define    DEC(c)    (((c) - ' ') & 077) /* single character decode */
  182.  
  183. static int
  184. decode (filename)
  185.      char *filename;
  186. {
  187.   struct passwd *pw;
  188.   register int n;
  189.   register char ch, *p;
  190.   int mode, n1;
  191.   char buf[2 * BUFSIZ];
  192.   char *outname;
  193.  
  194.   /* search for header line */
  195.   do
  196.     {
  197.       if (fgets (buf, sizeof (buf), stdin) == NULL)
  198.     {
  199.       fprintf (stderr,
  200.           "%s:%s: no \"begin\" line\n", program_name, filename);
  201.       return 1;
  202.     }
  203.     }
  204.   while (strncmp (buf, "begin ", 6) != 0);
  205.  
  206.   sscanf (buf, "begin %o %s", &mode, buf);
  207.  
  208.   /* handle ~user/file format */
  209.   if (buf[0] != '~')
  210.     outname = buf;
  211.   else
  212.     {
  213.       p = buf + 1;
  214.       while (*p != '/')
  215.     ++p;
  216.       if (*p == '\0')
  217.     {
  218.       fprintf (stderr, "%s:%s: illegal ~user\n", program_name,
  219.            filename);
  220.       return 1;
  221.     }
  222.       *p++ = '\0';
  223.       pw = getpwnam (buf + 1);
  224.       if (pw == NULL)
  225.     {
  226.       fprintf (stderr, "%s:%s: no user %s\n", program_name,
  227.            filename, buf + 1);
  228.       return 1;
  229.     }
  230.       n = strlen (pw->pw_dir);
  231.       n1 = strlen (p);
  232.       outname = (char *) alloca (n + n1 + 2);
  233.       memcpy (outname + n + 1, p, n1 + 1);
  234.       memcpy (outname, pw->pw_dir, n);
  235.       outname[n] = '/';
  236.     }
  237.  
  238.   /* create output file, set mode */
  239.   if (freopen (outname, "w", stdout) == NULL
  240.       || fchmod (fileno (stdout),
  241.          mode & (S_IRWXU | S_IRWXG | S_IRWXO)))
  242.     {
  243.       fprintf (stderr, "%s:%s:", program_name, outname);
  244.       perror (filename);
  245.       return 1;
  246.     }
  247.  
  248.   /* for each input line */
  249.   while (1)
  250.     {
  251.       if (fgets (buf, sizeof(buf), stdin) == NULL)
  252.     {
  253.       fprintf (stderr, "%s:%s: short file.\n", program_name,
  254.            filename);
  255.       return 1;
  256.     }
  257.       p = buf;
  258.       /*
  259.        * `n' is used to avoid writing out all the characters
  260.        * at the end of the file.
  261.        */
  262.       n = DEC (*p);
  263.       if (n <= 0)
  264.     break;
  265.       for (++p; n > 0; p += 4, n -= 3)
  266.     {
  267.       if (n >= 3)
  268.         {
  269.           ch = DEC (p[0]) << 2 | DEC (p[1]) >> 4;
  270.           putchar (ch);
  271.           ch = DEC (p[1]) << 4 | DEC (p[2]) >> 2;
  272.           putchar (ch);
  273.           ch = DEC (p[2]) << 6 | DEC (p[3]);
  274.           putchar (ch);
  275.         }
  276.       else
  277.         {
  278.           if (n >= 1)
  279.         {
  280.           ch = DEC (p[0]) << 2 | DEC (p[1]) >> 4;
  281.           putchar (ch);
  282.         }
  283.           if (n >= 2)
  284.         {
  285.           ch = DEC (p[1]) << 4 | DEC (p[2]) >> 2;
  286.           putchar (ch);
  287.         }
  288.         }
  289.     }
  290.     }
  291.  
  292.   if (fgets (buf, sizeof(buf), stdin) == NULL
  293.       || strcmp (buf, "end\n"))
  294.     {
  295.       fprintf (stderr, "%s:%s: no \"end\" line.\n", program_name,
  296.            filename);
  297.       return 1;
  298.     }
  299.  
  300.   return 0;
  301. }
  302.  
  303. static void
  304. usage (f, status)
  305.      FILE *f;
  306.      int status;
  307. {
  308.   fprintf (f, "usage: %s [file ...]\n", program_name);
  309.   exit (status);
  310. }
  311.