blob: 1449d9aeb272650a84d45c8199bfc214060368c3 [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 *
"Robert P. J. Day"801ab142006-07-12 07:56:04 +00008 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Eric Andersen2b6ab3c2000-06-13 06:54:53 +00009 */
Rob Landleyd921b2e2006-08-03 15:41:12 +000010
Eric Andersencbe31da2001-02-20 06:14:08 +000011#include "busybox.h"
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000012
Glenn L McGrath089deca2001-07-28 21:06:13 +000013/* Conversion table. for base 64 */
Manuel Novoa III cad53642003-03-19 09:13:01 +000014static const char tbl_base64[65] = {
Glenn L McGrath089deca2001-07-28 21:06:13 +000015 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
16 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
17 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
18 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
19 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
20 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
21 'w', 'x', 'y', 'z', '0', '1', '2', '3',
Tim Riker95bf6da2002-05-01 05:57:16 +000022 '4', '5', '6', '7', '8', '9', '+', '/',
23 '=' /* termination character */
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000024};
25
Manuel Novoa III cad53642003-03-19 09:13:01 +000026static const char tbl_std[65] = {
Glenn L McGrath089deca2001-07-28 21:06:13 +000027 '`', '!', '"', '#', '$', '%', '&', '\'',
28 '(', ')', '*', '+', ',', '-', '.', '/',
29 '0', '1', '2', '3', '4', '5', '6', '7',
30 '8', '9', ':', ';', '<', '=', '>', '?',
31 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
32 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
33 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
Tim Riker95bf6da2002-05-01 05:57:16 +000034 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
Eric Andersen2276d832002-07-11 11:11:56 +000035 '`' /* termination character */
Eric Andersen2b6ab3c2000-06-13 06:54:53 +000036};
37
Glenn L McGrath089deca2001-07-28 21:06:13 +000038/*
39 * Encode the string S of length LENGTH to base64 format and place it
40 * to STORE. STORE will be 0-terminated, and must point to a writable
41 * buffer of at least 1+BASE64_LENGTH(length) bytes.
42 * where BASE64_LENGTH(len) = (4 * ((LENGTH + 2) / 3))
Eric Andersen4e573f42000-11-14 23:29:24 +000043 */
"Vladimir N. Oleynik"87be3162006-01-31 14:25:52 +000044static void uuencode (const unsigned char *s, char *store, const int length, const char *tbl)
Glenn L McGrath089deca2001-07-28 21:06:13 +000045{
46 int i;
"Vladimir N. Oleynik"87be3162006-01-31 14:25:52 +000047 char *p = store;
Eric Andersen4e573f42000-11-14 23:29:24 +000048
Glenn L McGrath089deca2001-07-28 21:06:13 +000049 /* Transform the 3x8 bits to 4x6 bits, as required by base64. */
50 for (i = 0; i < length; i += 3) {
51 *p++ = tbl[s[0] >> 2];
52 *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
53 *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
54 *p++ = tbl[s[2] & 0x3f];
55 s += 3;
56 }
57 /* Pad the result if necessary... */
58 if (i == length + 1) {
Tim Riker95bf6da2002-05-01 05:57:16 +000059 *(p - 1) = tbl[64];
Glenn L McGrath089deca2001-07-28 21:06:13 +000060 }
61 else if (i == length + 2) {
Tim Riker95bf6da2002-05-01 05:57:16 +000062 *(p - 1) = *(p - 2) = tbl[64];
Glenn L McGrath089deca2001-07-28 21:06:13 +000063 }
64 /* ...and zero-terminate it. */
65 *p = '\0';
66}
Eric Andersen4e573f42000-11-14 23:29:24 +000067
Eric Andersenb077c9f2002-12-06 21:39:48 +000068#define SRC_BUF_SIZE 45 // This *MUST* be a multiple of 3
69#define DST_BUF_SIZE 4 * ((SRC_BUF_SIZE + 2) / 3)
Glenn L McGrath089deca2001-07-28 21:06:13 +000070int uuencode_main(int argc, char **argv)
71{
"Vladimir N. Oleynik"87be3162006-01-31 14:25:52 +000072 const size_t src_buf_size = SRC_BUF_SIZE;
73 const size_t dst_buf_size = DST_BUF_SIZE;
74 size_t write_size = dst_buf_size;
Glenn L McGrath089deca2001-07-28 21:06:13 +000075 struct stat stat_buf;
76 FILE *src_stream = stdin;
Manuel Novoa III cad53642003-03-19 09:13:01 +000077 const char *tbl;
Glenn L McGrath089deca2001-07-28 21:06:13 +000078 size_t size;
79 mode_t mode;
Eric Andersenb077c9f2002-12-06 21:39:48 +000080 RESERVE_CONFIG_BUFFER(src_buf, SRC_BUF_SIZE + 1);
81 RESERVE_CONFIG_BUFFER(dst_buf, DST_BUF_SIZE + 1);
Glenn L McGrath089deca2001-07-28 21:06:13 +000082
Manuel Novoa III cad53642003-03-19 09:13:01 +000083 tbl = tbl_std;
84 if (bb_getopt_ulflags(argc, argv, "m") & 1) {
85 tbl = tbl_base64;
Glenn L McGrath089deca2001-07-28 21:06:13 +000086 }
87
88 switch (argc - optind) {
89 case 2:
Rob Landleyd921b2e2006-08-03 15:41:12 +000090 src_stream = xfopen(argv[optind], "r");
Rob Landleyc5b1d4d2006-03-13 15:45:16 +000091 xstat(argv[optind], &stat_buf);
Glenn L McGrath089deca2001-07-28 21:06:13 +000092 mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
93 if (src_stream == stdout) {
Manuel Novoa III cad53642003-03-19 09:13:01 +000094 puts("NULL");
Glenn L McGrath089deca2001-07-28 21:06:13 +000095 }
96 break;
97 case 1:
Glenn L McGrathb6071b62001-07-29 06:04:26 +000098 mode = 0666 & ~umask(0666);
Glenn L McGrath089deca2001-07-28 21:06:13 +000099 break;
100 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +0000101 bb_show_usage();
Glenn L McGrath089deca2001-07-28 21:06:13 +0000102 }
103
Manuel Novoa III cad53642003-03-19 09:13:01 +0000104 bb_printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000105
106 while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) {
Tim Riker95bf6da2002-05-01 05:57:16 +0000107 if (size != src_buf_size) {
108 /* write_size is always 60 until the last line */
109 write_size=(4 * ((size + 2) / 3));
110 /* pad with 0s so we can just encode extra bits */
111 memset(&src_buf[size], 0, src_buf_size - size);
112 }
Glenn L McGrath089deca2001-07-28 21:06:13 +0000113 /* Encode the buffer we just read in */
Eric Andersen5e678872006-01-30 19:48:23 +0000114 uuencode((unsigned char*)src_buf, dst_buf, size, tbl);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000115
Tim Riker95bf6da2002-05-01 05:57:16 +0000116 putchar('\n');
117 if (tbl == tbl_std) {
118 putchar(tbl[size]);
119 }
120 if (fwrite(dst_buf, 1, write_size, stdout) != write_size) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000121 bb_perror_msg_and_die(bb_msg_write_error);
Tim Riker95bf6da2002-05-01 05:57:16 +0000122 }
Glenn L McGrath089deca2001-07-28 21:06:13 +0000123 }
Manuel Novoa III cad53642003-03-19 09:13:01 +0000124 bb_printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n");
Glenn L McGrath089deca2001-07-28 21:06:13 +0000125
Rob Landleyd921b2e2006-08-03 15:41:12 +0000126 xferror(src_stream, "source"); /* TODO - Fix this! */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000127
128 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000129}