|
Added
Link Here
|
| 1 |
/*********************************************************************\ |
| 2 |
|
| 3 |
MODULE NAME: b64.c |
| 4 |
|
| 5 |
AUTHOR: Bob Trower 08/04/01 |
| 6 |
|
| 7 |
PROJECT: Crypt Data Packaging |
| 8 |
|
| 9 |
COPYRIGHT: Copyright (c) Trantor Standard Systems Inc., 2001 |
| 10 |
|
| 11 |
NOTE: This source code may be used as you wish, subject to |
| 12 |
the MIT license. See the LICENCE section below. |
| 13 |
|
| 14 |
DESCRIPTION: |
| 15 |
This little utility implements the Base64 |
| 16 |
Content-Transfer-Encoding standard described in |
| 17 |
RFC1113 (http://www.faqs.org/rfcs/rfc1113.html). |
| 18 |
|
| 19 |
This is the coding scheme used by MIME to allow |
| 20 |
binary data to be transferred by SMTP mail. |
| 21 |
|
| 22 |
Groups of 3 bytes from a binary stream are coded as |
| 23 |
groups of 4 bytes in a text stream. |
| 24 |
|
| 25 |
The input stream is 'padded' with zeros to create |
| 26 |
an input that is an even multiple of 3. |
| 27 |
|
| 28 |
A special character ('=') is used to denote padding so |
| 29 |
that the stream can be decoded back to its exact size. |
| 30 |
|
| 31 |
Encoded output is formatted in lines which should |
| 32 |
be a maximum of 72 characters to conform to the |
| 33 |
specification. This program defaults to 72 characters, |
| 34 |
but will allow more or less through the use of a |
| 35 |
switch. The program enforces a minimum line size |
| 36 |
of 4 characters. |
| 37 |
|
| 38 |
Example encoding: |
| 39 |
|
| 40 |
The stream 'ABCD' is 32 bits long. It is mapped as |
| 41 |
follows: |
| 42 |
|
| 43 |
ABCD |
| 44 |
|
| 45 |
A (65) B (66) C (67) D (68) (None) (None) |
| 46 |
01000001 01000010 01000011 01000100 |
| 47 |
|
| 48 |
16 (Q) 20 (U) 9 (J) 3 (D) 17 (R) 0 (A) NA (=) NA (=) |
| 49 |
010000 010100 001001 000011 010001 000000 000000 000000 |
| 50 |
|
| 51 |
|
| 52 |
QUJDRA== |
| 53 |
|
| 54 |
Decoding is the process in reverse. A 'decode' lookup |
| 55 |
table has been created to avoid string scans. |
| 56 |
|
| 57 |
DESIGN GOALS: Specifically: |
| 58 |
Code is a stand-alone utility to perform base64 |
| 59 |
encoding/decoding. It should be genuinely useful |
| 60 |
when the need arises and it meets a need that is |
| 61 |
likely to occur for some users. |
| 62 |
Code acts as sample code to show the author's |
| 63 |
design and coding style. |
| 64 |
|
| 65 |
Generally: |
| 66 |
This program is designed to survive: |
| 67 |
Everything you need is in a single source file. |
| 68 |
It compiles cleanly using a vanilla ANSI C compiler. |
| 69 |
It does its job correctly with a minimum of fuss. |
| 70 |
The code is not overly clever, not overly simplistic |
| 71 |
and not overly verbose. |
| 72 |
Access is 'cut and paste' from a web page. |
| 73 |
Terms of use are reasonable. |
| 74 |
|
| 75 |
VALIDATION: Non-trivial code is never without errors. This |
| 76 |
file likely has some problems, since it has only |
| 77 |
been tested by the author. It is expected with most |
| 78 |
source code that there is a period of 'burn-in' when |
| 79 |
problems are identified and corrected. That being |
| 80 |
said, it is possible to have 'reasonably correct' |
| 81 |
code by following a regime of unit test that covers |
| 82 |
the most likely cases and regression testing prior |
| 83 |
to release. This has been done with this code and |
| 84 |
it has a good probability of performing as expected. |
| 85 |
|
| 86 |
Unit Test Cases: |
| 87 |
|
| 88 |
case 0:empty file: |
| 89 |
CASE0.DAT -> -> |
| 90 |
(Zero length target file created |
| 91 |
on both encode and decode.) |
| 92 |
|
| 93 |
case 1:One input character: |
| 94 |
CASE1.DAT A -> QQ== -> A |
| 95 |
|
| 96 |
case 2:Two input characters: |
| 97 |
CASE2.DAT AB -> QUJD -> AB |
| 98 |
|
| 99 |
case 3:Three input characters: |
| 100 |
CASE3.DAT ABC -> QUJD -> ABC |
| 101 |
|
| 102 |
case 4:Four input characters: |
| 103 |
case4.dat ABCD -> QUJDRA== -> ABCD |
| 104 |
|
| 105 |
case 5:All chars from 0 to ff, linesize set to 50: |
| 106 |
|
| 107 |
AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj |
| 108 |
JCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZH |
| 109 |
SElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWpr |
| 110 |
bG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P |
| 111 |
kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKz |
| 112 |
tLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX |
| 113 |
2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7 |
| 114 |
/P3+/w== |
| 115 |
|
| 116 |
case 6:Mime Block from e-mail: |
| 117 |
(Data same as test case 5) |
| 118 |
|
| 119 |
case 7: Large files: |
| 120 |
Tested 28 MB file in/out. |
| 121 |
|
| 122 |
case 8: Random Binary Integrity: |
| 123 |
This binary program (b64.exe) was encoded to base64, |
| 124 |
back to binary and then executed. |
| 125 |
|
| 126 |
case 9 Stress: |
| 127 |
All files in a working directory encoded/decoded |
| 128 |
and compared with file comparison utility to |
| 129 |
ensure that multiple runs do not cause problems |
| 130 |
such as exhausting file handles, tmp storage, etc. |
| 131 |
|
| 132 |
------------- |
| 133 |
|
| 134 |
Syntax, operation and failure: |
| 135 |
All options/switches tested. Performs as |
| 136 |
expected. |
| 137 |
|
| 138 |
case 10: |
| 139 |
No Args -- Shows Usage Screen |
| 140 |
Return Code 1 (Invalid Syntax) |
| 141 |
case 11: |
| 142 |
One Arg (invalid) -- Shows Usage Screen |
| 143 |
Return Code 1 (Invalid Syntax) |
| 144 |
case 12: |
| 145 |
One Arg Help (-?) -- Shows detailed Usage Screen. |
| 146 |
Return Code 0 (Success -- help request is valid). |
| 147 |
case 13: |
| 148 |
One Arg Help (-h) -- Shows detailed Usage Screen. |
| 149 |
Return Code 0 (Success -- help request is valid). |
| 150 |
case 14: |
| 151 |
One Arg (valid) -- Uses stdin/stdout (filter) |
| 152 |
Return Code 0 (Sucess) |
| 153 |
case 15: |
| 154 |
Two Args (invalid file) -- shows system error. |
| 155 |
Return Code 2 (File Error) |
| 156 |
case 16: |
| 157 |
Encode non-existent file -- shows system error. |
| 158 |
Return Code 2 (File Error) |
| 159 |
case 17: |
| 160 |
Out of disk space -- shows system error. |
| 161 |
Return Code 3 (File I/O Error) |
| 162 |
|
| 163 |
------------- |
| 164 |
|
| 165 |
Compile/Regression test: |
| 166 |
gcc compiled binary under Cygwin |
| 167 |
Microsoft Visual Studio under Windows 2000 |
| 168 |
Microsoft Version 6.0 C under Windows 2000 |
| 169 |
|
| 170 |
DEPENDENCIES: None |
| 171 |
|
| 172 |
LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc. |
| 173 |
|
| 174 |
Permission is hereby granted, free of charge, to any person |
| 175 |
obtaining a copy of this software and associated |
| 176 |
documentation files (the "Software"), to deal in the |
| 177 |
Software without restriction, including without limitation |
| 178 |
the rights to use, copy, modify, merge, publish, distribute, |
| 179 |
sublicense, and/or sell copies of the Software, and to |
| 180 |
permit persons to whom the Software is furnished to do so, |
| 181 |
subject to the following conditions: |
| 182 |
|
| 183 |
The above copyright notice and this permission notice shall |
| 184 |
be included in all copies or substantial portions of the |
| 185 |
Software. |
| 186 |
|
| 187 |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY |
| 188 |
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
| 189 |
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
| 190 |
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS |
| 191 |
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| 192 |
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| 193 |
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| 194 |
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 195 |
|
| 196 |
VERSION HISTORY: |
| 197 |
Bob Trower 08/04/01 -- Create Version 0.00.00B |
| 198 |
vss 04/25/01 -- Added decode_buffer |
| 199 |
|
| 200 |
\******************************************************************* */ |
| 201 |
|
| 202 |
#include <stdio.h> |
| 203 |
#include <stdlib.h> |
| 204 |
|
| 205 |
/* |
| 206 |
** Translation Table as described in RFC1113 |
| 207 |
*/ |
| 208 |
static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 209 |
|
| 210 |
/* |
| 211 |
** Translation Table to decode (created by author) |
| 212 |
*/ |
| 213 |
static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq"; |
| 214 |
|
| 215 |
/* |
| 216 |
** encodeblock |
| 217 |
** |
| 218 |
** encode 3 8-bit binary bytes as 4 '6-bit' characters |
| 219 |
*/ |
| 220 |
void encodeblock( unsigned char in[3], unsigned char out[4], int len ) |
| 221 |
{ |
| 222 |
out[0] = cb64[ in[0] >> 2 ]; |
| 223 |
out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ]; |
| 224 |
out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '='); |
| 225 |
out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '='); |
| 226 |
} |
| 227 |
|
| 228 |
/* |
| 229 |
** encode |
| 230 |
** |
| 231 |
** base64 encode a stream adding padding and line breaks as per spec. |
| 232 |
*/ |
| 233 |
void encode( FILE *infile, FILE *outfile, int linesize ) |
| 234 |
{ |
| 235 |
unsigned char in[3], out[4]; |
| 236 |
int i, len, blocksout = 0; |
| 237 |
|
| 238 |
while( !feof( infile ) ) { |
| 239 |
len = 0; |
| 240 |
for( i = 0; i < 3; i++ ) { |
| 241 |
in[i] = (unsigned char) getc( infile ); |
| 242 |
if( !feof( infile ) ) { |
| 243 |
len++; |
| 244 |
} |
| 245 |
else { |
| 246 |
in[i] = 0; |
| 247 |
} |
| 248 |
} |
| 249 |
if( len ) { |
| 250 |
encodeblock( in, out, len ); |
| 251 |
for( i = 0; i < 4; i++ ) { |
| 252 |
putc( out[i], outfile ); |
| 253 |
} |
| 254 |
blocksout++; |
| 255 |
} |
| 256 |
if( blocksout >= (linesize/4) || feof( infile ) ) { |
| 257 |
if( blocksout ) { |
| 258 |
fprintf( outfile, "\r\n" ); |
| 259 |
} |
| 260 |
blocksout = 0; |
| 261 |
} |
| 262 |
} |
| 263 |
} |
| 264 |
|
| 265 |
/* |
| 266 |
** decodeblock |
| 267 |
** |
| 268 |
** decode 4 '6-bit' characters into 3 8-bit binary bytes |
| 269 |
*/ |
| 270 |
void decodeblock( unsigned char in[4], unsigned char out[3] ) |
| 271 |
{ |
| 272 |
out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4); |
| 273 |
out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2); |
| 274 |
out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]); |
| 275 |
} |
| 276 |
|
| 277 |
/* |
| 278 |
** decode |
| 279 |
** |
| 280 |
** decode a base64 encoded stream discarding padding, line breaks and noise |
| 281 |
*/ |
| 282 |
void decode( FILE *infile, FILE *outfile ) |
| 283 |
{ |
| 284 |
unsigned char in[4], out[3], v; |
| 285 |
int i, len; |
| 286 |
|
| 287 |
while( !feof( infile ) ) { |
| 288 |
for( len = 0, i = 0; i < 4 && !feof( infile ); i++ ) { |
| 289 |
v = 0; |
| 290 |
while( !feof( infile ) && v == 0 ) { |
| 291 |
v = (unsigned char) getc( infile ); |
| 292 |
v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]); |
| 293 |
if( v ) { |
| 294 |
v = (unsigned char) ((v == '$') ? 0 : v - 61); |
| 295 |
} |
| 296 |
} |
| 297 |
if( !feof( infile ) ) { |
| 298 |
len++; |
| 299 |
if( v ) { |
| 300 |
in[ i ] = (unsigned char) (v - 1); |
| 301 |
} |
| 302 |
} |
| 303 |
else { |
| 304 |
in[i] = 0; |
| 305 |
} |
| 306 |
} |
| 307 |
if( len ) { |
| 308 |
decodeblock( in, out ); |
| 309 |
for( i = 0; i < len - 1; i++ ) { |
| 310 |
putc( out[i], outfile ); |
| 311 |
} |
| 312 |
} |
| 313 |
} |
| 314 |
} |
| 315 |
|
| 316 |
// tmp |
| 317 |
#ifdef __cplusplus |
| 318 |
extern "C" |
| 319 |
#endif |
| 320 |
int decode_buffer( const char* inBuffer, int inLen, char* outBuffer) |
| 321 |
{ |
| 322 |
unsigned char in[4], out[3], v; |
| 323 |
int i, len; |
| 324 |
int inp = 0, outp = 0; |
| 325 |
|
| 326 |
while( inp < inLen ) { |
| 327 |
for( len = 0, i = 0; i < 4 && inp < inLen; i++ ) { |
| 328 |
v = 0; |
| 329 |
while( inp < inLen && v == 0 ) { |
| 330 |
v = (unsigned char) inBuffer[ inp++ ]; |
| 331 |
v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]); |
| 332 |
if( v ) { |
| 333 |
v = (unsigned char) ((v == '$') ? 0 : v - 61); |
| 334 |
} |
| 335 |
} |
| 336 |
if( inp < inLen ) { |
| 337 |
len++; |
| 338 |
if( v ) { |
| 339 |
in[ i ] = (unsigned char) (v - 1); |
| 340 |
} |
| 341 |
} |
| 342 |
else { |
| 343 |
in[i] = 0; |
| 344 |
} |
| 345 |
} |
| 346 |
if( len ) { |
| 347 |
decodeblock( in, out ); |
| 348 |
for( i = 0; i < len - 1; i++ ) { |
| 349 |
outBuffer[ outp++ ] = out[i]; |
| 350 |
} |
| 351 |
} |
| 352 |
} |
| 353 |
return outp; |
| 354 |
} |
| 355 |
|
| 356 |
/* |
| 357 |
** returnable errors |
| 358 |
** |
| 359 |
** Error codes returned to the operating system. |
| 360 |
** |
| 361 |
*/ |
| 362 |
#define B64_SYNTAX_ERROR 1 |
| 363 |
#define B64_FILE_ERROR 2 |
| 364 |
#define B64_FILE_IO_ERROR 3 |
| 365 |
#define B64_ERROR_OUT_CLOSE 4 |
| 366 |
#define B64_LINE_SIZE_TO_MIN 5 |
| 367 |
|
| 368 |
/* |
| 369 |
** b64_message |
| 370 |
** |
| 371 |
** Gather text messages in one place. |
| 372 |
** |
| 373 |
*/ |
| 374 |
char *b64_message( int errcode ) |
| 375 |
{ |
| 376 |
#define B64_MAX_MESSAGES 6 |
| 377 |
char *msgs[ B64_MAX_MESSAGES ] = { |
| 378 |
"b64:000:Invalid Message Code.", |
| 379 |
"b64:001:Syntax Error -- check help for usage.", |
| 380 |
"b64:002:File Error Opening/Creating Files.", |
| 381 |
"b64:003:File I/O Error -- Note: output file not removed.", |
| 382 |
"b64:004:Error on output file close.", |
| 383 |
"b64:004:linesize set to minimum." |
| 384 |
}; |
| 385 |
char *msg = msgs[ 0 ]; |
| 386 |
|
| 387 |
if( errcode > 0 && errcode < B64_MAX_MESSAGES ) { |
| 388 |
msg = msgs[ errcode ]; |
| 389 |
} |
| 390 |
|
| 391 |
return( msg ); |
| 392 |
} |
| 393 |
|
| 394 |
/* |
| 395 |
** b64 |
| 396 |
** |
| 397 |
** 'engine' that opens streams and calls encode/decode |
| 398 |
*/ |
| 399 |
|
| 400 |
int b64( int opt, char *infilename, char *outfilename, int linesize ) |
| 401 |
{ |
| 402 |
FILE *infile; |
| 403 |
int retcode = B64_FILE_ERROR; |
| 404 |
|
| 405 |
if( !infilename ) { |
| 406 |
infile = stdin; |
| 407 |
} |
| 408 |
else { |
| 409 |
infile = fopen( infilename, "rb" ); |
| 410 |
} |
| 411 |
if( !infile ) { |
| 412 |
perror( infilename ); |
| 413 |
} |
| 414 |
else { |
| 415 |
FILE *outfile; |
| 416 |
if( !outfilename ) { |
| 417 |
outfile = stdout; |
| 418 |
} |
| 419 |
else { |
| 420 |
outfile = fopen( outfilename, "wb" ); |
| 421 |
} |
| 422 |
if( !outfile ) { |
| 423 |
perror( outfilename ); |
| 424 |
} |
| 425 |
else { |
| 426 |
if( opt == 'e' ) { |
| 427 |
encode( infile, outfile, linesize ); |
| 428 |
} |
| 429 |
else { |
| 430 |
decode( infile, outfile ); |
| 431 |
} |
| 432 |
if (ferror( infile ) || ferror( outfile )) { |
| 433 |
retcode = B64_FILE_IO_ERROR; |
| 434 |
} |
| 435 |
else { |
| 436 |
retcode = 0; |
| 437 |
} |
| 438 |
if( outfile != stdout ) { |
| 439 |
if( fclose( outfile ) != 0 ) { |
| 440 |
perror( b64_message( B64_ERROR_OUT_CLOSE ) ); |
| 441 |
retcode = B64_FILE_IO_ERROR; |
| 442 |
} |
| 443 |
} |
| 444 |
} |
| 445 |
if( infile != stdin ) { |
| 446 |
fclose( infile ); |
| 447 |
} |
| 448 |
} |
| 449 |
|
| 450 |
return( retcode ); |
| 451 |
} |
| 452 |
|
| 453 |
/* |
| 454 |
** showuse |
| 455 |
** |
| 456 |
** display usage information, help, version info |
| 457 |
*/ |
| 458 |
void showuse( int morehelp ) |
| 459 |
{ |
| 460 |
{ |
| 461 |
printf( "\n" ); |
| 462 |
printf( " b64 (Base64 Encode/Decode) Bob Trower 08/03/01 \n" ); |
| 463 |
printf( " (C) Copr Bob Trower 1986-01. Version 0.00B \n" ); |
| 464 |
printf( " Usage: b64 -option [ -l num ] [<FileIn> [<FileOut>]] \n" ); |
| 465 |
printf( " Purpose: This program is a simple utility that implements\n" ); |
| 466 |
printf( " Base64 Content-Transfer-Encoding (RFC1113). \n" ); |
| 467 |
} |
| 468 |
if( !morehelp ) { |
| 469 |
printf( " Use -h option for additional help. \n" ); |
| 470 |
} |
| 471 |
else { |
| 472 |
printf( " Options: -e encode to Base64 -h This help text. \n" ); |
| 473 |
printf( " -d decode from Base64 -? This help text. \n" ); |
| 474 |
printf( " Note: -l use to change line size (from 72 characters)\n" ); |
| 475 |
printf( " Returns: 0 = success. Non-zero is an error code. \n" ); |
| 476 |
printf( " ErrCode: 1 = Bad Syntax, 2 = File Open, 3 = File I/O \n" ); |
| 477 |
printf( " Example: b64 -e binfile b64file <- Encode to b64 \n" ); |
| 478 |
printf( " b64 -d b64file binfile <- Decode from b64 \n" ); |
| 479 |
printf( " b64 -e -l40 infile outfile <- Line Length of 40 \n" ); |
| 480 |
printf( " Note: Will act as a filter, but this should only be \n" ); |
| 481 |
printf( " used on text files due to translations made by \n" ); |
| 482 |
printf( " operating systems. \n" ); |
| 483 |
printf( " Release: 0.00.00, Tue Aug 7 2:00:00 2001, ANSI-SOURCE C\n" ); |
| 484 |
} |
| 485 |
} |
| 486 |
|
| 487 |
#define B64_DEF_LINE_SIZE 72 |
| 488 |
#define B64_MIN_LINE_SIZE 4 |
| 489 |
|
| 490 |
#define THIS_OPT(ac, av) (ac > 1 ? av[1][0] == '-' ? av[1][1] : 0 : 0) |
| 491 |
|
| 492 |
/* |
| 493 |
** main |
| 494 |
** |
| 495 |
** parse and validate arguments and call b64 engine or help |
| 496 |
*/ |
| 497 |
|
| 498 |
#ifdef BASE64_MAIN |
| 499 |
int main( int argc, char **argv ) |
| 500 |
{ |
| 501 |
int opt = 0; |
| 502 |
int retcode = 0; |
| 503 |
int linesize = B64_DEF_LINE_SIZE; |
| 504 |
char *infilename = NULL, *outfilename = NULL; |
| 505 |
|
| 506 |
while( THIS_OPT( argc, argv ) ) { |
| 507 |
switch( THIS_OPT(argc, argv) ) { |
| 508 |
case 'l': |
| 509 |
linesize = atoi( &(argv[1][2]) ); |
| 510 |
if( linesize < B64_MIN_LINE_SIZE ) { |
| 511 |
linesize = B64_MIN_LINE_SIZE; |
| 512 |
printf( "%s\n", b64_message( B64_LINE_SIZE_TO_MIN ) ); |
| 513 |
} |
| 514 |
break; |
| 515 |
case '?': |
| 516 |
case 'h': |
| 517 |
opt = 'h'; |
| 518 |
break; |
| 519 |
case 'e': |
| 520 |
case 'd': |
| 521 |
opt = THIS_OPT(argc, argv); |
| 522 |
break; |
| 523 |
default: |
| 524 |
opt = 0; |
| 525 |
break; |
| 526 |
} |
| 527 |
argv++; |
| 528 |
argc--; |
| 529 |
} |
| 530 |
switch( opt ) { |
| 531 |
case 'e': |
| 532 |
case 'd': |
| 533 |
infilename = argc > 1 ? argv[1] : NULL; |
| 534 |
outfilename = argc > 2 ? argv[2] : NULL; |
| 535 |
retcode = b64( opt, infilename, outfilename, linesize ); |
| 536 |
break; |
| 537 |
case 0: |
| 538 |
retcode = B64_SYNTAX_ERROR; |
| 539 |
case 'h': |
| 540 |
showuse( opt ); |
| 541 |
break; |
| 542 |
|
| 543 |
} |
| 544 |
if( retcode ) { |
| 545 |
printf( "%s\n", b64_message( retcode ) ); |
| 546 |
} |
| 547 |
|
| 548 |
return( retcode ); |
| 549 |
} |
| 550 |
|
| 551 |
#endif |