blob: 6a82a4b43362e8a3a0ec7384e27a252135d19229 [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");
Rob Landleyc5b1d4d2006-03-13 15:45:16 +0000108 xstat(argv[optind], &stat_buf);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000109 mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
110 if (src_stream == stdout) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000111 puts("NULL");
Glenn L McGrath089deca2001-07-28 21:06:13 +0000112 }
113 break;
114 case 1:
Glenn L McGrathb6071b62001-07-29 06:04:26 +0000115 mode = 0666 & ~umask(0666);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000116 break;
117 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +0000118 bb_show_usage();
Glenn L McGrath089deca2001-07-28 21:06:13 +0000119 }
120
Manuel Novoa III cad53642003-03-19 09:13:01 +0000121 bb_printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000122
123 while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) {
Tim Riker95bf6da2002-05-01 05:57:16 +0000124 if (size != src_buf_size) {
125 /* write_size is always 60 until the last line */
126 write_size=(4 * ((size + 2) / 3));
127 /* pad with 0s so we can just encode extra bits */
128 memset(&src_buf[size], 0, src_buf_size - size);
129 }
Glenn L McGrath089deca2001-07-28 21:06:13 +0000130 /* Encode the buffer we just read in */
Eric Andersen5e678872006-01-30 19:48:23 +0000131 uuencode((unsigned char*)src_buf, dst_buf, size, tbl);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000132
Tim Riker95bf6da2002-05-01 05:57:16 +0000133 putchar('\n');
134 if (tbl == tbl_std) {
135 putchar(tbl[size]);
136 }
137 if (fwrite(dst_buf, 1, write_size, stdout) != write_size) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000138 bb_perror_msg_and_die(bb_msg_write_error);
Tim Riker95bf6da2002-05-01 05:57:16 +0000139 }
Glenn L McGrath089deca2001-07-28 21:06:13 +0000140 }
Manuel Novoa III cad53642003-03-19 09:13:01 +0000141 bb_printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n");
Glenn L McGrath089deca2001-07-28 21:06:13 +0000142
Manuel Novoa III cad53642003-03-19 09:13:01 +0000143 bb_xferror(src_stream, "source"); /* TODO - Fix this! */
144
145 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000146}