blob: fd3326d808f80559b6cc6ac0c4e6fc0a7c16483f [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 */
Manuel Novoa III cad53642003-03-19 09:13:01 +000032static const 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
Manuel Novoa III cad53642003-03-19 09:13:01 +000044static const 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
Eric Andersenb077c9f2002-12-06 21:39:48 +000086#define SRC_BUF_SIZE 45 // This *MUST* be a multiple of 3
87#define DST_BUF_SIZE 4 * ((SRC_BUF_SIZE + 2) / 3)
Glenn L McGrath089deca2001-07-28 21:06:13 +000088int uuencode_main(int argc, char **argv)
89{
Eric Andersenb077c9f2002-12-06 21:39:48 +000090 const int src_buf_size = SRC_BUF_SIZE;
91 const int dst_buf_size = DST_BUF_SIZE;
Tim Riker95bf6da2002-05-01 05:57:16 +000092 int write_size = dst_buf_size;
Glenn L McGrath089deca2001-07-28 21:06:13 +000093 struct stat stat_buf;
94 FILE *src_stream = stdin;
Manuel Novoa III cad53642003-03-19 09:13:01 +000095 const char *tbl;
Glenn L McGrath089deca2001-07-28 21:06:13 +000096 size_t size;
97 mode_t mode;
Eric Andersenb077c9f2002-12-06 21:39:48 +000098 RESERVE_CONFIG_BUFFER(src_buf, SRC_BUF_SIZE + 1);
99 RESERVE_CONFIG_BUFFER(dst_buf, DST_BUF_SIZE + 1);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000100
Manuel Novoa III cad53642003-03-19 09:13:01 +0000101 tbl = tbl_std;
102 if (bb_getopt_ulflags(argc, argv, "m") & 1) {
103 tbl = tbl_base64;
Glenn L McGrath089deca2001-07-28 21:06:13 +0000104 }
105
106 switch (argc - optind) {
107 case 2:
Manuel Novoa III cad53642003-03-19 09:13:01 +0000108 src_stream = bb_xfopen(argv[optind], "r");
109 if (stat(argv[optind], &stat_buf) < 0) {
110 bb_perror_msg_and_die("stat");
111 }
Glenn L McGrath089deca2001-07-28 21:06:13 +0000112 mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
113 if (src_stream == stdout) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000114 puts("NULL");
Glenn L McGrath089deca2001-07-28 21:06:13 +0000115 }
116 break;
117 case 1:
Glenn L McGrathb6071b62001-07-29 06:04:26 +0000118 mode = 0666 & ~umask(0666);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000119 break;
120 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +0000121 bb_show_usage();
Glenn L McGrath089deca2001-07-28 21:06:13 +0000122 }
123
Manuel Novoa III cad53642003-03-19 09:13:01 +0000124 bb_printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000125
126 while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) {
Tim Riker95bf6da2002-05-01 05:57:16 +0000127 if (size != src_buf_size) {
128 /* write_size is always 60 until the last line */
129 write_size=(4 * ((size + 2) / 3));
130 /* pad with 0s so we can just encode extra bits */
131 memset(&src_buf[size], 0, src_buf_size - size);
132 }
Glenn L McGrath089deca2001-07-28 21:06:13 +0000133 /* Encode the buffer we just read in */
Glenn L McGratheba26052001-07-29 05:47:33 +0000134 uuencode(src_buf, dst_buf, size, tbl);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000135
Tim Riker95bf6da2002-05-01 05:57:16 +0000136 putchar('\n');
137 if (tbl == tbl_std) {
138 putchar(tbl[size]);
139 }
140 if (fwrite(dst_buf, 1, write_size, stdout) != write_size) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000141 bb_perror_msg_and_die(bb_msg_write_error);
Tim Riker95bf6da2002-05-01 05:57:16 +0000142 }
Glenn L McGrath089deca2001-07-28 21:06:13 +0000143 }
Manuel Novoa III cad53642003-03-19 09:13:01 +0000144 bb_printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n");
Glenn L McGrath089deca2001-07-28 21:06:13 +0000145
Manuel Novoa III cad53642003-03-19 09:13:01 +0000146 bb_xferror(src_stream, "source"); /* TODO - Fix this! */
147
148 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
Glenn L McGrath089deca2001-07-28 21:06:13 +0000149}