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/* Conversion table. for base 64 */ 32static char tbl_base64[64] = { 33 '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', 40 '4', '5', '6', '7', '8', '9', '+', '/' 41}; 42 43static char tbl_std[64] = { 44 '`', '!', '"', '#', '$', '%', '&', '\'', 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', 51 'X', 'Y', 'Z', '[', '\\', ']', '^', '_' 52}; 53 54/* 55 * Encode the string S of length LENGTH to base64 format and place it 56 * to STORE. STORE will be 0-terminated, and must point to a writable 57 * buffer of at least 1+BASE64_LENGTH(length) bytes. 58 * where BASE64_LENGTH(len) = (4 * ((LENGTH + 2) / 3)) 59 */ 60static void uuencode (const unsigned char *s, const char *store, const int length, const char *tbl) 61{ 62 int i; 63 unsigned char *p = (unsigned char *)store; 64 65 /* Transform the 3x8 bits to 4x6 bits, as required by base64. */ 66 for (i = 0; i < length; i += 3) { 67 *p++ = tbl[s[0] >> 2]; 68 *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)]; 69 *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)]; 70 *p++ = tbl[s[2] & 0x3f]; 71 s += 3; 72 } 73 /* Pad the result if necessary... */ 74 if (i == length + 1) { 75 *(p - 1) = '='; 76 } 77 else if (i == length + 2) { 78 *(p - 1) = *(p - 2) = '='; 79 } 80 /* ...and zero-terminate it. */ 81 *p = '\0'; 82} 83 84int uuencode_main(int argc, char **argv) 85{ 86 const int src_buf_size = 60; // This *MUST* be a multiple of 3 87 const int dst_buf_size = 4 * ((src_buf_size + 2) / 3); 88 RESERVE_BB_BUFFER(src_buf, src_buf_size + 1); 89 RESERVE_BB_BUFFER(dst_buf, dst_buf_size + 1); 90 struct stat stat_buf; 91 FILE *src_stream = stdin; 92 char *tbl = tbl_std; 93 size_t size; 94 mode_t mode; 95 int opt; 96 int column = 0; 97 int write_size = 0; 98 int remaining; 99 int buffer_offset = 0; 100#ifdef FILE_SUPPORT 101 char *ufile=NULL; //Added by Joey to save encode into file 102 char *fp; //Added by Joey to save encode into file 103#endif 104 105#ifdef FILE_SUPPORT 106 while ((opt = getopt(argc, argv, "mf:")) != -1) { 107#else 108 while ((opt = getopt(argc, argv, "m")) != -1) { 109#endif 110 switch (opt) { 111 case 'm': 112 tbl = tbl_base64; 113 break; 114#ifdef FILE_SUPPORT 115 case 'f': 116 ufile = optarg; 117 break; 118#endif 119 default: 120 show_usage(); 121 } 122 } 123 124 switch (argc - optind) { 125 case 2: 126 src_stream = xfopen(argv[optind], "r"); 127 stat(argv[optind], &stat_buf); 128 mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 129 if (src_stream == stdout) { 130 printf("NULL\n"); 131 } 132 break; 133 case 1: 134 mode = 0666 & ~umask(0666); 135 break; 136 default: 137 show_usage(); 138 } 139 140#ifdef REMOVE_WL600 141 printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]); 142#endif 143 144#ifdef FILE_SUPPORT 145 // Added by Joey 146 fp = NULL; 147 if (ufile!=NULL) fp=fopen(ufile, "w"); 148 if (fp==NULL) fp=stdout; 149#endif 150 151 while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) { 152 /* Encode the buffer we just read in */ 153 uuencode(src_buf, dst_buf, size, tbl); 154 155 /* Write the buffer to stdout, wrapping at 60 chars. 156 * This looks overly complex, but it gets tricky as 157 * the line has to continue to wrap correctly if we 158 * have to refill the buffer 159 * 160 * Improvments most welcome 161 */ 162 163 /* Initialise values for the new buffer */ 164 remaining = 4 * ((size + 2) / 3); 165 buffer_offset = 0; 166 167 /* Write the buffer to stdout, wrapping at 60 chars 168 * starting from the column the last buffer ran out 169 */ 170 do { 171 if (remaining > (60 - column)) { 172 write_size = 60 - column; 173 } 174 else if (remaining < 60) { 175 write_size = remaining; 176 } else { 177 write_size = 60; 178 } 179 180 /* Setup a new row if required */ 181 if (column == 0) 182 { 183#ifdef FILE_SUPPORT 184 fputc('\n', fp); 185#else 186 putchar('\n'); 187#endif 188 if (tbl == tbl_std) { 189#ifdef FILE_SUPPORT 190 fputc('M', fp); 191#else 192 putchar('M'); 193#endif 194 } 195 } 196#ifdef FILE_SUPPORT 197 // Modify by Joey to write to file 198 if (fwrite(&dst_buf[buffer_offset], 1, write_size, fp) != write_size) { 199#else 200 if (fwrite(&dst_buf[buffer_offset], 1, write_size, stdout) != write_size) { 201#endif 202 perror("Couldnt finish writing"); 203 } 204 /* Update variables based on last write */ 205 buffer_offset += write_size; 206 remaining -= write_size; 207 column += write_size; 208 if (column % 60 == 0) { 209 column = 0; 210 } 211 } while (remaining > 0); 212 } 213 214#ifdef FILE_SUPPORT 215 fputc('\n', fp); 216#else 217 printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n"); 218#endif 219 return(EXIT_SUCCESS); 220} 221