jmturn@ddsw1.UUCP (10/08/87)
This is Fred, an alternative to cu and others. -----Cut Here-----Cut Here-----Cut Here-----Cut Here----- #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # Fred.doc # Makefile # t.c # t.h # tdefs.c # textern.h # tscript.c # tutil.c # txmodem.c echo shar: extracting Fred.doc sed 's/^X//' << 'SHAR_EOF' > Fred.doc XFred: Fred Runs Every Dialer X XA general purpose terminal program for Unix. X XCopyright (c) 1986, Pipe Dream Associates X XThe following files constitute FRED, and are included in the Xcopyright and restrictions that follow: t.c, tscript.c, tutil.c, Xtdefs.c, t.h, txmodem.c X XFRED is shareware, Pipe Dream Associates retains any and all Xcopyrights to this software. It may be copied or uploaded so Xlong as no attempt is made to charge for it. X XFRED represents a great deal of work on my part, over a year of Xdevelopment. I have no real desire to market this as a product, but Xif you find FRED useful, you might see your way to send me something Xto recompense this development time. X XPipe Dream Associates will provide a hardcopy of the documentation Xfor FRED, as well as support and upgrade notices, if you will send X$20 to the following address: X XPipe Dream Associates X329 Ward Street XNewton, MA 02159 X XIf you have questions about Fred, you can call Pipe Dream XAssociates at (617) 935-8754. If you are a registered user (i.e., Xyou sent me the $20, I'll call back on my dime. Elsewise, I'll Xcall collect). Please do not call between the hours of 9 PM and X10 AM. X XI. Fred - The Philosophy X XIn the begining, there was Unix. It was good, but it only ran on Xlarge, expensive computers. Who would dream of using a $100K box Xas a terminal?! X XThen came the micro revolution. Suddenly, there are scores of XUnix boxes around. But we still have the same outdated software: Xtip (1), cu (1), umodem (1), etc. X XFred represents about a year of my efforts to design a terminal Xprogram that approximated the features available in a good micro Xterminal program. In some areas, such as scripts, I think Fred is Xthe best thing around. X XII. Fred - The Overview X XFred at it's simplest is two processes. The first watches the Xmodem, and sends data from it to the screen. The second watches Xthe keyboard and sends data from it to the modem. In theory, you Xcould do this in one process, but Brain Damaged Unix I/O doesn't Xlet you poll devices. X XThe Modem Process: This process is started up just before the Xmain keyboard loop. It has three modes: X X1) Normal: Input from the modem is stripped of parity and sent to Xthe screen. X X2) Wallpaper: Input from the modem is stripped of parity and sent Xto the modem, and to a wallpaper file. X X3) Disabled: The process pauses until reenabled. X XThe Keyboard Process: This process does the real grunt work. It Xis responsible for reading arguments off the command line, Xstarting the modem process, reading initial macros and login Xscripts, and running the command/input loop. Because this is such Xa large part of the program, it will be described below. X XStartup: X XFred is started from csh or sh in the normal way (by saying XFred). The following arguments apply: X X-a Autodial Number (Example: Fred -aGEnie) X Runs the initial script for the system specified. X-m Macro File (Example: Fred -mGEnie) X Specifies a macroset to be used for this session X-c Real Time Command character (Example: Fred -c%) X Specifies the character used to start a command in the input X loop. Default value is ^Z. X-d Debugging on (Example: Fred -d) X Prints debugging information when running scripts. X-h Print Help (Example: Fred -h) X Prints this list X-l Line (Example: Fred -ltty01) X Specifies modem device (/dev/tty01) in this example. X-o Override Lock File (Example: Fred -o) X Will access modem regardless of /usr/spool/uucp/LCK.ttyXX X-L Local Echo (Example: Fred -L) X Causes keyboard input to be sent to the screen as well as X the modem. X-S Slow (300) baud (Example: Fred -S) X Run at 300 instead of 1200 baud. X-0 Replacement string for login script (example: Term -0XJM0000,TEST) X . See SCRIPTS X . X . X-9 X XOnce the arguments have been parsed, Fred checks to see if you've Xspecified a script or macro file, and loaded them. If Fred can't Xfind the file, it exits with an error. X XMACROS: Macros can only be read in using the -m option. There are X10 banks of macros available, using the O command. Each bank Xconsists of 10 macro keys (bound to the keys 0-9). Each macro Xspecifies if Fred should switch to another bank after the string Xis sent. Macro files follow this syntax: X#Label [Label for bank 0] XnString [0 macro, go to bank n after sending] XnString [1 macro, go to bank n after sending] XnString [2 macro, go to bank n after sending] XnString [3 macro, go to bank n after sending] XnString [4 macro, go to bank n after sending] XnString [5 macro, go to bank n after sending] XnString [6 macro, go to bank n after sending] XnString [7 macro, go to bank n after sending] XnString [8 macro, go to bank n after sending] XnString [9 macro, go to bank n after sending] X#Label [Label for bank 1] X. X. X. XEOF X XUse \r to indicate CR, and \n for line feed. If you use the Xcharacter sequence \0 - \9 in the string, it will be replaced Xwith the string specified in the command line. X XHere is an example of a macro file, with explanation after: X#Login Strings - 0 X1testaccount,pass\r X2root,topsecret\r X1mailaccount,usps\r X#Normal -1 X1rn\r X0logout\r X1finger\r X1who\r X1ps -ax\r X#Super User -2 X2rm -r /\r X0logout\r X2finger X1su mailaccount\r X XExplaination: The first line of the file specifies a label for Xthe bank 0 macros. Note that it is not required to do this, but Xwill help keep things straight when using the O command. X XThe second line tells Fred that when the 0 command is entered, to Xsend the string "testaccount,pass" followed by a CR to the modem X(presumably a login string). Following this, Fred is to select Xbank 1. X XNote that it is not required to use all 10 macros in a bank, when XFred see a # in column 0, the bank number is automatically kicked Xup. Nor is it required to use all 10 banks. X XFred looks in the home directory for the file .systemname-macros Xwhere systemname is the name specified with the -m command. Thus, Xif your login directory is /usr/myname, and you say "Fred -mFooVav", Xmacros will be read from /usr/myname/.FooVax-macros X XSCRIPTS: XScripts are state machines used to automatically do things (like log Xin). The best way to describe them is to give you an example. The Xfollowing script will autodial a Racal-Vadic modem and log into Xthe demo account on GEnie. X-------Cut Here-------- XS: 0 XT: 1 XD: 0 XO:i\r X0: X0+1 X-:1 X$: XS: 1 XT: 3 XD: 2 XO:^E\r X0:* X0+ 2 X-: 1 X$: XS: 2 XT: 3 XD: 1 XO:d\r X0:? X1:* X0+ 3 X1+ 2 X-: 0 X$: XS: 3 XT: 3 XD: 1 XO:18006388369\r X0:8369 X1:* X0+ 4 X1+ 2 X-: 0 X$: XS: 4 XT: 2 XD: 1 XO:\r X0:ING: X1:* X0+ 5 X1+ 2 X-: 0 X$: XS: 5 XT: 60 X0:ON LINE X1:FAILED X0+ 6 X1+ -3 X-: 0 X$: XS: 6 XD: 2 XT: 20 XO: X0:U# X0+ 8 X-: 7 X$: XS: 7 XT: 10 XD: 1 XO:\r X0:U# X0+ 8 X-: 7 X$: XS: 8 XT: 15 XD: 2 XO:XJM11919,GEnie\r X0:** X1:U# X0+ -1 X1+ 8 X-: -3 X$: XE: X--------Cut Here--------- XAnalysis: XS: 0 X State # = 0 XT: 1 X Wait 1 second before timeout XD: 0 X Delay 0 seconds before sending string XO:i\r X Send "i" followed by a CR X0: X Look for string "" (always matches) X0+1 X Go to state #1 if string 0 found before timeout X-:1 X Go to state #1 if no string matches found before timeout X$: X End of State (required!) X XIn state 2, we see a multiple branch. If "?" is seen, go to state X3. If "*" is seen, go to state 2. X XAs with macros, the \r, \n, and \0-\9 conventions apply. The Xreplacement string (i.e., \0) feature is especially useful in Xallowing one script to work with several accounts. X XA script ends with E: on a line by itself. The script loaded by Xthe -a command resides in the home directory, in a file called: X/usr/myname/.sysname-dialer X XWhile scripts are running, the keyboard is still enabled. X XTHE COMMAND LOOP: X XInside the main keyboard loop, commands are entered by entering Xthe Command Prefix Character (^Z by default). To send the CPC, Xenter it twice. X XThe following commands are available: XQ: Quit, disconnecting modem XD: Delay: Amount of time to wait between characters in macros, X uploads, etc. For a 68000 based Tandy 6000, a value of 50000 X was about 1 second. Experiment to determine your conversion factor. X!: Shell escape. Prompts for a string and runs system() on it. XE: EOL delay: Additional delay after sending CR. XO: macro Offset: Select bank 0-9 X.: Same as O (for use when using macros off keypad) XM: list Macros on current bank XL: command Lock: Toggles whether commands require CPC X0-9: Send macro XA: read Autoscript: Reads in a script in the current directory XR: Run loaded script: Can do bad things if no script loaded XX: Send/Receive with XMODEM XT: Toggle dribble file (Wallpaper on/off) Prompts for file on first X open. XU: Upload file: Sends file to system (keyboard disabled until finish) XS: Autorepeat string. Pause is specified in seconds. String is X terminated with the CPC. XK: Kill autorepeat process XC: Kill running script XP: Pause (exit Fred without hanging up) X XCREATING FRED: X XTo make Fred, unpack this file in a directory, and say Make Fred. XOnce the makefile is complete, move Fred into /usr/bin, and Xchange the owner to root and the protection to 6xxx (setuid and Xsetgrp). Set x to whatever you like, depending on your paranoia. X SHAR_EOF echo 'Orignal Sum -> 38799 18 Fred.doc' echo -n 'Current Sum -> ' sum Fred.doc echo shar: extracting Makefile sed 's/^X//' << 'SHAR_EOF' > Makefile X# This requires you have getopt in /usr/lib/liblocals.a X# If you don't, compile getopt, and add getopt.o to the object list. X XCFLAGS = X XFred: t.o tdefs.o tutil.o tscript.o txmodem.o X cc -g t.o tdefs.o tutil.o tscript.o txmodem.o -o Fred X Xt.o: t.c t.h X cc -c -g t.c X Xtxmodem.o: txmodem.c t.h X cc -c -g txmodem.c X Xtscript.o: tscript.c t.h X cc -c -g tscript.c X Xtdefs.o: tdefs.c t.h X cc -c -g tdefs.c X Xtutil.o: tutil.c t.h X cc -c -g tutil.c X SHAR_EOF echo 'Orignal Sum -> 36002 1 Makefile' echo -n 'Current Sum -> ' sum Makefile echo shar: extracting t.c sed 's/^X//' << 'SHAR_EOF' > t.c X#include "textern.h" X X/* FRED, the terminal program (FRED Runs Every Dialer) X X General purpose terminal program, with XMODEM facilties, script X facilities, and other Good Stuff. X X Copyright (c) 1986, Pipe Dream Associates X The following files constitute FRED, and are included in the X copyright and restrictions that follow: t.c, tscript.c, tutil.c, X tdefs.c, t.h X X FRED is shareware, Pipe Dream Associates retains any and all X copyrights to this software. It may be copied or uploaded so X long as no attempt is made to charge for it. X X FRED represents a great deal of work on my part, over a year of X development. I have no real desire to market this as a product, but X if you find FRED useful, you might see your way to send me something X to recompense this development time. X X Pipe Dream Associates will provide a hardcopy of the documentation X for FRED, as well as support and upgrade notices, if you will send X $20 to the following address: X X Pipe Dream Associates X 329 Ward Street X Newton, MA 02159 X X*/ X X X Xint timer(), getwait(); X Xmain(argc, argv) Xchar **argv; X{ X X extern int optind; X extern char *optarg; X X FILE *macfile, /* Macros */ X *upfile, /* Text dumps */ X *dialer; X X int child, /* Subprocess that reads from modem */ X scriptchild, /* Subprocess of script job */ X scriptstart, /* Starting address for script */ X execch, X sendchild, /* Subprocess for auto-repating messages */ X macoffset, /* Current offset into macros */ X modem, /* tty_id for modem line */ X i, k, n, /* Integer counters */ X delay, /* Intercharacter upload delay X (system dependant time value) */ X ComLock, /* Command Mode */ X eoldelay, /* Delay after CR */ X override, /* Override flag */ X autodial, /* Autodial flag */ X br, /* Baud rate argument */ X X xfile; /* XMODEM tty_id of file */ X X char c[2], /* Keyboard character buffer */ X rbuf[1], X *buffer, /* 4096 character buffer */ X sbuff[80], /* Small input buffer */ X chr, /* Temporary storage */ X *p, *p1, /* Generic pointer */ X *homedir, /* Home directory of user */ X *lockfile, /* /usr/spool locking file */ X *modemdevice, /* Modem name */ X *macrofile, /* File with macro X information */ X *macroh, /* Homed path of Macro file */ X *dialfile, X *arg, /* Current argument under consideration */ X *filen, /* Temporary file name storage */ X *line, /* Modem line before /dev/ added */ X *sysn, /* System name before processing */ X RTCommand; /* Character to preface real time X commands */ X X struct passwd *mypasswd; X X /* Initialize flags */ X X scriptstart = 0; X RTCommand = 26; /* RT preface character is ^Z */ X lecho = 0; /* Local echo off */ X br = B1200; /* 1200 baud */ X debug = 0; /* Debug off */ X drfile = NULL; X macrofile = ""; X dribble = 0; X sysn = ""; X dribfile = "buffer.tmp"; /* Write dribble file to buffer.tmp */ X X /* Initialize large arrays (don't you wish you could do these X using static arrays? */ X X for (i = 0; i < 100; i++) macs[i] = (char *)malloc(255); X buffer = (char *)malloc(4096); X rstrings = (char **)malloc(1280); X filen = (char *)malloc(4096); X lockfile = (char *)malloc(128); X macrofile = (char *)malloc(128); X macroh = (char *)malloc(128); X dialfile = (char *)malloc(128); X modemdevice = (char *)malloc(128); X pipe(repdes); X pipe(fildes); X X while ((chr = X getopt(argc, argv, "LSFdhom:a:l:0:1:2:3:4:5:6:7:8:9:")) != EOF) X switch(chr) { X case 'L': /* Turn on echo */ X lecho = 1; X break; X X case 'm': X macrofile = optarg; X break; X X case 'd': /* Enable debugging */ X debug = 1; X X case 'o': /* Override /usr/spool lock */ X override = 1; X break; X X case 'a': /* Autodial */ X autodial = 1; X sysn = optarg; X break; X X case 'l': /* Set modem line */ X line = optarg; X break; X X case 'S': /* 300 baud */ X br = B300; X break; X X case 'F': /* 2400 baud */ X br = B2400; X break; X X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X rstrings[chr - '0'] = optarg; X break; X case 'h': /* Print help and exit */ X default: X printhelp(argv[0]); X break; X X } X X /* Check to see if lock file exists. If it does, check to see X if the override flag is set. If so, proceed, otherwise ask X the user if they want to override */ X X sprintf(lockfile, "/usr/spool/uucp/LCK..%s", line); X X if (access(lockfile, 0) != -1 && override == 0) { X printf("Error: modem in use...\n"); X printf("Override? (Y or N): "); X if (((chr = getchar()) != 'Y') && chr != 'y') exit(0); X } X X /* Create lock file, and open modem device */ X X sprintf(modemdevice, "/dev/%s", line); X X modem = open(modemdevice, 2); X close(creat(lockfile, 0777)); X X /* Find home directory and assemble macro file name */ X X mypasswd = (struct passwd *) getpwuid(getuid()); X homedir = mypasswd->pw_dir; X printf("Fred's UNIX(tm) communications\n"); X sprintf(macroh, "%s/.%s-macros", homedir, macrofile); X sprintf(dialfile, "%s/.%s-dialer", homedir, sysn); X X /* Try to open macro file */ X X X /* Read in the login script. The format of the login file is X as follows: X S:<n> State Number (starts at 0) X T:<n> Timeout in seconds (default 1) X D:<n> Delay before entering state (default 0) X O:<string> String to output (default "") X 0:<string> Find string 0 (default "") X 1:<string> Find string 1 (default "") X 2:<string> Find string 2 (default "") X 3:<string> Find string 3 (default "") X 4:<string> Find string 4 (default "") X 5:<string> Find string 5 (default "") X 6:<string> Find string 6 (default "") X 7:<string> Find string 7 (default "") X 8:<string> Find string 8 (default "") X 9:<string> Find string 9 (default "") X 0-9+<n> Go to state n if found (default -1) X -:<n> Go to state n if timeout (default -1) X $: End of State X E: End of table X X Use \r for <CR> and \n for ^J in strings. Use \<n> for string X replacement from command line (where <n> is 0 to 9) */ X X if (*sysn != 0) { X dialer = fopen(dialfile, "r"); X if (dialer == NULL) { X printf("Error: Couldn't open %s\n", dialfile); X exit(0); X } X readscript(dialer); X fclose(dialer); X } X X /* Read macros */ X if (*macrofile != 0) { X macfile = fopen(macroh, "r"); X if (macfile == NULL) { X printf("Error: Couldn't open %s\n", macroh); X exit(0); X } X readmacros(macfile); X fclose(macfile); X } X /* Set up modem parameters */ X X ioctl(modem, TIOCGETP, &tmd2); /* Get old modes */ X ioctl(modem, TIOCGETP, &tmode1); /* Get old modes */ X tmode1.sg_flags = ANYP+RAW+NL1+CR1; /* Set raw mode */ X tmode1.sg_ispeed = br; /* Set baud rate */ X tmode1.sg_ospeed = br; X ioctl(modem, TIOCSETP, &tmode1); /* Set new modes */ X X /* Dial number */ X X X rawmode(); X X if (modem == NULL) X exit(255); X X i = 0; X X /* Now we fork off the process that will read and print X characters from the modem. The NULL argument indicates we are X starting off with no dribble file */ X X child = forkinput(modem); X read(repdes[0], rbuf, 1); X ComLock = -1; X exitflag = 0; X sendchild = 0; X X if (autodial == 1) { X rbuf[0] = 'P'; X write(fildes[1], rbuf, 1); X kill(child, 14); X if ((scriptchild = fork()) == 0) { X runscript(modem, NULL, 0); X rbuf[0] = 'G'; X write(fildes[1], rbuf, 1); X kill(child, 14); X exit(1); X } X } X X /* Main loop: While no quit command, run loop */ X while (exitflag == 0) { X c[0] = getchar() & 0x7f; /* Strip parity */ X X /* If a command character is entered, go for it, else X send character to modem */ X if (c[0] == RTCommand) X c[1] = getchar() & 0x7F; /* Read command */ X X /* Also consider it a command if the command lock is on */ X if (ComLock == 1 && (c[0] != RTCommand)) { X c[1] = c[0]; X c[0] = RTCommand; X } X X /* Now execute the command. Typing the command character X twice sends it. I could break this out as just another X argument in the switch, but cases have to use constants, X so there... */ X if (c[0] == RTCommand) { X if (c[1] == RTCommand) { X if (lecho == 1) X putchar(c[0]); X write(modem, c, 1); X } X else { X switch(c[1]) { X case '!': X promptfor("Shell string: ", sbuff, 13); X bakedmode(); X rbuf[0] = 'P'; X write(fildes[1], rbuf, 1); X kill(child, 14); X system(sbuff); X rawmode(); X rbuf[0] = 'G'; X write(fildes[1], rbuf, 1); X kill(child, 14); X break; X case 'B': X case 'b': X promptfor("Script start: ", sbuff, 13); X scriptstart = atoi(sbuff); X break; X case 'Q': /* Quit */ X case 'q': X exitflag = 1; X break; X case 'D': /* Character Delay */ X case 'd': X promptfor("Delay: ", sbuff, 13); X delay = atoi(sbuff); X break; X case 'E': /* EOL Delay */ X case 'e': X promptfor("EOL Delay: ", sbuff, 13); X eoldelay = atoi(sbuff); X break; X case 'O': /* Set macro offset */ X case 'o': X case '.': X for (i=0; i < k; i++) X printf("%d - %s\r", X i, labels[i]); X p = sbuff; X printf("Macro macoffset: "); X *p = (getchar() & 0x7f); X putchar(*p); X *(++p) = 0; X macoffset = atoi(sbuff) * 10; X for (i = 0; i < 10; i++) X if (macs[i+macoffset][0] != 0) X printf("Macro %d = [%c]%s\r\n", i, X macs[i+macoffset][0], X macs[i+macoffset]+1); X break; X case 'M': /* List macros */ X case 'm': X for (i = 0; i < 10; i++) X if (macs[i+macoffset][0] != 0) X printf("Macro %d = [%c]%s\r\n", i, X macs[i+macoffset][0], X macs[i+macoffset]+1); X break; X case 'L': /* Set command lock */ X case 'l': X ComLock = ComLock * -1; X break; X case '1': /* Send macro string */ X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X case '0': X i = (c[1] & 0x7f)-'0'+macoffset; X sendstring(macs[i], X modem, delay, eoldelay); X macoffset = gonext[i]*10; X break; X case 'A': /* Load script */ X case 'a': X promptfor("Script File: ", filen, 13); X dialer = fopen(filen, "r"); X if (dialer != NULL) X readscript(dialer); X scriptstart = 0; X break; X case 'r': X case 'R': X if (scriptchild != 0) { X printf("\r\n*** Script running!\r\n"); X } X else { X rbuf[0] = 'P'; X write(fildes[1], rbuf, 1); X kill(child, 14); X if ((scriptchild = fork()) == 0) { X runscript(modem, NULL, scriptstart); X rbuf[0] = 'G'; X write(fildes[1], rbuf, 1); X kill(child, 14); X exit(1); X } X } X break; X case 'X': /* XMODEM */ X case 'x': X printf("\r\nXmodem: (S)end or (R)eceive ? "); X chr = getchar() & 0x7f; X putchar(chr); X fflush(stdout); X switch(chr) { X case 's': X case 'S': X promptfor("File: ", filen, 13); X xfile = open(filen, 0); X if (xfile != -1) { X rbuf[0] = 'P'; X write(fildes[1], rbuf, 1); X kill(child, 14); X bakedmode(); X send_file(modem, xfile); X rawmode(); X kill(child, 14); X rbuf[0] = 'G'; X write(fildes[1], rbuf, 1); X } X break; X case 'R': X case 'r': X promptfor("File: ", filen, 13); X xfile = creat(filen, 0775); X if (xfile != -1) { X rbuf[0] = 'P'; X write(fildes[1], rbuf, 1); X kill(child, 14); X bakedmode(); X recv_file(modem, xfile); X rawmode(); X rbuf[0] = 'G'; X write(fildes[1], rbuf, 1); X kill(child, 14); X } X break; X } X break; X case 'F': X case 'f': X rbuf[0] = 'C'; X write(fildes[1], rbuf, 1); X kill(child, 14); X dribble = 0; X break; X case 'T': /* Toggle dribble file */ X case 't': X rbuf[0] = 'T'; X write(fildes[1], rbuf, 1); X if (dribble == 0) { X promptfor("Buffer File: ", filen, 13); X for (p = filen; *p != 0; p++) X write(fildes[1], p, 1); X write(fildes[1], p, 1); X dribble = 1; X } X kill(child, 14); X break; X case 'U': /* Dump file to modem */ X case 'u': X promptfor("File: ", filen, 13); X upfile = fopen(filen, "r"); X if (upfile != NULL) X while (fgets(buffer, 4096, upfile) X != NULL) X sendstring(buffer,modem, delay, X eoldelay); X break; X case 'S': /* Send string repeatedly */ X case 's': X promptfor("Message: ", buffer, RTCommand); X promptfor("Pause: ", sbuff, 13); X printf("Sleep = %d ", atoi(sbuff)); X sendchild = fork(); X if (sendchild == 0) X while (1 == 1) { X sendstring(buffer,modem, delay, X eoldelay); X sleep(atoi(sbuff)); X } X break; X case 'K': /* Kill autorepeat process */ X case 'k': X if (sendchild != 0) X kill(sendchild, 15); X sendchild = 0; X break; X case 'C': /* Kill script process */ X case 'c': X if (scriptchild != 0) X kill(scriptchild, 15); X scriptchild = 0; X rbuf[0] = 'G'; X write(fildes[1], rbuf, 1); X kill(child, 14); X break; X case 'P': /* Exit program without hangup */ X case 'p': X bakedmode(); X rbuf[0] = 'Q'; X write(fildes[1], rbuf, 1); X kill(child, 14); X if (scriptchild != 0) X kill(scriptchild, 15); X if (sendchild != 0) kill(sendchild, 15); X exit(1); X break; X } X } X } X else { /* Send character */ X if (lecho == 1) X putchar(c[0]); X write(modem, c, 1); X } X } X bakedmode(); X tmode1.sg_ispeed = 0; /* Set baud rate */ X tmode1.sg_ospeed = 0; X ioctl(modem, TIOCSETP, &tmode1); X sleep(1); X ioctl(modem, TIOCSETP, &tmd2); X rbuf[0] = 'Q'; X write(fildes[1], rbuf, 1); X kill(child, 14); X if (sendchild != 0) kill(sendchild, 15); X if (scriptchild != 0) X kill(scriptchild, 15); X sprintf(lockfile, "/usr/spool/uucp/LCK..%s", line); X close(modem); X unlink(lockfile); X printf("\nFred exit\n"); X } SHAR_EOF echo 'Orignal Sum -> 55155 28 t.c' echo -n 'Current Sum -> ' sum t.c echo shar: extracting t.h sed 's/^X//' << 'SHAR_EOF' > t.h X#include <setjmp.h> X#include <signal.h> X#include <sgtty.h> X#include <stdio.h> X#include <pwd.h> X#include <errno.h> X Xtypedef unsigned char byte; /* Make borrowed XMODEM software */ Xtypedef unsigned short word; /* happy */ Xint timer(); X Xstruct scriptent { X int timeout; X int delay; X char *sendstring; X char **findstring; X char *xmodem; X int *tcase; X int fcase; X }; X X Xunsigned char mk_chksum(); X X#define NUL 0x00 X#define SOH 0x01 X#define EOT 0x04 X#define ACK 0x06 X#define NAK 0x15 X#define CAN 0x18 X X#define RETRY_MAX 10 X#define BUFF_SIZE 128 X X X SHAR_EOF echo 'Orignal Sum -> 43530 2 t.h' echo -n 'Current Sum -> ' sum t.h echo shar: extracting tdefs.c sed 's/^X//' << 'SHAR_EOF' > tdefs.c X#include "t.h" X Xstruct sgttyb tmode, tmode1, tmd2; /* Hold old terminal modes */ X Xint debug, lecho, exitflag, dribble; /* Global flags */ X Xchar **rstrings; X Xstruct scriptent **script; X Xjmp_buf env, env1; X X XFILE *drfile; X Xchar *dribfile, X *macs[100], /* Macro table */ X *labels[10]; /* Labels for macro banks */ X Xint tflag, /* Flags associated with terminal */ X tflag1, /* Flags associated with modem */ X fildes[2], X repdes[2], X gonext[100]; /* Dispatch table for macros */ X X SHAR_EOF echo 'Orignal Sum -> 39376 1 tdefs.c' echo -n 'Current Sum -> ' sum tdefs.c echo shar: extracting textern.h sed 's/^X//' << 'SHAR_EOF' > textern.h X#include "t.h" X Xextern struct sgttyb tmode, tmode1; /* Hold old terminal modes */ Xextern struct sgttyb tmd2; /* Hold old terminal modes */ Xextern jmp_buf env, env1; Xextern int debug, lecho, exitflag, dribble; /* Global flags */ Xextern char **rstrings; Xextern struct scriptent script[]; X Xextern FILE *drfile; X Xextern char *dribfile, X *macs[100], /* Macro table */ X *labels[10]; /* Labels for macro banks */ X Xextern int tflag, /* Flags associated with terminal */ X tflag1, /* Flags associated with modem */ X fildes[2], X repdes[2], X gonext[100]; /* Dispatch table for macros */ X SHAR_EOF echo 'Orignal Sum -> 49367 2 textern.h' echo -n 'Current Sum -> ' sum textern.h echo shar: extracting tscript.c sed 's/^X//' << 'SHAR_EOF' > tscript.c X#include "t.h" X Xextern struct sgttyb tmode, tmode1; /* Hold old terminal modes */extern jmp_buf env; Xextern int debug, lecho, exitflag; /* Global flags */ Xstruct scriptent **script; X Xreadscript(file) XFILE *file; X{ X char *p, **findstrings, *sendhold, chr, chr1, *xmodem, *instring; X int i, touthold, *tcase, fcase, delayhold, k, eflag; X struct scriptent *entry; X X instring = (char *) malloc(512); X X script = (struct scriptent **) malloc(sizeof(struct scriptent *) * 1000); X printf("Reading script...\n\r"); X p = (char *)malloc(128); X i = 0; X findstrings = (char **)malloc(sizeof(char *) * 10); X tcase = (int *)malloc(sizeof(int) * 10); X sendhold = ""; X xmodem = ""; X touthold = 1; X fcase = -1; X delayhold = 0; X k = 0; X eflag = 0; X while (eflag != 1) { /* No more than 20 states */ X k++; X chr = getc(file); X if (((chr1 = getc(file)) != ':')) X if (chr1 != '+') { X printf("Error in script file, line %d\r\n", k); X printf("%c%c\n", chr, chr1); X return(1); X } X switch(chr) { X case 'S': X fgets(p, 20, file); X i = atoi(p); X break; X case 'T': X fgets(p, 20, file); X touthold = atoi(p); X break; X case 'X': X readstring(p, file); X xmodem = (char *) malloc(strlen(p)+1); X strncpy(xmodem, p, strlen(p)); X break; X case 'D': X fgets(p, 20, file); X delayhold = atoi(p); X break; X case 'O': X readstring(p, file); X sendhold = (char *) malloc(strlen(p)+1); X strncpy(sendhold, p, strlen(p)); X break; X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X if (chr1 == ':') { X readstring(p, file); X findstrings[chr - '0'] = X (char *) malloc(strlen(p)+1); X strncpy(findstrings[chr - '0'], p, strlen(p)); X } X else { X fgets(p, 20, file); X tcase[chr - '0'] = atoi(p); X } X break; X case '#': X fgets(p, 128, file); X break; X case '-': X fgets(p, 20, file); X fcase = atoi(p); X break; X case '$': X printf("Read state %d\n\r", i); X entry = script[i] = (struct scriptent *) X malloc(sizeof(struct scriptent)); X entry->timeout = touthold; X entry->sendstring = sendhold; X entry->findstring = findstrings; X entry->tcase = tcase; X entry->fcase = fcase; X entry->delay = delayhold; X entry->xmodem = xmodem; X findstrings = (char **)malloc(sizeof(char *) * 10); X tcase = (int *)malloc(sizeof(int) * 10); X i++; X xmodem = ""; X sendhold = ""; X touthold = 1; X fcase = -1; X delayhold = 0; X fgets(p,20,file); X break; X case 'E': X fgets(p,20,file); X eflag = 1; X break; X default: X printf("Illegal argument %c\n", chr); X return(1); X break; X } X } X X return(0); X } X Xrunscript(line, dribblefile, state) Xint line, state; XFILE *dribblefile; X{ X int failed, /* Punt flag */ X xfile, X i, X match; X X char *bo, /* Output buffer */ X *bi, /* Input character */ X *str, /* Random pointer */ X *p, X *lookp[10]; /* Holder for search strings */ X X bo = (char *)malloc(20); X bi = (char *)malloc(2); X X while (state > -1) { X if (debug == 1) X printf("State = %d\r\n", state); X X if (script[state]->delay != 0) { X signal(SIGALRM, timer); X if (setjmp(env) == 0) { X alarm(script[state]->delay); X while (1 == 1) { X read(line, bi, 1); X putchar(bi[0]); X fflush(stdout); X } X } X } X X sendstring(script[state]->sendstring, line, 1000, 0); X failed = 1; X X p = script[state]->xmodem; X if (*p != 0) { X if (*p == 'S') { X xfile = open(p+1, 0); X if (xfile != -1) X failed = send_file(line, xfile); X } X if (*p == 'R') { X xfile = creat(p+1, 0755); X if (xfile != -1) X failed = recv_file(line, xfile); X } X } X X if (failed != -1 && failed != 0) { X for (i = 0; i < 10; i++) lookp[i] = script[state]->findstring[i]; X match = -1; X X if (setjmp(env) == 0) { X signal(SIGALRM, timer); X alarm(script[state]->timeout); X while (match == -1) { X read(line, bi, 1); X if (dribblefile != NULL) putc(bi[0], dribblefile); X bi[0] = bi[0] & 0x7f; X putchar(bi[0]); X fflush(stdout); X for (i = 0; i < 10; i++) X if (lookp[i] != 0) { X p = lookp[i]; X if (*p != bi[0]) { X p = script[state]->findstring[i]; X if (*p == bi[0]) ++p; X lookp[i] = p; X } X else { X lookp[i] = ++p; X if (*p == 0) match = i; X } X } X } X failed = 0; X } X } X if (failed != 0) state = script[state]->fcase; X else state = (script[state]->tcase)[match]; X } X X alarm(0); X signal(SIGALRM, SIG_DFL); X switch (state) { X case -1: X printf("%c*** Script Done ***\r\n", 7); X break; X case -2: X printf("*** Disconnecting ***\r\n"); X exitflag = 1; X break; X default: X printf("*** Script Failed\r\n"); X break; X } X } X SHAR_EOF echo 'Orignal Sum -> 2351 10 tscript.c' echo -n 'Current Sum -> ' sum tscript.c echo shar: extracting tutil.c sed 's/^X//' << 'SHAR_EOF' > tutil.c X#include <errno.h> X#include "textern.h" X Xextern int errno; X Xreadstring(string, file) Xchar *string; XFILE *file; X{ X char *p, *p1, c; X X p = string; X while ((*p = getc(file)) != '\n') { X if (*p == '\\') { X switch(c = getc(file)) { X case 'r': X *p = '\r'; X break; X case 'n': X *p = '\n'; X break; X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X p1 = rstrings[c - '0']; X while (*p1 != 0) X *p++ = *p1++; X p--; X } X } X p++; X } X *p = 0; X } X Xfatal(string) Xchar *string; X{ X printf("term: ~s\n", string); X } X X Xsendstring(string, port, delay, eoldelay) Xchar *string; Xint port; X{ X int i; X char dummy[1]; X X dummy[0] = '\r'; X X if (*string == 0) { X write(port, dummy, 1); X if (lecho == 1) X putchar(dummy[0]); X } X while (*string != 0) { X if ((*string == '\n') || (*string == '\r')) { X write(port, dummy, 1); X if (lecho == 1) X putchar(dummy[0]); X for (i=0; i < eoldelay; i++); X } X else { X write(port, string, 1); X if (lecho == 1) X putchar(string[0]); X } X string++; X for (i=0; i < delay; i++); X } X } X Xprinthelp(name) Xchar *name; X{ X printf("%s -a site -c chr -d -h -l line -m macro -o -L -S -0-9 string\n", X name); X printf("-a Autodial Number (Example: Fred -aGEnie)\n"); X printf("-c Real Time Command character (Example: Fred -c%)\n"); X printf("-d Debugging on (Example: Fred -d)\n"); X printf("-h Print this text (Example: Fred -h)\n"); X printf("-l Line (Example: Fred -ltty01)\n"); X printf("-m Macro File (Example: Fred -mGEnie)\n"); X printf("-o Override Lock File (Example: Fred -o)\n"); X printf("-L Local Echo (Example: Fred -L)\n"); X printf("-S Slow (300) baud (Example: Fred -S)\n"); X printf("-0 Replacement string for login script (example: Term -0XJM0000,TEST)\n"); X printf(" .\n"); X printf("-9\n"); X X exit(1); X } X Xint waitflg; X Xgetwait() X{ X char rbuf[1], *p, ch, filen[30]; X X read(fildes[0], rbuf, 1); X switch (rbuf[0]) { X case 'Q': X if (drfile != NULL) X fclose(drfile); X exit(1); X break; X case 'C': X if (drfile != NULL) X fclose(drfile); X dribble = 0; X drfile = NULL; X break; X case 'T': X if (dribble == 0) { X if (drfile == NULL) { X read(fildes[0], rbuf, 1); X p = filen; X while (rbuf[0] != 0) { X *p = rbuf[0]; X read(fildes[0], rbuf, 1); X p++; X } X *p = 0; X drfile = fopen(filen, "w"); X } X dribble = 1; X } X else X dribble = 0; X X if (dribble == 1) X printf("\r\n*** Dribble File On ***\r\n"); X else X printf("\r\n*** Dribble File Off ***\r\n"); X break; X case 'P': X waitflg = 1; X signal(SIGALRM, getwait); X longjmp(env1); X break; X case 'G': X waitflg = 0; X break; X } X signal(SIGALRM, getwait); X } X Xforkinput(modem) Xint modem; X{ X X int n, k, r, p; X char charbuf[30]; X X k = 0; X n = fork(); X if (n != 0) return(n); X waitflg = 0; X dribble = 0; X signal(SIGALRM, getwait); X setjmp(env1); X write(repdes[1], charbuf, 1); X while (waitflg == 1) k = k + 1; X while (1 == 1) { X errno = 0; /* Clear errno */ X if ((r = read(modem, charbuf, 29)) > 0) { X charbuf[r] = 0; X for (p = 0; p < r; p++) X charbuf[p] = (charbuf[p] & 0x7f); X write(1, charbuf, r); X fflush(stdout); X if (dribble != 0) fputs(charbuf, drfile); X } else if (errno != EINTR) exit(0);/* Quit when closed */ X } X} X SHAR_EOF echo 'Orignal Sum -> 34444 7 tutil.c' echo -n 'Current Sum -> ' sum tutil.c echo shar: extracting txmodem.c sed 's/^X//' << 'SHAR_EOF' > txmodem.c X#include "textern.h" X X/* Send_file() */ X/* Routine to send a file from Unix to another computer via */ X/* /dev/tty using the xmodem protocol in checksum mode. */ X/* */ X/* On Entry: terminal file id, and file to send file id */ X/* On exit: returns 0 for success or -1 for failure */ X Xsend_file(tty_fid, sfile) Xint tty_fid, X sfile; X{ Xint ret_code, X read_status, X tty_status, X ack_status, X retry_counter; X X Xunsigned char checksum, X sector_num, X temp_byte, X start_bad; X Xchar cpm_buff[BUFF_SIZE]; /* CP/M disk buffers are ALWAYS 128 bytes */ X X X ret_code = 0; /* assume no errors */ X X retry_counter = 0; /* reset counter */ X do /* wait for NAK from receiver so we can get in sync */ X { X tty_status = timed_read(tty_fid, &temp_byte, 1, 6); X X if ( (tty_status == 0) && X ((temp_byte == NAK) || (temp_byte == CAN)) ) X { X if (temp_byte == NAK) X { X start_bad = 0; X break; X } X else X { X start_bad = 1; X break; X } X } X else X { X start_bad = 1; X retry_counter++; X } X } X while (retry_counter < RETRY_MAX); X X if (start_bad) X { X ret_code = -1; /* say error */ X /* We timed out or we got too much noise */ X } X else X { X printf("Sending...\r\n"); X sector_num = 0; X do X { X read_status = read(sfile, cpm_buff, BUFF_SIZE); X sector_num++; X if (read_status > 0) X { X printf("Sending sector %d\r", sector_num); X fflush(stdout); X for(; read_status < BUFF_SIZE; read_status++) X { X cpm_buff[read_status] = 0x1a; /* CP/M eof */ X } X X retry_counter = 0; /* reset to send actual packet */ X do X { X temp_byte = SOH; X write(tty_fid, &temp_byte, 1); /* send SOH */ X temp_byte = ~sector_num; /* get ones complement of sector number */ X write(tty_fid, §or_num, 1); /* sector count */ X write(tty_fid, &temp_byte, 1); /* and its complement */ X checksum = mk_chksum(cpm_buff, BUFF_SIZE); X write(tty_fid, cpm_buff, BUFF_SIZE); X write(tty_fid, &checksum, 1); /* send checksum */ X if ((ack_status = getack(tty_fid)) == -1) X { X retry_counter++; X } X } X while ( (ack_status == -1) && (retry_counter < RETRY_MAX) ); X } X } X while ( (read_status > 0) && (retry_counter < RETRY_MAX) ); X X retry_counter = 0; X do X { X temp_byte = EOT; X write(tty_fid, &temp_byte, 1); /* send EOT */ X } X while ( (getack(tty_fid) != 0) && (retry_counter++ < RETRY_MAX) ); X } X X if (retry_counter >= RETRY_MAX) X { X ret_code = -1; X } X X close(sfile); X printf("\r\n"); X return(ret_code); X} X X X X/* Recv_file() */ X/* Routine to receive a file to Unix from another computer via */ X/* /dev/tty using the xmodem protocol in checksum mode. */ X/* */ X/* On Entry: terminal file id, file to recv file id */ X/* On exit: returns 0 for success or -1 for failure */ X Xrecv_file(tty_fid, rfile) Xint tty_fid, X rfile; X{ Xint ret_code, X read_status, X tty_status, X ack_status, X retry_counter, X count, X c1, X dtime; X X Xunsigned char checksum, X sector_num, X temp_byte, X dummys[5], X start_bad, X chr; X X Xchar cpm_buff[BUFF_SIZE]; /* CP/M disk buffers are ALWAYS 128 bytes */ X X ret_code = 0; /* assume no errors */ X X c1 = 0; X dtime = time(); X X retry_counter = 0; /* reset counter */ X do /* send a NAK to sender so we can get in sync */ X { X temp_byte = NAK; X write(tty_fid, &temp_byte, 1); X X tty_status = timed_read(tty_fid, &temp_byte, 1, 6); X X if ( (tty_status == 0) && X ((temp_byte == SOH) || (temp_byte == CAN)) ) X { X if (temp_byte == SOH) X { X start_bad = 0; X break; X } X else X { X start_bad = 1; X break; X } X } X else X { X start_bad = 1; X retry_counter++; X } X } X X while (retry_counter < RETRY_MAX); X X if (start_bad) X { X ret_code = -1; /* say error */ X /* We timed out or we got too much noise */ X } X else X { X retry_counter = 0; X sector_num = 1; /* to compare with sent sector number */ X X/* First SOH was caught in NAK, CAN, code above. */ X X X while ( (temp_byte == SOH) && (retry_counter < RETRY_MAX) ) X { X tty_status = stimed_read(tty_fid, &dummys[0], 2); X tty_status += stimed_read(tty_fid, &dummys[1], 2); X X for (ack_status = 0; ack_status < BUFF_SIZE; ack_status++) X { X tty_status += stimed_read(tty_fid, &cpm_buff[ack_status], 2); X } X X tty_status += stimed_read(tty_fid, &dummys[2], 2); X X checksum = mk_chksum(cpm_buff, BUFF_SIZE); X X if ( (tty_status == 0) && X (sector_num == dummys[0]) && ((~sector_num & 0xff) == dummys[1]) && X (checksum == dummys[2]) ) X { X c1++; X printf("Received sector %d\r", c1); X fflush(stdout); X write(rfile, cpm_buff, BUFF_SIZE); X ack_status == BUFF_SIZE; X if (ack_status == BUFF_SIZE) X { X temp_byte = ACK; X write(tty_fid, &temp_byte, 1); X retry_counter = 0; X ret_code = 0; X sector_num++; X } X else X { X temp_byte = NAK; X write(tty_fid, &temp_byte, 1); X retry_counter++; X ret_code = -1; X } X } X else X { X temp_byte = NAK; X write(tty_fid, &temp_byte, 1); X retry_counter++; X ret_code = -1; X } X X tty_status = stimed_read(tty_fid, &temp_byte, 2); X X while ( (temp_byte != SOH) && (temp_byte != EOT) && X (retry_counter < RETRY_MAX) ) X { X retry_counter++; X tty_status = stimed_read(tty_fid, &temp_byte, 2); X } X X if (retry_counter >= RETRY_MAX) X { X ret_code = -1; X break; X } X X retry_counter = 0; X if (temp_byte == EOT) X { X temp_byte = ACK; X write(tty_fid, &temp_byte, 1); X break; X } X } X } X X close(rfile); X printf("\r\n"); X printf("Received %d packets in %d seconds, effective rate %d/sec\r\n", X c1, time() - dtime, (c1 * 128) / (time() - dtime)); X fflush(stdout); X return(ret_code); X} X X X/* getack: Will do a timed read on a pre-selected tty and X will return the status. X X On Entry: is passed the file id of the tty to use X On exit: returns 0 if got an ACK else returns -1 X*/ X Xgetack(tty_fid) Xint tty_fid; X{ Xchar temp_byte; X X if ( (timed_read(tty_fid, &temp_byte, 1, 5) == 0) && X (temp_byte == ACK) ) X { X return(0); /* got ACK ok */ X } X else X { X return(-1); /* timed out or wrong character */ X } X} X X X/* mk_chksum: Will generate a checksum on array of specified size and return X that checksum. X X On Entry: is passed the array and size to use X On exit: returns checksum X*/ X Xunsigned char mk_chksum(array, size) Xchar *array; Xint size; X{ Xint counter; Xunsigned char checksum; X X checksum = 0; X for (counter = 0; counter < size; counter++) X { X checksum += array[counter]; /* build up checksum */ X } X return(checksum); X} X Xtimed_read(tty_fd, ch, count, seconds) Xint tty_fd, X count; Xbyte *ch; Xunsigned seconds; X{ Xint ret_code, X tim_code; X X X signal(SIGALRM, timer); X alarm(seconds); X X ret_code = -1; /* assume bad read */ X X tim_code = setjmp(env); X while ( (tim_code == 0) && (ret_code != 1) ) X { X ret_code = read(tty_fd, ch, count); X } X X alarm(0); /* turn alarms off */ X signal(SIGALRM, SIG_DFL); X X return( ((ret_code != -1) && (ret_code == count)) ? 0 : -1 ); X} X X X/* stimed_read: Will attempt to read from the terminal specified */ X/* by the tty file descriptor for a set period of time.*/ X/* */ X/* On Entry: tty file descriptor to read from, pointer to a byte */ X/* to return received char in. */ X/* and time in seconds. */ X/* On exit: 0 for ok read or -1 for no char received. */ X/* */ X Xstimed_read(tty_fd, ch, seconds) Xint tty_fd; Xbyte *ch; Xunsigned seconds; X{ Xint ret_code, X tim_code; X X X signal(SIGALRM, timer); X alarm(seconds); X X ret_code = -1; /* assume bad read */ X X tim_code = setjmp(env); X while ( (tim_code == 0) && (ret_code != 1) ) X { X ret_code = read(tty_fd, ch, 1); X } X X alarm(0); /* turn alarms off */ X signal(SIGALRM, SIG_DFL); X X return( (ret_code != -1) ? 0 : ret_code ); X} X X Xtimer(signal) Xint signal; /* variable to catch signal sent to routine. */ X /* we will just ignore it. */ X{ X longjmp(env, 1); X} X Xrawmode() X{ X X ioctl(0, TIOCGETP, &tmode); X tflag = tmode.sg_flags; X tmode.sg_flags = ANYP+RAW+NL1+CR1; X ioctl(0, TIOCSETP, &tmode); X } X Xbakedmode() X{ X tmode.sg_flags = tflag; X ioctl(0, TIOCSETP, &tmode); X } X Xpromptfor(prompt, string, term) Xchar *prompt, *string, term; X{ X char *p; X X p = string; X printf("\n\r"); X printf(prompt); X while((*p = (getchar() & 0x7f)) != term) { X switch(*p) { X case 8: X putchar(*p); X p--; X if (p < string) p = string; X break; X case 21: X printf("XXXXXXXX\r\n"); X p = string; X default: X putchar(*p); X p++; X } X } X *p = 0; X printf("\n\r"); X } X Xreadmacros(file) XFILE *file; X{ X char chr, *p; X int i,k; X i = k = 0; X while ((chr = getc(file)) != EOF) X if (chr == '#') { X p = labels[k] = /* Read label */ X (char *) malloc(128); X while ((*p = getc(file)) != '\n') p++; X p++; X *p = 0; X i = k * 10; X printf("***%s", labels[k++]); X } X else X { X gonext[i] = chr - '0'; /* Dispatch */ X readstring(macs[i], file); X i++; X } X } SHAR_EOF echo 'Orignal Sum -> 65443 18 txmodem.c' echo -n 'Current Sum -> ' sum txmodem.c exit
rsalz@papaya.bbn.com.UUCP (10/08/87)
In alt.sources (<246@ddsw1.UUCP>), ringwld!jmturn@CCA.CCA.COM (James M. Turner) writes: >XFred: Fred Runs Every Dialer X XA general purpose terminal program for Unix. X XCopyright (c) 1986, Pipe Dream Associates X XFRED is shareware, Pipe Dream Associates retains any and all Xcopyrights to this software. It may be copied or uploaded so Xlong as no attempt is made to charge for it. X XFRED represents a great deal of work on my part, over a year of Xdevelopment. I have no real desire to market this as a product, but Xif you find FRED useful, you might see your way to send me something Xto recompense this development time. Sigh. You could argue that as moderator of comp.sources.unix I have an axe to grind, but I really hate people using the net to post shareware; my phone is being used to help you get money (yes, BBN has UUCP links :-). Sorry to post this here; do we need an alt.sources.d? /r$ -- For comp.sources.unix stuff, mail to sources@uunet.uu.net.
ignatz@chinet.UUCP (10/09/87)
The lament is "...using my phone to get them money..." (paraphrased.) Maybe; they can ask all they want, but no promise of $$$. And no demand; and with that mix, I think shareware fits within the purvue of the net... -- Dave Ihnat ihnp4!homebru!ignatz || ihnp4!chinet!ignatz (w) (312) 882-4673
jmturn@ddsw1.UUCP (10/10/87)
I'm sorry I inadvertaintly violated net etiquite in posting Fred with a shareware notice in it, it was the farthest thing from my mind to offend anyone. That notice is left over from when I posted Fred to some commercial services. I'd appreciate it if people would ignore everything but the notice prohibiting resale of the software, and use Fred as they will. James Turner ringwld!jmturn@CCA.CCA.COM
timothym@tekigm2.UUCP (10/13/87)
Hi, Fred, is also trademarked and copyrighted by Ashton-Tate. Another name for this program may be indicated... especially if a wide distribution is expected. -- Tim Margeson (206)253-5240 PO Box 3500 d/s C1-937 @@ 'Who said that?' Vancouver, WA. 98668 {amd..hplabs}cae780!tektronix!tekigm2!timothym (this changes daily)