amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (03/04/91)
Submitted-by: <umueller@iiic.ethz.ch> Posting-number: Volume 91, Issue 028 Archive-name: shells/cshell-5.00/part02 #!/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 2 (of 6)." # Contents: changes.doc rawcon.c sub.c # Wrapped by tadguy@ab20 on Sun Mar 3 16:55:58 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'changes.doc' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'changes.doc'\" else echo shar: Extracting \"'changes.doc'\" \(13639 characters\) sed "s/^X//" >'changes.doc' <<'END_OF_FILE' XOverview X XThe new CShell 4.9 is no longer adequate to low end systems, it's too large Xand consumes too much memory. I advise everybody who doesn't own a hard Xdrive to stick with the old versions. For those who can afford to run it, Xhowever, this version is a practical tool in command mode and a powerful Xlanguage for writing scripts while remaining compatible with its old Xscripts. As the version number 4.9 suggests, I'm note quite done yet, and Xthere might be bugs left. I count on you to report them to me. The source Xis not included this time, but still available. X XSome of the new features: X X- works fine on an Amiga 3000 and under Kickstart 2.0 X- is residentable X- file name completion with TAB X- freely programmable command line editing keys X- many new editing functions X- jump scrolling (three lines scrolled in one step, useful in interlace) X- automatic cd (type 'system' instead of 'cd system') X- quick cd (cd knows about all directories on your HD and jumps directly) X- ~ stands for previous current directory X- special support for the closing kickstart 2.0 gadget X- you can 'rback' programs by adding a single '&' to the command line X- it is possible to install menus to the console window X- some internal functions csh have become faster X- runs on VT terminals again, even command line editing works now X- many builtin functions now like 'echo @strleft( hello 3 )' X- you can finally use foreign character sets X- any letter can be coded using backslash: echo \101 ouputs 'A' X- more startup options: -b (priority -1) -t (terminal) -k (no ^C) etc. X- automatic rx-ing: you can 'rx' .rexx files by typing their name X- ^D now aborts batchfiles like under AmigaDOS X- will 'source' files with script bit set X- limit of 256 arguments removed X- limit of 20 commands per line removed X- limit of 256 bytes per source line extended to 512 X XNew commands (and options): X X- 'addbuffers' accepts any number drive/buffer pairs X- 'action' sends a action request to a file class X- 'alias'es can have more than one argument X- 'alias'es can prevent wild card expansion X- 'ascii' shows an ascii table X- 'assign' accepts any number logical/physical pairs X- 'assign' can create late/nonbinding assigns under kick 2.0 X- 'cd' has an option to generate the list of all your directories X- 'class' defines a class of files and the actions allowed on them X- 'close' without arguments closes all open files X- 'cls' clears the screen, but now also works on a vt terminal X- 'copy' now copies the protection bits but clears archive bit X- 'copy -f' now 'freshens' like zoo. NOTE: *incompatible* with 4.02 X- 'date' has a stopwatch built in X- 'dir' can sort forwards and backwards by name, size or time. X- 'dir' can hide .info files and files with the h-bit set X- 'dir' can show differences between directories X- 'dir' can show filenotes and file types X- 'echo' has an option to print to stderr X- 'exec' works better now X- 'filenote' can display filenotes, too X- 'getenv' reads a ARP or ENV: environment variable X- 'head', a filter, displays the first n lines of stdin X- 'input' can get characters in single character mode (!) X- 'info' also gives information on a single device X- 'linecnt', a filter, counts number of lines X- 'man' gets documentation to a shell command X- 'mem' can show only chip, only fast or bytes used sinc last mem -s X- 'menu' adds a menu X- 'mv' now clears the archive bit X- 'path' can also be used to set the path, not only to list it X- 'protect' can clear and set bits without disturbing the others X- 'ps' by default only shows the basenames of the started commands X- 'qsort' quicksorts from stdin to stdout X- 'readfile' completely reads a file and stores it in a variable X- 'rxsend' can receive results (now it's useful!) X- 'search' is much faster and has new output X- 'setenv' is used to set ENV: variables X- 'tail', a filter, prints the last lines of a file X- 'tee' copies stdin to stdout and stderr X- 'truncate' cuts the width of an ascii file X- 'touch' now clears the archive bit X- 'uniq' removes consecutive identical lines X- 'usage' shows the usage of a command X- 'waitforport' waits for an (arexx) port X- 'whereis' looks for a file on your hard drive X XNew system variables: X X- '_every' contains a command to be executed before the prompt appears X- '_hilite' holds the highlighting attributes X- '_history' now can be set to 0, which disables history X- '_kick2x' indicates whether V36 dos.library could be opened X- '_lcd' is the last current directoy X- '_minrows' is the minimum number of rows a window must have to quickscroll X- '_nobreak', if set, disables ^C X- '_noreq' disables system requesters X- '_path' no more need slashes at the end of directories X- '_prompt' now has many special symbols like %t for current time X- '_qcd' holds the name of the file where the directoy list for cd is stored X- '_rxpath' stores the list of directories where .rexx files reside X- '_scroll' contains the scroll jump or 0 for no quick scrolling X- '_terminal' indicates wheter or not shell was started in terminal mode X- '_titlebar' can have special %-symbols like _prompt X- '_tool_xxx' holds default tools for file ending .xxx X- '_version' is the current shell version number X XFunctions: X X- @abbrev is true if the str1 is an abbreviation of str2 X- @abs returns absolute value of <num> X- @appext appends an extension to a string X- @availmem returns free 'chip', 'fast' or otherwise total memory X- @basename returns the file name without path X- @center centers a string X- @checkport indicates if given port exists X- @clinum returns the number of the given process X- @complete returns the first word an abbreviation matches X- @concat concats all args in one blank separated string X- @confirm gets confirmation for all its arguments X- @dectohex returns a string representing number in hex X- @delword returns a string with the n-th word deleted. X- @delwords deletes the next m words from the n-th. X- @dirs returns the directories among the given file names X- @drive outputs the drive ( device ) name associated to path X- @drives outputs all available drives X- @exists tells whether a file exists or not X- @fileblks returns the # of blocks needed for the files X- @filelen count the total number of bytes of the given files X- @fileprot returns a string like ---arwed X- @filereq brings up the arp file requester and returns the selected file X- @files gives you the files among those names, no directories X- @freebytes the number of free bytes on the given path X- @freeblks the number of free blocks on the given path X- @freestore the amount of free store on that path, given in K, M and G X- @getenv returns the value of the named env: variable X- @howmany indicates the # of shells running X- @index returns the index of str2 in str1 (starting at 1) X- @info the corresponding line from the 'info' command X- @intersect returns all words which are in both lists X- @lookfor looks for a file in the current directory and the given paths X- @lower lowercases its arguments X- @match returns the words in the that match the arp-pattern X- @max computes the maximum of all given numbers X- @megs expresses a number in K, M and G (-bytes) X- @member tells you if the first arg is among the remaining X- @min computes the minimum of all given numbers X- @nameext returns all after the last dot of filename. X- @nameroot returns all before the LAST dot of filename. X- @union returns all names that are in either list X- @pathname strips the base name from a path X- @pickargs picks of its arguments those which don't start with a '-' X- @pickopts picks of its arguments those which start witch a '-' X- @rpn computes the rpn expression. See rpn command X- @sortargs sorts its arguments alphabetically X- @split makes each blank separated part of @string a word X- @strcmp returns -1, 0 or 1 depending of alphabetical comparison X- @strhead see strhead command X- @strleft see strleft command X- @strmid see strmid command X- @strright see strright command X- @strtail see strtail command X- @subword returns the n-th word of the given list X- @subword returns the next m words word of the given list starting from n X- @tackon see tackon command X- @unique sorts the arguments and makes each of them unique X- @upper upper cases the given words X- @volume returns the volume name in that path or "" if no disk present X- @without returns all names of list 1 that are not in list 2 X- @word same as @subword X- @words returns the number of args X XBug fixes: X X- recursive wild card expansion does not crash the Amiga 3000 anymore X- recursive wild card expansion does not lose memory anymore X- now works on AUX: X- trying to start a non-object-file now properly prints 'Command Not Found' X- automatic sourcing now also works if you already add .sh to the file name X- files longer than 999999 bytes no longer misalign 'dir' X- exec does not discard the rest of the command line ('exec echo hi;echo ho') X- all memory trashing fixed. Thanks to C= for their great debugging tools! X- source doesn't forget last character if batchfile was not CR terminated X- run & rback also search AmigaDOS path now X- division by zero does not crash rpn anymore X- temporary pipe files are now written to t: instead of ram: X- shift-tab does not cause a lockup anymore X- running the shell via aux: no longer crashes the machine X- 'history partial' now numbers the lines correctly X- strleft, strright and strmid no longer crash on strings > 256 bytes X- source with no arguments now prints correct error message X- 'input' now cuts down lines longer than 256 bytes instead of crashing X- cursor-up no more deletes lines if there's an invalid entry in the history X- if history fails, no empty history entry is generated X- 'echo "---"' and even 'echo ---' work, but 'echo "-a"' still doesn't X- international character sets can be used X- 'copy -u' won't copy a file with identical date stamp but in uppercase X- 'copy -u' will no longer access low memory X- 'echo "echo mem | shell" | shell' now works, not only every second time X- starting from workbench now prevented X- editing lines longer than 256 bytes is now correctly prevented X- word-right cursor movement works correclty with multiple blanks X- 'if'-stack will be adjusted when a batch file is exited X- relabel occasionally crashed in Syquest drives. should be okay now X XNew to 4.02A: X X- Fixed bug that caused loss of memory on exit. X- cp now copies protection bits; use -f switch if you want to avoid this. X- Added commands: man (and alias manlist), uniq, head, tail, tee. X- This doc has been reformatted to work with man. X XNew to 4.01A: X X- This version features mostly bug fixes and corrections: X * Window title is restored after quitting. X * rxrec now answers to the 'bye' message. X * rpn can now be redirected and piped; however, this causes X some problem (see rpn for info). X * resident list now works with ARP 1.3. To recompile source, you must X modify include file "libraries/arpbase.h". X Change definition of rpn_Usage in struct ResidentProgramNode from LONG X to WORD. X * pri no more assumes 20 CLI maximum. X * you can now split long lines in source files even into more than 2 lines. X- Added much info in this doc about source files (chapter XI) X- Added copyright notice (see under restrictions). X XNew to 4.00A: X X- This version is called 4.00A because it is not 100% compatible with X previous versions. We choose to accept this in order to better support X the new ARP.library 1.3. X- External commands are searched in a different order than before; Shell X path is now searched AFTER current directory, AmigaDOS path and C:. X- ARP pattern matching has been implemented (in part for line arg expanding, X fully for search -w). X- Internal changes for various optimizations. X- Search command has been improved in several ways. X- New commands: basename, tackon. X- New options: if -v, resident -d, fornum -v -s, dir -n. X- Fixed bugs with dir (some dirs remained locked), foreach -v, htype X (blanks were treated as binary), info (for devices > 32M). X- rback command now works ok (run, however, doesn't). X- Oh, I forgot: it also has an AREXX port... And you don't even have to get X AREXX to use it. See new commands rxsend, rxrec X XNew to 3.03A: X X- New filter commands fltlower, fltupper. X- Added configuration file feature: now if you have a file named S:.login, X it will be sourced for every Shell you start. X- New option dir -c. X- New editing feature: shift-left(right) arrow move cursor to previous(next) X word. X- Bugs fixed: alias command wasn't listed in help; typing a number as a X command was interpreted like 'alias'. X XNew to 3.02A: X X- New commands: fornum, forline, strleft, strright, strmid, strlen, exec. X- Improved commands: foreach, pri. X- New system variable _clinumber. X- You can now split long lines in source files (see source for details). X- window -q now lists also position of screens/windows, not only dimension. X- Since strings are handled directly from Shell with new commands, X rpn is now used only for calculations; string commands are gone. X However, now RPN is really usable. X- Changed rawgets() to fix some problems with function keys, multi-line X editing and window resizing; also, fixed bug with ^E. X- cat now warns you if it can't find any file matching your pattern. X- Now uses DOS packets to get ptr to CLI window; this fixes a bug that X caused problems if Shell was run on unactive windows. X- Fixed minor bugs (htype printed some more ASCII bytes, some commands X returned random values, history didn't print CR's). X- Heavy mods to this file. X END_OF_FILE if test 13639 -ne `wc -c <'changes.doc'`; then echo shar: \"'changes.doc'\" unpacked with wrong size! fi # end of 'changes.doc' fi if test -f 'rawcon.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rawcon.c'\" else echo shar: Extracting \"'rawcon.c'\" \(17773 characters\) sed "s/^X//" >'rawcon.c' <<'END_OF_FILE' X/* X * rawcon.c X * X * Shell 2.07M 17-Jun-87 X * console handling, command line editing support for Shell X * using new console packets from 1.2. X * Written by Steve Drew. (c) 14-Oct-86. X * 16-Dec-86 Slight mods to rawgets() for Disktrashing. X * X * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90 X * Version 5.00L by Urban Mueller 17-Feb-91 X * X */ X X#include "shell.h" X Xstatic int myget( void ); Xstatic void myunget(int c); Xstatic void setrawcon( long flag, int ievent ); Xstatic int get_seq( long *param ); Xstatic int bkspcword( int i, int max, int cnt ); X X X#if RAW_CONSOLE X Xstatic char *tyahdptr, *lasttya; Xstatic int tabctr, qcdctr, unget; X X#define SETRAW setrawcon(-1L,1); X#define SETCON setrawcon( 0L,1); X Xint w_width; Xextern char *MenuCommand[MAXMENUS][MAXITEMS]; X X#define CTRL -64 X#define SHIFT 512 X#define ESC 1024 X X#define CUP 256 X#define CDN 257 X#define CRT 258 X#define CLT 259 X#define TAB 9 X Xstatic int Curmap; Xstatic USHORT *Keymap[8]; Xstatic USHORT DefKeymap0[]={ X CLT, 0, /* CursLt = Move.Left */ X CRT, 1, /* CursRt = Move.Right */ X SHIFT+CLT, 2, /* SCursLt= Move.WordL */ X SHIFT+CRT, 3, /* SCursRt= Move.WordR */ X ESC+CLT, 4, /* ESC-CLt= Move.SOL */ X ESC+CRT, 5, /* ESC-CRt= Move.EOL */ X CTRL+'A', 4, /* ^A = Move.SOL */ X CTRL+'E', 5, /* ^E = Move.EOL */ X CTRL+'Z', 4, /* ^Z = Move.SOL */ X 8, 10, /* BackSp = Del.BackSp */ X 127, 11, /* Delete = Del.Delete */ X ESC+ 8, 12, /* ESC-BkS= Del.WordL */ X ESC+127, 13, /* ESC-Del= Del.WordR */ X CTRL+'W', 12, /* ^W = Del.WordL */ X CTRL+'B', 14, /* ^B = Del.SOL */ X CTRL+'K', 15, /* ^K = Del.EOL */ X ESC+'x',513, /* ESC-x = Setmap 1 */ X ESC+'d', 16, /* ESC-d = Del.Line */ X CTRL+'X', 16, /* ^X = Del.Line */ X CUP, 20, /* CursUp = Hist.Back */ X CDN, 21, /* CursDn = Hist.Forw */ X SHIFT+CUP, 22, /* SCursUp= Hist.Beg */ X SHIFT+CDN, 23, /* SCursDn= Hist.End */ X ESC+'!', 24, /* ESC-! = Hist.Compl */ X ESC+ 13, 25, /* ESC-Ret= Hist.Exec */ X CTRL+'T', 26, /* ^T = Hist.Tail */ X TAB, 30, /* Tab = Comp.Norm */ X SHIFT+TAB, 31, /* STab = Comp.Part */ X ESC+TAB, 32, /* ESC-TAB= Comp.All */ X ESC+'c', 33, /* ESC-c = Comp.CD */ X ESC+'~', 34, /* ESC-~ = Comp.LastCD*/ X ESC+'i', 40, /* ESC-i = Spec.Insert*/ X CTRL+'L', 43, /* ^L = Spec.Refr */ X 10, 44, /* Enter = Spec.Accept*/ X 13, 44, /* ^Enter = Spec.Accept*/ X CTRL+'N', 45, /* ^N = Spec.Next */ X CTRL+'O', 48, /* ^O = Spec.EchoO */ X CTRL+'\\', 46, /* ^\ = Spec.EOF */ X 260, 42, /* Help = Misc.Help */ X 271, 51, /* Menu = Menu */ X CTRL+'U', 52, /* Undo = Spec.Undo */ X CTRL+'R', 53, /* Repeat = Spec.Repeat*/ X 0, 0 X}; X Xstatic USHORT DefKeymap1[]={ X 8, 14, X 127, 15 X}; X Xstatic char *Line, *Prompt; Xstatic int Pl; Xstatic char LastDir[128]; X Xvoid Xinitmap(void) X{ X if( !Keymap[0] ) X Keymap[0]=DefKeymap0, Keymap[1]=DefKeymap1; X} X Xchar * Xrawgets( char line[], char prompt[] ) X{ X static int inslen, lastrecall=-1; X static int lastfn, lastkey; X X int n, pl, max, i, c, key, fn, cnt; X USHORT *p; X char *s, *ps, typeahd[256], undo[256]; X int savn, insert=1, recall, undo_i, undo_max; X struct HIST *hist; X char **eav=NULL, *ret, fake; X int eac, eactr; X long param[10], *par; X X typeahd[0]=0; X tyahdptr=lasttya=typeahd; X X newwidth(); X X if ( o_noraw || !IsInteractive(Input()) ) { X if( IsInteractive(Input())) { X printf("%s",prompt); X fflush(stdout); X } X return(gets(line)); X } X X if (WaitForChar((long)Input(), 100L) || /* don't switch to 1L ...*/ X CHARSWAIT(stdin)) { /* else causes read err's*/ X gets(line); X return(line); X } X X SETRAW; Xbegin: X printf("\015%s\033[6n",prompt); X fake= savn = pl = n = 0; X tyahdptr = typeahd; X X while( (typeahd[n]=getchar()) != 'R') { X if (typeahd[n] == 155) savn = n; X if (typeahd[n] == 27 && getchar()=='[') X typeahd[n] =155, savn=n; X n++; X } X /* typeahd now contains possible type a head chars X followed by <CSI> cursor position report. */ X X typeahd[savn] = '\0'; X if (typeahd[n-2] != ';') pl = (typeahd[n-2] -'0') * 10; X pl += typeahd[n-1] - 49; X ps = line + pl; X line[max = i = pl] = '\0'; X X Line=line; Prompt=prompt; Pl=pl; X X if (s = get_var (LEVEL_SET, "_insert")) insert = atoi(s) ? 1 : 0; X X if( (recall=lastrecall)>=0 ) { X lastrecall=-1; X goto recallh; X } X X while( (c=myget()) != -1) { X int esc=0; X key=-1; X if( c==27 ) esc=ESC, c=myget(); X switch(c) { X case 155: X switch(c=myget()) { X case 'A': key=256; break; /* CursUp */ X case 'B': key=257; break; /* CursDn */ X case 'C': key=258; break; /* CursRt */ X case 'D': key=259; break; /* CursLt */ X case 'T': key=256+SHIFT; break; /* SCursUp */ X case 'S': key=257+SHIFT; break; /* SCursDn */ X case ' ': X switch( myget() ) { X case '@': key=258+SHIFT; break; /* SCursRt */ X case 'A': key=259+SHIFT; break; /* SCursLt */ X } break; X case 'Z': key=9+SHIFT; break; /* STab */ X case '?': key=260; myget(); break; /* Help */ X default : X myunget(c); X par=param; X do { X for( *par=0; (c=myget())>='0' && c<='9'; ) X *par=10* *par + c-'0'; X par++; X } while( c==';' ); X if( c=='~' ) { X key=param[0]+261; X if( key>270 ) key+=SHIFT-10; X } X if( c=='|' ) key=271; X } break; X default: key=c; break; X } X key+=esc; X X for( fn=-1, p=Keymap[Curmap]; *p; p+=2 ) X if( *p==key ) X { fn=p[1]; break; } X if( fn==-1 && key>=261 && key<=270 || key>=261+SHIFT && key<=270+SHIFT ) X fn=50; X X if( fn!=52 && !*lasttya) { X memcpy( undo+pl, line+pl, max-pl ); X undo_i=i; undo_max=max; X } X X switch( fn/512 ) { X case 1: X fn&=511; X if( fn<8 && Keymap[fn] ) Curmap=fn; X fn=-2; X break; X case 2: X key=fn&511, fn=-1; X break; X } X X if( fn!=-2 ) X Curmap=0; X X if( fn!=53 && !*lasttya ) X lastfn=fn, lastkey=key; X Xdofn: X switch( fn ) { X case -2: X break; X X case 0: /* cursor left */ X if (i > pl) X i--, printf("\033[D"); X break; X case 1: /* cursor right */ X if (i < max) X i++, printf("\033[C"); X break; X case 2: /* word left */ X for (cnt=0; i>pl && line[i-1] == ' '; cnt++,i--); X for ( ; i>pl && line[i-1] != ' '; cnt++,i--); X if( cnt ) printf("\033[%dD",cnt); X break; X case 3: /* word right */ X for( cnt=0; i<max && line[i] != ' '; i++,cnt++) ; X for( ; i<max && line[i] == ' '; i++,cnt++) ; X if( cnt ) printf("\033[%dC",cnt); X break; X case 4: /* beg of line */ X if (i>pl) printf("\033[%dD",i-pl); X i = pl; X break; X case 5: /* end of line */ X if (i!=max) printf("\033[%dC",max - i); X i = max; X break; X X case 10: /* backspace */ X if (i > pl) { X i--; X printf("\010"); X } else break; X case 11: /* delete */ X if (i < max) { X int j,t,l = 0; X memmove(&line[i],&line[i+1],max-i); X --max; X printf("\033[P"); X j = w_width - i % w_width - 1; /* amount to end */ X t = max/w_width - i/w_width; /* no of lines */ X for(n = 0; n < t; n++) { X l += j; /* # of char moved*/ X if (j) printf("\033[%dC",j);/* goto eol */ X printf("%c\033[P",line[w_width*(i/w_width+n+1)-1]); X j = w_width-1; X } X if (t) X printf("\033[%dD",l+t); /* get back */ X } X break; X case 12: /* bkspc word */ X cnt= bkspcword(i,max,-1); X max-=cnt; i-=cnt; X break; X case 13: X for( cnt=0; i<max && line[i]!=' '; i++,cnt++ ) ; X for( ; i<max && line[i]==' '; i++,cnt++ ) ; X if ( cnt ) printf("\033[%dC",cnt); X cnt=bkspcword(i,max,cnt); X i-=cnt; max-=cnt; X break; X case 14: X cnt=bkspcword(i,max,i-pl); X i-=cnt; max-=cnt; X break; X case 16: /* delete line */ X if (i>pl) printf("\033[%dD",i-pl); X i = pl; X case 15: /* delete to EOL */ X printf("\033[J"); X max = i; X line[i] = '\0'; X break; X X X case 20: /* history up */ X ++recall; X case 21: /* history down */ X line[pl] = '\0'; X if (recall >= 0 || fn==20) { X if ( fn==21 ) --recall; Xrecallh: X n=recall; X if (recall >= 0) { X for(hist = H_head; hist && n--; X hist = hist->next); X if (hist) strcpy(&line[pl],hist->line); X else recall = H_len; X } X } X if (i != pl) X printf("\033[%dD",i-pl); X printf("\033[J%s",ps); X i = max = strlen(ps) + pl; X break; X case 22: /* beg of hist */ X recall = H_len-1; X case 23: /* end of hist */ X line[pl] = '\0'; X if (fn == 23) { X recall = 0; X if (H_head) strcpy(&line[pl], H_head->line); X } else if (H_tail) X strcpy(&line[pl], H_tail->line); X printf("\015\033[J%s%s", prompt, ps); X i = max = strlen(ps) + pl; X break; X case 24: /* complete hist */ X line[max]=0; X if( s=get_history(&line[pl-1],0 )) { X if (i>pl) printf("\033[%dD\033[J",i-pl); X line[i=max=pl]=0; X strncpy(typeahd,s,256); X tyahdptr=typeahd; X } X break; X case 25: /* exec hist */ X lastrecall= recall; X goto done; X case 26: /* tail of prev */ X if( H_head && (s=H_head->line) && (s=index(s,' ')) ) X tyahdptr=s; X break; X X case 30: /* complete */ X case 31: X case 32: X case 33: { X static int lastcompl; X int j, k, n, e, cnt, len, radlen; X char *name, *q, abbrev; X X abbrev= fn==31; Xcomplete: X tyahdptr=""; X if( tabctr!=0 ) { X char *dest=typeahd, *lcd; X X lastcompl=fn; X for( cnt=0; i<max && line[i]!=' '; ++i, ++cnt ) ; X if(cnt) printf("\033[%dC",cnt); X for( e=i, j=i-1, cnt=0; j>=pl && line[j]!=' ' && line[j]!='<' && X line[j]!='>' && line[j]!=';' ; --j ) cnt++; X ++j; X X if( line[j]=='~' && (lcd=get_var(LEVEL_SET,v_lcd))) { X strcpy(dest,lcd); X dest+=strlen(dest); X j++; X } X memcpy(dest,&line[j],e-j); X dest+=e-j; X if( fn!=33 ) X *dest++='*'; X *dest=0; X if( eav ) free_expand( eav ), eav=NULL; X breakreset(); X tabctr=1; X if( fn==33 ) { X strncpy(LastDir,typeahd,128); X if( !quick_cd( name=typeahd+128, LastDir, 0)) X { putchar(7); break; } X } else { X eav =expand(typeahd,&eac); X if( eac==0 ) { putchar(7); break; } X QuickSort(eav, eac); X if( fn==30 ) X name=eav[ eactr=0 ]; X else X name=compile_av(eav,0,eac,' ',1), tabctr=0; X } X inslen=cnt; X } else { X abbrev=0, tabctr=1; X if( lastcompl==33 ) { X quick_cd( name=typeahd+128, LastDir, 1); X } else { X if( !eac ) break; X name=eav[eactr=++eactr % eac]; X } X } X len=bkspcword(i,max,inslen); X i-=len; max-=len; X if( abbrev && eac>1) { X strcpy( typeahd, eav[0] ); X radlen= 9999; X for( k=0; k<eac; k++ ) { X if ( (n=strlen(eav[k])) < radlen ) radlen=n; X for( n=0; n<radlen && eav[0][n]==eav[k][n]; n++ ) ; X if ( n<radlen ) radlen=n; X } X typeahd[radlen]=0; X eactr--; X } else { X if( lastcompl==32 ) { X strncpy( typeahd,name,250 ); X name[250]=0; X } else { X strcpy(typeahd,(q=index( name, ' ' )) ? "\"" : "" ); X strcat(typeahd,name); X if( q ) strcat(typeahd,"\""); X if( lastcompl==33 || isdir(name) ) X appendslash( typeahd ); X else X strcat( typeahd, " " ); X } X } X tyahdptr=typeahd; X inslen=strlen(typeahd); X } X break; X case 34: X strncpy(typeahd,get_var( LEVEL_SET, v_lcd ),230); X appendslash(tyahdptr=typeahd); X break; X X case 40: /* ins/ovr */ X insert ^= 1; X break; X case 41: /* quit */ X strcpy(ps,"quit"); X goto done; X case 42: /* help */ X strcpy(ps,"help"); X goto done; X case 43: /* refresh */ X if ((n = i/w_width)) printf("\033[%dF",n); X printf("\015\033[J%s%s",prompt,ps); X i = max; X break; X case 44: X line[max] = '\0'; Xdone: printf("\033[%dC\n",max - i); X strcpy(line, ps); X ret=line; X if( fake ) goto begin; X goto exit; X case 45: /* leave */ X line[max] = '\0'; X add_history( ps ); X fake=1; X goto done; X case 46: /* EOF */ X ret=NULL; X goto exit; X case 47: X break; X case 48: X printf("\017"); X break; X case 49: X printf("\07"); X break; X X case 50: { X char fkeys[8]; X sprintf(fkeys,"%c%d",param[0]>=10?'F':'f',param[0]%10+1); X if (s = get_var(LEVEL_SET, fkeys)) { X tyahdptr = strcpy(typeahd,s); X a0tospace( tyahdptr ); X } X break; X } X case 51: { X int class=param[0], code=param[2]; X if( class==10 ) { X int num=MENUNUM( code ), item=ITEMNUM( code ); X tyahdptr=""; X if( num>=0 && num<MAXMENUS && item>=0 && item<=MAXITEMS ) X tyahdptr=MenuCommand[num][item]; X } X if( class==11 ) { X strcpy(ps,"quit"); X goto done; X } X } X case 52: { X int t; X X if ((n = i/w_width)) printf("\033[%dF",n); X swapmem( undo+pl, line+pl, MAX( max, undo_max)-pl ); X t=max; max=undo_max; undo_max=t; X t=i; i =undo_i; undo_i =t; X line[max]=0; X printf("\015\033[J%s%s",prompt,ps); X if( i<max ) printf("\033[%dD",max-i); X } X break; X case 53: X fn=lastfn; key=lastkey; X goto dofn; X X default: X key&=255; X if (key == 9) key = 32; X if (key > 31 && (insert?max:i) < 256) { X if (i < max && insert) { X int j,t,l = 0; X memmove(&line[i+1], &line[i], max - i); X printf("\033[@%c",key); X t = max/w_width - i/w_width; X j = w_width - i % w_width - 1; X for(n = 0; n < t; n++) { X l += j; X if (j) printf("\033[%dC",j); X printf("\033[@%c",line[w_width*(i/w_width+n+1)]); X j = w_width-1; X } X if (t) printf("\033[%dD",l + t); X ++max; X } X else { X if(i == pl && max == i) printf("\015%s%s",prompt,ps); X putchar(key); X } X line[i++] = key; X if (max < i) max = i; X line[max] = '\0'; X } X } X } X ret=NULL; Xexit: X newwidth(); X if( eav ) free_expand(eav); X SETCON; X return ret; X} X Xint Xbkspcword( int i, int max, int cnt ) X{ X int o=i; X X if( !cnt ) return 0; X X if( cnt==-1 ) { X cnt=0; X while( i>Pl && Line[i-1]==' ' ) i--, cnt++; X while( i>Pl && Line[i-1]!=' ' ) i--, cnt++; X } else X i-=cnt; X X if( cnt ) printf("\033[%dD",cnt); X memmove( Line+i, Line+o, max-o ); X memset ( Line+max-cnt, ' ', cnt ); X X printf("%s",Line+i); X X if( max-i ) printf("\033[%dD", max-i ); X fflush(stdout); X Line[max-=cnt]=0; X X return cnt; X} X Xvoid Xsetrawcon( long flag, int ievent ) /* -1L=RAW:, 0L=CON: */ X{ X static char menuon, button; X long packargs[8]; X X if( !o_nowindow && ievent && flag==0 && menuon) X printf("\033[10}"), menuon=0; X X packargs[0]=flag; X SendPacket(994L, packargs, (void *)Myprocess->pr_ConsoleTask); X X if( !o_nowindow && ievent && flag==-1 ) { X if( !menuon ) X printf("\033[10{"), menuon=1; X if( !button ) X printf("\033[11{"), button=1; X } X} X X X Xstatic int row, height, cnt, noquick=1; Xstatic char scrollstr[10]; X Xextern char *Cin_name, *Cout_name; Xextern BPTR OldCin; X Xstatic int FromTee; X Xvoid Xprepscroll( int fromtee ) X{ X BPTR truecin=0; X long param[8]; X X row=height=0; X FromTee=fromtee; X X if(( noquick=!o_scroll ||o_noraw || o_nofastscr )) X return; X if(( noquick=Cout_name && !fromtee )) X return; X if( Cin_name ) { X truecin=Myprocess->pr_CIS; X X if( noquick=!IsInteractive(OldCin) ) X return; X X Myprocess->pr_CIS = DEVTAB(stdin) = OldCin; X } X X if( !CHARSWAIT(stdin) ) { X SETRAW; X fprintf(fromtee?stderr:stdout,"\033[ q"); X get_seq( param ); X height=param[2]; X while( getchar()!='r') ; X X fprintf(fromtee?stderr:stdout,"\033[6n"); X get_seq( param ); X row=param[0]; X X SETCON; X X cnt= height-row+1; X noquick= height<o_minrows; X } X X sprintf(scrollstr,"\033[%cS\033[%cA", o_scroll+'0', o_scroll+'0'); X X if( truecin ) X Myprocess->pr_CIS = DEVTAB(stdin) = truecin; X} X Xstatic int Xget_seq( long *param ) X{ X int c; X X while( (c=getchar())!=155 ) ; X do { X *param=0; X while( (c=getchar())>='0' && c<='9' ) X *param=10* *param + c-'0'; X param++; X } while( c==';' ); X X return c; X} X X Xvoid Xquickscroll( void ) X{ X if( noquick ) return; X X if( --cnt<=0 ) { X cnt=o_scroll; X fprintf( FromTee ? stderr : stdout, "%s",scrollstr); X } X} X Xint Xdo_keymap( void ) X{ X int i, n, len; X USHORT *tmp, *put, *get, *map; X char *ind; X X n=myatoi(av[1],0,7); X if( atoierr ) return 20; X X map=Keymap[n]; len=0; X if( map ) X for( len=0; map[2*len]; len++ ) ; X X put=tmp=malloc((len+ac)*2*sizeof(USHORT)); X for( i=2; i<ac; i++ ) { X if( !(ind=index(av[i],'='))) { X ierror( av[i],500); X free( tmp ); X return 20; X } X *put++=atoi(av[i]); X *put++=atoi(ind+1); X } X X for( i=0; i<len; i++ ) { X for( get=tmp; get<put; get+=2 ) X if( *get==map[2*i] ) X break; X if( get==put ) { X *put++=map[2*i]; X *put++=map[2*i+1]; X } X } X X if( map && map!=DefKeymap0 && map!=DefKeymap1 ) X free( map ); X Keymap[n]=tmp; X Curmap=0; X X return 0; X} X Xstatic int Xmyget( void ) X{ X int c; X X lasttya=tyahdptr; X if( unget ) X c=unget, unget=0; X else if( tyahdptr && *tyahdptr) X c=*tyahdptr++; X else { X#ifndef AZTEC_C X fflush(stdout); X#endif X if( (c=getchar())!=155 ) X tabctr--, qcdctr--; X } X X return c; X} X Xstatic void Xmyunget(int c) X{ X unget=c; X} X Xint Xnewwidth( void ) X{ X extern struct Window *Win; X X if( !o_nowindow && Win ) X w_width=(Win->Width-(Win->BorderLeft+Win->BorderRight))/ X Win->RPort->TxWidth; X else X w_width=80; X return w_width; X} X X X X#else X Xprepscroll(){} Xquickscroll(){} X X#endif X END_OF_FILE if test 17773 -ne `wc -c <'rawcon.c'`; then echo shar: \"'rawcon.c'\" unpacked with wrong size! fi # end of 'rawcon.c' fi if test -f 'sub.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'sub.c'\" else echo shar: Extracting \"'sub.c'\" \(21051 characters\) sed "s/^X//" >'sub.c' <<'END_OF_FILE' X X/* X * SUB.C X * X * (c)1986 Matthew Dillon 9 October 1986 X * X * Version 2.07M by Steve Drew 10-Sep-87 X * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90 X * Version 5.00L by Urban Mueller 17-Feb-91 X * X */ X X#include "shell.h" X#include "proto.h" X Xstatic void del_history( void ); Xstatic int hasspace( char *s ); Xstatic int dnext( struct DPTR *dp, char **pname, int *stat); Xstatic char *svfile( char *s1, char *s2, FIB *fib); Xstatic int exall( BPTR lock, char *path ); Xstatic void quicksort( char **av, int n ); X X X#define HM_STR 0 /* various HISTORY retrieval modes */ X#define HM_REL 1 X#define HM_ABS 2 X Xvoid Xseterr( void ) X{ X char buf[32], *val; X int stat=0; X X sprintf(buf, "%d", Lastresult); X set_var(LEVEL_SET, v_lasterr, buf); X if( val=get_var(LEVEL_SET, v_stat)) X stat = atoi(val); X if (stat < Lastresult) set_var(LEVEL_SET, v_stat, buf); X} X X#define ISSPACE(c) ((c)==' ' || (c)==9 || (c)==0xA0) X Xchar * Xnext_word( char *str ) X{ X while (*str && ! ISSPACE(*str)) ++str; X while (*str && ISSPACE(*str)) ++str; X return str; X} X Xstatic int Xhasspace( char *s ) X{ X for ( ; *s; s++) X if (ISSPACE(*s)) return 1; X return 0; X} X Xchar * Xcompile_av(char **av, int start, int end, char delim, int quote) X{ X char *cstr, *p; X int len, i; X X len = 1; X for (i = start; i < end; ++i) len += strlen(av[i]) + 3; X p = cstr = malloc(len); X *cstr = '\0'; X for (i = start; i < end; ++i) { X if (debug) fprintf (stderr, "AV[%2d] :%s:\n", i, av[i]); X if (quote && hasspace(av[i])) X p += sprintf(p, "\"%s\"", av[i]); X else X p += sprintf(p, "%s", av[i]); X if (i+1 < end) *p++=delim; X } X *p='\0'; X return cstr; X} X X/* X * FREE(ptr) --frees without actually freeing, so the data is still good X * immediately after the free. X */ X X Xvoid XFree( void *ptr ) X{ X static char *old_ptr; X X if (old_ptr) free (old_ptr); X old_ptr = ptr; X} X X/* X * Add new string to history (H_head, H_tail, H_len, X * S_histlen X */ X Xvoid Xadd_history( char *str ) X{ X struct HIST *hist; X char *get; X X for( get=str; *get; get++ ) X if( (*get&127)<' ') X *get=' '; X X if (H_head != NULL && !strcmp(H_head->line, str)) X return; X while (H_len > S_histlen) X del_history(); X hist = (struct HIST *)malloc (sizeof(struct HIST)); X if (H_head == NULL) { X H_head = H_tail = hist; X hist->next = NULL; X } else { X hist->next = H_head; X H_head->prev = hist; X H_head = hist; X } X hist->prev = NULL; X hist->line = malloc (strlen(str) + 1); X strcpy (hist->line, str); X ++H_len; X} X Xstatic void Xdel_history() X{ X if (H_tail) { X --H_len; X ++H_tail_base; X free (H_tail->line); X if (H_tail->prev) { X H_tail = H_tail->prev; X free (H_tail->next); X H_tail->next = NULL; X } else { X free (H_tail); X H_tail = H_head = NULL; X } X } X} X Xchar * Xget_history( char *ptr, int echo ) X{ X struct HIST *hist; X int len; X int mode = HM_REL; X int num = 1; X char *str; X char *result = NULL; X X if (ptr[1] >= '0' && ptr[1] <= '9') { X mode = HM_ABS; X num = atoi(&ptr[1]); X goto skip; X } X switch (ptr[1]) { X case '!': X break; X case '-': X num += atoi(&ptr[2]); X break; X default: X mode = HM_STR; X str = ptr + 1; X break; X } Xskip: X switch (mode) { X case HM_STR: X len = strlen(str); X for (hist = H_head; hist; hist = hist->next) { X if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') { X result = hist->line; X break; X } X } X break; X case HM_REL: X for (hist = H_head; hist && num--; hist = hist->next); X if (hist) X result = hist->line; X break; X case HM_ABS: X len = H_tail_base; X for (hist = H_tail; hist && len != num; hist = hist->prev, ++len); X if (hist) X result = hist->line; X break; X } X if( echo ) X fprintf(stderr, result ? "%s\n" : "History failed\n", result); X if( !result ) result=""; X return result; X} X Xvoid Xreplace_head( char *str ) X{ X if (str && strlen(str) && H_head) { X free (H_head->line); X H_head->line = malloc (strlen(str)+1); X strcpy (H_head->line, str); X } X} X X X#if 0 X#define CDLEN 20 Xstatic int cd_len=CDLEN, cd_read, cd_write, cd_current; Xstatic char *cd_hist[CDLEN]; X Xadd_cdhist( char *str ) X{ X if( !str ) X return; X if( cd_hist[cd_write] ) X free(cd_hist[cd_write]); X cd_hist[cd_write++]=str; X cd_write%=cd_len; X cd_current=cd_write; X} X Xchar * Xback_cdhist( void ) X{ X if( cd_current!=cd_write ) cd_current= --cd_current % cd_len; X return cd_hist[cd_current]; X} X Xchar * Xforw_cdhist( void ) X{ X if( cd_current!=cd_read ) cd_current= ++cd_current % cd_len; X return cd_hist[cd_current]; X} X#endif X Xvoid XpError(char *str ) X{ X int ierr = (long)IoErr(); X ierror(str, ierr); X} X Xierror( char *str, int err ) X{ X struct PERROR *per = Perror; X X if (err) { X for (; per->errstr; ++per) { X if (per->errnum == err) { X fprintf (stderr, "%s%s%s\n", X per->errstr, X (str) ? ": " : "", X (str) ? str : ""); X return err; X } X } X fprintf (stderr, "Unknown DOS error %d %s\n", err, (str) ? str : ""); X } X return err; X} X X/* X * Disk directory routines X * X * dptr = dopen(name, stat) X * struct DPTR *dptr; X * char *name; X * int *stat; X * X * dnext(dptr, name, stat) X * struct DPTR *dptr; X * char **name; X * int *stat; X * X * dclose(dptr) -may be called with NULL without harm X * X * dopen() returns a struct DPTR, or NULL if the given file does not X * exist. stat will be set to 1 if the file is a directory. If the X * name is "", then the current directory is openned. X * X * dnext() returns 1 until there are no more entries. The **name and X * *stat are set. *stat = 1 if the file is a directory. X * X * dclose() closes a directory channel. X * X */ X Xextern long IoError; X Xstruct DPTR * Xdopen( char *name, int *stat) X{ X struct DPTR *dp; X X *stat = 0; X dp = (struct DPTR *)malloc(sizeof(struct DPTR)); X if (*name == '\0') X dp->lock = DupLock(Myprocess->pr_CurrentDir); X else X dp->lock = Lock (name,ACCESS_READ); X if (dp->lock == NULL) { X IoError=IoErr(); X free (dp); X return NULL; X } X dp->fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC); X if (!Examine (dp->lock, dp->fib)) { X pError (name); X dclose (dp); X return NULL; X } X if (dp->fib->fib_DirEntryType >= 0) *stat = 1; X return dp; X} X Xstatic int Xdnext( struct DPTR *dp, char **pname, int *stat) X{ X if (dp == NULL) return (0); X if (ExNext (dp->lock, dp->fib)) { X *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1; X *pname = dp->fib->fib_FileName; X return 1; X } X return 0; X} X Xint Xdclose( struct DPTR *dp ) X{ X if (dp == NULL) X return 1; X if (dp->fib) X FreeMem (dp->fib,(long)sizeof(*dp->fib)); X if (dp->lock) X UnLock (dp->lock); X free (dp); X return 1; X} X X Xint Xisdir( char *file ) X{ X struct DPTR *dp; X int stat; X X stat = 0; X if (dp = dopen (file, &stat)) X dclose(dp); X return (stat == 1); X} X X Xvoid Xfree_expand( char **av ) X{ X char **get = av; X X if (av) { X while (*get) X free (*get++-sizeof(struct file_info)); X free (av); X } X} X X/* X * EXPAND(base,pac) X * base - char * (example: "df0:*.c") X * pac - int * will be set to # of arguments. X * X * 22-May-87 SJD. Heavily modified to allow recursive wild carding and X * simple directory/file lookups. Returns a pointer to X * an array of pointers that contains the full file spec X * eg. 'df0:c/sear*' would result in : 'df0:C/Search' X * X * Now no longer necessary to Examine the files a second time X * in do_dir since expand will return the full file info X * appended to the file name. Set by formatfile(). X * eg. fullfilename'\0'rwed NNNNNN NNNN DD-MMM-YY HH:MM:SS X * X * Caller must call free_expand when done with the array. X * X * base bname = ename = X * ------ ------- ------- X * "*" "" "*" X * "!*.info" "" "*.info" (wild_exclude set) X * "su*d/*" "" "*" (tail set) X * "file.*" "" "file.*" X * "df0:c/*" "df0:c" "*" X * "" "" "*" X * "df0:.../*" "df0:" "*" (recur set) X * "df0:sub/.../*" "df0:sub" "*" (recur set) X * X * ---the above base would be provided by execom.c or do_dir(). X * ---the below base would only be called from do_dir(). X * X * "file.c" "file.c" "" if (dp == 0) fail else get file.c X * "df0:" "df0:" "*" X * "file/file" "file/file" "" (dp == 0) so fail X * "df0:.../" "df0:" "*" (recur set) X * X */ X Xint expand_err; X Xchar ** Xexpand( char *base, int *pac ) X{ X char *ptr; X char **eav = (char **)malloc(sizeof(char *) * (2)); X short eleft, eac; X char *name; X char *bname, *ename, *tail; X int stat, recur, scr, bl; X struct DPTR *dp; X X expand_err = *pac = recur = eleft = eac = 0; X X base = strcpy(malloc(strlen(base)+1), base); X for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr); X X if (!*ptr) /* no wild cards */ X --ptr; X else X for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr); X X if (ptr < base) { X bname = strcpy (malloc(1), ""); X } else { X scr = ptr[1]; X ptr[1] = '\0'; X if (!strcmp(ptr-3,".../")) { X recur = 1; X *(ptr-3) = '\0'; X } X bname = strcpy (malloc(strlen(base)+2), base); X ptr[1] = scr; X } X bl = strlen(bname); X ename = ++ptr; X for (; *ptr && *ptr != '/'; ++ptr); X scr = *ptr; X *ptr = '\0'; X if (scr) ++ptr; X tail = ptr; X X if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) { X free (bname); X free (base); X free (eav); X expand_err=1; X return (NULL); X } X X if (!stat) { /* eg. 'dir file' */ X char *p,*s; X for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p; X if (s != bname) ++s; X *s ='\0'; X eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib); X goto done; X } X if (!*ename) ename = "*"; /* eg. dir df0: */ X if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */ X bname[bl] = '/'; X bname[++bl] = '\0'; X } X while ((dnext (dp, &name, &stat)) && !breakcheck()) { X int match = compare_ok(ename,name,0); X if (match && !(!recur && *tail)) { X if (eleft < 2) { X char **scrav = (char **)malloc(sizeof(char *) * (eac + 10)); X memmove (scrav, eav, (eac + 1) << 2); X free (eav); X eav = scrav; X eleft = 10; X } X eav[eac++] = svfile(bname,name,dp->fib); X --eleft; X } X if ((*tail && match) || recur) { X int alt_ac; X char *search, **alt_av, **scrav; X BPTR lock; X X if (!stat) /* expect more dirs, but this not a dir */ X continue; X lock = CurrentDir (dp->lock); X search = malloc(strlen(ename)+strlen(name)+strlen(tail)+6); X strcpy (search, name); X strcat (search, "/"); X if (recur) { X strcat(search, ".../"); X strcat(search, ename); X } X strcat (search, tail); X scrav = alt_av = expand (search, &alt_ac); X free(search); X CurrentDir (lock); X if (scrav) { X while (*scrav) { X int l; X if (eleft < 2) { X char **scrav = (char **)malloc(sizeof(char *)*(eac+10)); X memmove ( scrav, eav, (eac + 1) << 2); X free (eav); X eav = scrav; X eleft = 10; X } X X l = strlen(*scrav); X eav[eac] = malloc(bl+l+1+sizeof(struct file_info)); X memcpy( eav[eac], *scrav-sizeof(struct file_info), X sizeof(struct file_info)); X eav[eac]+=sizeof(struct file_info); X strcpy( eav[eac], bname); X strcat( eav[eac], *scrav); X X free (*scrav-sizeof(struct file_info)); X ++scrav; X --eleft, ++eac; X } X free (alt_av); X } X } X } Xdone: X dclose (dp); X *pac = eac; X eav[eac] = NULL; X free (bname); X free (base); X if (eac) X return (eav); X free (eav); X return (NULL); X} X Xchar * Xstrupr( char *s ) X{ X char *old=s; X while (*s) *s=toupper(*s), s++; X return old; X} X Xchar * Xstrlwr( char *s ) X{ X char *old=s; X while (*s) *s=tolower(*s), s++; X return old; X} X X/* X * Compare a wild card name with a normal name X */ X Xint Xcompare_ok( char *wild, char *name, int casedep) X{ X int queryflag; X char buf[260], wildbuf[260], *lowname; X X if (queryflag=(*wild=='&')) wild++; X if (*wild=='!') *wild='~'; X X if (! casedep) { X strupr(wild); X strcpy(buf,name); X strupr(buf); X lowname=buf; X } else X lowname=name; X X PreParse(wild, wildbuf); X if ( ! PatternMatch(wildbuf,lowname)) return 0; X X if (queryflag) { X printf("Select %s%-16s%s [y/n] ? ",o_hilite,name,o_lolite); X gets(buf); X return (toupper(*buf)=='Y'); X } X return 1; X} X Xstatic char * Xsvfile( char *s1, char *s2, FIB *fib) X{ X int len=strlen(s1)+strlen(s2)+1; X char *p = malloc (len+sizeof(struct file_info)); X struct file_info *info; X X info=(struct file_info *)p; X p+=sizeof(struct file_info); X strcpy(p, s1); X strcat(p, s2); X info->flags = fib->fib_Protection; X if( fib->fib_DirEntryType<0 ) { X info->size = fib->fib_Size; X info->blocks= fib->fib_NumBlocks; X } else { X info->size = -1; X info->blocks= 0; X } X if( fib->fib_Comment[0] ) X info->flags|= 1<<30; X info->date=fib->fib_Date; X info->class[0]=1; X return p; X} X X X Xstatic FILE *out; Xstatic int NumDirs; X Xvoid Xexpand_all( char *name, FILE *file ) X{ X BPTR lock; X char path[300]; X FIB *fib; X X out=file; X printf( " %s\n", name ); X NumDirs=0; X X if(fib=AllocMem(sizeof(struct FileInfoBlock),0)) { X if( lock=Lock( name, ACCESS_READ )) { X strcpy( path, name ); X exall( lock, path ); X printf( "\n", NumDirs ); X } X FreeMem(fib,sizeof(struct FileInfoBlock)); X } X} X Xstatic int Xexall( BPTR lock, char *path ) X{ X BPTR old, sublock; X int len; X struct FileInfoBlock *fib; X X old=CurrentDir( lock ); X X if( !(fib=AllocMem(sizeof(struct FileInfoBlock),0)) ) X return 1; X X len=strlen( path ); X Examine( lock, fib ); X while( ExNext( lock, fib ) ) { X if( fib->fib_DirEntryType>=0 ) X if( sublock=Lock( fib->fib_FileName, ACCESS_READ )) { X if( !len || path[len-1]==':' ) X sprintf(path+len,"%s", fib->fib_FileName); X else X sprintf(path+len,"/%s", fib->fib_FileName); X fprintf( out, "%s\n", path ); X fprintf( stdout, " Directories: %d\015", ++NumDirs ); X fflush ( stdout ); X if(exall( sublock, path )) X break; X path[len]=0; X } X } X FreeMem( fib, sizeof(struct FileInfoBlock)); X CurrentDir( old ); X return dobreak(); X} X X X X/* Sort routines */ X Xint reverse; X Xint Xcmp( char *s1, char *s2) X{ X int r=Strcmp(s1, s2); X return reverse ? -r : r; X} X Xint Xsizecmp( char *s1, char *s2) X{ X int r= ((struct file_info *)(s2-sizeof(struct file_info)))->size - X ((struct file_info *)(s1-sizeof(struct file_info)))->size; X return reverse ? -r : r; X} X Xint Xdatecmp( char *s1, char *s2 ) X{ X int r; X struct DateStamp X *d1=&((struct file_info *)(s1-sizeof(struct file_info)))->date, X *d2=&((struct file_info *)(s2-sizeof(struct file_info)))->date; X if( !(r= d2->ds_Days - d1->ds_Days)) X if( !(r=d2->ds_Minute - d1->ds_Minute ) ) X r=d2->ds_Tick - d1->ds_Tick; X return reverse ? -r : r; X} X X Xstatic void Xenterclass( FILEINFO *info ) X{ X char *class, *iclass=info->class, *t; X X if( *iclass==1 ) { X if( class=getclass( (char *)(info+1))) { X strncpy( iclass, class, 11 ); X iclass[11]=0; X if( t=index(iclass,0xA0)) X *t=0; X } else X iclass[0]=0; X } X} X Xint Xclasscmp( char *s1, char *s2 ) X{ X int r; X FILEINFO *info1=(FILEINFO *)s1-1, *info2=(FILEINFO *)s2-1; X X enterclass( info1 ); X enterclass( info2 ); X X r= Strcmp( info1->class, info2->class ); X if( !r ) r=Strcmp(s1, s2); X return reverse ? -r : r; X} X X Xvoid XQuickSort( char *av[], int n) X{ X DirQuickSort( av, n, cmp, 0 ); X} X Xstatic int (*compare)(char *, char *); X Xvoid XDirQuickSort( char *av[], int n, int (*func)(char *,char *), int rev) X{ X reverse=rev; compare=func; X quicksort( av, n-1 ); X} X Xstatic void Xquicksort( char **av, int n ) X{ X char **i, **j, *x, *t; X X X if( n>0 ) { X i=av; j=av+n; x=av[ n>>1 ]; X do { X while( (*compare)(*i,x)<0 ) i++; X while( (*compare)(x,*j)<0 ) --j; X if( i<=j ) X { t=*i; *i=*j; *j=t; i++; j--; } X } while( i<=j ); X X if( j-av < av+n-i ) { X quicksort( av, j-av ); X quicksort( i , av+n-i); X } else { X quicksort( i , av+n-i); X quicksort( av, j-av ); X } X } X} X X Xint Xfilesize( char *name ) X{ X BPTR lock; X struct FileInfoBlock *fib; X int len=0; X X if( lock = Lock (name,ACCESS_READ)) { X if( fib=(struct FileInfoBlock *)AllocMem(sizeof(*fib),MEMF_PUBLIC)) { X if (Examine (lock, fib)) X len=fib->fib_Size; X FreeMem( fib, sizeof(*fib)); X } X UnLock(lock); X } X return len; X} X X X#ifndef MIN X#define MIN(x,y) ((x)<(y)?(x):(y)) X#endif X Xchar ** Xand( char **av1, int ac1, char **av2, int ac2, int *ac, int base ) X{ X char **av=(char **)malloc(MIN(ac1,ac2)*sizeof(char *) ), *str; X int i, j, k=0; X X for( i=0; i<ac1; i++ ) X for( j=0, str=base ? BaseName(av1[i]) : av1[i]; j<ac2; j++ ) X if( !Strcmp(str, base ? BaseName(av2[j]) : av2[j])) X av[k++]=av1[i]; X *ac=k; X return av; X} X Xchar ** Xwithout( char **av1, int ac1, char **av2, int ac2, int *ac, int base ) X{ X char **av=(char **)malloc(ac1*sizeof(char *) ), *str; X int i, j, k=0; X X for( i=0; i<ac1; i++ ) { X for( j=0, str=base ? BaseName(av1[i]) : av1[i]; j<ac2; j++ ) X if( !Strcmp(str, base ? BaseName(av2[j]) : av2[j] ) ) X break; X if( j==ac2 ) X av[k++]=av1[i]; X } X *ac=k; X return av; X} X Xchar ** Xor( char **av1, int ac1, char **av2, int ac2, int *ac, int base ) X{ X char **av=(char **)malloc((ac1+ac2)*sizeof(char *) ), *str; X int i, j, k=0; X X for( i=0; i<ac1; i++ ) X av[k++]=av1[i]; X X for( i=0; i<ac2; i++ ) { X for( j=0, str=base ? BaseName(av2[i]) : av2[i]; j<ac1; j++ ) X if( !Strcmp(str, base ? BaseName(av1[j]) : av1[j] ) ) X break; X if( j==ac1 ) X av[k++]=av2[i]; X } X X *ac=k; X return av; X} X Xvoid Xclear_archive_bit( char *name ) X{ X struct DPTR *dp; X int stat; X X if(dp = dopen(name,&stat) ) { X SetProtection( name, dp->fib->fib_Protection&~FIBF_ARCHIVE); X dclose( dp ); X } X} X Xchar * Xitoa( int i ) X{ X static char buf[20]; X char *pos=buf+19; X int count=4, flag=0; X X if( i<0 ) X flag=1, i=-i; X X do { X if( !--count ) X count=3, *--pos='\''; X *--pos= i%10+'0'; X } while( i/=10 ); X X if( flag ) X *--pos='-'; X X return pos; X} X Xchar * Xitok( int i ) X{ X static char buf[16], which; X char *exp=" KMG", *ptr= buf+(which=8-which); X X do X i=(i+512)/1024, exp++; X while( i>1024 ); X sprintf( ptr,"%d%c",i,*exp); X X return ptr; X} X Xchar * Xnext_a0( char *str ) X{ X while( *str && *str!=0xA0 && *str!='=' && *str!=',') str++; X return *str ? str+1 : NULL; X} X Xstatic int Xgethex( char *str, int l ) X{ X int i, val=0, n, c; X X if( *str=='.' ) return l==2 ? 256 : 0; X X for( i=0; i<l || !l; i++ ) { X c=*str++; X if ( c>='0' && c<='9' ) n=c-'0'; X else if( c>='a' && c<='f' ) n=c-'a'+10; X else if( c>='A' && c<='F' ) n=c-'A'+10; X else break;; X val=16*val+n; X } X return (l && i!=l) ? -1 : val; X} X Xstrwrdcmp( char *str, char *wrd ) X{ X int len1=strlen(str); X char *ind=index(wrd,0xA0); X if( ind ) X return len1!=ind-wrd || Strncmp(str,wrd,len1); X else X return Strcmp(str,wrd); X X} X Xint Xwrdlen( char *str ) X{ X char *old=str; X X while( *str && *str!=0xA0 ) str++; X return str-old; X} X Xchar *classfile; X Xchar * Xgetclass(char *file) X{ X CLASS *cl; X char *class, *str, *arg, *get, *buf; X int offs, byte, len, fail; X BPTR fh; X X if( classfile ) { X char buf[80]; X sprintf(buf,"source %s",classfile); X execute(buf); X classfile=0; X } X X if( isdir(file) ) return "dir"; X X if( !(buf=calloc(1024,1))) return NULL; X if( !(fh=Open(file,MODE_OLDFILE))) return NULL; X len=Read( fh,buf,1023); X Close(fh); X X for( cl=CRoot; cl; cl=cl->next ) { X class=cl->name; X if(!(str=next_a0(cl->name))) continue; X while( str ) { X if(!(arg=next_a0( str ))) goto nextclass; X switch( *str ) { X case 's': X if( (offs=strlen(file)-wrdlen(arg))<0 ) break; X if( !strwrdcmp(file+offs,arg)) goto found; X break; X case 'n': X if( !strwrdcmp(BaseName(file),arg) ) goto found; X break; X case 'd': X goto found; X case 'o': X offs=gethex(arg,0); X if( !(arg=index(arg,','))) goto nextclass; X if( offs>len-10 ) break; X for( get=buf+offs, ++arg; (byte=gethex(arg,2))>=0; arg+=2 ) X if( *get++!=byte && byte!=256 ) X goto nexttry; X goto found; X case 'c': X if( !len ) X goto nexttry; X for( get=buf, fail=0; get<buf+len; get++ ) X if( *get<9 || *get>13 && *get<32 || *get>127 ) X fail++; X if( fail*8>len ) X goto nexttry; X goto found; X case 'a': X goto nextclass; X default: X goto nextclass; X } Xnexttry: str=next_a0(arg); X } Xnextclass: ; X } X X free(buf); X return NULL; X Xfound: X free(buf); X return class; X} X Xchar * Xgetaction( char *class, char *action ) X{ X CLASS *cl; X char *cur, *ind; X int len; X X for( len=0; class[len] && class[len]!=0xA0; len++ ) ; X for( cl=CRoot; cl; cl=cl->next ) { X if( strncmp( cur=cl->name,class,len+1 )) X continue; X do X cur=index( cur,0xA0 ); X while( cur && *++cur!='a'); X X if( cur && (cur=index( ++cur,0xA0 ))) { X do { X if( !(ind=index( ++cur,'=' ))) X return NULL; X len=ind-cur; X if( len==strlen(action) && !strncmp(action,cur,len)) X return ++ind; X } while( cur=index(cur,0xA0) ); X } X } X return NULL; X} X Xint Xdoaction( char *file, char *action, char *args ) X{ X char *class, *com, *c, *copy; X X if( !(class=getclass(file))) X return 10; X if( !(com=getaction(class,action))) X return 11; X if( c=index(com,0xA0) ) X *c=0; X copy=malloc( strlen(com)+strlen(file)+strlen(args)+5 ); X sprintf(copy,"%s %s %s",com,file,args); X execute(copy); X free(copy); X if( c ) X *c=0xA0; X return 0; X} END_OF_FILE if test 21051 -ne `wc -c <'sub.c'`; then echo shar: \"'sub.c'\" unpacked with wrong size! fi # end of 'sub.c' fi echo shar: End of archive 2 \(of 6\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 4 5 6 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 6 archives. 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.