/****************************************************************************** Program: pull.c Version: 3.3 Platform: UNIX, DOS/WINDOWS, VMS, and OS/2 Function: extract the original file(s) from uuencoded/compressed/split/ archived file(s), and compactly pack file for email delivery. Usage 1: pull [-hBCDGILSUV] -- print help info Usage 2: pull [file1 file2 file3 ...] -- extract original file pull [-s] metafn -- metafn contains metachars (wild card) Usage 3: pull -d file -- "De-pull = push", reverse extracting process Compile: on Unix: "cc -o pull pull.c", or "cc -O -o pull pull.c" with optimization on VMS: "define lnk$library sys$library:vaxcrtl" (step 1. specify I/O) "cc pull /define=(VMS_PULL)" (step 2. compile) "link pull" (step 3. link) "pull == "$disk:[directory]pull.exe"" (step 4. set symbol) Comment: This software is provided "as is" without any warranty. Redistribution and non-commercial use are permitted. Date: Sept 20, 1997 Author: Yao Li (ah163@freenet.carleton.ca) Copyright (C) 1995-97 Thanks: VMS porting received help from W.M. (Canada) and Seak (France) History: The initial pull 1.0 was released on Feb. 10, 1995. Subsequent releases: 1.1-1.4 (4), 2.0-2.9 (10), 3.0-3.2 (3) 1.0-1.4 in Unix Bourne shell; 2.0 and above in C. ******************************************************************************/ #include #include #include #if (OS2FAT_PULL || OS2HPFS_PULL) #define OS2_PULL 1 #endif #if (DOS_PULL || OS2_PULL) #include #include #include #include #elif VMS_PULL #include #endif #ifdef OS2_PULL #include #endif #define CSTAR (char *) #define CNULL (char) NULL #define DASH '-' #define SNULL (char *)NULL #define SSNULL (char **)NULL #define FNULL (FILE *)NULL #define FFNULL (FILE **)NULL #define OPTEND "--" #define NAMELEN 60 #define LINELEN 120 #define BUFSIZE 255 #define ARGUMENTS 11 #define EOL '\n' #define K 1024 #define FALSE 0 #define TRUE 1 #define SUFXLEN 8 #define NOT_FOUND -2 #define MAXFILES 10 #define MINPARTS 1 #define MAXPARTS 9 #define UNSPECIFIED -3 #define FILE_IO_MODE 5 #if (!(MAC_PULL || VMS_PULL || DOS_PULL || MSWIN_PULL || OS2_PULL)) #define UNIX_PULL 1 #endif #if (DOS_PULL || UNIX_PULL || OS2_PULL) #define WILD_CHAR "?" #elif VMS_PULL #define WILD_CHAR "%" #endif #define enc(c) ((c) ? ((c) & 077) + ' ': '`') #define scf_error(f, x) rc = 0; fprintf(stderr, f, (*argv)[0],x) #define strequ(s1, s2) !strcmp(s1, s2) #if (DOS_PULL || OS2_PULL) #define SETMODE(x) setmode(fileno((x)), O_BINARY) #endif float version = 3.3; char *date = "Sept 20, 1997"; char *my_eaddress = ""; char *copyright = "1995-97"; int pull_one_input_file(char*), pull_multiple_input_files(int, char**), lookup(char*, int, char*), sort_check_input_files(int, char*[]), encoded_files(char*), expand_concatenated_file(char*, int*, char***), trim_last_char(char*); int is_option(char*), is_binary_file(char*), decompress_file(char*), exec_command(char*, char*, char*, char*), split(char**, int, char*, int, long int*), word_count(char*), merge(char*, char*, int, char*), my_rename(char*, char*), is_file(char*), str_empty(char*), decode(char*, char*), scf(char*, char*, int*, char**[]), uudecode(char*, char*), good_args(char*, char*, char*), strtrim_left(char*, char**); char *strccat(char*, int), last_char(char*); char *find_decoded_file_name(char*), *map_suffix_up(char*), *map_suffix_down(char*), *get_last_suffix(char*), *get_base_name(char*), *last_char_removed(char*), *last_suffix_removed(char*), *map2col1(char*), *compress_file(char*, char*), *last_char_removed(char*), *str_dup(char*); void print_manual(void), bug_report(void), print_gzip_ftp_info(void), compilation(void), installation(void), print_license_info(void), handle_cm_ps_file(void), print_usage(void), print_short_usage(void), print_version(void), print_help_info(char*), print_push(void); void wordcnt_file(char*, int*, long int*, long int*), uue77(char*, char*, char*, char*), encoding(FILE*, FILE*), outdec(register char *, FILE *), fatal_error(char*), pr_err(char*), print_output_msg(char*), push_files(char**, int, long, int), push_with_split(char**, int, char*, long int, long, int), expand_file_name(int, char*[], int*, char***), print_illegal_option(void), copy_stdin_to_file(FILE*, char*), copy_file_to_stdout(char*, FILE*); void validate_cmd_options(void), parse_cmd_options(int*, char**[]), turn_opt_on(char*), free_str(char*), *calloc_mem(unsigned int, char type[NAMELEN], char name[NAMELEN]); FILE *f_open(char*, char*, char*); float k_bytes(long int); int gzip(char*, char*), gunzip(char*), compress(char*, char*), uncompress(char*), zip(char*, char*), unzip(char*); #if (DOS_PULL || OS2FAT_PULL) char *str2lower_case(char*); #elif VMS_PULL int match_file(char*, char*, int, int*), lib$find_file(); char *get_extension(char*), *extension_removed(char*); void file_copy(FILE*, FILE*), expand_vms_filename(char*, int*, char***); #endif #if (DOS_PULL || OS2_PULL) void expand_dos_filename(char*, int*, char***); #endif int inputFiles = 0; char **inputFile = SSNULL; long int maxPartSize; int file_expanded = FALSE; struct suffix_tag { char sp[SUFXLEN]; char mp[SUFXLEN]; char mc[SUFXLEN]; } suffixTbl[] = { ".gb", ".gb", ".b", ".bg5", ".b5", ".5", ".ps", ".ps", ".s", ".fps", ".fs", ".f", ".pdf", ".pd", ".d", ".eps", ".es", ".e", ".gif", ".gf", ".i", ".mpg", ".mp", ".m", ".jpg", ".jp", ".j", ".c", ".c", ".c", ".p", ".p", ".p", ".exe", ".ex", ".x", ".doc", ".do", ".o", ".txt", ".tx", ".t", "NULL", "NULL", "NULL" }; struct compression_tag { char format[SUFXLEN]; char shrt[SUFXLEN]; char shortest[SUFXLEN]; } compr[] = { #ifdef VMS_PULL "-gz", "-gz", "z", "-Z", "-Z", "Z", "-zip", "-zp", "p", #else ".gz", ".gz", "z", ".Z", ".Z", "Z", ".zip", ".zp", "p", #endif "NULL", "NULL", "NULL" }; struct cmd_option_tag { char std_in; char std_out; char b; char c; char d; char f; char l; char n; char p; char q; char s; char z; } cmd_option[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 }; char *bvalue, *pvalue; int cmd_option_combinations = 14; int sum_cmd_options = 0; struct help_option_tag { char h; char B; char C; char D; char G; char I; char L; char S; char U; char V; } help_option[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int sum_helps = 0; int sum_options = 0; #ifdef VMS_PULL char stdin_file[] = "stdin_f.tmp"; #else char stdin_file[] = "stdin_f"; #endif int pull_one_file_recursions = 0; int main(int argc, char *argv[]) { int i, j, new_argc, tmp_argc; char **new_argv, **tmp_argv; int chunks; long int chunkSize; char tmp_infile[NAMELEN]; FILE *ifp; parse_cmd_options(&argc, &argv); if ((sum_options == 0 && strequ(argv[argc-1], "--")) || (sum_options == 0 && strequ(argv[argc-1], "-")) || ((cmd_option[0].d || cmd_option[0].s || cmd_option[0].q || cmd_option[0].c) && (strequ(argv[argc-1], "--") || strequ(argv[argc-1], "-")))) { cmd_option[0].std_in = 1; copy_stdin_to_file(stdin, stdin_file); if (strequ(argv[argc-1], "--")) tmp_argc = argc+1; else if (strequ(argv[argc-1], "-")) tmp_argc = argc; tmp_argv = calloc_mem(tmp_argc+1, "char **", "tmp_argv"); for (j=0; j1) { if (inputFiles > MAXPARTS) { fprintf(stderr, "Warning: there are more than %i input files.\n", MAXPARTS); fprintf(stderr, " It might cause problem when merging files.\n"); } if (!cmd_option[0].q && !file_expanded) { if (inputFiles <= 4) fprintf(stderr, "Extracting ...\n"); else { fprintf(stderr, "Extracting from "); for (i=0; i0) { for (i=0; iMAXPARTS) { fprintf(stderr, "Number of split parts %i ", chunks); fprintf(stderr, "out of range %i--%i.\n", MINPARTS, MAXPARTS); exit(1); } } else chunks = UNSPECIFIED; push_files(inputFile, inputFiles, chunkSize, chunks); } else print_illegal_option(); for (i=0; i 0) free(inputFile); for (i=0; i 2) fatal_error("Number of input files exceeds 2."); } if (cmd_option[0].s && (inputFiles > 1) && (sum_helps == 0)) { if (cmd_option[0].std_out) fatal_error("-c -s in conflict when there are multiple input files."); else if (cmd_option[0].std_in && cmd_option[0].std_out) fatal_error("- -c -s in conflict when there are multiple input files."); } for (i=1; i outfile]\n"); #endif fprintf(stderr, " -d[cq] [-b bytes] [header] file\n"); fprintf(stderr, " -d[cq] [-p parts] [header] file\n"); fprintf(stderr, " -d[cq] -f [-b bytes] file\n"); fprintf(stderr, " -d[cq] -l [-b bytes] file\n"); fprintf(stderr, " -d[cq] -n [header] file\n"); } void expand_file_name(int argc, char *argv[], int *new_argc, char ***new_argv) { int i; int j = 1; int tmp_argc, num_of_parts, num_of_files; char **tmp_argv, **part, **file, *infile; int try_expand = FALSE, bad_file = FALSE; tmp_argv = calloc_mem(argc+1, "char **", "tmp_argv"); tmp_argv[0] = (char *) str_dup(argv[0]); for (i=1; i 9) { fprintf(stderr, "%i encoded files in %s, max = 9\n", num_of_parts, infile); exit(1); } free(tmp_argv[tmp_argc-1]); tmp_argv = (char **) realloc(tmp_argv, (tmp_argc+num_of_parts)*sizeof(char *)); for (i=tmp_argc-1; i 99) fatal_error("Too many file names (>99) expanded"); } free(leading_path); free_str(filename); *num_of_outFiles = count; *outFile = outfile; } #endif #ifdef VMS_PULL void expand_vms_filename(char *wild_name, int *num_of_outFiles, char ***outFile) { int count = 0; int env = 0; char **outfile; char newname[BUFSIZE]; outfile = calloc_mem(count+1, "char **", "outfile"); while (match_file(wild_name, newname, sizeof(newname), &env)) { if ((outfile = (char **) realloc(outfile, (count+2)*sizeof(char *))) == SSNULL) fatal_error("realloc outfile failed in expand_vms_filename()"); outfile[count++] = (char*)str_dup(newname); if (count > 99) fatal_error("Too many file names (>99) expanded"); } *num_of_outFiles = count; *outFile = outfile; } int match_file(char *wildcard, char *matched, int matchedLen, int *env) { struct Str_desc { int length; char *addr; } strIn, strOut; int rc, i=0; strIn.length = strlen(wildcard); strIn.addr = wildcard; strOut.length = matchedLen; strOut.addr = matched; #ifndef COMPILE_VMS_ON_PC rc = lib$find_file(&strIn, &strOut, env); #endif while (strOut.addr[i] != ' ') i++; strOut.addr[i] = '\0'; strOut.length = strlen(strOut.addr); if (rc != 0) rc = rc % 2; return rc; } #endif void fatal_error(char *s) { fprintf(stderr, "%s\n", s); exit(1); } int expand_concatenated_file(char *infile, int *num_of_outFiles, char ***outFile) { int i, num_of_files, num_of_words; int reading_file = 0; char *basename, **outfile; FILE *ifp, **ofp; int in_a_part = FALSE; char line[BUFSIZE], *line2; char s1[BUFSIZE], s2[BUFSIZE], s3[BUFSIZE]; num_of_files = encoded_files(infile); if (num_of_files <= 1) return FALSE; else { ifp = f_open(infile, "r", "expand_concat..."); basename = get_base_name(infile); ofp = calloc_mem(num_of_files, "FILE **", "ofp"); outfile = calloc_mem(num_of_files, "char **", "outfile"); for (i=0; i num_of_ends) { fprintf(stderr, "Input %s missing %i `end's.\n", infile, num_of_begins-num_of_ends); exit(1); } else { fprintf(stderr, "Input %s missing %i `begin's.\n", infile, num_of_ends-num_of_begins); exit(1); } } return returned_numbers; } char *str_dup(char *s) { return strcpy((char*)malloc(strlen(s) + 1), s); } int sort_check_input_files(int argc, char *argv[]) { int i, j=1, index, maxSize, *list; int Min = ARGUMENTS; int Max = 0; char *decodedFile; char **inFile, **baseName; char lastChar, tmpString[3]; int marked[30]; int error = FALSE; int num_of_errors = 0; inFile = calloc_mem(inputFiles+1, "char **", "inFile"); baseName = calloc_mem(inputFiles+1, "char **", "baseName"); list = calloc_mem(inputFiles+1, "int *", "list"); for (i=argc-inputFiles; i<=argc-1; i++) { if ((decodedFile = find_decoded_file_name(argv[i])) != SNULL) inFile[j] = decodedFile; else inFile[j] = (char*)str_dup(argv[i]); baseName[j] = get_base_name(inFile[j]); lastChar = last_char(inFile[j]); if (isdigit(lastChar)) { tmpString[0] = lastChar; tmpString[1] = '\0'; sscanf(tmpString, "%d", &index); if (index < Min) Min = index; if (index > Max) Max = index; free(inputFile[index-1]); inputFile[index-1] = (char *)str_dup(argv[i]); list[j] = index; } else { fprintf(stderr, "%s is not a valid input file.\n.", argv[i]); exit(1); } j++; } for (i=1; i<=inputFiles-1; i++) for (j=i+1; j<=inputFiles; j++) { if (!strequ(baseName[i], baseName[j])) { fprintf(stderr, "(decoded) input file %i: %s and ", i,inFile[i]); fprintf(stderr, "file %i: %s \n", j, inFile[j]); fprintf(stderr, " have different basenames: %s, %s\n", baseName[i], baseName[j]); fprintf(stderr, " They may not be from the same original file.\n"); error = TRUE; if (++num_of_errors>4) { fprintf(stderr, "Too many errors! "); fprintf(stderr, "All input files have to belong to one file.\n"); exit(1); } } if (strequ(inFile[i], inFile[j])) { fprintf(stderr, "The same (decoded) input file is used again.\n"); fprintf(stderr, " They are file %i: %s and file %i: %s\n", i, inFile[i], j, inFile[j]); error = TRUE; if (++num_of_errors>4) { fprintf(stderr, "Too many errors! "); fprintf(stderr, "All input files have to belong to one file.\n"); exit(1); } } } if (error) exit(1); maxSize = inputFiles; if (maxSize < Max) maxSize = Max; for (i=0; i<=maxSize; i++) marked[i] = FALSE; for (i=1; i<=inputFiles; i++) marked[list[i]] = TRUE; for (i=1; i<=maxSize; i++) { if (marked[i] == FALSE) { fprintf(stderr, "Missing input file whose part number in its"); fprintf(stderr, " decoded filename is: %i\n", i); exit(1); } } for (i=1; i<=inputFiles; i++) { free_str(inFile[i]); free_str(baseName[i]); } free(inFile); free(list); free(baseName); return TRUE; } int pull_multiple_input_files(int inFiles, char **inFile) { int i; char *baseName, *suffix, *newSuffix, *decodedFileName; char *file1, *file2, *sufxCol2, *sufxCol3, *comprCol3; int numFiles; int calloc_count = 0; file1 = calloc_mem(NAMELEN, "char *", "file1"); file2 = calloc_mem(NAMELEN, "char *", "file2"); sufxCol2 = calloc_mem(NAMELEN, "char *", "sufxCol2"); sufxCol3 = calloc_mem(NAMELEN, "char *", "sufxCol3"); comprCol3 = calloc_mem(SUFXLEN, "char *", "comprCol3"); numFiles = inFiles; for (i=0; i= 3) strncpy(sufxCol2, suffix, strlen(suffix)-1); if ((int)strlen(sufxCol2) == 3) { comprCol3[0] = '\0'; strccat(comprCol3, last_char(sufxCol2)); strncpy(sufxCol3, sufxCol2, strlen(sufxCol2)-1); } if ((lookup("suffix", 2, sufxCol2) != NOT_FOUND) || (lookup("compression", 2, sufxCol2) != NOT_FOUND) || ((lookup("suffix", 3, sufxCol3) != NOT_FOUND) && (lookup("compression", 3, comprCol3) != NOT_FOUND))) { merge(inFile[i], file1, i+1, "binary"); } } else { fprintf(stderr, "Unknown file type. pull can't process "); fprintf(stderr, "%s\n", inFile[i]); exit(1); } } else { fprintf(stderr, "Unknown file type. %s does not have suffix.\n", inFile[i]); exit(1); } } } newSuffix = map_suffix_up(suffix); sprintf(file2, "%s%s", baseName, newSuffix); my_rename(file1, file2); free_str(baseName); free_str(sufxCol2); free_str(sufxCol3); free_str(comprCol3); free_str(suffix); free_str(newSuffix); if (pull_one_input_file(file2)) return TRUE; pr_err("pull_one... in pull_multiple fails"); return FALSE; } int pull_one_input_file(char *inFile) { char *suffix, *decodedFileName, tmpname[NAMELEN], *extension; char *sufxCol2, *comprCol3, *junk; int rc = TRUE; #ifdef VMS_PULL if ((decodedFileName = find_decoded_file_name(inFile)) != SNULL) #else if ((decodedFileName = find_decoded_file_name(inFile)) != SNULL) #endif { if (!decode(inFile, decodedFileName)) pr_err("decode fails in pull_one..."); if (file_expanded) remove(inFile); strcpy(tmpname, decodedFileName); free_str(decodedFileName); pull_one_file_recursions++; pull_one_input_file(tmpname); return TRUE; } else if ((suffix = get_last_suffix(inFile)) != SNULL) { comprCol3 = calloc_mem(SUFXLEN, "char *", "comprCol3"); strccat(comprCol3, last_char(suffix)); sufxCol2 = last_char_removed(suffix); #ifdef VMS_PULL extension = get_extension(inFile); if ((lookup("compression", 1, extension) != NOT_FOUND) || ((lookup("suffix", 2, sufxCol2) != NOT_FOUND) && (lookup("compression", 3, comprCol3) != NOT_FOUND))) { free_str(extension); #else if ((lookup("compression", 1, suffix) != NOT_FOUND) || ((lookup("suffix", 2, sufxCol2) != NOT_FOUND) && (lookup("compression", 3, comprCol3) != NOT_FOUND))) { #endif free_str(suffix); free_str(sufxCol2); free_str(comprCol3); if (!(rc = decompress_file(inFile))) pr_err("decompress_file fails in pull_one..."); return rc; } else rc = FALSE; free_str(suffix); free_str(sufxCol2); free_str(comprCol3); #ifdef VMS_PULL free_str(extension); #endif } else { rc = FALSE; } if (cmd_option[0].std_out) { copy_file_to_stdout(inFile, stdout); if (!cmd_option[0].q && pull_one_file_recursions>0) fprintf(stderr, "%s extracted and sent to stdout\n", inFile); if (pull_one_file_recursions>0) remove(inFile); } else if (!cmd_option[0].q && pull_one_file_recursions>0) fprintf(stderr, "%s extracted\n", inFile); return rc; } void pr_err(char *s) { fprintf(stderr, "%s\n", s); } void print_manual() { printf("File extractor and packer: pull; Version %3.1f (%s); with usages:\n", version, date); printf("1. pull [-s] [file ...] -- extracts original file(s)\n"); printf("a) jointly: extracts a single file by combining a set of compressed/split/\n"); printf(" encoded files that can be in arbitrary sequence. \n"); printf(" pull file1 file2 file3 ...\n"); printf(" pull metafile -- a set of files expanded from `metafile', i.e., a filename\n"); #ifdef UNIX_PULL printf(" including metachars (wild card) *, ?, and [...], [!...]\n"); #elif (DOS_PULL || OS2_PULL) printf(" including metachars (wild card) * and ?.\n"); #elif VMS_PULL printf(" including metachars (wild card) * and %s.\n", WILD_CHAR); #endif printf(" pull catfile -- several encoded files concatenated within a `catfile' file.\n"); printf("b) separately: extract files independently from several files. No file merging.\n"); printf(" `pull -s file1 file2 ...', `pull -s metafile', or `pull -s catfile'\n"); printf("2. pull -d file -- packs file. `De' pull = push. Reverse `extracting' process.\n"); printf(" compresses, (splits), then encodes file(s). See 'pull -D'.\n"); #ifdef VMS_PULL printf("3. pull -- read from stdin/terminal.\n"); #else printf("3. pull [-] -- read from stdin/terminal.\n"); #endif printf(" pull -c file -- send to stdout/terminal.\n"); printf(" pull -q file -- quiet.\n"); printf("4. pull [-hBCDGILSUV] -- displays help pages\n"); #ifdef VMS_PULL printf(" Upper case options need quotes, e.g. pull \"-V\"\n"); #endif printf(" -h : this Help -I : installation\n"); printf(" -B : bug report & comment -L : license\n"); printf(" -C : compilation & link -S : ps file viewing and printing\n"); printf(" -D : 'de' pull, packing file -U : usage examples\n"); printf(" -G : gzip/gunzip ftp info -V : version number\n"); #if (UNIX_PULL || DOS_PULL || OS2_PULL) printf(" pull [-hBCDGILSUV] > helppage -- save a help page in file: helppage\n"); #endif exit(0); } int is_file(char *name) { FILE *fp = FNULL; if ((fp = fopen(name, "r")) == FNULL) return FALSE; fclose(fp); return TRUE; } int is_binary_file(char *inFile) { FILE *fp = FNULL; int c; fp = f_open(inFile, "rb", "is_binary_file"); while (( c = getc(fp)) != EOF) { if (!isascii(c)) { fclose(fp); return TRUE; } } fclose(fp); return FALSE; } FILE *f_open(char *filename, char *mode, char *where) { FILE *fp; if ((fp = fopen(filename, mode)) == FNULL) { fprintf(stderr, "can't open file %s for \"%s\" from %s()\n", filename, mode, where); exit(1); } return fp; } void *calloc_mem(unsigned int nobj, char type[NAMELEN], char name[NAMELEN]) { void *mptr; int fail = FALSE; unsigned int size; if (strequ(type, "char *")) { size = sizeof(char); if ((mptr = (char *)calloc(nobj, size)) == SNULL) fail = TRUE; } else if (strequ(type, "char **")) { size = sizeof(char *); if ((mptr = (char **)calloc(nobj, size)) == SSNULL) fail = TRUE; } else if (strequ(type, "FILE **")) { size = sizeof(FILE *); if ((mptr = (FILE **)calloc(nobj, size)) == FFNULL) fail = TRUE; } else if (strequ(type, "int *")) { size = sizeof(int); if ((mptr = (int *)calloc(nobj, size)) == NULL) fail = TRUE; } else if (strequ(type, "long int *")) { size = sizeof(long int); if ((mptr = (long int *)calloc(nobj, size)) == NULL) fail = TRUE; } else { fprintf(stderr, "unkown type %s in calloc_mem()\n", type); exit(1); } if (fail) { fprintf(stderr, "Can't calloc memory for %s in size of %i x %i\n", name, nobj, size); exit(1); } return mptr; } char *find_decoded_file_name(char *inFile) { FILE *fp; char *s1, *s2, *s3, *decoded_fn=SNULL; char line[BUFSIZE]; if (is_binary_file(inFile)) #ifdef VMS_PULL { return SNULL; } #else return SNULL; #endif s1 = calloc_mem(BUFSIZE, "char *", "s1"); s2 = calloc_mem(BUFSIZE, "char *", "s2"); s3 = calloc_mem(BUFSIZE, "char *", "s3"); fp = f_open(inFile, "r", "find_decoded_file_name"); while (fgets(line, BUFSIZE, fp) != SNULL) { if (word_count(line) == 3) { sscanf(line, "%s %s %s", s1, s2, s3); if (strequ(s1, "begin")) { decoded_fn = (char*)str_dup(s3); break; } } } fclose(fp); free_str(s1); free_str(s2); free_str(s3); return decoded_fn; } int lookup(char *table, int column, char *entry) { int i = 0; if (!entry) return NOT_FOUND; if (strequ(table, "suffix")) { if (column == 1) { while (!strequ(suffixTbl[i].sp, "NULL")) if (strequ(suffixTbl[i++].sp, entry)) return i-1; } else if (column == 2) { while (!strequ(suffixTbl[i].mp, "NULL")) if (strequ(suffixTbl[i++].mp, entry)) return i-1; } else if (column == 3) { while (!strequ(suffixTbl[i].mc, "NULL")) if (strequ(suffixTbl[i++].mc, entry)) return i-1; } else fatal_error("Search undefined table column."); } else if (strequ(table, "compression")) { if (column == 1) { while (!strequ(compr[i].format, "NULL")) if (strequ(compr[i++].format, entry)) return i-1; } else if (column == 2) { while (!strequ(compr[i].shrt, "NULL")) if (strequ(compr[i++].shrt, entry)) return i-1; } else if (column == 3) { while (!strequ(compr[i].shortest, "NULL")) if (strequ(compr[i++].shortest, entry)) return i-1; } else fatal_error("Search undefined table column."); } else { fprintf(stderr, "Search unknown table: %s in lookup()\n", table); exit(1); } return NOT_FOUND; } char *get_last_suffix(char *fileName) { char *extension, *ext2, *suffix; int dot = FALSE; int i, len; if ((len=strlen(fileName)) > 0) { for (i=0; i 0) { if (!strcmp(suffix, ".Z") || !strcmp(suffix, ".z")) strcpy(suffix, ".Z"); else { ext2 = str2lower_case(suffix); free(suffix); suffix = ext2; } } #endif return suffix; } #ifdef VMS_PULL char *get_extension(char *fileName) { char *extension, *ext2, *suffix; if (strlen(fileName) == 0) return SNULL; if ((suffix = get_last_suffix(fileName)) == SNULL) return SNULL; if (!strchr(suffix, '-')) { free(suffix); return SNULL; } extension = (char*)strrchr(suffix,'-'); if (extension == SNULL) return extension; ext2 = (char*)str_dup(extension); free(suffix); return ext2; } #endif #if (DOS_PULL || OS2FAT_PULL) char *str2lower_case(char *s) { int i = -1; char *t = (char*)str_dup(s); if (s == SNULL) return SNULL; while (s[++i] != '\0') if (isalpha(s[i]) && isupper(s[i])) t[i] = tolower(s[i]); return t; } #endif char *get_base_name(char *fileName) { char *baseName, *fullName; fullName = (char *)str_dup(fileName); baseName = (char *)strtok(fullName, "."); return baseName; } char *last_suffix_removed(char *fileName) { char *longBaseName; int i, length; if (!strchr(fileName, '.')) return fileName; else if ((length = strlen(fileName)) > 0) { longBaseName = calloc_mem(NAMELEN, "char *", "longBaseName"); for (i=length-1; i>=0; i--) if (fileName[i] == '.') break; longBaseName = (char *)strncpy(longBaseName, fileName, i); longBaseName[i] = '\0'; return longBaseName; } else return SNULL; } #ifdef VMS_PULL char *extension_removed(char *fileName) { char *longBaseName; char *suffix; int i, length; if (fileName == SNULL) return SNULL; if ((suffix = get_last_suffix(fileName)) == SNULL) return fileName; if (!strchr(suffix, '-')) { free(suffix); return fileName; } else if ((length = strlen(fileName)) > 0) { longBaseName = calloc_mem(NAMELEN, "char *", "longBaseName"); for (i=length-1; i>=0; i--) if (fileName[i] == '-') break; longBaseName = (char *)strncpy(longBaseName, fileName, i); longBaseName[i] = '\0'; return longBaseName; } else return SNULL; } #endif void free_str(char *s) { if (s) free(s); } char *map_suffix_up(char *inSuffix) { char *shortSuffix, *outSuffix, *sufxCol3, *comprCol3; int index, index2; int len; comprCol3 = calloc_mem(SUFXLEN, "char *", "comprCol3"); len = strlen(inSuffix); if (len < 2) { fprintf(stderr, "suffix: %s is short than 2 chars.\n", inSuffix); return SNULL; } shortSuffix = last_char_removed(inSuffix); len = strlen(shortSuffix); if (len == 3) { strccat(comprCol3, last_char(shortSuffix)); sufxCol3 = last_char_removed(shortSuffix); } if ((lookup("suffix", 2, shortSuffix) != NOT_FOUND) || (lookup("compression", 2, shortSuffix) != NOT_FOUND)) { outSuffix = (char*)str_dup(shortSuffix); } else if (((index = lookup("suffix", 3, sufxCol3)) != NOT_FOUND) && ((index2 = lookup("compression", 3, comprCol3)) != NOT_FOUND)) { outSuffix = calloc_mem(SUFXLEN, "char *", "outSuffix"); strcpy(outSuffix, suffixTbl[index].mp); strccat(outSuffix, last_char(compr[index2].shortest)); } else { fprintf(stderr, "Don't know how to process suffix: %s\n", inSuffix); return SNULL; } free_str(shortSuffix); free_str(sufxCol3); free_str(comprCol3); return outSuffix; } char *map_suffix_down(char *inSuffix) { char *outSuffix, *sufxCol2, *comprCol3; int index; comprCol3 = calloc_mem(SUFXLEN, "char *", "comprCol3"); outSuffix = calloc_mem(SUFXLEN, "char *", "outSuffix"); strccat(comprCol3, last_char(inSuffix)); sufxCol2 = last_char_removed(inSuffix); if ((lookup("suffix", 1, inSuffix) != NOT_FOUND) || (lookup("compression", 1, inSuffix) != NOT_FOUND)) outSuffix = inSuffix; else if (((index = lookup("suffix", 2, sufxCol2)) != NOT_FOUND) && (lookup("compression", 3, comprCol3) != NOT_FOUND)) { strcpy(outSuffix, suffixTbl[index].mc); strccat(outSuffix, last_char(inSuffix)); } else { fprintf(stderr, "Don't know how to process suffix: %s\n", inSuffix); return SNULL; } free_str(sufxCol2); free_str(comprCol3); return outSuffix; } char *map2col1(char *inSuffix) { char *outSuffix, *sufxCol3, *comprCol3; int index, len; comprCol3 = calloc_mem(SUFXLEN, "char *", "comprCol3"); outSuffix = calloc_mem(SUFXLEN, "char *", "outSuffix"); len = strlen(inSuffix); if (len < 3) return SNULL; sufxCol3 = last_char_removed(inSuffix); strccat(comprCol3, last_char(inSuffix)); if (((index = lookup("suffix", 3, sufxCol3)) != NOT_FOUND) && (lookup("compression", 3, comprCol3) != NOT_FOUND)) { strcpy(outSuffix, suffixTbl[index].sp); } else { return SNULL; } free_str(comprCol3); free_str(sufxCol3); return outSuffix; } int decompress_file(char *inFile) { char *baseName, *suffix, *file_zz; char *sufxCol2, *comprCol3, *file_out; int index, index2; int rc, gunzip_rc, len; file_zz = calloc_mem(NAMELEN, "char *", "file_zz"); file_out = calloc_mem(NAMELEN, "char *", "file_out"); comprCol3= calloc_mem(SUFXLEN, "char *", "comprCol3"); #ifdef VMS_PULL if ((suffix = get_last_suffix(inFile)) == SNULL) { fprintf(stderr, "%s has no suffix in decompress_file(inFile)\n", inFile); exit(1); } if (!strchr(suffix, '-')) baseName = last_suffix_removed(inFile); else { free_str(suffix); baseName = extension_removed(inFile); suffix = get_extension(inFile); } #else baseName = last_suffix_removed(inFile); if ((suffix = get_last_suffix(inFile)) == SNULL) { fprintf(stderr, "%s has no suffix in decompress_file(inFile)\n", inFile); exit(1); } #endif len = strlen(suffix); if (len >= 3) { sufxCol2 = last_char_removed(suffix); strccat(comprCol3, last_char(suffix)); } if ((index2 = lookup("compression", 1, suffix)) != NOT_FOUND) { if (index2 == 0) { if (gunzip(inFile)) { if (!cmd_option[0].std_out) print_output_msg(baseName); else { copy_file_to_stdout(baseName, stdout); remove(baseName); } rc = TRUE; } else { rc = FALSE; } } else if (index2 == 1) { #if (DOS_PULL || VMS_PULL || OS2_PULL) if (gunzip(inFile)) { if (!cmd_option[0].std_out) print_output_msg(baseName); else { copy_file_to_stdout(baseName, stdout); remove(baseName); } rc = TRUE; } else rc = FALSE; #elif MAC_PULL rc = TRUE; #elif UNIX_PULL if (uncompress(inFile)) { if (!cmd_option[0].std_out) print_output_msg(baseName); else { copy_file_to_stdout(baseName, stdout); remove(baseName); } rc = TRUE; } else rc = FALSE; #endif } else if (index2 == 2) { fprintf(stderr, ".zip not implemented yet\n"); rc = FALSE; } } else if (((index = lookup("suffix", 2, sufxCol2)) != NOT_FOUND) && ((index2 = lookup("compression", 3, comprCol3)) != NOT_FOUND)) { #if (UNIX_PULL || DOS_PULL || OS2_PULL) sprintf(file_zz, "%s%s", baseName, compr[index2].format); #elif (VMS_PULL) sprintf(file_zz, "%s%s%s", baseName, suffixTbl[index].sp, compr[index2].format); #endif my_rename(inFile, file_zz); gunzip_rc = gunzip(file_zz); if (gunzip_rc == 1 || gunzip_rc == 2) { sprintf(file_out, "%s%s", baseName, suffixTbl[index].sp); #if (UNIX_PULL || DOS_PULL || OS2_PULL) my_rename(baseName, file_out); #endif if (!cmd_option[0].std_out) { if (!cmd_option[0].q) print_output_msg(file_out); } else { copy_file_to_stdout(file_out, stdout); if (!cmd_option[0].q) fprintf(stderr, "%s extracted and sent to stdout\n", file_out); remove(file_out); } rc = TRUE; } else { if (is_file(file_zz)) remove(file_zz); if (gunzip_rc == 0) rc = FALSE; else if (gunzip_rc == 3) exit(0); else fatal_error("Impossible gunzip rc from decompress_file()"); } } #ifdef VMS_PULL else if (strequ(suffix, ".zp") || strequ(suffix, "-zp")) { sprintf(file_zz, "%s-zip", baseName); #else else if (strequ(suffix, ".zp")) { sprintf(file_zz, "%s.zip", baseName); #endif my_rename(inFile, file_zz); rc = unzip(file_zz); } else { fprintf(stderr, "Unknown suffix: %s. Don't know how to decompress\n", suffix); rc = FALSE; } free_str(comprCol3); free_str(suffix); free_str(sufxCol2); free_str(baseName); free_str(file_out); free_str(file_zz); return rc; } char last_char(char *s) { int length = 0; length = strlen(s); if (length == 0) return CNULL; return s[length-1]; } int trim_last_char(char *s) { int length = 0; length = strlen(s); if (length <= 1) return FALSE; s[length-1] = '\0'; return TRUE; } char *last_char_removed(char *s) { char *fileName; int length = 0; length = strlen(s); if (length <= 1) return SNULL; fileName = (char *)str_dup(s); fileName[length-1] = '\0'; return fileName; } int exec_command(char *command, char *inFile, char *outFile, char *format) { int rc=FALSE; #ifdef VMS_PULL char dummy[NAMELEN]; #endif strcat(command, inFile); #if (UNIX_PULL || DOS_PULL || MAC_PULL || OS2_PULL) strcat(command, " > "); strcat(command, outFile); #elif VMS_PULL strcpy(dummy, outFile); #endif if (!cmd_option[0].q) fprintf(stderr, " %s compressing %s ... ", format, inFile); #ifdef VMS_PULL if ((rc = system(command)) != 0) #else if (system(command) == 0) #endif { if (!cmd_option[0].q) fprintf(stderr, " done.\n"); rc = TRUE; } else rc = FALSE; return rc; } int merge(char *file1, char *file2, int seq, char *filetype) { int c; FILE *fp1 = FNULL, *fp2 = FNULL; char mode[FILE_IO_MODE]; if (strequ(filetype, "binary")) strcpy(mode, "rb"); else if (strequ(filetype, "ascii")) strcpy(mode, "r"); else fatal_error("In calling merge(), invalid filetype specified"); fp1 = f_open(file1, mode, "merge"); if (seq < 1) { fatal_error("In calling merge(), seq # must > 0"); } else if (seq == 1) { if (strequ(filetype, "binary")) strcpy(mode, "wb"); else strcpy(mode, "w"); } else { if (strequ(filetype, "binary")) strcpy(mode, "ab"); else strcpy(mode, "a"); } fp2 = f_open(file2, mode, "merge"); if (strequ(filetype, "binary")) { c = getc(fp1); while (!feof(fp1)) { putc(c, fp2); c = getc(fp1); } } else { while ((c = getc(fp1)) != EOF) putc(c, fp2); } fclose(fp1); fclose(fp2); return TRUE; } int my_rename(char *file1, char *file2) { FILE *ifp, *ofp; #if (DOS_PULL || OS2_PULL) if ((ofp = fopen(file2, "r")) != FNULL) { fclose(ofp); remove(file2); } #endif rename(file1, file2); return TRUE; } int gunzip(char *infile) { char *outfile; char sys_command[LINELEN]; int rc; FILE *fp; int oldOutfileExist = FALSE; strcpy(sys_command, "gzip -d "); strcat(sys_command, infile); #ifdef VMS_PULL outfile = extension_removed(infile); #else outfile = get_base_name(infile); #endif oldOutfileExist = is_file(outfile); rc = system(sys_command); if (!oldOutfileExist) if (!is_file(outfile)) rc = 0; else rc = 1; else if (!is_file(infile)) rc = 2; else rc = 3; free_str(outfile); if (rc<0 || rc>3) { fprintf(stderr, "impossible gunzip outcome, rc = %i\n", rc); exit(1); } return rc; } int uncompress(char *file) { char sys_command[LINELEN]; #if (DOS_PULL || OS2_PULL) strcpy(sys_command, "gzip -d -n "); #elif MAC_PULL strcpy(sys_command, "gzip -d "); #elif UNIX_PULL strcpy(sys_command, "uncompress "); #elif VMS_PULL strcpy(sys_command, "gzip -d -n "); #endif strcat(sys_command, file); if (system(sys_command) == 0) return TRUE; return FALSE; } int gzip(char *inFile, char *outFile) { char sys_command[LINELEN]; int rc=0; #ifdef VMS_PULL char tmpInfile[NAMELEN], tmpOutfile[NAMELEN]; FILE *ofp, *tmpofp; #endif #if (DOS_PULL || OS2_PULL) if (is_binary_file(inFile)) strcpy(sys_command, "gzip -9 -c "); else strcpy(sys_command, "gzip -9 -ac "); #elif MAC_PULL strcpy(sys_command, "gzip -9 -c "); #elif UNIX_PULL strcpy(sys_command, "gzip -9 -c "); #elif VMS_PULL strcpy(sys_command, "gzip -9 "); #endif #ifdef VMS_PULL strcpy(tmpInfile, inFile); strcat(tmpInfile, "tmp"); strcpy(tmpOutfile, tmpInfile); strcat(tmpOutfile, "-gz"); rc = exec_command(sys_command, inFile, outFile, "-gz"); ofp = f_open(outFile, "rb", "gzip"); tmpofp = f_open(tmpOutfile, "wb", "gzip"); file_copy(ofp, tmpofp); fclose(ofp); fclose(tmpofp); gunzip(tmpOutfile); my_rename(tmpInfile, inFile); #else rc = exec_command(sys_command, inFile, outFile, ".gz"); #endif return rc; } void file_copy(FILE *ifp, FILE *ofp) { int c; while ((c=getc(ifp)) != EOF) putc(c, ofp); } int compress(char *inFile, char *outFile) { char sys_command[LINELEN]; #if (DOS_PULL || OS2_PULL) strcpy(sys_command, "compress -c "); #elif MAC_PULL strcpy(sys_command, "compress -c "); #elif UNIX_PULL strcpy(sys_command, "compress -c "); #elif VMS_PULL strcpy(sys_command, "compress -c "); #endif #ifdef VMS_PULL return exec_command(sys_command, inFile, outFile, "-Z"); #else return exec_command(sys_command, inFile, outFile, ".Z"); #endif } int zip(char *inFile, char *outFile) { char sys_command[LINELEN]; #if (DOS_PULL || OS2_PULL) strcpy(sys_command, "pkzip -c "); #else strcpy(sys_command, "zip -c "); #endif #ifdef VMS_PULL return exec_command(sys_command, inFile, outFile, "-zip"); #else return exec_command(sys_command, inFile, outFile, ".zip"); #endif } int unzip(char *file) { char sys_command[LINELEN]; #if (DOS_PULL || OS2_PULL) strcpy(sys_command, "pkunzip "); #elif MAC_PULL strcpy(sys_command, "gzip -d "); #elif VMS_PULL strcpy(sys_command, "gzip -d "); #elif UNIX_PULL strcpy(sys_command, "unzip "); #endif strcat(sys_command, file); if (system(sys_command) == 0) return TRUE; return FALSE; } int decode(char *inFile, char *outFile) { char inFile2[NAMELEN]; int rc; if (strequ(inFile, outFile)) { #ifdef VMS_PULL sprintf(inFile2, "%s%s", get_base_name(inFile), "-xyz"); #else sprintf(inFile2, "%s%s", get_base_name(inFile), ".xyz"); #endif fprintf(stderr, "Naming conflict: %s and its decoded file use the same name.\n", inFile); fprintf(stderr, "Rename encoded %s to %s\n", inFile, inFile2); rename(inFile, inFile2); rc = uudecode(inFile2, outFile); } else rc = uudecode(inFile, outFile); if (rc==FALSE) exit(1); return rc; } int is_option(char *argument) { if ((strlen(argument) != 2) || (argument[0] != '-') || !isalpha(argument[1])) return FALSE; else return TRUE; } void print_help_info(char *option) { if (!strcmp(option, "-h")) print_manual(); else if (!strcmp(option, "-B")) bug_report(); else if (!strcmp(option, "-C")) compilation(); else if (!strcmp(option, "-D")) print_push(); else if (!strcmp(option, "-G")) print_gzip_ftp_info(); else if (!strcmp(option, "-I")) installation(); else if (!strcmp(option, "-L")) print_license_info(); else if (!strcmp(option, "-S")) handle_cm_ps_file(); else if (!strcmp(option, "-U")) print_usage(); else if (!strcmp(option, "-V")) print_version(); else fprintf(stderr, "unknown option: %s\n", option); exit(0); } char *compress_file(char *inFile, char *format) { char *baseName, *file_zz; char gzsuf[SUFXLEN], Zsuf[SUFXLEN], zipsuf[SUFXLEN]; file_zz = calloc_mem(NAMELEN, "char *", "file_zz"); #if (DOS_PULL || OS2FAT_PULL) baseName = get_base_name(inFile); strcpy(file_zz, baseName); strcpy(gzsuf, ".gz"); strcpy(Zsuf, ".Z"); strcpy(zipsuf, ".zip"); #elif MAC_PULL baseName = get_base_name(inFile); strcpy(file_zz, baseName); strcpy(gzsuf, ".gz"); strcpy(Zsuf, ".Z"); strcpy(zipsuf, ".zip"); #elif (UNIX_PULL || OS2HPFS_PULL) strcpy(file_zz, inFile); strcpy(gzsuf, ".gz"); strcpy(Zsuf, ".Z"); strcpy(zipsuf, ".zip"); #elif VMS_PULL strcpy(file_zz, inFile); strcpy(gzsuf, "-gz"); strcpy(Zsuf, "-Z"); strcpy(zipsuf, "-zip"); #endif if (strequ(format, gzsuf)) { strcat(file_zz, gzsuf); if (gzip(inFile, file_zz)) return file_zz; } else if (strequ(format, Zsuf)) { strcat(file_zz, Zsuf); if (compress(inFile, file_zz)) return file_zz; } else if (!strcmp(format, zipsuf)) { strcat(file_zz, zipsuf); if (zip(inFile, file_zz)) return file_zz; } else { fatal_error("Unknown compressing format."); } return SNULL; } void push_files(char **inFile, int num_of_infiles, long chunkSize, int chunks) { char *remoteFile, *remoteFile2, *outFile1, *outFile2, *outFile3; char outFile1x[NAMELEN], outFile2x[NAMELEN], outFile3x[NAMELEN]; char **input_file; char *suffix, *newSuffix, *newSuffix2, *baseName, *file_zz, outfn[NAMELEN]; char gzsuf[SUFXLEN], Zsuf[SUFXLEN], uuesuf[SUFXLEN]; int lines; long int words, chars; int index, len; int N = num_of_infiles; FILE *tmp_ofp; #ifdef VMS_PULL strcpy(gzsuf, "-gz"); strcpy(Zsuf, "-Z"); strcpy(uuesuf, "-uue"); #else strcpy(gzsuf, ".gz"); strcpy(Zsuf, ".Z"); strcpy(uuesuf, ".uue"); #endif if (N<1 || N>2) { fprintf(stderr, "number of infiles %i to push_files() out of range [1, 2]\n", N); exit(1); } suffix = get_last_suffix(inFile[N-1]); #ifdef VMS_PULL if (strlen(suffix)<=1) { fprintf(stderr, "File typeless error of %s\n", inFile[N-1]); exit(1); } #endif baseName = get_base_name(inFile[N-1]); len = strlen(baseName); if (len > 8) fprintf(stderr, "Warning: length of file base name %s exceeds 8 chars.\n", inFile[N-1]); if ((file_zz = compress_file(inFile[N-1], gzsuf)) == SNULL) { fatal_error("gzip fails (not available?)"); } remoteFile = calloc_mem(NAMELEN, "char *", "remoteFile"); remoteFile2 = calloc_mem(NAMELEN, "char *", "remoteFile2"); outFile1 = calloc_mem(NAMELEN, "char *", "outFile1"); outFile2 = calloc_mem(NAMELEN, "char *", "outFile2"); outFile3 = calloc_mem(NAMELEN, "char *", "outFile3"); newSuffix = calloc_mem(NAMELEN, "char *", "newSuffix"); newSuffix2 = calloc_mem(NAMELEN, "char *", "newSuffix2"); strcpy(remoteFile, baseName); strcpy(remoteFile2, baseName); if ((index = lookup("suffix", 1, suffix)) != NOT_FOUND) { sprintf(newSuffix, "%sz", suffixTbl[index].mp); sprintf(newSuffix2, "%sZ", suffixTbl[index].mp); } else { #ifdef VMS_PULL if (strlen(suffix) > 1) { sprintf(newSuffix, "%s%s", suffix, gzsuf); sprintf(newSuffix2, "%s%s", suffix, Zsuf); } else { fprintf(stderr, "File type error of %s\n", inFile[N-1]); exit(1); } #else strcpy(newSuffix, gzsuf); strcpy(newSuffix2, Zsuf); #endif } strcat(remoteFile, newSuffix); strcat(remoteFile2, newSuffix2); #if (DOS_PULL || OS2FAT_PULL) strcpy(outFile1, baseName); sprintf(outFile2, "%s.zue", baseName); sprintf(outFile3, "%s.Zue", baseName); sprintf(outFile1x, "%s.uue", inFile[N-1]); sprintf(outFile2x, "%s.gz.uue", inFile[N-1]); sprintf(outFile3x, "%s.Z.uue", inFile[N-1]); #elif MAC_PULL strcpy(outFile1, baseName); sprintf(outFile2, "%s.zue", baseName); sprintf(outFile3, "%s.Zue", baseName); #elif (UNIX_PULL || OS2HPFS_PULL) strcpy(outFile1, inFile[N-1]); sprintf(outFile2, "%s.uue", file_zz); sprintf(outFile3, "%s.Z.uue", inFile[N-1]); #elif VMS_PULL strcpy(outFile1, inFile[N-1]); sprintf(outFile2, "%s-uue", file_zz); sprintf(outFile3, "%s-Z-uue", inFile[N-1]); #endif strcat(outFile1, uuesuf); if (N==1) uue77(file_zz, remoteFile, outFile2, "w"); else { merge(inFile[0], outFile2, 1, "ascii"); tmp_ofp = f_open(outFile2, "a", "push_files"); fprintf(tmp_ofp, "\n"); fclose(tmp_ofp); uue77(file_zz, remoteFile, outFile2, "a"); } if (N == 2) { wordcnt_file(inFile[0], &lines, &words, &chars); if (chunkSize < chars) { fprintf(stderr, "%s file size %ld too large.\n", inFile[0], chars); fprintf(stderr, "Must be smaller than default or specified chunk size %ld.", chunkSize); exit(1); } } wordcnt_file(outFile2, &lines, &words, &chars); if (chunkSize < chars/MAXPARTS) { fprintf(stderr, "Specified bytes %ld too small.", chunkSize); fprintf(stderr, " Must be greater than %ld \n", chars/MAXPARTS); fprintf(stderr, " in order to limit number of split files "); fprintf(stderr, "within %i.\n", MAXPARTS); exit(1); } if ((chars>chunkSize || cmd_option[0].p) && !cmd_option[0].n) { remove(outFile2); if (cmd_option[0].std_out) fprintf(stderr, "-c surpressed as in conflict with multiple output files\n"); input_file = calloc_mem(N+1, "char **", "input_file"); if (N==2) input_file[0] = (char *)str_dup(inFile[0]); input_file[N-1] = file_zz; push_with_split(input_file, N, newSuffix, chars, chunkSize, chunks); } else if (cmd_option[0].n || chunks==1 || chunkSize>=chars) { remove(file_zz); if (cmd_option[0].std_out) { copy_file_to_stdout(outFile2, stdout); remove(outFile2); strcpy(outfn, "\"stdout\" "); } else strcpy(outfn, outFile2); #if (DOS_PULL || OS2FAT_PULL) if (!cmd_option[0].q) { fprintf(stderr, "\nchars (K) lines words output file stands for\n"); fprintf(stderr, "%5ld %6.2f %5d %6ld %s %s\n", chars, k_bytes(chars), lines, words, outfn, outFile2x); } #elif (UNIX_PULL || OS2HPFS_PULL) if (!cmd_option[0].q) { fprintf(stderr, "\nchars (K) lines words output file\n"); fprintf(stderr, "%5d %6.2f %5d %6d %s\n", chars, k_bytes(chars), lines, words, outfn); } #elif VMS_PULL if (!cmd_option[0].q) { fprintf(stderr, "\nchars (K) lines words output file\n"); fprintf(stderr, "%5d %6.2f %5d %6d %s\n", chars, k_bytes(chars), lines, words, outfn); } #endif } else ; free(remoteFile); free(remoteFile2); free_str(outFile2); free_str(outFile3); free_str(newSuffix); free_str(newSuffix2); free_str(baseName); } void push_with_split(char **inFile, int num_of_infiles, char *suffix, long int chars, long chunkSize, int chunks) { int i, noOfParts; int lines; int N = num_of_infiles; long bytes, words, bytesPerPart, bytesPerAsciiPart, *fileSize, header_size; char *newSuffix; char *prefix, *baseName; int newline_size; #if (DOS_PULL || OS2_PULL) newline_size = 2; #elif MAC_PULL newline_size = 2; #elif UNIX_PULL newline_size = 1; #elif VMS_PULL newline_size = 1; #endif i = cmd_option[0].z; if (chunks==UNSPECIFIED) { noOfParts = (int) (chars / chunkSize); if (chars % chunkSize > 0L) noOfParts++; } if (chunks>1) noOfParts = chunks; fileSize = calloc_mem(noOfParts+1, "long int *", "fileSize"); wordcnt_file(inFile[N-1], &lines, &words, &bytes); if ((cmd_option[0].f+cmd_option[0].l==0) || (chunks > 1)) { if (N==1) { bytesPerPart = (long int)bytes / noOfParts; if (bytes % noOfParts > 0L) bytesPerPart++; for (i=0; i 0L) bytesPerAsciiPart++; wordcnt_file(inFile[0], &lines, &words, &header_size); header_size += (long) newline_size; bytesPerPart = (long) bytesPerAsciiPart * ((float)bytes / (float)(chars-header_size)); fileSize[0] = bytes - (noOfParts-1)*bytesPerPart; for (i=1; i MAXFILES) { fprintf(stderr, "Warning: num of split files (%i) > MAXFILES (%i)\n", noOfParts, MAXFILES); fprintf(stderr, "Raise MAXFILES.\n"); } fileName = calloc_mem(noOfParts, "char **", "fileName"); for (i=0; i> 2; c2 = (*p << 4) & 060 | (p[1] >> 4) & 017; c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03; c4 = p[2] & 077; putc(enc(c1), f); putc(enc(c2), f); putc(enc(c3), f); putc(enc(c4), f); } int uudecode(char *filename, char *outFile) { register int n; register char ch, *p; int mode; char buf[BUFSIZE]; FILE *ifp, *ofp; ifp = f_open(filename, "r", "uudecode"); ofp = f_open(outFile, "wb", "uudecode"); do { if (!fgets(buf, sizeof(buf), ifp)) { (void)fprintf(stderr, "uudecode: %s: no \"begin\" line\n", filename); fclose(ifp); fclose(ofp); return FALSE; } } while (strncmp(buf, "begin ", 6)); (void)sscanf(buf, "begin %o %s", &mode, buf); for (;;) { if (!fgets(p = buf, sizeof(buf), ifp)) { (void)fprintf(stderr, "uudecode: %s: short file.\n", filename); fclose(ifp); fclose(ofp); return FALSE; } #define DEC(c) (((c) - ' ') & 077) if ((n = DEC(*p)) <= 0) break; for (++p; n > 0; p += 4, n -= 3) if (n >= 3) { ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; putc(ch, ofp); ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; putc(ch, ofp); ch = DEC(p[2]) << 6 | DEC(p[3]); putc(ch, ofp); } else { if (n >= 1) { ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; putc(ch, ofp); } if (n >= 2) { ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; putc(ch, ofp); } if (n >= 3) { ch = DEC(p[2]) << 6 | DEC(p[3]); putc(ch, ofp); } } } if (!fgets(buf, sizeof(buf), ifp) || strcmp(buf, "end\n")) { (void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n", filename); fclose(ifp); fclose(ofp); return FALSE; } fclose(ifp); fclose(ofp); return TRUE; } void print_output_msg(char *outFile) { if (!cmd_option[0].q) fprintf(stderr, "%s extracted\n", outFile); } void bug_report() { printf("First please read the help file pullhelp.htm or pullhelp.txt\n"); printf("If still can't resolve the problem, then send a bug report to\n"); printf(" Yao Li at %s\n", my_eaddress); printf("Please include\n"); printf(" - complete error/warning msg displayed on your screen,\n"); printf(" including command option, file names in command line\n"); #if (UNIX_PULL || DOS_PULL || OS2_PULL) printf(" - version number of pull, type `pull -V'\n"); #elif VMS_PULL printf(" - version number of pull, type `pull \"-V\"'\n"); #endif printf(" - operating system, platform, C compiler if used\n"); #ifdef UNIX_PULL printf(" on Unix, command `uname -a' displays OS, platform, ...\n"); #endif printf("\nYour comments are always welcome.\n"); } void print_gzip_ftp_info() { printf("pull uses gzip/gunzip that is stored at anonymous ftp sites\n"); printf("(for Unix, MSDOS, OS/2, VMS, Mac, Atari, Amiga, Primos):\n"); printf("prep.ai.mit.edu:/pub/gnu/gzip-1.2.4.tar (or .shar or .tar.gz : source)\n"); printf("prep.ai.mit.edu:/pub/gnu/gzip-msdos-1.2.4.exe (MSDOS, lha self-extract)\n"); printf("garbo.uwasa.fi:/unix/arcers/gzip-1.2.4.tar.Z (source)\n"); printf("garbo.uwasa.fi:/pc/unix/gzip124.zip (MSDOS exe)\n"); printf("ftp.uu.net:/pub/archiving/zip/VMS/gzip124x.vax_exe (VMS exe)\n"); printf("mac.archive.umich.edu:/mac/util/compression/macgzip0.22.cpt.hqx (Mac)\n"); printf("src.doc.ic.ac.uk:/computing/systems/mac/info-mac/cmp/mac-gzip-022.hqx\n"); printf("mac.archive.umich.edu:/mac/development/source/macgzip0.2src.cpt.hqx\n"); printf("Reference: Usenet Newsgroup comp.compression FAQ Part 1\n"); printf("stored at: rtfm.mit.edu:/pub/usenet/news.answers/compression-faq/part[1-3]\n"); } void compilation() { #ifdef DOS_PULL printf("Compile and link pull.c for ms-dos version\n\n"); printf("Example: use Turbo C++ 2.0 compiler\n"); printf("`tcc -DDOS_PULL=1 -O pull' or `tcc -DDOS_PULL=1 pull'\n"); printf("The created executable: pull.exe\n"); #elif OS2FAT_PULL printf("Compile and link pull.c for OS/2 FAT version\n\n"); printf("Example: use Borland C++ compiler\n"); printf("`bcc -4 -DOS2FAT_PULL=1 pull.c'\n"); printf("The created executable: pull.exe\n"); #elif OS2HPFS_PULL printf("Compile and link pull.c for OS/2 HPFS version\n\n"); printf("Example: use Borland C++ compiler\n"); printf("`bcc -4 -DOS2HPFS_PULL=1 pull.c'\n"); printf("The created executable: pull.exe\n"); #elif UNIX_PULL printf("Compile and link pull.c for Unix version\n\n"); printf("1. Issue `cc -o pull pull.c'\n"); printf(" pull.c is compiled to pull, if no error. Ignore warning msg.\n"); printf("2. Or, with optimization: issue `cc -O -o pull pull.c'\n"); #elif VMS_PULL printf("Compile and link pull.c for VMS version\n\n"); printf("1. Issue `cc pull /define=(VMS_PULL)', where VMS_PULL must be in uppercase.\n"); printf(" pull.c is compiled to pull.obj, if no error. Ignore warning msg.\n"); printf("2. `link pull' -- link pull.obj to pull.exe\n"); printf("3. `pull == \"$disk:[directory]pull.exe\"' -- set symbol for pull.exe\n"); printf("4. `delete pull.obj;1' -- delete pull.obj\n"); printf("5. Issue `pull \"-I\"' for installation.\n\n"); printf("Notes: after step 3, pull is ready for use, BUT only good for current\n"); printf("terminal (login) session. To make it a system command, do step 5.\n"); #endif printf("\n"); printf("Having successfully compiled pull, you may issue \"pull -h\" (not \"pull\").\n"); } void installation() { printf("Benefit: after installation, pull can be used as if using a system\n"); printf(" command from any directory.\n\n"); #ifdef DOS_PULL printf("Install pull.exe on MS-DOS:\n\n"); printf("pull.exe may be put under c:\\bin directory, or any bin directory \n"); printf("that its path is listed in autoexec.bat file. pull.exe requires gzip\n"); printf("also installed as a system command or at least under the same directory\n"); printf("with pull.exe."); #elif OS2_PULL printf("Install pull.exe on OS/2:\n\n"); printf("pull.exe may be put under c:\\bin directory, or any bin directory \n"); printf("that its path is listed in config.sys file. pull.exe requires gzip\n"); printf("also installed as a system command or at least under the same directory\n"); printf("with pull.exe."); #elif UNIX_PULL printf("Install pull on Unix\n\n"); printf("There are two options:\n"); printf("1. Move pull to your bin dir. Then it can be used from any dir.\n"); printf(" If you don't have 'bin' directory,\n"); printf(" a) at your home dir, issue `mkdir bin' -- creates bin under your home dir;\n"); printf(" b) edit your .cshrc or .login file by adding bin to search path, i.e.,\n"); printf(" add a line `set path = ($path /absolutePathToYourHome/bin)' or alike;\n"); printf(" To get the value of `absolutePathToYourHome', issue `cd' or\n"); printf(" `cd ~/' to return to your home directory. Then issue `pwd'.\n"); printf(" Finally, it might look something like:\n"); printf(" `set path = ($path /users/group3/john/bin)'\n"); printf(" c) logout then login (for once only). This is a safe way, but slow.\n"); printf(" Or you may issue `source .cshrc' or `source .login' in each\n"); printf(" window you'll use pull if you are in window system.\n"); printf("2. Define an alias pull in your .cshrc file pointing where pull resides\n"); printf("Once all done, to save disk space, you might remove pull.c\n"); #elif VMS_PULL printf("Install pull on VMS\n\n"); printf("Place following line in your LOGIN.COM file\n\n"); printf("pull==\"$disk:[directory]pull.exe\"\n\n"); printf("Modify disk and directory appropriately to point to pull.exe\n"); printf("If you don't have LOGIN.COM file, you can create one.\n"); printf("Once all done, to save disk space, you might delete pull.c\n"); #endif } void print_license_info() { printf("This software is provided \"as is\" without any warranty;\n"); printf("without even the implied warranty of merchantability.\n"); printf("Redistribution and non-commercial use are permitted.\n"); printf("Author: Yao Li %s.\n", my_eaddress); printf("Copyright: %s.\n\n", copyright); printf("For user's convenience, uuencode.c and uudecode.c are trimed and\n"); printf("included with the key change to uuencode.c of widening the output from 61\n"); printf("chars/line to 77 chars/line. These two utilities have\n"); printf("Copyright (c) 1983/1993 Regents of the University of California.\n\n"); #ifdef VMS_PULL printf("Acknowledgement: VMS porting received help from W.M. (Canada) and Seak (France)\n"); #endif } void handle_cm_ps_file() { printf("View Chinese magazine PS version:\n\n"); printf("Need a ps interpreter and a previewer. They are widely available as freeware.\n"); printf("Unix: check`pageview' on Sun, `ghostview' on HP etc.\n"); printf("MS-WIN, OS/2: GSview and Aladdin Ghostscript; VMS: GhostView-VMS\n"); printf("Check info at ftp://ftp.cs.wisc.edu/ghost/gsfaq.txt\n"); printf(" http://www.cs.wisc.edu/~ghost/gsfaq.html\n"); printf("Mac: ftp://ftp.cs.wisc.edu/pub/ghost/aladdin/mac/\n"); printf(" http://www.glyphic.com/glyphic/projects/macgs.html\n"); printf("Ghostscript, Ghostview and GSview Home page: http://ftp.cs.wisc.edu/~ghost/\n"); printf("\nFor more information on ps viewers and ps file, you may read the FAQ\n"); printf("of Usenet newsgroup comp.sources.postscript (also available from ftp:\n"); printf("wilma.cs.brown.edu/pub/comp.sources.postscript)\n"); printf("\nPrint Chinese magazine PS version:\n"); printf("\nPrintable on the PostScript laser printer, or a personal laser printer\n"); printf("plus a PostScript interpreter such as Ghostscript.\n"); printf("Please avoid printing ps file during working hours as it is slow.\n"); printf("\nHaving extracted cm.ps, you may delete ps mails to save mailbox space,\n"); printf("and use `gzip' to compress large ps file.\n"); } void print_push() { printf("push a file = packing a file. Compress, split, and encode a file\n\n"); printf("1. One input file\n"); printf("pull -d [-fln -b bytes -p parts] file\n"); printf(" -d file equal size split, up to default 64k/chunk\n"); printf(" -d -n file no split\n"); printf(" -d -b bytes file equal size split, up to 'bytes'/chunk\n"); printf(" -d -p parts file equal size split, into number of 'parts' (1--9)\n"); printf(" -d -f [-b bytes] file first file aligned split.\n"); printf(" -d -l [-b bytes] file last file aligned split.\n"); printf(" First/Last N-1 files has chunk size 'bytes' or\n"); printf(" default 64k each. The Nth file has remaining size.\n"); printf("2. Two input files\n"); printf("pull -d [-n -b bytes -p parts] header file\n"); printf("Ascii 'header' file with arbitrary filename is prepended intact to the\n"); printf("first part of output files. All parts are of equal size in bytes.\n"); printf(" -d header file equal size split, up to default 64k/chunk\n"); printf(" -d -n header file no split\n"); printf(" -d -b bytes header file equal size split, up to 'bytes'/chunk\n"); printf(" -d -p parts header file equal size split, into number of 'parts' (1--9)\n"); } void print_usage() { printf("1. To extract foo9508a.ps from 4 received mails, use ONE of methods below\n"); printf("1.1 without saving file(s), from your mailer, pipe the ps mails to pull;\n"); #ifdef UNIX_PULL printf(" Ex 1. in Elm, press 't' to tag the ps mails one by one; then from\n"); printf(" one of tagged mails, press '|'; then issue `pull', `pull -c > foo.ps',\n"); printf(" or `pull -c | lpr -prtname' to extract, extract to file, to printer.\n"); printf(" Ex 2. in 'mail' prompt &, `| 5-8 pull' pipes mails 5-8 to pull.\n"); #endif printf("1.2 save 4 received mails, in any order, into one file, say foo.uue;\n"); printf(" Ex. in Netscape 3 mailer, click on 4 mails while holding `Ctrl' key.\n"); printf(" Click `File | Save As...' to default file name and type `untitled.html'.\n"); printf(" Issuing `pull foo.uue' or `pull untitled.html' extracts foo9508a.ps\n"); #if DOS_PULL printf(" More conveniently, use double-click or drag-and-drop in Windows.\n"); printf(" Please read the accompanying pullhelp.html or pullhelp.txt for details.\n"); #endif #if (UNIX_PULL || DOS_PULL || OS2_PULL) printf("1.3 save received mails in 4 separate files: foo1, foo2, foo3, and foo4.\n"); printf(" Assume foo1, foo2, foo3, foo4 uudecoded to foo9508a.sz1, ...foo9508a.sz4\n"); printf(" - `pull foo?': `?' matches any single char\n"); printf(" - `pull f*': `*' matches zero or more chars\n"); # ifdef UNIX_PULL printf(" - `pull foo[1-4]': matches exactly files foo1, foo2, foo3, and foo4.\n"); # endif #elif VMS_PULL printf("1.3 save received mails in 4 separate files: foo1.uue, ..., foo4.uue.\n"); printf(" Assume foo1.uue, ..., foo4.uue uudecoded to foo9508a.sz1, ...foo9508a.sz4\n"); printf(" - `pull foo%s.uue': `%s' matches any single char\n", WILD_CHAR, WILD_CHAR); printf(" - `pull f*.uue': `*' matches zero or more chars\n"); #endif #ifdef VMS_PULL printf(" - `pull foo1.uue foo2.uue foo3.uue foo4.uue' or any order.\n"); printf(" - `pull foo4.uue foo9508a.sz1 foo2.uue foo9508a.sz3', in mixed formats.\n"); #else printf(" - `pull foo1 foo2 foo3 foo4' or any order.\n"); printf(" - `pull foo4 foo9508a.sz1 foo2 foo9508a.sz3', in mixed formats.\n"); #endif printf(" - `pull foo9508a.sz1 foo9508a.sz2 foo9508a.sz3 foo9508a.sz4'.\n"); printf("2. To extract foo9508a.gb or foo9508a.bg5 from received mail\n"); printf(" Issue `pull foo.uue', assuming the mail saved in file `foo.uue'\n"); printf("3. To decompress, `pull file.gz' or `pull file.Z'\n"); printf("4. To split foo9508a.ps into multiple emailable parts of equal size in bytes:\n"); printf("4.1 `pull -d header foo9508a.ps' creates 4 mails, 'header' prepended to mail 1\n"); printf("4.2 `pull -d foo9508a.ps' creates 4 sendable mails\n"); printf("5. To uuencode file in 77-char line, `pull -d foo9508a.gb' or `pull -d ..bg5'\n"); } void print_version() { printf(" Version: %3.1f\n", version); printf("Platform: "); #ifdef DOS_PULL printf("DOS/WINDOWS\n"); #elif MAC_PULL printf("MAC\n"); #elif UNIX_PULL printf("UNIX\n"); #elif VMS_PULL printf("VMS\n"); #elif OS2FAT_PULL printf("OS/2 FAT\n"); #elif OS2HPFS_PULL printf("OS/2 HPFS\n"); #endif printf(" Date: %s\n", date); printf(" Author: Yao Li %s\n", my_eaddress); printf(" ftp: uwalpha.uwinnipeg.ca: pub/fcssc/fhy/HELP/pull.c -- Unix, VMS\n"); printf(" pub/fcssc/fhy/HELP/pull.exe -- DOS/MS-WIN\n"); printf(" pub/fcssc/fhy/HELP/pull.zip -- OS/2\n"); printf(" ccic.ifcss.org: pub/software/unix/utils/pull.c.gz -- Unix\n"); printf(" pub/software/dos/utils/pull.exe -- DOS/MS-WIN\n"); printf(" pub/software/vms/utils/pull.c-gz -- VMS\n"); printf(" pub/software/os2/utils/pull.zip -- OS/2\n"); printf(" http: ccic.ifcss.org/ftp-pub/software/unix/utils/pull.c.gz -- Unix\n"); printf(" ftp-pub/software/dos/utils/pull.exe -- DOS/MS-WIN\n"); printf(" ftp-pub/software/vms/utils/pull.c-gz -- VMS\n"); printf(" ftp-pub/software/os2/utils/pull.zip -- OS/2\n"); printf(" email: to obtain the latest version of pull, send an email to\n"); printf(" listserv@uwalpha.uwinnipeg.ca\n"); printf(" with a one-line command in mail body as below:\n"); printf(" `help fhy-ps' for Unix and VMS version, or\n"); printf(" `help fhy-psdos' for DOS version.\n"); printf(" Then the listserv `machine' will automatically email you a copy.\n"); } void wordcnt_file(char *inFile, int *lineCnt, long int *wordCnt, long int *charCnt) { int c; FILE *ifp; int inWord = FALSE; *lineCnt = 0; *wordCnt = *charCnt = 0L; if (!is_binary_file(inFile)) { ifp = f_open(inFile, "r", "wordcnt_file"); #if (DOS_PULL || OS2_PULL) SETMODE(ifp); #endif while ((c = getc(ifp)) != EOF) { ++(*charCnt); if (c == EOL) ++(*lineCnt); if (isspace(c)) inWord = FALSE; else if (!inWord) { inWord = TRUE; ++(*wordCnt); } } } else { ifp = f_open(inFile, "rb", "wordcnt_file"); while (!feof(ifp)) { c = getc(ifp); ++(*charCnt); if (c == EOL) ++(*lineCnt); if (isspace(c)) inWord = FALSE; else if (!inWord) { inWord = TRUE; ++(*wordCnt); } } if ((*charCnt) > 0) (*charCnt)--; } fclose(ifp); } int word_count(char *line) { int words = 0; int i, length; int inWord = FALSE; if (str_empty(line)) return 0; length = strlen(line); for (i=0; i