1/* vi: set sw=4 ts=4: */ 2/* 3 * Copyright (C) 2000 by Glenn McGrath 4 * 5 * 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. 7 * 8 * 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. 12 * 13 * 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. 17 * 18 * 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. 21 */ 22#include <getopt.h> 23#include <stdio.h> 24#include <stdlib.h> 25#include <sys/types.h> 26#include <sys/stat.h> 27#include <unistd.h> 28#include "busybox.h" 29 30#define FILE_SUPPORT 1 31 32/* Conversion table. for base 64 */ 33static char tbl_base64[64] = { 34 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 35 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 36 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 37 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 38 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 39 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 40 'w', 'x', 'y', 'z', '0', '1', '2', '3', 41 '4', '5', '6', '7', '8', '9', '+', '/' 42}; 43 44static char tbl_std[64] = { 45 '`', '!', '"', '#', '$', '%', '&', '\'', 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', 52 'X', 'Y', 'Z', '[', '\\', ']', '^', '_' 53}; 54 55/* 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)) 60 */ 61static void uuencode (const char *s, const char *store, const int length, const char *tbl) 62{ 63 int i; 64 unsigned char *p = (unsigned char *)store; 65 66 /* 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) { 76 *(p - 1) = '='; 77 } 78 else if (i == length + 2) { 79 *(p - 1) = *(p - 2) = '='; 80 } 81 /* ...and zero-terminate it. */ 82 *p = '\0'; 83} 84 85int uuencode_main(int argc, char **argv) 86{ 87 const int src_buf_size = 60; // This *MUST* be a multiple of 3 88 const int dst_buf_size = 4 * ((src_buf_size + 2) / 3); 89 RESERVE_BB_BUFFER(src_buf, src_buf_size + 1); 90 RESERVE_BB_BUFFER(dst_buf, dst_buf_size + 1); 91 struct stat stat_buf; 92 FILE *src_stream = stdin; 93 char *tbl = tbl_std; 94 size_t size; 95 mode_t mode; 96 int opt; 97 int column = 0; 98 int write_size = 0; 99 int remaining; 100 int buffer_offset = 0; 101#ifdef FILE_SUPPORT 102 char *ufile=NULL; //Added by Joey to save encode into file 103 char *fp; //Added by Joey to save encode into file 104#endif 105 106#ifdef FILE_SUPPORT 107 while ((opt = getopt(argc, argv, "mf:")) != -1) { 108#else 109 while ((opt = getopt(argc, argv, "m")) != -1) { 110#endif 111 switch (opt) { 112 case 'm': 113 tbl = tbl_base64; 114 break; 115#ifdef FILE_SUPPORT 116 case 'f': 117 ufile = optarg; 118 break; 119#endif 120 default: 121 show_usage(); 122 } 123 } 124 125 switch (argc - optind) { 126 case 2: 127 src_stream = xfopen(argv[optind], "r"); 128 stat(argv[optind], &stat_buf); 129 mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 130 if (src_stream == stdout) { 131 printf("NULL\n"); 132 } 133 break; 134 case 1: 135 mode = 0666 & ~umask(0666); 136 break; 137 default: 138 show_usage(); 139 } 140 141 printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]); 142 143#ifdef FILE_SUPPORT 144 // Added by Joey 145 fp = NULL; 146 if (ufile!=NULL) fp=fopen(ufile, "w"); 147 if (fp==NULL) fp=stdout; 148#endif 149 150 while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) { 151 /* Encode the buffer we just read in */ 152 uuencode(src_buf, dst_buf, size, tbl); 153 154 /* Write the buffer to stdout, wrapping at 60 chars. 155 * This looks overly complex, but it gets tricky as 156 * the line has to continue to wrap correctly if we 157 * have to refill the buffer 158 * 159 * Improvments most welcome 160 */ 161 162 /* Initialise values for the new buffer */ 163 remaining = 4 * ((size + 2) / 3); 164 buffer_offset = 0; 165 166 /* Write the buffer to stdout, wrapping at 60 chars 167 * starting from the column the last buffer ran out 168 */ 169 do { 170 if (remaining > (60 - column)) { 171 write_size = 60 - column; 172 } 173 else if (remaining < 60) { 174 write_size = remaining; 175 } else { 176 write_size = 60; 177 } 178 179 /* Setup a new row if required */ 180 if (column == 0) { 181#ifdef FILE_SUPPORT 182 fputc('\n', fp); 183#else 184 putchar('\n'); 185#endif 186 if (tbl == tbl_std) { 187#ifdef FILE_SUPPORT 188 fputc('M', fp); 189#else 190 putchar('M'); 191#endif 192 } 193 } 194 /* Write to the 60th column */ 195#ifdef FILE_SUPPORT 196 // Modify by Joey to write to file 197 if (fwrite(&dst_buf[buffer_offset], 1, write_size, fp) != write_size) { 198#else 199 if (fwrite(&dst_buf[buffer_offset], 1, write_size, stdout) != write_size) { 200#endif 201 perror("Couldnt finish writing"); 202 } 203 /* Update variables based on last write */ 204 buffer_offset += write_size; 205 remaining -= write_size; 206 column += write_size; 207 if (column % 60 == 0) { 208 column = 0; 209 } 210 } while (remaining > 0); 211 } 212 213#ifdef FILE_SUPPORT 214 fputc('\n', fp); 215#else 216 printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n"); 217#endif 218 219 return(EXIT_SUCCESS); 220} 221