blob: 1d42494fdc1e0584711837cb4bef6c94ea5361d6 [file] [log] [blame]
Glenn L McGrath089deca2001-07-28 21:06:13 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2000 by Glenn McGrath
Eric Andersen2b6ab3c2000-06-13 06:54:53 +00004 *
Glenn L McGrath089deca2001-07-28 21:06:13 +00005 * based on the function base64_encode from http.c in wget v1.6
6 * Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
Eric Andersen2b6ab3c2000-06-13 06:54:53 +00007 *
Glenn L McGrath089deca2001-07-28 21:06:13 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000012 *
Glenn L McGrath089deca2001-07-28 21:06:13 +000013 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Library General Public License for more details.
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000017 *
Glenn L McGrath089deca2001-07-28 21:06:13 +000018 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000021 */
Eric Andersen999bf722000-07-09 06:59:58 +000022#include <getopt.h>
Glenn L McGrath089deca2001-07-28 21:06:13 +000023#include <stdio.h>
Eric Andersen2276d832002-07-11 11:11:56 +000024#include <string.h>
Eric Andersened3ef502001-01-27 08:24:39 +000025#include <stdlib.h>
Glenn L McGrath089deca2001-07-28 21:06:13 +000026#include <sys/types.h>
27#include <sys/stat.h>
28#include <unistd.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000029#include "busybox.h"
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000030
Glenn L McGrath089deca2001-07-28 21:06:13 +000031/* Conversion table. for base 64 */
Tim Riker95bf6da2002-05-01 05:57:16 +000032static char tbl_base64[65] = {
Glenn L McGrath089deca2001-07-28 21:06:13 +000033 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
34 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
35 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
36 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
37 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
38 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
39 'w', 'x', 'y', 'z', '0', '1', '2', '3',
Tim Riker95bf6da2002-05-01 05:57:16 +000040 '4', '5', '6', '7', '8', '9', '+', '/',
41 '=' /* termination character */
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000042};
43
Tim Riker95bf6da2002-05-01 05:57:16 +000044static char tbl_std[65] = {
Glenn L McGrath089deca2001-07-28 21:06:13 +000045 '`', '!', '"', '#', '$', '%', '&', '\'',
46 '(', ')', '*', '+', ',', '-', '.', '/',
47 '0', '1', '2', '3', '4', '5', '6', '7',
48 '8', '9', ':', ';', '<', '=', '>', '?',
49 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
50 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
51 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
Tim Riker95bf6da2002-05-01 05:57:16 +000052 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
Eric Andersen2276d832002-07-11 11:11:56 +000053 '`' /* termination character */
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000054};
55
Glenn L McGrath089deca2001-07-28 21:06:13 +000056/*
57 * Encode the string S of length LENGTH to base64 format and place it
58 * to STORE. STORE will be 0-terminated, and must point to a writable
59 * buffer of at least 1+BASE64_LENGTH(length) bytes.
60 * where BASE64_LENGTH(len) = (4 * ((LENGTH + 2) / 3))
Eric Andersen4e573f42000-11-14 23:29:24 +000061 */
Glenn L McGratheba26052001-07-29 05:47:33 +000062static void uuencode (const char *s, const char *store, const int length, const char *tbl)
Glenn L McGrath089deca2001-07-28 21:06:13 +000063{
64 int i;
65 unsigned char *p = (unsigned char *)store;
Eric Andersen4e573f42000-11-14 23:29:24 +000066
Glenn L McGrath089deca2001-07-28 21:06:13 +000067 /* Transform the 3x8 bits to 4x6 bits, as required by base64. */
68 for (i = 0; i < length; i += 3) {
69 *p++ = tbl[s[0] >> 2];
70 *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
71 *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
72 *p++ = tbl[s[2] & 0x3f];
73 s += 3;
74 }
75 /* Pad the result if necessary... */
76 if (i == length + 1) {
Tim Riker95bf6da2002-05-01 05:57:16 +000077 *(p - 1) = tbl[64];
Glenn L McGrath089deca2001-07-28 21:06:13 +000078 }
79 else if (i == length + 2) {
Tim Riker95bf6da2002-05-01 05:57:16 +000080 *(p - 1) = *(p - 2) = tbl[64];
Glenn L McGrath089deca2001-07-28 21:06:13 +000081 }
82 /* ...and zero-terminate it. */
83 *p = '\0';
84}
Eric Andersen4e573f42000-11-14 23:29:24 +000085
Glenn L McGrath089deca2001-07-28 21:06:13 +000086int uuencode_main(int argc, char **argv)
87{
Tim Riker95bf6da2002-05-01 05:57:16 +000088 const int src_buf_size = 45;// This *MUST* be a multiple of 3
Glenn L McGrath089deca2001-07-28 21:06:13 +000089 const int dst_buf_size = 4 * ((src_buf_size + 2) / 3);
Tim Riker95bf6da2002-05-01 05:57:16 +000090 int write_size = dst_buf_size;
Eric Andersenbdfd0d72001-10-24 05:00:29 +000091 RESERVE_CONFIG_BUFFER(src_buf, src_buf_size + 1);
92 RESERVE_CONFIG_BUFFER(dst_buf, dst_buf_size + 1);
Glenn L McGrath089deca2001-07-28 21:06:13 +000093 struct stat stat_buf;
94 FILE *src_stream = stdin;
95 char *tbl = tbl_std;
96 size_t size;
97 mode_t mode;
98 int opt;
Glenn L McGrath089deca2001-07-28 21:06:13 +000099
100 while ((opt = getopt(argc, argv, "m")) != -1) {
101 switch (opt) {
102 case 'm':
103 tbl = tbl_base64;
104 break;
105 default:
106 show_usage();
107 }
108 }
109
110 switch (argc - optind) {
111 case 2:
112 src_stream = xfopen(argv[optind], "r");
113 stat(argv[optind], &stat_buf);
114 mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
115 if (src_stream == stdout) {
116 printf("NULL\n");
117 }
118 break;
119 case 1:
Glenn L McGrathb6071b62001-07-29 06:04:26 +0000120 mode = 0666 & ~umask(0666);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000121 break;
122 default:
123 show_usage();
124 }
125
126 printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]);
127
128 while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) {
Tim Riker95bf6da2002-05-01 05:57:16 +0000129 if (size != src_buf_size) {
130 /* write_size is always 60 until the last line */
131 write_size=(4 * ((size + 2) / 3));
132 /* pad with 0s so we can just encode extra bits */
133 memset(&src_buf[size], 0, src_buf_size - size);
134 }
Glenn L McGrath089deca2001-07-28 21:06:13 +0000135 /* Encode the buffer we just read in */
Glenn L McGratheba26052001-07-29 05:47:33 +0000136 uuencode(src_buf, dst_buf, size, tbl);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000137
Tim Riker95bf6da2002-05-01 05:57:16 +0000138 putchar('\n');
139 if (tbl == tbl_std) {
140 putchar(tbl[size]);
141 }
142 if (fwrite(dst_buf, 1, write_size, stdout) != write_size) {
143 perror("Couldnt finish writing");
144 }
Glenn L McGrath089deca2001-07-28 21:06:13 +0000145 }
146 printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n");
147
148 return(EXIT_SUCCESS);
149}