- int opt;
- struct stat sb;
- int mode;
-
- trans_ptr = uu_std; /* Standard encoding is old uu format */
-
- /* Parse any options */
- while ((opt = getopt (argc, argv, "m")) != EOF) {
- switch (opt) {
- case 'm':
- trans_ptr = uu_base64;
- break;
-
- case 0:
- break;
-
- default:
- usage(uuencode_usage);
- }
- }
-
- switch (argc - optind) {
- case 2:
- /* Optional first argument is input file. */
- if (!freopen (argv[optind], "r", stdin) || fstat (fileno (stdin), &sb)) {
- errorMsg("%s: %s\n", argv[optind], strerror(errno));
- return EXIT_FAILURE;
- }
- mode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
- optind++;
- break;
-
- case 1:
- mode = RW & ~umask (RW);
- break;
-
- case 0:
- default:
- usage(uuencode_usage);
- }
-
- printf("begin%s %o %s\n", trans_ptr == uu_std ? "" : "-base64",
- mode, argv[optind]);
- encode();
- printf(trans_ptr == uu_std ? "end\n" : "====\n");
- if (ferror (stdout)) {
- errorMsg("Write error\n");
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
+ const int src_buf_size = 60; // This *MUST* be a multiple of 3
+ const int dst_buf_size = 4 * ((src_buf_size + 2) / 3);
+ RESERVE_BB_BUFFER(src_buf, src_buf_size + 1);
+ RESERVE_BB_BUFFER(dst_buf, dst_buf_size + 1);
+ struct stat stat_buf;
+ FILE *src_stream = stdin;
+ char *tbl = tbl_std;
+ size_t size;
+ mode_t mode;
+ int opt;
+ int column = 0;
+ int write_size = 0;
+ int remaining;
+ int buffer_offset = 0;
+
+ while ((opt = getopt(argc, argv, "m")) != -1) {
+ switch (opt) {
+ case 'm':
+ tbl = tbl_base64;
+ break;
+ default:
+ show_usage();
+ }
+ }
+
+ switch (argc - optind) {
+ case 2:
+ src_stream = xfopen(argv[optind], "r");
+ stat(argv[optind], &stat_buf);
+ mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+ if (src_stream == stdout) {
+ printf("NULL\n");
+ }
+ break;
+ case 1:
+ mode = 0666 & ~umask(0666);
+ break;
+ default:
+ show_usage();
+ }
+
+ printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]);
+
+ while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) {
+ /* Encode the buffer we just read in */
+ uuencode(src_buf, dst_buf, size, tbl);
+
+ /* Write the buffer to stdout, wrapping at 60 chars.
+ * This looks overly complex, but it gets tricky as
+ * the line has to continue to wrap correctly if we
+ * have to refill the buffer
+ *
+ * Improvments most welcome
+ */
+
+ /* Initialise values for the new buffer */
+ remaining = 4 * ((size + 2) / 3);
+ buffer_offset = 0;
+
+ /* Write the buffer to stdout, wrapping at 60 chars
+ * starting from the column the last buffer ran out
+ */
+ do {
+ if (remaining > (60 - column)) {
+ write_size = 60 - column;
+ }
+ else if (remaining < 60) {
+ write_size = remaining;
+ } else {
+ write_size = 60;
+ }
+
+ /* Setup a new row if required */
+ if (column == 0) {
+ putchar('\n');
+ if (tbl == tbl_std) {
+ putchar('M');
+ }
+ }
+ /* Write to the 60th column */
+ if (fwrite(&dst_buf[buffer_offset], 1, write_size, stdout) != write_size) {
+ perror("Couldnt finish writing");
+ }
+ /* Update variables based on last write */
+ buffer_offset += write_size;
+ remaining -= write_size;
+ column += write_size;
+ if (column % 60 == 0) {
+ column = 0;
+ }
+ } while (remaining > 0);
+ }
+ printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n");
+
+ return(EXIT_SUCCESS);