[comp.sources.amiga] v91i094: YES 1.0 - YES: device, always answers yes, Part01/01

amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (05/08/91)

Submitted-by: elg@elgamy.RAIDERNET.COM (Eric Lee Green)
Posting-number: Volume 91, Issue 094
Archive-name: devices/yes-1.0/part01

When used as stdin for a program, returns "yes\n" or whatever string
you give it as the "standard" reply. Similar to the "yes" program under
Unix. Mostly just flash and dazzle... there's no real reason the
same thing couldn't be done with pipes.

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  Makefile README c.a mem.c misc.c
# Wrapped by tadguy@ab20 on Tue May  7 19:39:38 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(480 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#########################################################################
X#
X#               YesHandler Makefile
X#               For Lattice 5.10a
X#
X#########################################################################
X
XCFLAGS = -d2 -cu -v -rr -ms -O
X
XYesHandler     : misc.o mem.o c.o
X    blink c.o misc.o mem.o to YesHandler sc sd nd lib lib:lcr.lib
X
Xmisc.o  : misc.c
X        lc $(CFLAGS) misc
X
Xmem.o : mem.c
X        lc $(CFLAGS) mem
X
Xc.o : c.a
X        asm -u -iINCLUDE: c.a
END_OF_FILE
if test 480 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1586 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XThis little gem is a YES: handler. So what's that, you ask?
X
XLet's say you're unlharcing something and you want it to always create
Xdirectories/tromp/etc. Then -- lharc <YES:y x archive will always say "y"
Xwhen it asks "Create this Directory?".
X
XThis handler is a triumph of modern compiler technology, trite but true.
XWho could have even dreamed that a program written in "C" could be less
Xthan 1400 bytes, after all?
X
XTotal syntax:
X
XJust plain YES: returns "yes\n" for each call to Read().
XYES:<text>  returns the text whenever the program reads from YES:.
X  The following are special-cased:
X    // -- one slash character
X    \\ -- one backslash character
X    \n -- a linefeed
X    \c -- a carriage return
X    \<octal> -- an octal character.
X
XYES:<text>/c turns off the automatic "\n" ordinarily added to the text.
X
XTo use: Plunk YesHandler into your L: directory. Then put this into your
XMountlist:
X
XYES: Handler = L:YesHandler
X    StackSize = 2000
X    Priority = 0
X    GlobVec = -1
X#
X
X
XNext type "mount YES:" and presto, you're done.
X
XKnown bugs: None. However, note that YES:/c  will NOT generate
Xthe text "yes" without the carriage return... there has to be text between
Xthe colon and the "/c".
X
XPermission granted for all uses, but please send bug reports to me:
X
XEric Lee Green
XP.O. Box 92191
XLafayette, LA 70509
X(318) 984-1820
X
XBIX: egreen
XInternet: elg@elgamy.RAIDERNET.COM (Eric's Amiga @ Home)
XUUCP: uunet!mjbtn!raider!elgamy!elg
X
XNOTE: I am currently looking for a job as of 4/91. If you know of a company
Xthat's hiring Unix or Amiga software people, please drop me a line.
END_OF_FILE
if test 1586 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'c.a' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'c.a'\"
else
echo shar: Extracting \"'c.a'\" \(1425 characters\)
sed "s/^X//" >'c.a' <<'END_OF_FILE'
X* this be my startup, though I took much of it from elsewhere.
X* Eric Lee Green, 2/91
X
X        INCLUDE "exec/types.i"
X        INCLUDE "exec/memory.i"
X        INCLUDE "exec/execbase.i"
X
XFUNCDEF         MACRO   * function
X_LVO\1          EQU     FUNC_CNT
XFUNC_CNT        SET     FUNC_CNT-6
X                ENDM
X
XFUNC_CNT        SET     LIB_NONSTD
X        INCLUDE "exec/exec_lib.i"
X
X        xref    LinkerDB        * linker defined base value
X        xref    _BSSBAS         * linker defined base of BSS
X        xref    _BSSLEN         * linker defined length of BSS
X
X        section text,code
X
X        xref    @_main
X
Xstart:
X        movem.l d1-d6/a0-a6,-(a7)
X
X        move.l  a0,a2
X        move.l  d0,d2
X        lea     LinkerDB,a4
X
X        lea     _BSSBAS,a3
X        moveq   #0,d1
X        move.l  #_BSSLEN,d0
X        bra.s   clr_lp
Xclr_bss move.l  d1,(a3)+
Xclr_lp  dbf     d0,clr_bss
X        move.l  a7,_StackPtr(A4)
X        move.l  04,a6
X        move.l  a6,SysBase(A4)
Xmain
X        jsr     @_main(PC)              * call C entrypoint
X
X; NOTE: We're never intended to return from here! So the following
X; should *NEVER* be executed!
X
X        move.l _StackPtr(A4),a7
X        movem.l (a7)+,d1-d6/a0-a6       * restore registers
X        moveq  #0,d0
X        rts
X
X        section __MERGED,BSS
X
X        xdef    NULL,SysBase
X
XNULL            ds.b    4       *
XSysBase         ds.b    4
X_StackPtr       ds.b    4
X                END
END_OF_FILE
if test 1425 -ne `wc -c <'c.a'`; then
    echo shar: \"'c.a'\" unpacked with wrong size!
fi
# end of 'c.a'
fi
if test -f 'mem.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mem.c'\"
else
echo shar: Extracting \"'mem.c'\" \(10404 characters\)
sed "s/^X//" >'mem.c' <<'END_OF_FILE'
X/* YES: handler by Eric Green. Based on Eric Green's MEM: handler.
X * Copyright 1991 Eric Green
X *
X * MEM: handler by Eric Green. Based on Steve Drew's AUX: handler.
X * Copyright 1990 Eric Green
X *
X *Copyright 1987 Steve Drew
X *  52-Castledale Cres. N.E.
X *  Calgary, Ab. Canada.
X *
X *  |You may freely distribute this source as long as |
X *  |the Copyright notice is left intact.             |
X ***************************************************************************/
X
X/* note from Eric -- I don't know why I keep Steve's notice here,
X   since this thing is totally gutted. Maybe just nostalgia. */
X
X/* following includes dos.h, exec/types, etc. */
X#include <libraries/dosextens.h>
X#include <libraries/filehandler.h>
X
X/* #include <ctype.h> */
X
X#include <exec/memory.h>
X#include <proto/exec.h>
X#include <string.h>
X
Xtypedef unsigned char u_char;
X
X#undef  BADDR
X#define BADDR(x)   ((APTR)((long)x << 2))
X
X
X
X#define DOS_FALSE               0L
X#define DOS_TRUE               -1L
X
X#define MAXFNAME 256 /* space for null terminate */
X
Xvoid
Xreturnpkt(struct DosPacket *packet,struct Process *myproc, ULONG res1, ULONG res2);
X
Xstruct DosPacket *
Xtaskwait(struct MsgPort *myport);
X
X/* My Globals */
X
Xstruct MyFile {
X     char *current;  /* pointer into text. */
X     char *text;     /* current text. */
X     int  FreeWhenDone;
X};
X
Xstruct Process    *myproc;          /* my process                     */
Xstruct DosPacket  *mypkt;           /* a pointer to the dos packet    */
X
Xu_char fnamebuff[MAXFNAME];     /* max file name length is 64. */
X
X/* char       *version =           "Ver 0.1 Copyright 1991 Eric Green"; */
X
X/* Format of filenames:
X   filename:   "YES:"[string]["/"options]
X
X   string: (char)+
X
X   char: ^"/" ||
X         "//"
X
X \\ == the character "\" in a string.
X \<ditdit> puts a binary character.
X \n       puts a carriage return (one is standard at EOL, see below)
X \t       puts a tab.
X \c       puts a chr$(13) character.
X
XOther \x sequences are not supported.
X
Xoptions:
X    n -- no CR appended to string.
X
XState machine: I'm not going to draw the stupid thing into DPAINT, it's
Xscribbled. Instead:
X
XState1:
X     <get>
X     \0 --> FINI
X     ":" --> State2
X     otherwise: State1
XState2:
X    <get>
X     "\" --> St_FNback
X     "/" --> St_FNslash
X     \0 --> FINI
X     otherwise: State3
XState3:
X   <Add-char>
X   <get>
X     "\" --> St_FNback
X     "/" --> St_FNslash
X     \0 --> FINI
X     otherwise: State3
XSt_FNback:
X   <init-dit>
X   <get>
X   "\" --> State3
X   "dit" --> St_BackDit
X   "n" --> <char = /n> State3
X   "c" --> <char = 13> State3
X   "t" --> <char = TAB> State3
X   \0 --> FINI
X   otherwise: State3   ; we just ate it, sigh.
XSt_BackDit:
X   <add-dit>
X   <get>
X   "dit" --> St_BackDit
X   \0 --> <addchar dit> FINI
X   otherwise: <addchar dit> State35
XSt_FNslash:
X  <get>
X  "/" --> State3
X  \0 --> FINI
X  otherwise: St_Opts
XSt_Opts:
X   <process-option>
X   <get>
X   \0 --> FINI
X   otherwise: St_Opts
X
X*/
X
X#define State1  1
X#define State2  2
X#define State3  3
X#define St_FNback 4
X#define St_BackDit 5
X#define St_FNslash 6
X#define St_Opts 7
X#define FINI 8
X#define State35 9
X
Xstruct MyFile *process_filename(char *name);
X
Xstruct MyFile *process_filename(char *name)
X{
X
X    struct MyFile *f;
X
X    static char fnbuf[256];
X
X    char *currfn = fnbuf;
X
X    char *s;
X
X    u_char got_name = 0; /* nope, we didn't get a filename. */
X
X    u_char i;
X    u_char ch;
X
X    u_char cr_flag = 1;  /* we put a cr here... */
X
X     int dit;  /* our single char... */
X     u_char state = 1;
X
X
X    i = *name++;               /* i = length of the BSTR. */
X    if ( i >= MAXFNAME-1 ) {  /* oh oh, file name too long! */
X         return NULL;                 /* non-zero = error. */
X    }
X
X    f = (struct MyFile *) AllocMem(sizeof(struct MyFile),MEMF_CLEAR);
X    if (f==NULL)
X        return NULL;
X
X/* let's first copy it into fnamebuff: */
X    s=fnamebuff;
X    while (i--) {
X        *s++ = *name++;
X    }
X    *s = 0;
X    name = fnamebuff;
X
X/* Okay, now set up initial stuff for what we're doing: */
X    f->current = "yes\n";
X    f->text = f->current;  /* set up defaults. */
X
X/* state machine:  there's probably more efficient ways to do this,
X   but this works.
X*/
X    for (;;) {
X        switch (state) {
X         case State1:
X            ch = *name++;
X            switch (ch) {
X             case 0: state = FINI;
X                    break;
X             case ':': state = State2;
X                    break;
X             default: state = State1;
X                    break;
X            }
X            break;
X        case State3:
X            *currfn++ = ch;  /* <add> */
X            got_name = 1;   /*  **WARNING** deliberately falls through! */
X        case State2:
X            ch = *name++;  /* <get> */
X        case State35:          /* **WARNING deliberately falls through! */
X            switch (ch) {
X                case 0: state = FINI; break;
X                case '/': state = St_FNslash; break;
X                case '\\': state = St_FNback; break;
X                default: state = State3;
X            }
X            break;
X        case St_FNback:
X            dit = 0;      /* stuff to add there... */
X            ch = *name++;  /* <get> */
X            switch (ch) {
X                case 0: state = FINI; break;
X                case '\\': state = State3; break;
X                case 'n': ch = 10; state = State3; break;
X                case 'c': ch = 13; state = State3; break;
X                case 't': ch = '\t'; state = State3; break;
X                case '0': case '1': case '2': case '3':
X                   case '4': case '5': case '6': case '7':
X                        state =St_BackDit; break;
X                default: state = State3;  /* we just ate that slash! */
X            }
X            break;
X        case St_BackDit:
X            dit = dit << 3;  /* octal. */
X            dit += (ch-'0');
X            ch = *name++;  /* <get> */
X            if (!(ch >= '0' && ch <= '7')) {
X                if (dit) { *currfn++ = dit; got_name = 1; }  /* <add> */
X                if (!ch) state = FINI;
X                    else state = State35;
X            } /* default: same state. */
X            break;
X        case St_FNslash:
X            ch = *name++;  /* <get> */
X            if (ch=='/') state = State3;
X             else if (!ch) state = FINI;
X             else state = St_Opts;
X            break;
X       case St_Opts:
X            if (ch == 'c') cr_flag = 0;
X            ch = *name++;  /* <get> */
X            if (!ch) state = FINI; /* otherwise, state = St_Opts. */
X            break;
X      case FINI:
X            f->FreeWhenDone = 0;
X            if (!got_name) return (f);
X            if (cr_flag) *currfn++ = '\n';
X            *currfn = 0;
X            f->current = (char *) AllocMem(strlen(fnbuf)+2, 0L); /* any ole
X                                                                   memory. */
X            if (!f->current) return NULL;  /* sorry, couldn't alloc it. */
X            f->text = f->current;
X            f->FreeWhenDone = 1;  /* means free f->text upon close. */
X            strcpy(f->text,fnbuf);  /* copy the string over... */
X            return f; /* and done! */
X        }  /* end of case statement. */
X    } /* end of do loop. */
X}  /* end of function. */
X
X/* send a "bad" packet. Save a few bytes, I hope. If not, macro-ize this.
X*/
Xvoid bad(void);
X
Xvoid bad(void)
X{
X   returnpkt(mypkt,myproc,DOS_FALSE,ERROR_OBJECT_NOT_FOUND);
X}
X
X
X    struct DeviceNode *mynode;          /* our device node (parmpkt Arg3) */
X
Xvoid _main(void);
X
Xvoid _main(void)
X{
X    struct MsgPort    *myport;
X
X    ULONG count;   /* # of bytes actually xferred */
X
X    struct MyFile *f;   /* ptr to whatever. */
X    struct FileHandle *fh;
X/*     struct FileLock *fl;
X    struct FileInfoBlock *fib; */
X
X    char *s;
X    int i;
X
X        /* Initializing the handler */
X
X    myproc      = (struct Process *)FindTask(0L);
X    myport      = &myproc->pr_MsgPort;
X
X
X    mypkt       = taskwait(myport);      /* Wait for my startup message */
X
X        /* I don't need the name or extra info passed in Arg1/2 */
X
X    mynode              = (struct DeviceNode *)BADDR(mypkt->dp_Arg3);
X    mynode->dn_Task     = &myproc->pr_MsgPort;
X    returnpkt(mypkt, myproc, DOS_TRUE, mypkt->dp_Res2);
X
X
X
X        /* done initial stuff, now for some work */
X
X    for (;;) {                       /* endless loop. */
X        mypkt = taskwait(myport);
X
X        switch(mypkt->dp_Type) {        /* find what action to perform */
X
X        case ACTION_FINDINPUT:
X/* localize all the f's here to help out optimizer's register allocation.  */
X            f = process_filename((u_char *) BADDR(mypkt->dp_Arg3));
X
X            if (f==NULL) {     /* bad filename. */
X                bad();  /* return a bad packet. */
X                break;
X            }
X
X            fh = (struct FileHandle *) (BADDR(mypkt->dp_Arg1));
X
X            fh->fh_Arg1 = (LONG) f;  /* register allocator help... */
X
X            fh->fh_Port = (struct MsgPort *) -1;
X
X                     /* okay, now set up our littel file tracker: */
X            returnpkt(mypkt,myproc,DOS_TRUE,0L);
X            break;
X
X        case ACTION_READ:
X            f = (struct MyFile *) mypkt->dp_Arg1;
X
X            /* okay, first see if it's within bounds: we have two problems
X               here. We can be past the end of the "file", or we can be
X               overflowed, wrapped around. I can't detect all wrap-arounds,
X               just those that don't pass up f->start. */
X
X
X            count = mypkt->dp_Arg3;
X
X            i = 0;
X            s = (char *) mypkt->dp_Arg2;  /* pointer to destination buffer. */
X            while (*(f->current) && i++ < count) {
X                *s++ = *(f->current++);
X            }
X            if (!*(f->current)) f->current = f->text;
X
X            returnpkt(mypkt,myproc,i,0);
X            break;
X
X        case ACTION_END:  /* close a file: */
X            if (mypkt->dp_Arg1 == 0) {  /* check for null filehandle */
X                returnpkt(mypkt,myproc,DOS_TRUE,0);
X                break;
X            }
X            f = (struct Myfile *) mypkt->dp_Arg1;
X            if (f->FreeWhenDone) {
X                FreeMem((APTR)f->text,strlen(f->text)+2);
X            }
X            FreeMem((APTR)f,sizeof(struct MyFile));
X            returnpkt(mypkt,myproc,DOS_TRUE,0);
X            break;
X        default:
X            returnpkt(mypkt, myproc, DOS_FALSE, ERROR_ACTION_NOT_KNOWN);
X            break;
X        }
X    } /* end while */
X/*    mynode->dn_Task = FALSE; */
X}
END_OF_FILE
if test 10404 -ne `wc -c <'mem.c'`; then
    echo shar: \"'mem.c'\" unpacked with wrong size!
fi
# end of 'mem.c'
fi
if test -f 'misc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'misc.c'\"
else
echo shar: Extracting \"'misc.c'\" \(1818 characters\)
sed "s/^X//" >'misc.c' <<'END_OF_FILE'
X/*
X *  misc.c  - support routines - Phillip Lindsay (C) Commodore 1986
X *  You may freely distribute this source and use it for Amiga Development -
X *  as long as the Copyright notice is left intact.
X *
X * 30-SEP-86
X *
X */
X#include <stdio.h>
X#include <exec/types.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <exec/ports.h>
X#include <exec/libraries.h>
X#include <exec/devices.h>
X#include <exec/io.h>
X#include <exec/memory.h>
X#include <devices/console.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <libraries/filehandler.h>
X
X#include <proto/exec.h>
X
Xextern void returnpkt();
X
X/* returnpkt() - packet support routine
X * here is the guy who sends the packet back to the sender...
X *
X * (I modeled this just like the BCPL routine [so its a little redundant] )
X */
X
X
X
X
Xvoid
Xreturnpkt(struct DosPacket *packet,struct Process *myproc, ULONG res1, ULONG res2);
X
X
X
Xvoid
Xreturnpkt(struct DosPacket *packet,struct Process *myproc, ULONG res1, ULONG res2)
X{
X    struct Message *mess;
X    struct MsgPort *replyport;
X
X    packet->dp_Res1          = res1;
X    packet->dp_Res2          = res2;
X    replyport                = packet->dp_Port;
X    mess                     = packet->dp_Link;
X    packet->dp_Port          = &myproc->pr_MsgPort;
X    mess->mn_Node.ln_Name    = (char *) packet;
X    mess->mn_Node.ln_Succ    = NULL;
X    mess->mn_Node.ln_Pred    = NULL;
X    PutMsg(replyport, mess);
X}
X
X
Xstruct DosPacket *
Xtaskwait(struct MsgPort *);
X/*
X * taskwait() ... Waits for a message to arrive at your port and
X *   extracts the packet address which is returned to you.
X */
X
Xstruct DosPacket *
Xtaskwait(struct MsgPort *myport)
X{
X    struct Message *mymess;
X
X    WaitPort(myport);
X    mymess = GetMsg(myport);
X    return((struct DosPacket *)mymess->mn_Node.ln_Name);
X}
X
X/* end of misc.c    */
X
X
END_OF_FILE
if test 1818 -ne `wc -c <'misc.c'`; then
    echo shar: \"'misc.c'\" unpacked with wrong size!
fi
# end of 'misc.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.misc.