blob: d45565c6ec2ffb14d2ff2bb2b127cb50c777606f [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 */
Glenn L McGrath089deca2001-07-28 21:06:13 +000022#include <stdio.h>
Eric Andersen2276d832002-07-11 11:11:56 +000023#include <string.h>
Eric Andersened3ef502001-01-27 08:24:39 +000024#include <stdlib.h>
Glenn L McGrath089deca2001-07-28 21:06:13 +000025#include <sys/types.h>
26#include <sys/stat.h>
27#include <unistd.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000028#include "busybox.h"
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000029
Glenn L McGrath089deca2001-07-28 21:06:13 +000030/* Conversion table. for base 64 */
Manuel Novoa III cad53642003-03-19 09:13:01 +000031static const char tbl_base64[65] = {
Glenn L McGrath089deca2001-07-28 21:06:13 +000032 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
33 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
34 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
35 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
36 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
37 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
38 'w', 'x', 'y', 'z', '0', '1', '2', '3',
Tim Riker95bf6da2002-05-01 05:57:16 +000039 '4', '5', '6', '7', '8', '9', '+', '/',
40 '=' /* termination character */
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000041};
42
Manuel Novoa III cad53642003-03-19 09:13:01 +000043static const char tbl_std[65] = {
Glenn L McGrath089deca2001-07-28 21:06:13 +000044 '`', '!', '"', '#', '$', '%', '&', '\'',
45 '(', ')', '*', '+', ',', '-', '.', '/',
46 '0', '1', '2', '3', '4', '5', '6', '7',
47 '8', '9', ':', ';', '<', '=', '>', '?',
48 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
49 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
50 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
Tim Riker95bf6da2002-05-01 05:57:16 +000051 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
Eric Andersen2276d832002-07-11 11:11:56 +000052 '`' /* termination character */
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000053};
54
Glenn L McGrath089deca2001-07-28 21:06:13 +000055/*
56 * Encode the string S of length LENGTH to base64 format and place it
57 * to STORE. STORE will be 0-terminated, and must point to a writable
58 * buffer of at least 1+BASE64_LENGTH(length) bytes.
59 * where BASE64_LENGTH(len) = (4 * ((LENGTH + 2) / 3))
Eric Andersen4e573f42000-11-14 23:29:24 +000060 */
"Vladimir N. Oleynik"87be3162006-01-31 14:25:52 +000061static void uuencode (const unsigned char *s, char *store, const int length, const char *tbl)
Glenn L McGrath089deca2001-07-28 21:06:13 +000062{
63 int i;
"Vladimir N. Oleynik"87be3162006-01-31 14:25:52 +000064 char *p = store;
Eric Andersen4e573f42000-11-14 23:29:24 +000065
Glenn L McGrath089deca2001-07-28 21:06:13 +000066 /* Transform the 3x8 bits to 4x6 bits, as required by base64. */
67 for (i = 0; i < length; i += 3) {
68 *p++ = tbl[s[0] >> 2];
69 *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
70 *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
71 *p++ = tbl[s[2] & 0x3f];
72 s += 3;
73 }
74 /* Pad the result if necessary... */
75 if (i == length + 1) {
Tim Riker95bf6da2002-05-01 05:57:16 +000076 *(p - 1) = tbl[64];
Glenn L McGrath089deca2001-07-28 21:06:13 +000077 }
78 else if (i == length + 2) {
Tim Riker95bf6da2002-05-01 05:57:16 +000079 *(p - 1) = *(p - 2) = tbl[64];
Glenn L McGrath089deca2001-07-28 21:06:13 +000080 }
81 /* ...and zero-terminate it. */
82 *p = '\0';
83}
Eric Andersen4e573f42000-11-14 23:29:24 +000084
Eric Andersenb077c9f2002-12-06 21:39:48 +000085#define SRC_BUF_SIZE 45 // This *MUST* be a multiple of 3
86#define DST_BUF_SIZE 4 * ((SRC_BUF_SIZE + 2) / 3)
Glenn L McGrath089deca2001-07-28 21:06:13 +000087int uuencode_main(int argc, char **argv)
88{
"Vladimir N. Oleynik"87be3162006-01-31 14:25:52 +000089 const size_t src_buf_size = SRC_BUF_SIZE;
90 const size_t dst_buf_size = DST_BUF_SIZE;
91 size_t write_size = dst_buf_size;
Glenn L McGrath089deca2001-07-28 21:06:13 +000092 struct stat stat_buf;
93 FILE *src_stream = stdin;
Manuel Novoa III cad53642003-03-19 09:13:01 +000094 const char *tbl;
Glenn L McGrath089deca2001-07-28 21:06:13 +000095 size_t size;
96 mode_t mode;
Eric Andersenb077c9f2002-12-06 21:39:48 +000097 RESERVE_CONFIG_BUFFER(src_buf, SRC_BUF_SIZE + 1);
98 RESERVE_CONFIG_BUFFER(dst_buf, DST_BUF_SIZE + 1);
Glenn L McGrath089deca2001-07-28 21:06:13 +000099
Manuel Novoa III cad53642003-03-19 09:13:01 +0000100 tbl = tbl_std;
101 if (bb_getopt_ulflags(argc, argv, "m") & 1) {
102 tbl = tbl_base64;
Glenn L McGrath089deca2001-07-28 21:06:13 +0000103 }
104
105 switch (argc - optind) {
106 case 2:
Manuel Novoa III cad53642003-03-19 09:13:01 +0000107 src_stream = bb_xfopen(argv[optind], "r");
108 if (stat(argv[optind], &stat_buf) < 0) {
109 bb_perror_msg_and_die("stat");
110 }
Glenn L McGrath089deca2001-07-28 21:06:13 +0000111 mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
112 if (src_stream == stdout) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000113 puts("NULL");
Glenn L McGrath089deca2001-07-28 21:06:13 +0000114 }
115 break;
116 case 1:
Glenn L McGrathb6071b62001-07-29 06:04:26 +0000117 mode = 0666 & ~umask(0666);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000118 break;
119 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +0000120 bb_show_usage();
Glenn L McGrath089deca2001-07-28 21:06:13 +0000121 }
122
Manuel Novoa III cad53642003-03-19 09:13:01 +0000123 bb_printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000124
125 while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) {
Tim Riker95bf6da2002-05-01 05:57:16 +0000126 if (size != src_buf_size) {
127 /* write_size is always 60 until the last line */
128 write_size=(4 * ((size + 2) / 3));
129 /* pad with 0s so we can just encode extra bits */
130 memset(&src_buf[size], 0, src_buf_size - size);
131 }
Glenn L McGrath089deca2001-07-28 21:06:13 +0000132 /* Encode the buffer we just read in */
Eric Andersen5e678872006-01-30 19:48:23 +0000133 uuencode((unsigned char*)src_buf, dst_buf, size, tbl);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000134
Tim Riker95bf6da2002-05-01 05:57:16 +0000135 putchar('\n');
136 if (tbl == tbl_std) {
137 putchar(tbl[size]);
138 }
139 if (fwrite(dst_buf, 1, write_size, stdout) != write_size) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000140 bb_perror_msg_and_die(bb_msg_write_error);
Tim Riker95bf6da2002-05-01 05:57:16 +0000141 }
Glenn L McGrath089deca2001-07-28 21:06:13 +0000142 }
Manuel Novoa III cad53642003-03-19 09:13:01 +0000143 bb_printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n");
Glenn L McGrath089deca2001-07-28 21:06:13 +0000144
Manuel Novoa III cad53642003-03-19 09:13:01 +0000145 bb_xferror(src_stream, "source"); /* TODO - Fix this! */
146
147 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000148}