home *** CD-ROM | disk | FTP | other *** search
- /* UUXFER -- a complete uuencode/uudecode package
- *
- * ver. 2.0 copyright (C) 1990 David M. Read All rights reserved.
- *
- *
- * In the lines below, you should #define whatever is appropriate
- * for your system. If you have the CURSES package available, I
- * suggest you use it. DUMB_IO will be defined if neither CURSES
- * nor TURBO_C is defined.
- *
- * If you are using an ANSI-compliant compiler, define ANSI_C.
- *
- */
-
- #define ANSI_C
- #define MS_DOS
- #define TURBO_C
-
- /*
- #define DUMB_IO
- #define CURSES
- #define UNIX
- */
-
- #if (!defined (CURSES) && !defined (TURBO_C) && !defined (DUMB_IO))
- #define DUMB_IO
- #endif
-
- #define ESC 27
- #define OFF 0
- #define ON ~OFF
- #define INIT 0
- #define UPDATE 1
- #define SEEK_SET 0
- #define SEEK_CUR 1
- #define SEEK_END 2
-
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
-
- #ifdef MS_DOS
- #include <stdlib.h>
- #include <io.h>
- #define UPDATE_CHAR 176
- #endif
-
- #ifdef TURBO_C
- #include <conio.h>
- #endif
-
- #ifdef UNIX
- #include <sys/types.h>
- #include <sys/stat.h>
- #endif
-
- #ifdef CURSES
- #include <curses.h>
- #define clrscr clearscr
- #define gotoxy moveto
- #define printf printw
-
- #ifdef DUMB_IO
- #undef DUMB_IO
- #endif
-
- #endif
-
- #ifdef DUMB_IO
- #define clrscr clearscr
- #define gotoxy moveto
- #define getch getcharacter
- #endif
-
- #ifndef UPDATE_CHAR
- #define UPDATE_CHAR 'X'
- #endif
-
- typedef unsigned char uchar;
-
- /* Global variables which are parameters for the en/decoding process */
-
- int cells_per_line = 15,
- multiple_input = OFF,
- multiple_output = OFF,
- overwrite = OFF,
- interactive = ON,
- xx_set = OFF,
- table_output = OFF,
- line_count = 0,
- ext_set = OFF;
- long max_size = 32767;
-
- uchar xx_chars[] = "+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
- uchar uu_chars[65],
- ext_chars[65];
- uchar *char_set = uu_chars,
- table[128];
-
- #ifdef ANSI_C /* function prototypes for ANSI C compilers */
-
- int encode_file (char *infilename, char *tempfilename);
- int encode_line (uchar *indata, uchar *outdata, int bytes_in);
- int encode_block (FILE *infile, FILE *outfile, char *infilename,
- char *outfilename, int section, int two_percent);
- int encode_cell (uchar *indata, uchar *outdata);
- int process_command_line (int argc, char **argv, char *infilename);
- int get_parameters (int argc, char **argv);
- int decode_file (char *infilename, char *tempfilename);
- int decode_line (char *indata, char *outdata);
- int decode_cell (char *indata, char *outdata);
- int find_good_data_line (FILE *infile, char *indata, int line_excess);
- int get_excess (FILE *infile, char *indata);
- int get_outfilename (char *indata, FILE *infile, int *mode);
- int get_filenames (char *infilename, char *outfilename);
- void get_filesize (void);
- void get_cells_per_line (void);
- void show_status_line (void);
- void clear_extension (char *filename);
- int no_extension (char *filename);
- void menu (void);
- void show_about (void);
- int ok_to_write (char *filename);
- int build_table (void);
- void build_uu_chars (void);
- int read_charset (FILE *infile);
- int write_table (FILE *outfile);
- int read_external_set (void);
- int check_xx (int byte);
- long get_size (char *filename);
- int update_progress (int mode);
- long filesize (FILE *fileptr);
- void press_key (void);
- void curses_refresh (void);
-
- #ifdef CURSES
- void clearscr (void);
- void moveto (int x, int y);
- int wherex (void);
- int wherey (void);
- #endif
-
- #ifdef DUMB_IO
- void clearscr (void);
- void moveto (int x, int y);
- int getcharacter (void);
- #endif
-
- #else /* function prototypes for UNIX systems */
-
- void get_filesize ();
- void get_cells_per_line ();
- void show_status_line ();
- void clear_extension ();
- void menu ();
- void show_about ();
- void build_uu_chars ();
- void press_key ();
- void curses_refresh ();
- long get_size ();
- long filesize ();
-
- #ifdef CURSES
- void clearscr ();
- void moveto ();
- int wherex ();
- int wherey ();
- #endif
-
- #ifdef DUMB_IO
- void clearscr ();
- void moveto ();
- int getcharacter ();
- #endif
-
- #endif /* end of #ifdef ANSI_C */
-
- /* Constants for use in command-line parsing */
-
- #define NOTHING 0
- #define ENCODE 1
- #define DECODE 2
-
-
- main (argc, argv)
- int argc;
- char **argv;
- {
- char infilename[64],
- outfilename[64];
- int action;
-
- #ifndef CURSES
- clrscr();
- #else
- initscr ();
- cbreak ();
- echo ();
- leaveok (stdscr, FALSE);
- refresh ();
- #endif
-
- if (get_parameters (argc, argv)) /* Gets parameters from the */
- return 0; /* command line */
-
- if (xx_set)
- char_set = xx_chars;
- build_uu_chars ();
- build_table ();
-
- do
- {
- action = process_command_line (argc, argv, infilename);
-
- /* process_command_line selects the next action/filename specified
- * on the command line and copies it into infilename, returning
- * what action was specified: encode or decode. Returns
- * action = nothing if there are no more files on the command line.
- */
-
- *outfilename = '\0'; /* clear outfilename in the command-line case */
-
- if (action == ENCODE)
- encode_file (infilename, outfilename);
- else if (action == DECODE)
- decode_file (infilename, outfilename);
-
- } while (action != NOTHING); /* stop command-line processing */
-
- if (interactive) /* interactive is set to 1 if */
- { /* get_parameters detects no */
- menu (); /* action parameters */
- show_about ();
- }
- else
- {
- printf ("\n\nUUXFER ver 2.0 copyright (c) 1990 David M. Read\n\n");
- printf ("This program is shareware. Read the instructions concerning\n");
- printf ("program registration, available by typing `uuxfer -i' from\n");
- printf ("the command-line, or by activating the program in menu-driven mode.\n\n");
- curses_refresh ();
- }
-
- return 0;
- }
-
-
- encode_file (infilename, outfilename)
- char *infilename,
- *outfilename;
- {
- FILE *infile,
- *outfile;
- char extension[4];
- int rcode,
- section = 1,
- tot_sections,
- two_percent;
- long in_size,
- out_size;
-
- printf ("\nOpening input file %s for encoding...\n", infilename);
- curses_refresh ();
-
- if ((infile = fopen (infilename, "rb")) == NULL)
- {
- printf ("Error opening input file %s\n", infilename);
- curses_refresh ();
- return -1;
- }
-
- in_size = filesize (infile);
- out_size = (in_size * 1424) / 1000;
-
- /* The factor of 1.42 comes mostly from the conversion from 3 input bytes
- * to 4 output bytes, and the remaining part comes from the extra bytes
- * added to every output line...This isn't a *great* estimate, but it's
- * better than nothing, and it only has to be accurate to a few hundred
- * bytes or so...
- *
- * In the next section, the addition of the denominator to the
- * numerand cures the "round-down" problem of integer division;
- * without it, tot_sections will be too small (resulting in the
- * incorrect output of the number of sections), and two_percent
- * will be too small, resulting in 51 updates instead of 50.
- */
-
- if (multiple_output)
- tot_sections = (max_size - 1 + out_size) / max_size;
- else
- tot_sections = 1;
-
- two_percent = 1 + (49 + in_size) / 50;
-
- if (strlen(outfilename) == 0) /* check if we need to supply an */
- { /* output filename */
- strcpy (outfilename, infilename); /* copy the infilename */
- clear_extension (outfilename); /* kills off anything past '.' */
- if (xx_set)
- strcat (outfilename, "xxe"); /* add '.xxe' to the end */
- else
- strcat (outfilename, "uue"); /* add '.uue' to the end */
- }
-
- printf ("0%%..............................................100%%\n");
- update_progress (INIT);
-
- do
- {
- if (multiple_output) /* We'll be supplying the sequen-*/
- { /* tial extensions here. */
- clear_extension (outfilename);
- sprintf (extension, "%d", section); /* convert number -> text */
- strcat (outfilename, extension); /* stick it on the end */
- }
-
- printf ("\nWriting uuencoded file %s...", outfilename);
- curses_refresh ();
-
- if (!ok_to_write (outfilename))
- return -1;
- if ((outfile = fopen (outfilename, "wt")) == NULL)
- {
- printf ("\nError opening output file %s", outfilename);
- press_key ();
- return -1;
- }
-
- /* add 'cut here' lines and other info to make netters happy */
-
- if (section == 1)
- {
- fprintf (outfile, "\n%12s: decoded size: %li\n", infilename, in_size);
- fprintf (outfile, "%12s encoded size: %li (approximate)\n", " ", out_size);
- }
-
- fprintf (outfile, "\n%-12s section %2d/%-2d",
- infilename, section, tot_sections);
- fprintf (outfile, " UUXFER ver 2.0 by David M. Read\n\n");
-
- fprintf (outfile, "BEGIN----------------------CUT HERE--------------------------\n");
-
- if (ext_set)
- if (read_external_set ())
- {
- printf ("Unable to open external table file TABLE.UUX.\n");
- curses_refresh ();
- return -1;
- }
-
- if (table_output)
- write_table (outfile);
-
- rcode = encode_block (infile, outfile, infilename, outfilename,
- section, two_percent);
-
- /* encode_block encodes pieces of the file. It looks at the
- * multiple_output global variable to see whether it should return
- * after encoding max_size bytes. It returns -1 on an error or
- * encountering EOF.
- */
-
- fprintf (outfile, "END------------------------CUT HERE--------------------------\n");
-
- section++; /* increment section for file-naming */
- fclose (outfile);
-
- } while (rcode == 0);
-
- fclose (infile);
- return 0;
- }
-
-
- encode_block (infile, outfile, infilename, outfilename, section, two_percent)
- FILE *infile;
- FILE *outfile;
- char *infilename;
- char *outfilename;
- int section;
- int two_percent;
- {
- int bytes_in,
- bytes_out,
- rcode = -1;
- uchar indata[256],
- outdata[256];
- long section_bytes = 0;
- static long total_bytes,
- next_update;
-
- /* Output the 'begin' line, but only if on the 1st section.
- * Also, clear the static variables & set up the bargraph
- * update information.
- */
-
- if (section == 1)
- {
- fprintf (outfile, "begin 644 %s\n", infilename);
- total_bytes = 0;
- next_update = two_percent;
- }
-
- bytes_in = fread (indata, 1, 3 * cells_per_line, infile); /* get data */
- while (bytes_in > 0)
- {
- bytes_out = encode_line (indata, outdata, bytes_in);
-
- /* encode_line encodes one line of data, reading the unencoded data
- * from indata and placing the encoded data in outdata. It
- * then returns the total length of the encoded data line
- */
-
- if (fwrite (outdata, 1, bytes_out, outfile) != bytes_out)
- {
- printf ("\a\aError writing to output file %s\n", outfilename);
- curses_refresh ();
- return -1;
- }
- section_bytes += bytes_out;
- total_bytes += bytes_in;
-
- while (total_bytes > next_update)
- {
- update_progress (UPDATE);
- next_update += two_percent;
- }
-
- /* check to see if you're near the maximum size for output files...
- * make a guess about the size of the next line.
- */
-
- if (multiple_output != 0 && section_bytes + bytes_out > max_size)
- {
- rcode = 0;
- break;
- }
-
- bytes_in = fread (indata, 1, 3 * cells_per_line, infile);
- }
-
- if (bytes_in == 0) /* you're at the end of the file */
- { /* If you just stopped because */
- /* of multiple_output, bytes_in */
- putc (char_set[0], outfile); /* would be > 0 and you wouldn't */
- fprintf (outfile, "\nend\n"); /* want the 'end' line. The */
- } /* encoded 0 tells decoders to */
- /* stop. */
-
- return rcode;
- }
-
-
- encode_line (indata, outdata, bytes_in)
- uchar *indata;
- uchar *outdata;
- int bytes_in;
- {
- int bytes_out = 0,
- i;
-
- *outdata++ = char_set[bytes_in]; /* Encode the line length */
-
- for (i = 0; i < bytes_in; i += 3) /* Encode the data line, 1 cell at */
- { /* a time, until all done. */
- encode_cell (indata, outdata); /* This is what actually does the */
- indata += 3; /* encoding of each cell! */
- outdata += 4; /* increment all pointers and the */
- bytes_out += 4; /* number of output bytes. */
- }
-
- *outdata++ = '\n'; /* terminate the line with a LF */
-
- return bytes_out + 2; /* bytes_out + 1(count) + 1(LF) */
- }
-
-
- encode_cell (indata, outdata)
- uchar *indata;
- uchar *outdata;
- {
-
- /* This is just a simple table look-up into the table created earlier. */
-
- outdata[0] = char_set [((indata[0] >> 2) & 63)];
- outdata[1] = char_set [(((indata[0] << 4) | (indata[1] >> 4)) & 63)];
- outdata[2] = char_set [(((indata[1] << 2) | (indata[2] >> 6)) & 63)];
- outdata[3] = char_set [(indata[2] & 63)];
-
- return 0;
- }
-
-
- int decode_file (tempfilename, outfilename)
- char *tempfilename;
- char *outfilename;
- {
- FILE *infile,
- *outfile = NULL;
- char infilename[64],
- newfilename[64],
- extension[4],
- indata[256],
- outdata[256];
- int section = 1,
- done = 0,
- rc,
- num_bytes,
- line_excess,
- two_percent,
- mode;
- long tot_size,
- last_ftell,
- cur_ftell,
- next_update,
- total_bytes = 0;
-
- line_count = 1;
-
- do
- {
- last_ftell = 0;
-
- strcpy (infilename, tempfilename); /* This is all basically the */
- /* as the encode_file set-up */
-
- if (no_extension (infilename))
- if (xx_set)
- strcat (infilename, "xxe");
- else
- strcat (infilename, "uue");
-
- if (multiple_input)
- {
- if (section == 1)
- {
- clear_extension (infilename);
- tot_size = get_size (infilename);
- }
-
- clear_extension (infilename);
- sprintf (extension, "%d", section);
- strcat (infilename, extension);
- }
- else
- {
- tot_size = get_size (infilename);
- done = 1;
- }
-
- if (section == 1)
- {
- two_percent = (49 + tot_size) / 50;
- next_update = two_percent;
- printf ("0%%..............................................100%%\n");
- update_progress (INIT);
- }
-
- printf ("Opening input file %s for decoding...\n", infilename);
- curses_refresh ();
-
- if ((infile = fopen (infilename, "rt")) == NULL)
- {
- if (multiple_input)
- {
- printf (" Unable to open next file (%s)\n", infilename);
- printf (" ...assuming no more sections.");
- press_key ();
- if (!interactive)
- {
- printf ("\n");
- curses_refresh ();
- }
- done = 1;
- continue;
- }
- else
- {
- printf ("Unable to open input file %s!\n", infilename);
- curses_refresh ();
- return -1;
- }
- }
-
- if (section == 1)
- {
- /* get_outfilename searches for a 'begin' line and extracts the
- * output filename from it...if it can't find a 'begin' line,
- * it returns -1. It also watches for 'table' entries.
- */
-
- if (get_outfilename (newfilename, infile, &mode) == -1)
- return -1;
-
- cur_ftell = ftell (infile);
- total_bytes += cur_ftell - last_ftell;
- last_ftell = cur_ftell;
-
- if (*outfilename == '\0') /* if an alternate output */
- strcpy (outfilename, newfilename); /* filename was specified, */
- /* use it. Otherwise, use */
- /* the one extracted from */
- /* the data as the default */
-
- printf (" uudecoded output file will be named %s\n", outfilename);
- curses_refresh ();
-
- if (!ok_to_write (outfilename))
- return -1;
- if ((outfile = fopen (outfilename, "wb")) == NULL)
- {
- printf ("Error opening output file %s\n", outfilename);
- press_key ();
- return -1;
- }
-
- /* get_excess reads the first line after the 'begin' line and stores
- * it in indata, and then calculates the difference between the actual
- * line length & the predicted line length so find_good_data_line can
- * handle oddball encoders. Note that if the excess comes up less than
- * zero, it is set to zero. This can happen if a mailer program
- * truncates any trailing spaces from a data line, but not if the
- * encoding program inserts trailing characters to prevent this, in
- * which case the line excess will be > 0 anyway!
- *
- * get_excess also checks for the presence of an 'XX' character set,
- * and sets the xx_set parameter & builds the proper table if such
- * is detected.
- */
-
- if ((line_excess = get_excess (infile, indata)) < 0)
- {
- printf ("Error in file %s", infilename);
- press_key ();
- return -1;
- }
- }
- else
- {
-
- /* find_good_data_line searches for the next line of data in which the
- * encoded length of the line is equal to the actual length of the
- * line. This is how headers & trailers are skipped... the chances of
- * normal text meeting this condition are *small* but it might happen,
- * in which case you're basically screwed...trim off the header!
- */
-
- if (find_good_data_line (infile, indata, line_excess) == -1)
- {
- printf ("\aNo legitimate data found!\n");
- press_key ();
-
- return -1;
- }
- }
-
- do /* loops until there's no more valid data. */
- {
- /* decode_line is the decode counterpart to encode_line */
-
- if ((num_bytes = decode_line (indata, outdata)) == -1)
- break;
- else
- fwrite (outdata, 1, num_bytes, outfile);
-
- cur_ftell = ftell (infile);
- total_bytes += cur_ftell - last_ftell;
- last_ftell = cur_ftell;
-
- while (total_bytes > next_update)
- {
- update_progress (UPDATE);
- next_update += two_percent;
- }
-
- } while ((rc = find_good_data_line (infile, indata, line_excess)) == 0);
-
- cur_ftell = ftell (infile);
- total_bytes += cur_ftell - last_ftell;
- last_ftell = cur_ftell;
-
- fclose (infile);
-
- if (rc == -1 && !multiple_input)
- {
- printf ("'end' line not found!\n");
- curses_refresh ();
- }
-
- if (rc == 1)
- done = 1;
-
- section++;
-
- } while (!done && multiple_input);
-
- fclose (outfile);
-
- return 0;
- }
-
-
- int decode_line (indata, outdata)
- char *indata;
- char *outdata;
- {
- int num_bytes,
- i;
- char *dataptr;
-
- dataptr = outdata;
-
- /* decode the number of bytes to be output..again, see the long commen at
- * the end of the source module.
- */
-
- num_bytes = table [*indata];
-
- indata++; /* advance past the counter byte */
- for (i = 0; i < num_bytes; i += 3) /* loop over output byte count */
- { /* Next line does the work. */
- decode_cell (indata, dataptr);
- indata += 4; /* increment pointers & counters */
- dataptr += 3;
- }
-
- return num_bytes;
- }
-
-
- int decode_cell (indata, outdata)
- char *indata;
- char *outdata;
- {
- int i;
- char *iptr,
- ochar;
-
- /* see the big comment at the end. */
-
- iptr = indata;
- for (i = 0; i < 4; i++)
- {
- ochar = table[*iptr];
- if (ochar > 64)
- {
- printf ("\nFile corrupted! Bad data on line %i: %c",
- line_count, *iptr);
- curses_refresh ();
- return -1;
- }
- else
- *iptr = table[*iptr];
- iptr++;
- }
-
- outdata[0] = (indata[0] << 2) | (indata[1] >> 4);
- outdata[1] = (indata[1] << 4) | (indata[2] >> 2);
- outdata[2] = (indata[2] << 6) | indata[3];
- outdata[3] = '\0';
-
- return 0;
- }
-
-
- int find_good_data_line (infile, indata, line_excess)
- FILE *infile;
- char *indata;
- int line_excess;
- {
- int length,
- elength,
- num_bytes;
-
-
- while (fgets (indata, 255, infile) != NULL) /* read a line */
- {
- line_count++;
-
- if (strncmp (indata, "end", 3) == 0) /* Check for end of data */
- return 1;
-
- if (!multiple_input)
- return 0;
-
- num_bytes = table[*indata]; /* decode the count byte */
- elength = (( 2 + num_bytes) / 3) * 4 + 2; /* figure out how many */
- length = strlen (indata); /* bytes this implies... */
- /* Adding 2 makes it */
- /* round *up* */
-
- if (length == elength + line_excess) /* It's a good data line */
- return 0;
-
- }
-
- return -1;
- }
-
-
- int get_excess (infile, indata)
- FILE *infile;
- char *indata;
- {
- int length,
- elength,
- num_bytes;
-
-
- if (fgets (indata, 255, infile) == NULL) /* read a line */
- return -1;
-
- num_bytes = table[*indata]; /* decode the count byte */
-
- if (num_bytes == 255) /* check if it's valid */
- {
- num_bytes = check_xx (*indata); /* see if it's XX */
- if (num_bytes == 255) /* see if *this* one is */
- {
- printf ("Bad count byte!\n");
- curses_refresh ();
- return -1; /* valid; crash if it */
- }
- } /* is not */
-
- elength = (( 2 + num_bytes) / 3) * 4 + 2; /* figure out how many */
- length = strlen (indata); /* bytes this implies... */
- /* Adding 2 makes it */
- /* round *up* */
-
- return ((length > elength) ? length - elength : 0);
- }
-
-
- int get_outfilename (indata, infile, mode)
- char *indata;
- FILE *infile;
- int *mode;
- {
- char destname[64];
-
- while (1) /* read lines until one of them starts with 'begin' */
- {
- if (fgets ((char *)indata, 255, infile) == NULL)
- {
- printf ("Unable to find begin line!\n");
- curses_refresh ();
- return -1;
- }
-
- line_count++;
-
- if (strncmp ((char *)indata, "table", 5) == 0)
- read_charset (infile);
-
- if (strncmp((char *)indata, "begin ", 6) == 0)
- break;
- }
-
- /* Now that a line starts with 'begin' extract the filename and open
- * mode from it and return this info. I wrote this specifically for
- * MS-DOS, so the open mode is never actually used.
- */
-
- sscanf ((char *)indata, "begin %o %s", &mode, destname);
- strcpy ((char *)indata, destname);
-
- return 0;
- }
-
-
- int get_parameters (argc, argv)
- int argc;
- char **argv;
- {
- int i,
- val;
- long lval;
- char param;
-
- /* This one loops over parameters, extracting any information from
- * parameters it recognizes...if it sees -e or -d, it sets
- * interactive to OFF so that the program can be run from a batch.
- */
-
- for (i = 1; i < argc; i++)
- {
- if (*argv[i] == '-')
- {
- param = toupper(*(argv[i] + 1));
- switch (param)
- {
- case 'C':
- val = atoi (argv[i] + 2);
- if (val > 0 && val <= 19)
- cells_per_line = val;
- break;
- case 'D':
- case 'E':
- interactive = OFF;
- break;
- case 'I':
- show_about ();
- return -1;
- case 'M':
- multiple_input = ON;
- multiple_output = ON;
- break;
- case 'O':
- overwrite = ON;
- break;
- case 'R':
- ext_set = ON;
- table_output = ON;
- break;
- case 'S':
- lval = atol (argv[i] + 2);
- if (lval > 0 && val <= 32767)
- max_size = lval;
- break;
- case 'T':
- table_output = ON;
- break;
- case 'X':
- xx_set = ON;
- break;
- default:
- printf ("Disregarding unknown parameter %c\n", param);
- curses_refresh ();
- break;
- }
- }
- }
-
- return 0;
- }
-
-
- int process_command_line (argc, argv, infilename)
- int argc;
- char **argv;
- char *infilename;
- {
- int i,
- action = NOTHING;
- char param;
-
- static int start = 1;
-
- /* This one loops over command-line parameters, looking for -e or -d;
- * every time it finds one, it increments ths static variable 'start'
- * so that the next time through, it starts at the next parameter on the
- * command line.
- */
-
- for (i = start; i < argc; i++)
- {
- if (*argv[i] == '-')
- {
- param = toupper (*(argv[i] + 1));
- switch (param)
- {
- case 'C':
- break;
- case 'D':
- action = DECODE;
- strcpy (infilename, argv[i] + 2);
- start = i + 1;
- break;
- case 'E':
- action = ENCODE;
- strcpy (infilename, argv[i] + 2);
- start = i + 1;
- break;
- case 'I':
- break;
- case 'M':
- break;
- case 'O':
- break;
- case 'S':
- break;
- case 'X':
- break;
- default:
- break;
- }
- if (action != NOTHING)
- return action;
- }
- }
-
- return action;
- }
-
-
- void clear_extension (filename)
- char *filename;
- {
- char *ptr;
-
- /* really sophomoric...go until you get a '.' and then cut off what's
- * after it by putting a NULL byte there. If you reach a NULL byte,
- * put a '.' there...actually it does that either way.
- */
-
- ptr = filename;
- while (*ptr != '.' && *ptr != '\0')
- ptr++;
- *ptr++ = '.';
- *ptr = '\0';
-
- return;
- }
-
-
- int no_extension (filename)
- char *filename;
- {
- char *ptr;
- int extension = 0;
-
- ptr = filename;
- while (*ptr != '.' && *ptr != '\0')
- ptr++;
- if (*ptr == '\0')
- {
- strcat (filename, ".");
- extension = -1;
- }
- else if (*(ptr + 1) == '\0')
- extension = -1;
-
- return extension;
- }
-
-
- void show_about ()
- {
-
- clrscr();
-
- printf ("\nUUXFER ver 2.0 copyright (c) 1990 David M. Read\n\n");
- printf ("This program is shareware, which means that you are entitled\n");
- printf ("to use this program under the following conditions:\n\n");
- printf ("(1) You may not distribute altered versions of the source code\n");
- printf (" or the executable. You may not distribute this program unless\n");
- printf (" all documentation files are included with it.\n");
- printf ("(2) You may use this program without payment for a period of thirty\n");
- printf (" (30) days, after which you must register it if you intend\n");
- printf (" to continue using it. To register UUXFER, send $10 along with\n");
- printf (" your name and current address to\n\n");
- printf (" Blade Technologies\n");
- printf (" Attn: David Read\n");
- printf (" 6101 Balcones Dr. Suite 300\n");
- printf (" Austin, TX 78731\n\n");
- printf ("(3) You must leave this message intact. If you have suggestions or\n");
- printf (" questions concerning this program, please contact the author at\n");
- printf (" the above address or at readdm@dopey.cc.utexas.edu\n\n");
-
- curses_refresh ();
-
- return;
- }
-
-
- int get_filenames (infilename, outfilename)
- char *infilename;
- char *outfilename;
- {
- int quit = 0;
-
- if (infilename == NULL || outfilename == NULL)
- return -1;
-
- clrscr();
-
- #ifdef CURSES
- nocbreak ();
- #endif
-
- printf ("Enter input filename -=> ");
- curses_refresh ();
- gets (infilename);
- if (strlen(infilename) == 0)
- quit = 1;
-
- if (quit == 0)
- {
- printf ("Enter output filename -=> ");
- curses_refresh ();
- gets (outfilename);
- }
-
- #ifdef CURSES
- cbreak ();
- #endif
-
- if (quit == 0)
- return 0;
- else
- return -1;
-
- }
-
-
- void menu ()
- {
- int choice = 0,
- repaint = 1;
- char infilename[32],
- outfilename[32];
-
- do
- {
- if (repaint)
- {
- clrscr();
- printf ("\n\n\n\n");
-
- printf (" UUXFER MENU\n\n");
- printf (" E) Encode file\n");
- printf (" D) Decode file\n\n");
- printf (" I) Information\n");
- printf (" About Registering\n\n\n");
- printf (" 0) Exit UUXFER\n\n\n\n\n");
-
- #ifndef DUMB_IO
- printf (" Your choice -=>");
- repaint = 0;
- #else
- printf ("\n\n\n\n");
- repaint = 1;
- #endif
-
- curses_refresh ();
- show_status_line ();
- }
-
- do
- {
- gotoxy (43, 19);
-
- #ifdef CURSES
- noecho ();
- #endif
-
- choice = toupper (getch());
-
- #ifdef CURSES
- echo ();
- #endif
-
- switch (choice)
- {
- case '0':
- case ESC:
- choice = '0';
- clrscr();
- continue;
- case 'E':
- repaint = 1;
- if (get_filenames (infilename, outfilename))
- continue;
-
- encode_file (infilename, outfilename);
- break;
- case 'D':
- repaint = 1;
- if (get_filenames (infilename, outfilename))
- continue;
-
- decode_file (infilename, outfilename);
- break;
- case 'I':
- show_about ();
- getch();
- repaint = 1;
- break;
- case 'A':
- multiple_output = ~multiple_output;
- show_status_line ();
- break;
- case 'M':
- multiple_input = ~multiple_input;
- show_status_line ();
- break;
- case 'S':
- get_filesize ();
- repaint = 1;
- break;
- case 'C':
- get_cells_per_line ();
- repaint = 1;
- break;
- case 'X':
- xx_set = ~xx_set;
- show_status_line ();
- break;
- case 'T':
- table_output = ~table_output;
- show_status_line ();
- break;
- case 'R':
- ext_set = ~ext_set;
- if (ext_set)
- table_output = ON;
- show_status_line ();
- break;
- case 'O':
- overwrite = ~overwrite;
- show_status_line ();
- break;
- default:
- printf ("\a");
- choice = -1;
- break;
- }
- } while (choice == -1);
- } while (choice != '0');
-
- return;
- }
-
-
- void show_status_line ()
- {
-
- gotoxy (1, 23);
-
- printf (" A-Split = ");
- if (multiple_output)
- printf ("ON ");
- else
- printf ("OFF ");
-
- printf ("M-Merge = ");
- if (multiple_input)
- printf ("ON ");
- else
- printf ("OFF ");
-
- printf ("S-Max file size = %6ld ", max_size);
- printf ("C-Cells = %2d\n", cells_per_line);
-
- printf (" X-XX set = ");
- if (xx_set)
- printf ("ON ");
- else
- printf ("OFF ");
-
- printf ("T-Write table = ");
- if (table_output)
- printf ("ON ");
- else
- printf ("OFF ");
-
- printf ("R-Ext. set = ");
- if (ext_set)
- printf ("ON ");
- else
- printf ("OFF ");
-
- printf ("O-Overwrite = ");
- if (overwrite)
- printf ("ON ");
- else
- printf ("OFF ");
-
- curses_refresh ();
-
- return;
- }
-
-
- void get_cells_per_line ()
- {
- char buffer[32];
- int num = 0;
-
- do
- {
- clrscr();
-
- printf ("There may not be less than 1 cell or more than 19 on a line.\n");
- printf ("Enter number of output cells per line, or -1 to abort: ");
- curses_refresh ();
- gets (buffer);
- num = atol (buffer);
- if (num > 19)
- num = 0;
-
- } while (num == 0);
-
- if (num > 0)
- cells_per_line = num;
-
- return;
- }
-
-
- void get_filesize ()
- {
- char buffer[32];
- long num = 0;
-
- do
- {
- clrscr();
-
- printf ("Enter maximum size for output encoded data, or -1 to abort: ");
- curses_refresh ();
- gets (buffer);
- num = atol (buffer);
-
- } while (num == 0);
-
- if (num > 0)
- max_size = num;
-
- return;
- }
-
-
- int ok_to_write (filename)
- char *filename;
- {
- FILE *temp;
- char choice;
-
- temp = fopen (filename, "r");
- if (temp == NULL)
- return -1;
-
- fclose (temp);
-
- if (overwrite)
- return -1;
-
- printf ("\n File %s already exists. ", filename);
- curses_refresh ();
-
- if (interactive)
- {
- printf ("Overwrite? (N/y) ");
- curses_refresh ();
- while ((choice = toupper (getch())) != 'Y' && choice != 'N')
- ;
- printf ("\n");
- curses_refresh ();
- if (choice == 'Y')
- return -1;
- }
-
- return 0;
- }
-
-
- int build_table ()
- {
- char *ptr;
- int i,
- entry;
-
- ptr = (char *)table; /* clear table */
- for (i = 0; i < 128; i++)
- *(ptr++) = 127;
-
- ptr = (char *) char_set; /* fill table */
- for (i = 0; i < 64; i++)
- {
- entry = *(ptr++) & 127;
- if (table [entry] != 127)
- return -1;
- table [entry] = i;
- }
-
- if (!(xx_set || ext_set)) /* i.e. we're using the standard 'uu' set */
- table[' '] = 0; /* make it decode ' ' the same as ` */
-
- return 0;
- }
-
-
- void build_uu_chars ()
- {
- int i;
-
- for (i = 0; i < 64; i++)
- uu_chars [i] = i + 32;
-
- uu_chars[0] = 96; /* use ` instead of space */
-
- return;
- }
-
-
- int read_charset (infile)
- FILE *infile;
- {
- uchar ch,
- line[256],
- *ptr;
- int i,
- len;
-
-
- for (i = 0; i < 64; )
- {
- len = strlen (fgets ((char *)line, 255, infile));
- if (len <= 0)
- return -1;
-
- line_count++;
-
- if (strncmp ((char *)line, "begin ", 6) == 0)
- break;
-
- ptr = line;
- do
- {
- ch = *ptr;
- if (ch == '\n')
- break;
- if (ch > 0 && ch < 128)
- {
- ext_chars [i] = ch;
- i++;
- len--;
- ptr++;
- }
- } while (len > 0);
- }
-
- if (i < 64)
- {
- printf ("Invalid character table! (not enough characters in table)\n");
- curses_refresh ();
- return -1;
- }
-
- char_set = ext_chars;
- if (build_table () != 0)
- {
- printf ("Invalid character table! (table build failed)\n");
- curses_refresh ();
- return -1;
- }
-
- return 0;
- }
-
-
- int write_table (outfile)
- FILE *outfile;
- {
- int i;
-
- fprintf (outfile, "table\n");
-
- for (i = 0; i < 32; i++)
- fputc (char_set [i], outfile);
- fputc ('\n', outfile);
-
- for (i = 32; i < 64; i++)
- fputc (char_set [i], outfile);
- fputc ('\n', outfile);
-
- return 0;
- }
-
-
- int read_external_set ()
- {
- FILE *fileptr;
- int rc;
-
- if ((fileptr = fopen ("TABLE.UUX", "rt")) == NULL)
- return -1;
-
- rc = read_charset (fileptr);
-
- fclose (fileptr);
-
- return rc;
- }
-
-
- int check_xx (byte)
- int byte;
- {
- int i;
-
- for (i = 0; i < 64; i++)
- if (xx_chars[i] == byte)
- break;
-
- if (i == 64)
- return table[byte];
-
- xx_set = ON;
- char_set = xx_chars;
- build_table();
-
- return table[byte];
- }
-
-
- long get_size (filename)
- char *filename;
- {
- int i;
- long tot_size;
- FILE *fileptr;
- char extension[5];
-
-
- if (!multiple_input)
- {
- if ((fileptr = fopen (filename, "rt")) == NULL)
- return -1;
- tot_size = filesize (fileptr);
-
- fclose (fileptr);
-
- return tot_size;
- }
-
- tot_size = 0;
- for (i = 1; 1; i++)
- {
- clear_extension (filename);
- sprintf (extension, "%d", i);
- strcat (filename, extension);
-
- if ((fileptr = fopen (filename, "rt")) == NULL)
- break;
- tot_size += filesize (fileptr);
-
- fclose (fileptr);
- }
-
- return tot_size;
- }
-
-
- #ifndef DUMB_IO
-
- int update_progress (mode)
- int mode;
- {
- static int lastx,
- lasty;
- int curx,
- cury;
-
- if (mode == INIT)
- {
- lastx = wherex();
- lasty = wherey();
- printf ("\n");
- }
-
- curx = wherex();
- cury = wherey();
-
- gotoxy (lastx, lasty);
- #ifdef CURSES
- addch (UPDATE_CHAR);
- refresh();
- #else
- putchar (UPDATE_CHAR);
- #endif
- lastx = wherex();
- lasty = wherey();
-
- gotoxy (curx, cury);
-
- return 0;
- }
-
- #else /* dumb I/O */
-
- int update_progress (mode)
- int mode;
- {
- static int num_calls; /* will store # of times this routine has */
- /* been called. */
-
- if (mode == INIT)
- {
- num_calls = 0;
- printf (" ");
- }
- else
- {
- num_calls++;
- if ((num_calls % 5) == 0)
- printf (" %d%%", 10*(num_calls / 5));
- }
-
- return;
- }
-
-
- void clearscr ()
- {
- int i;
-
- for (i = 0; i < 24; i++)
- printf ("\n");
-
- return;
- }
-
-
- void moveto (x, y)
- int x;
- int y;
- {
- if (x == 0 || y == 0) /* Ok, this is really stupid, and I'm lazy. */
- ; /* I want this function to do nothing, and */
- /* for the compiler not to complain about it. */
- return;
- }
-
-
- int getcharacter ()
- {
- int i;
-
- i = getchar();
- fflush (stdin);
-
- return i;
- }
-
- #endif
-
- #ifdef CURSES
-
- void moveto (x, y)
- int x;
- int y;
- {
- move (y - 1, x - 1);
- refresh ();
-
- return;
- }
-
- int wherex ()
- {
- int x,
- y;
-
- getyx (stdscr, y, x);
-
- return x + 1;
- }
-
- int wherey ()
- {
- int x,
- y;
-
- getyx (stdscr, y, x);
-
- return y + 1;
- }
-
- void clearscr ()
- {
- clear ();
- refresh ();
- }
-
- #endif
-
- long filesize (fileptr)
- FILE *fileptr;
- {
- long cur_pos,
- length;
-
- cur_pos = ftell (fileptr);
- fseek (fileptr, 0, SEEK_END);
- length = ftell (fileptr);
- fseek (fileptr, cur_pos, SEEK_SET);
-
- return length;
- }
-
- void press_key ()
- {
- if (interactive)
- {
- printf ("Press any key to continue...");
- curses_refresh ();
- getch();
- }
-
- return;
- }
-
- void curses_refresh ()
- {
- #ifdef CURSES
- refresh ();
- #endif
-
- return;
- }
-