darcy@druid.uucp (D'Arcy J.M. Cain) (07/19/90)
As I mentioned in alt.sources.d, here is my pack/unpack utility. Before everyone points out that it isn't the perfect solution for the problems discussed in a.s.d let me hasten to beat you to it. The utilities in this distribution were originally written for different purposes and have been hacked on in order to make a start on some sort of solution. Some of the issues addressed (and hopefully solved) are: The lines can be split if desired and restored on the receiving end. Many troublesome characters are translated to less troublesome ones and restored on the receiving end. The files are transmitted in a form that can be read without any further processing. This is ***NOT*** a uuencoding type program. By modifying the code, systems that need some characters converted to trigraphs can do so by simply commenting out the case statement that converts the troublesome character(s). What it doesn't have yet is multi-part support other than splitting up the resulting file and restoring it by hand. I will try to do something about this. It also doesn't unpack itself like shar files do but the program is fairly simple and can easily be written for systems that can't use this one for some reason. In order to use the program that creates the script file you either have to pick up my getarg program which I recently posted or else hack the source to use normal getopt. If you can't get getarg from a local archive site you can get it from my machine's mail server. Send mail to unix-server@druid.UUCP with the following line in the body of the message: send getarg.c Note if the mail to the server gets too heavy I will have to shut it down for my neighbours sake so please use it as a last resort. This is just a lowly leaf node with a single 2400 baud modem. The program to unpack the files is self contained. #!/bin/sh # This is a shell archive (shar 3.10) # made 07/19/1990 05:37 UTC by darcy@druid # Source directory /usr/darcy/work/misc/genfiles # # existing files will NOT be overwritten # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 4689 -rw-r--r-- genfiles.c # 4100 -rw-r--r-- mkscript.c # 1601 -rw-r--r-- Makefile # touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$ if [ -s /tmp/s3_touch$$ ] then TOUCH=can else TOUCH=cannot fi rm -f /tmp/s3_touch$$ # ============= genfiles.c ============== if test -f genfiles.c; then echo "File genfiles.c exists"; else echo "x - extracting genfiles.c (Text)" sed 's/^X//' << 'SHAR_EOF' > genfiles.c && X/* Xgenfiles.c X XWritten by D'Arcy J.M. Cain XD'Arcy Cain Consulting X275 Manse Road, Unit # 24 XWest Hill, Ontario XM1E 4X8 X416 281 6094 X XUUCP: darcy@druid X XFile generation utility X XThis program may be freely distributed as long as credit is given to D'Arcy XJ.M. Cain, the source is included and this notice remains intact. There is Xspecifically no restrictions on use of the program including personal or Xcommercial. You may even charge others for this program as long as the above Xconditions are met. X XThis is not shareware and no registration fee is expected. If you like the Xprogram and want to support this method of distribution, write a program and Xdistribute it the same way and I will feel I have been paid. X XOf course gifts of money, drinks and extravagant jewels are always welcome. X XAs for documentation, you're looking at it. X XThis program reads a specially prepared text file from standard input and Xcreates a file or files based on the contents of the file. Each line of Xinput is examined to see if it is one of the following constructs. X X;text X This is a comment and is ignored X X!text X The line is accepted from the second character for processing without X further checking other than the % character described below. X X$text X The text is printed on the screen. X X=text X Text up to the first space or end of line is treated as a file name X which is opened as the current output. X Xtext X The line is put to the current output. X XWithin the text, the '%' character is handled differently. "%%" is treated Xas a single '%'. "%0" is replaced by the path name which was current when Xthe program was started. '%' followed by a single digit is replaced by Xthe corresponding argument from the command line. A '%' followed by an end Xof line joins the current line with the next one. In addition, the following Xcharacter translation is performed: X %= --> # X %/ --> \ X %' --> ^ X %( --> [ X %) --> ] X %! --> | X %< --> { X %> --> } X %- --> ~ XIf all of the above fails to match, the character is printed unchanged Xpreceded by ??. This allows you to comment out the case statements Xwhich convert to characters not handled by your system and automagically Xhave trigraphs. (Now you know where you saw the above table eh? :-) ) X X X*/ X X#include <stdio.h> X#include <string.h> X#include <ctype.h> X#include <malloc.h> X#include <stdlib.h> X X#ifdef __TURBOC__ X#include <dir.h> X#endif X Xchar *str_args[10], entry[512]; Xextern int errno; X Xstatic void mk_dir_env(char *path) X{ X char *p, c; X X if ((p = strchr(path, '\\')) == NULL) X p = strchr(path, '/'); X X if (p == NULL) X return; X X c = *p; X *p = 0; X mk_dir_env(path); X X#ifdef __MSDOS__ X mkdir(path); X#else X mkdir(path, 0); /* let umask determine permissions */ X#endif X X *p = c; X} X Xvoid main(int argc, char **argv) X{ X FILE *out_fp = NULL; X char c, *ptr; X int k; X X printf("GENFILES - File generation utility\n"); X printf("Copyright 1990 by D'Arcy J.M. Cain\n\n"); X X *str_args = getcwd(NULL, 64); X X for (k = 1; k < argc; k++) X str_args[k] = argv[k]; X X while (k < 10) X str_args[k++] = ""; X X while (gets(entry) != NULL) X { X switch (*entry) X { X case ';': /* comment */ X break; X X case '$': /* print */ X printf("%s\n", entry + 1); X break; X X case '=': /* open new file */ X if (out_fp != NULL) X fclose(out_fp); X X mk_dir_env(entry + 1); X X if ((out_fp = fopen(entry + 1, "wt")) == NULL) X { X fprintf(stderr, "\a\n%s: ", entry + 1); X perror("Can't open file"); X exit(errno); X } X break; X X default: /* ordinary string */ X if (out_fp == NULL) X { X fprintf(stderr, "\a\nNo file opened.\n"); X exit(1); X } X X ptr = entry; X X if (*entry == '!') /* escape */ X ptr++; X X while (*ptr) X { X if ((c = *ptr++) == '%') X { X c = *ptr++; X X if (isdigit(c)) X fprintf(out_fp, "%s", str_args[*ptr++ - '0']); X else X { X switch (c) X { X case 0: X if (gets(entry) == NULL) X *entry = 0; X X ptr = entry; X break; X X case '%': fputc('%',out_fp); break; X case '=': fputc('#',out_fp); break; X case '/': fputc('\\',out_fp); break; X case '\'': fputc('^',out_fp); break; X case '(': fputc('[',out_fp); break; X case ')': fputc(']',out_fp); break; X case '!': fputc('|',out_fp); break; X case '<': fputc('{',out_fp); break; X case '>': fputc('}',out_fp); break; X case '-': fputc('~',out_fp); break; X X default: X fprintf(out_fp, "??%c", c); X break; X } X } X } X else X fputc(c, out_fp); X } X X fputc('\n', out_fp); X break; X } X } X X free(*str_args); X fclose(out_fp); X exit(0); X} SHAR_EOF chmod 0644 genfiles.c || echo "restore of genfiles.c fails" if [ $TOUCH = can ] then touch -am 0719000390 genfiles.c fi fi # ============= mkscript.c ============== if test -f mkscript.c; then echo "File mkscript.c exists"; else echo "x - extracting mkscript.c (Text)" sed 's/^X//' << 'SHAR_EOF' > mkscript.c && X/* Xmkscript.c X XWritten by D'Arcy J.M. Cain XD'Arcy Cain Consulting X275 Manse Road, Unit # 24 XWest Hill, Ontario XM1E 4X8 X416 281 6094 X XUUCP: darcy@druid X Xcreates scripts for genfiles X XThis program may be freely distributed as long as credit is given to D'Arcy XJ.M. Cain, the source is included and this notice remains intact. There is Xspecifically no restrictions on use of the program including personal or Xcommercial. You may even charge others for this program as long as the above Xconditions are met. X XThis is not shareware and no registration fee is expected. If you like the Xprogram and want to support this method of distribution, write a program and Xdistribute it the same way and I will feel I have been paid. X XOf course gifts of money, drinks and extravagant jewels are always welcome. X XAs for documentation, you're looking at it. X Xthis program accepts a list of filenames and outputs a script suitable Xfor use by genfiles. X XSample usage: (Ignore underscores. They keep ANSI compilers from bitching.) X "mkscript src/_*.c src/_*.h src/makefile man/_* readme > dist.txt" X XNote the forward slash used above can be replaced by a backslash if you Xdo your DOS development on a DOS machine. (Who would do this?) (:-)) X XIf you didn't grab a copy of my getarg function, send mail to my machine Xto address unix-serever@druid.UUCP with the line "send getarg.c" in the Xbody of the message. You will need this to compile mkscript. X*/ X X#include <stdio.h> X#include <string.h> X#include <ctype.h> X#include <malloc.h> X#include <stdlib.h> X X#define BUFFER_SIZE 1024 X Xchar entry[BUFFER_SIZE]; Xextern int errno; Xextern char *optarg; X Xint main(int argc, char **argv) X{ X FILE *in_fp = NULL; X int k, c, line_len = BUFFER_SIZE; X char *p; X X printf("$ MKSCRIPT - GENFILES script generation utility\n"); X printf("$ Copyright 1990 by D'Arcy J.M. Cain\n; \n"); X X initarge(argc, argv); X X while ((c = getarg("l;")) != 0) X { X switch (c) X { X case 'l': X if (optarg == NULL) X line_len = BUFFER_SIZE; X else X line_len = atoi(optarg); X X if (line_len <= 8) /* the silly limit */ X { X fprintf(stderr, "%s: Limit must be more than 8\n", argv[0]); X exit(1); X } X break; X X case -1: X if ((in_fp = fopen(optarg, "rt")) == NULL) X { X fprintf(stderr, "%s: %s - ", argv[0], optarg); X perror("Can't open for input"); X exit(errno); X } X X printf("=%s\n", optarg); X printf("$Creating %s\n", optarg); X fprintf(stderr, "%s: Saving %s\n", argv[0], optarg); X X while (fgets(entry, sizeof(entry), in_fp) != NULL) X { X if ((p = strchr(entry, '\n')) != NULL) X *p = 0; X X k = 0; X putchar('!'); X X for (p = entry; *p; p++) X { X if (++k >= line_len) X { X printf("%\n"); X k = 0; X } X X switch (*p) X { X case '%': printf("%%%%"); break; X case '#': printf("%%="); break; X case '\\': printf("%%/"); break; X case '^': printf("%%'"); break; X case '[': printf("%%("); break; X case ']': printf("%%)"); break; X case '|': printf("%%!"); break; X case '{': printf("%%<"); break; X case '}': printf("%%>"); break; X case '~': printf("%%-"); break; X default: putchar(*p); break; X } X } X X putchar('\n'); X } X X fclose(in_fp); X break; X X default: X fprintf(stderr, "Unknown option - %c\n", c); X case 'h': X fprintf(stderr, "Usage: %s [-h] [-l[nn]] file_list\n", argv[0]); X X fprintf(stderr, X "The -h option prints this message. The -l option sets the maximum\n" X "length that the program will output. If no argument is given there\n" X "is no limit. If an argument is given there should be no space between\n" X "the 'l' and the number. The options can be placed anywhere in the\n" X "command line.\n"); X break; X X/* Note - this is not strictly true. If there is no argument to -l, it sets */ X/* the limit to the maximum buffer size. However, if an input line is longer */ X/* than that it will fail anyway so the above description is close enough for */ X/* Rock and Roll. */ X } X } X X return(0); X} SHAR_EOF chmod 0644 mkscript.c || echo "restore of mkscript.c fails" if [ $TOUCH = can ] then touch -am 0719005590 mkscript.c fi fi # ============= Makefile ============== if test -f Makefile; then echo "File Makefile exists"; else echo "x - extracting Makefile (Text)" sed 's/^X//' << 'SHAR_EOF' > Makefile && X# Makefile for genfiles X# Written by D'Arcy J.M. Cain X# X# Note: You will probably have to modify this file for your own use. Some X# of the things you will have to consider: X# The CFLAGS variable is for GNU C. Modify for your compiler. X# It is designed for a make that knows how to make both Unix and MSDOS X# executables. (I have modified GNU Make to do this.) X# My programs are stored in /usr/lbin. Modify BIN for your system. X# X# If you have a make that can't handle this file no matter what you do, you X# can simply compile the two programs. They are each single module programs. X XCFLAGS=-O -Wall -g XALL_BINARIES = genfiles mkscript XUNIX_BINARIES = $(ALL_BINARIES) XDOS_BINARIES = $(foreach i, $(ALL_BINARIES), $i.exe) XSCRIPTS = XDIST = genfiles.c mkscript.c $(SCRIPTS) Makefile XBIN = /usr/lbin XLBINS = $(foreach i, $(UNIX_BINARIES), $(BIN)/$i) XLBINS1 = $(foreach i, $(UNIX_BINARIES) $(SCRIPTS), $(BIN)/$i) X Xall: unix dos X Xunix: $(UNIX_BINARIES) X Xdos: $(DOS_BINARIES) X Xclean: X rm -f *.o *.obj core X Xclobber: clean X rm -f $(UNIX_BINARIES) $(DOS_BINARIES) genfiles.gen genfiles.shar X X# I use the following after I have done a clean and I want to work on a X# file without compiling everything. It simply makes sure that the BIN X# files are duplicated in the current directory. Xlink: X ln $(LBINS) . X Xinstall: unix X rm -f $(LBINS1) X chmod 711 $(UNIX_BINARIES) X ln $(UNIX_BINARIES) $(SCRIPTS) $(BIN) X Xdist: script shar X Xscript: genfiles.gen X Xgenfiles.gen: mkscript $(DIST) X mkscript $(DIST) > genfiles.gen X Xshar: genfiles.shar X Xgenfiles.shar: $(DIST) X shar -vxf $(DIST) > genfiles.shar SHAR_EOF chmod 0644 Makefile || echo "restore of Makefile fails" if [ $TOUCH = can ] then touch -am 0719013790 Makefile fi fi exit 0 -- D'Arcy J.M. Cain (darcy@druid) | Government: D'Arcy Cain Consulting | Organized crime with an attitude West Hill, Ontario, Canada | (416) 281-6094 |