amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (04/17/91)
Submitted-by: umueller@iiic.ethz.ch Posting-number: Volume 91, Issue 091 Archive-name: shells/cshell-5.10/part04 #!/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 4 (of 6)." # Contents: comm3.c csh.doc.aa # Wrapped by tadguy@ab20 on Tue Apr 16 15:34:35 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'comm3.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'comm3.c'\" else echo shar: Extracting \"'comm3.c'\" \(28599 characters\) sed "s/^X//" >'comm3.c' <<'END_OF_FILE' X/* X * COMM3.C 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 X/* comm3.c */ Xstatic void doassign(char *log, char *phy); Xstatic void assignlist(void); Xstatic int strings_in_file(char *s); Xstatic int htype_a_file(char *s); Xstatic void install_menu(char **mav, int mac); Xstatic int line_filter( char *(*line)(char *) ); X Xstatic int Xmyfgets( char *buf, FILE *in ) X{ X int l; X char *ret; X if( ret=fgets(buf,253,in) ) { X l=strlen(buf); X if( buf[l-1]!='\n' ) X buf[l]='\n', buf[l+1]=0; X } X return ret!=NULL && !dobreak(); X} X Xdo_tee( void ) X{ X char buf[256]; X FILE *out; X X prepscroll( ac==1 ); X if( ac>2 ) { ierror( av[2], 500 ); return 20; } X if( ac==1 ) out=stderr; X else if( !(out=fopen( av[1], "w" ))) { pError( av[1] ); return 20; } X while (myfgets(buf,stdin)) { X fputs(buf, stdout); X quickscroll(); X fprintf(out, "%s", buf); X } X if( ac!=1 ) fclose( out ); X return 0; X} X Xdo_head( char *garbage, int com ) X{ X int i, n; X FILE *f; X char buf[256]; X X if (ac>2) { X n=(int)(long)Atol(av[2]); X if (IoErr()) { X ierror(av[2],511); X return 20; X } X } else n=10; X X f=fopen(av[1], "r"); X if (f==NULL) { X pError(av[1]); X return 20; X } X if (com) { /* tail specific part */ X i=0; X while (fgets(buf, 256, f) && ! dobreak()) i++; X rewind(f); X if (n>i) n=i; X i=i-n; X while (i-- && fgets(buf, 256, f) && ! dobreak()) ; X } X for (i=1; i<=n && fgets(buf, 256, f) && ! dobreak(); i++) X printf("%s", buf); X fclose(f); X return 0; X} X Xstatic int Xexword( char **src, char *buf ) X{ X *buf=0; X if( **src==0 ) return 0; X while( **src && **src!=0xA0 ) X *buf++=*(*src)++; X *buf=0; X if( **src ) (*src)++; X return 1; X} X Xstatic char helpfound=0; X Xvoid Xman( FILE *f, char *s) X{ X char buf[140], entry[100]; X int len=sprintf(entry, " %s", s); X X prepscroll(0); X rewind(f); X do /* look for required argument */ X if (fgets(buf, 140, f) == NULL) X return; X while ( Strncmp(entry, buf, len) ); X helpfound=1; X do { /* display help */ X quickscroll(); X printf("%s", buf); X if (fgets(buf, 140, f) == NULL) return; X } while ( ( !isalphanum(*buf) ) && strncmp(buf, " ", 4) && !dobreak() ); X} X X Xdo_man( void ) X{ X FILE *f; X int i; X char buf[200], name[60], *src, *var, docfound=0; X X buf[0]=0; X if( var=get_var(LEVEL_SET,"_man" ) ) X strcpy(buf,var); X X if (ac==1) ac=2, av[1]="MAN"; X for (i=1; i<ac; i++) { X src=buf, helpfound=0; X while( exword( &src, name) ) X if( f=fopen(name, "r") ) { X docfound=1; X man(f, av[i]); X fclose(f); X if( helpfound ) X break; X } X if( !docfound ) X fprintf(stderr,"%s not found\n",buf); X else if( !helpfound ) X fprintf(stderr, "Help not found for %s\n", av[i]); X } X return 0; X} X Xdo_assign( void ) X{ X int i; X X if ( ac==1 ) assignlist(); X else if( ac==2 ) doassign(av[1], NULL); X else if( !(ac&1) ) ierror(NULL, 500); X else X for( i=1; i<ac; i+=2 ) X doassign( av[i],av[i+1] ); X return 0; X} X Xstatic char *assign_errors[4]={ X "", X "Name %s is not valid\n", X "Weird error\n", X "Can't cancel %s:\n" X }; X X Xstatic void Xdoassign(char *log, char *phy) X{ X int last=strlen(log) - 1; X X if (log[last] != ':') fprintf(stderr, "Bad name %s\n", log); X else { X log[last] = 0; X if( options && phy && o_kick20 ) { X BPTR lock; X int succ=0; X if ( options&1 ) succ=AssignLate( (UBYTE*)log,(UBYTE*)phy ); X else if( options&2 ) succ=AssignPath( (UBYTE*)log,(UBYTE*)phy ); X else if( options&4 ) X if( lock=Lock(phy,ACCESS_READ) ) X if( !(succ=AssignAdd(log,lock))) X UnLock(lock); X if( !succ ) X pError( log ); X } else if( !(options&4) ) { X int err=Assign(log, phy); X fprintf(stderr,assign_errors[err],err==1?phy:log); X } X } X} X Xextern struct RootNode2x *RootNode; X#define ENTRIES 128 X Xstatic void Xassignlist() X{ X char *ptr, *log, **arr; X int ctr, i; X X if(!(arr=expand_devs())) X return; X X printf("Devices:\n"); X for (i=ctr=0; arr[i] && *arr[i]==1; i++) { X printf("%-8s",arr[i]+1); X if (ctr++ == 5) { ctr=0; printf("\n"); } X } X X printf("\n\nVolumes:\n"); X for( ; arr[i] && *arr[i]==2; i++ ) X printf( "%-16s [Mounted]\n",arr[i]+1); X X printf("\nDirectories:\n"); X for( ; arr[i] && !dobreak(); i++ ) { X log=arr[i]+1; ptr=log+strlen(log)+1; X switch( *(log-1)) { X case 3: X printf("%-20s%s\n", log, ptr); X for(;;) { X ptr+=strlen(ptr)+1; X if( !*ptr ) break; X printf("%-19s+%s\n", "", ptr); X } X break; X case 4: printf("%-20s<%s>\n", log, ptr); break; X case 5: printf("%-20s[%s]\n", log, ptr); break; X } X } X X free_expand( arr ); X} X Xchar ** Xexpand_devs(void) X{ X static char Type[]={1,3,2,4,5}; X struct DosInfo *info=(void*)((long)RootNode->rn_Info*4); X struct DosList2x *list=(void*)((long) info->di_DevInfo*4); X struct AssignList2x *path; X char buf[256], **arr, *ptr; X int n; X X if( !(arr=malloc(ENTRIES*sizeof(char *)))) X return NULL; X X Forbid(); X for( n=0; list && n<ENTRIES; list=(void*)((long)list->dol_Next*4)) { X if( list->dol_Type<0 || list->dol_Type>DLST_NONBINDING ) X continue; X ptr=buf; X *ptr++=Type[list->dol_Type]; X ptr+=BtoCStr(ptr,list->dol_Name,200); X *ptr++=':'; *ptr++=0; X switch( list->dol_Type) { X case DLST_DIRECTORY : X if(list->dol_Lock) X PathName(list->dol_Lock, ptr, 200); X else X strcpy(ptr,"Nonexisting lock"); X ptr+=strlen(ptr)+1; X path=(void*)list->dol_misc.dol_assign.dol_List; X for( ; path; path=(void*)path->al_Next ) { X if(list->dol_Lock) X PathName(path->al_Lock, ptr, 200); X else X strcpy(ptr,"Nonexisting lock"); X ptr+=strlen(ptr)+1; X } X *ptr++=0; X break; X case DLST_LATE : X case DLST_NONBINDING: X ptr+= sprintf(ptr,"%s",list->dol_misc.dol_assign.dol_AssignName); X *ptr++=0; X break; X } X arr[n]=salloc(ptr+1-buf); X memcpy(arr[n++],buf,ptr+1-buf); X } X arr[n]=NULL; X Permit(); X X QuickSort( arr, n ); X X return arr; X} X X Xdo_join( void ) X{ X BPTR sou, dest; X char *buffer; X int i; X long n; X char *namedest=av[--ac]; X X if (options==0 && exists(namedest)) { ierror(namedest,203); return 20; } X if ( (buffer=malloc(8192)) == NULL ) { ierror(NULL,103); return 20; } X if ( (dest=Open(namedest, MODE_NEWFILE)) == NULL ) X { pError(namedest); goto fail1; } X for (i=1; i<ac; i++) { X if ( (sou=Open(av[i], MODE_OLDFILE)) == NULL ) pError(av[i]); X else X while( (n=Read(sou, buffer, 8192L)) > 0 ) X if (Write(dest, buffer, n) != n) X { pError(namedest); Close(sou); goto fail2; } X Close(sou); X } Xfail2: X Close(dest); Xfail1: X free(buffer); X return 0; X} X X#define BUFDIM 512L X#define MAXSTR 256 X Xint minstr; X Xstatic int Xstrings_in_file(char *s) X{ X char c; X char readbuf[BUFDIM+1], strbuf[MAXSTR+1]; X int i, strctr=0; X BPTR fh; X int out, n; X X prepscroll(0); X if ( fh=Open(s, MODE_OLDFILE) ) { X fprintf(stderr, "Strings in %s (len>=%d):\n",s,minstr); X while ( (n=(int)Read(fh, readbuf, BUFDIM)) > 0 && !CHECKBREAK() ) X for (i=0; i<n; i++) { X c=readbuf[i]; X if (c<0x20 || c>0x7f) { X out=(strctr>=minstr); X if (!out) strctr=0; X } else { X strbuf[strctr++]=c; X out=(strctr>=BUFDIM); X } X if (out) { X strbuf[strctr]='\0'; X puts(strbuf); X quickscroll(); X strctr=0; X } X } X Close(fh); X } else X pError(s); X return 0; X} X Xdo_strings( void ) X{ X minstr=myatoi(av[--ac],1,255); X all_args( strings_in_file, 0); X return 0; X} X XBPTR myfile[MAXMYFILES]; X Xdo_open( void ) X{ X long mode; X int n; X X switch (toupper(av[2][0])) { X case 'R': mode=MODE_OLDFILE; break; X case 'W': mode=MODE_NEWFILE; break; X default : ierror(NULL,500); return 1; X } X n=myatoi(av[3],0,MAXMYFILES-1); if (atoierr) return 20; X if (myfile[n]) myclose(n); X myfile[n]=Open(av[1],mode); X return myfile[n]==NULL; X} X Xdo_close( void ) X{ X int i, n; X X if (ac==1) X for (i=1; i<MAXMYFILES; i++) X myclose(i); X for (i=1; i<ac; i++) { X n=myatoi(av[i],0,MAXMYFILES-1); if (atoierr) return 20; X myclose(n); X } X return 0; X} X Xvoid Xmyclose(int n) X{ X if (myfile[n]) { Close(myfile[n]); myfile[n]=NULL; } X} X Xdo_fileslist( void ) X{ X int i, flag=0; X X printf("Open files:"); X for (i=0; i<MAXMYFILES; i++) X if (myfile[i]) { printf(" %d",i); flag=1; } X if (!flag) printf(" None!"); X printf("\n"); X return 0; X} X XBPTR XextOpen( char *name, long mode ) X{ X if (name[0]=='.') return myfile[atoi(name+1)]; X return Open(name,mode); X} X X Xvoid XextClose(BPTR fh) X{ X int i; X X for (i=0; i<MAXMYFILES; i++) X if (myfile[i]==fh) return; X Close(fh); X} X Xdo_basename( void ) X{ X set_var(LEVEL_SET, av[1], BaseName(av[2])); X return 0; X} X Xdo_tackon( void ) X{ X char buf[256]; X X strcpy(buf, av[2]); X TackOn(buf, av[3]); X set_var(LEVEL_SET, av[1], buf); X return 0; X} X Xextern char shellres[]; X Xdo_resident( void ) X{ X int i=1; X struct ResidentProgramNode *p; X char buf[256]; X X if (options==0 && ac>1) options=1; X switch (options) { X case 0: X ObtainSemaphore (& (ArpBase->ResPrgProtection) ); X if (p=ArpBase->ResidentPrgList) { X printf("Name Users Access\n"); X for (; p; p=p->rpn_Next) X printf("%-17s%5d%6d\n", X p->rpn_Name, p->rpn_Usage, p->rpn_AccessCnt); X } else X printf("No resident program(s)\n"); X ReleaseSemaphore(& (ArpBase->ResPrgProtection) ); X break; X case 1: X for (; i<ac; i++) X if (loadres(av[i])) X printf("OK! %s is now resident\n", BaseName(av[i])); X else X pError(av[i]); X break; X case 2: X for (; i<ac; i++) X if (RemResidentPrg(av[i])) ierror(av[i],202); X else printf("Removed %s\n",av[i]); X break; X case 4: X for (; i<ac; i++) { X if( !o_resident ) { X Setenv(shellres,"1"); X o_resident=1; X } X sprintf(buf,"res_%s",av[i]); X Setenv(buf,"1"); X } X break; X default: X ierror(NULL,500); X break; X } X return 0; X} X Xint Xloadres(char *s) X{ X BPTR seg; X X if (seg=(BPTR)LoadPrg(s)) AddResidentPrg(seg,BaseName(s)); X return (seg != NULL); X} X Xstatic struct ProcessControlBlock pcb={ X 4000, /* pcb_StackSize */ X 0, /* pcb_Pri */ X }; X/* remaining fields are NULL */ X Xdo_truerun(char *avline, int backflag) X{ X char name[100], *args, buf[10]; X int cli; X X if (backflag) { X pcb.pcb_Control=NULL; X pcb.pcb_Input=pcb.pcb_Output=Open("NIL:",MODE_OLDFILE); X } else { X pcb.pcb_Control=NULL; X pcb.pcb_Input=pcb.pcb_Output =NULL; X } X args=next_word(next_word(avline)); X X if((cli=ASyncRun(av[1],args,&pcb))<0) X if (dofind(av[1], "", name,v_path)) X cli=ASyncRun(name,args,&pcb); X X sprintf(buf,"%d",cli); X set_var(LEVEL_SET,"_newproc",buf); X X if( cli<0 ) { X ierror(av[1],205); X return 20; X } X return 0; X} X Xint Xexists( char *name ) X{ X BPTR lock; X X if (lock=Lock(name,ACCESS_READ)) { X UnLock(lock); X return 1; X } X return 0; X} X Xdo_aset( void ) X{ X Setenv(av[1],av[2]); X return 0; X} X X#define HTYPELINE 16L X Xstatic int Xhtype_a_file( char *s ) X{ X BPTR fh; X long n, filesize=0; X char buf[HTYPELINE+1]; X char out[80], *put; X int i; X X if ( (fh=Open(s,MODE_OLDFILE))==NULL ) { pError(s); return 20; } X prepscroll(0); X while ( (n=Read(fh,buf,HTYPELINE))>0 && !dobreak()) { X put=out; X put+=sprintf(put,"%06lx: ",filesize); X filesize+=n; X for (i=0; i<n; i++) { X put+=sprintf( put,(i&3) ? "%02x" : " %02x",buf[i]); X if ((buf[i]&127)<0x20) buf[i]='.'; X } X for ( ; i<HTYPELINE; i++) { X put+=sprintf( put, (i&3) ? " " : " "); X buf[i]=' '; X } X buf[i]=0; X sprintf(put," %s",buf); X puts(out); X quickscroll(); X } X Close(fh); X return 0; X} X Xdo_htype( void ) X{ X all_args( htype_a_file, 0); X return 0; X} X Xdo_stack( void ) X{ X long n; X X if (ac>1) { X n=Atol(av[1]); X if (!IoErr()) Mycli->cli_DefaultStack=(long)(n >> 2L); X } X else printf("current stack size is %ld bytes\n", X (long)Mycli->cli_DefaultStack << 2L); X return 0; X} X Xdo_fault( void ) X{ X struct PERROR *p; X int i, n; X X for (i=1; i<ac; i++) { X n=myatoi(av[i],0,32767); X if (!atoierr) { X for (p=Perror; p->errnum && p->errnum!=n; p++); X if (p->errnum) X printf("Fault %d: %s\n",n,p->errstr); X else X printf("Fault %d not recognized\n",n); X } X } X return 0; X} X Xstruct rpncommand { X char *str; X int parsin, parsout; X }; X Xstatic struct rpncommand rpn[]={ X "+", 2, 1, X "-", 2, 1, X "*", 2, 1, X "/", 2, 1, X "%", 2, 1, X "&", 2, 1, X "|", 2, 1, X "~", 1, 1, X ">", 2, 1, X "<", 2, 1, X "==", 2, 1, X "!", 1, 1, X "MAX", 2, 1, X "MIN", 2, 1, X "DUP", 1, 2, X "DROP", 1, 0, X "SWAP", 2, 2, X "HELP", 0, 0, X NULL, 0, 1, /* this looks for a number */ X}; X Xstatic long stack[50]; Xstatic int sp; X X Xeval_rpn( char **av, int ac, int flag ) X{ X char *zero="Division by zero\n"; X struct rpncommand *temp; X long n0, n1, t; X int j, i=0, oldsp=sp; X X for (; i<ac; i++) { X for (j=0; rpn[j].str && Strcmp(rpn[j].str,av[i]); j++) ; X n0=stack[sp-1]; X n1=stack[sp-2]; X sp -= (rpn[j].parsin); X if (sp<0) { fprintf(stderr, "RPN: Empty stack\n"); goto error; } X switch (j) { X case 0: n0 += n1; break; X case 1: n0 = n1-n0; break; X case 2: n0 *= n1; break; X case 3: if(n0) n0=n1/n0; else fprintf(stderr,zero); break; X case 4: if(n0) n0=n1%n0; else fprintf(stderr,zero); break; X case 5: n0 &= n1; break; X case 6: n0 |= n1; break; X case 7: n0 = ~n0 ; break; X case 8: n0 = (n1 > n0); break; X case 9: n0 = (n1 < n0); break; X case 10: n0 = (n0 == n1); break; X case 11: n0 = !n0; break; X case 12: n0=n1>n0 ? n1 : n0; break; X case 13: n0=n1<n0 ? n1 : n0; break; X case 14: n1=n0; break; X case 15: t=n0; n0=n1; n1=t; break; X case 16: break; X case 17: printf("In Commands Out\n"); X for (temp=rpn; temp->str; temp++) X printf(" %d %-10s%d\n", X temp->parsin,temp->str,temp->parsout); X break; X default: n0=Atol(av[i]); X if (IoErr()) { X fprintf(stderr, "Bad RPN cmd: %s\n",av[i]); X goto error; X } X break; X } X stack[sp]=n0; X stack[sp+1]=n1; X sp += rpn[j].parsout; X } X if( flag && sp-1) X fprintf( X stderr, X "RPN: Stack not empty\n" X ); X Xexit: X t=sp; sp=oldsp; X if( flag ) X return stack[t-1]; /* return top value */ X else X return t-sp; X Xerror: X sp=oldsp; X return 0; X} X X Xdo_rpn(char *garbage,int ifflag) /* ifflag!=0 if called from if */ X{ X int i=1; X long t; X X t=eval_rpn( av+i, ac-i, ifflag ); X if (ifflag) return t; /* called from if: return top value */ X for (i=sp+t-1;i>=sp;i--) printf("%ld\n", stack[i]);/* else print stack */ X X return t ? 0 : 20; X} X Xdo_path( void ) X{ X ULONG ll, ll1, *lp, new, *newp; X char buf[256]; X char buf2[256]; X BPTR lock; X int i; X X if( options&1 ) { X Forbid(); X for( ll= Mycli->cli_CommandDir; ll; ll= ll1 ) { X lp=(ULONG *)(4*ll); X ll1=*lp; X DosFreeMem( lp ); X } X Mycli->cli_CommandDir=0; X Permit(); X } else if( ac==1 ) { /* Should Forbid() here, but puts() Permit()s */ X puts("Current dir"); /* and failure here is not really harmful... */ X for( ll= Mycli->cli_CommandDir; ll; ll= *lp ) { X lp=(ULONG *)(4*ll); X PathName(lp[1], buf, 256L); X puts(buf); X } X puts("C:"); X return 0; X } X Forbid(); X for( i=1; i<ac; i++ ) { X if( !(lock=Lock(av[i],ACCESS_READ)) ) { X pError(av[i]); X continue; X } X PathName(lock, buf, 256L); X for( ll= Mycli->cli_CommandDir, lp=NULL; ll; ll= *lp ) { X lp=(ULONG *)(4*ll); X PathName(lp[1],buf2,256L); X if( !Strcmp(buf,buf2) ) { X UnLock(lock); X break; X } X } X if( !ll && (newp=DosAllocMem( 8 ))) { X newp[1]=lock; X new =(ULONG)newp/4; X if( lp ) X *lp=new; X else X Mycli->cli_CommandDir=new; X } X } X Permit(); X return 0; X} X Xdo_pri( void ) X{ X int t, pri; X struct Process *proc; X X t=(int)(long)FindCLI(0L); X t=myatoi(av[1],0,t); if (atoierr) return 20; X pri=myatoi(av[2],-128,127); if (atoierr) return 20; X Forbid(); X proc=(t==0 ? Myprocess : FindCLI((long)t)); X if (proc==NULL) fprintf(stderr, "process not found\n"); X else SetTaskPri((struct Task *)proc, (long)pri); X Permit(); X return 0; X} X Xdo_strleft( void ) X{ X int n; X X n=posatoi(av[3]); if (atoierr) return 20; X set_var_n(LEVEL_SET, av[1], av[2], n); X return 0; X} X Xdo_strright( void ) X{ X int n, len=strlen(av[2]); X X n=posatoi(av[3]); if (atoierr) return 20; X if( n>len ) n=len; X set_var(LEVEL_SET, av[1], av[2]+len-n ); X return 0; X} X Xdo_strmid( void ) X{ X int n1, n2=999999, len=strlen(av[2]); X X n1=myatoi(av[3],1,999999)-1; if (atoierr) return 20; X if (n1>len) n1=len; X if (ac>4) { X n2=posatoi(av[4]); if (atoierr) return 20; X } X set_var_n(LEVEL_SET, av[1], av[2]+n1, n2); X return 0; X} X Xdo_strlen( void ) X{ X char buf[16]; X X sprintf(buf,"%d",strlen(av[2])); X set_var(LEVEL_SET, av[1], buf); X return 0; X} X Xint atoierr; X Xmyatoi(char *s,int mmin,int mmax) X{ X int n; X X n=Atol(s); X if (atoierr=IoErr()) X ierror(s,511); X else if (n<mmin || n>mmax) { X atoierr=1; n=mmin; X fprintf( stderr, "%s(%d) not in (%d,%d)\n",s,n,mmin,mmax ); X } X return n; X} X Xunlatoi(char *s) X{ X int n=Atol(s); X if (atoierr=IoErr()) X ierror(s,511), n=0; X return n; X} X Xposatoi(char *s) X{ X int n=Atol(s); X if (atoierr=IoErr()) X ierror(s,511); X else if (n<0 ) X atoierr=1, n=0, fprintf( stderr, "%s must be positive\n",s ); X return n; X} X X Xdo_fltlower( void ) X{ X return line_filter( strlwr ); X} X Xdo_fltupper( void ) X{ X return line_filter( strupr ); X} X X#if 0 Xchar * Xstripcr( char *get ) X{ X char *old=get, *put; X X for( put=get; *get; get++ ) X if( *get!=13 ) X *put++=*get; X *put++=0; X return old; X} X Xdo_fltstripcr( void ) X{ X return line_filter( stripcr ); X} X#endif X Xint Xline_filter( char *(*func)( char * ) ) X{ X char buf[256]; X X while (!CHECKBREAK() && gets(buf)) X puts((*func)(buf)); X return 0; X} X Xdo_linecnt( void ) X{ X int count=0; X char buf[256]; X X while (!CHECKBREAK() && gets(buf)) ++count; X printf("%d lines\n",count); X return 0; X} X Xdo_uniq( void ) X{ X int firstline=1; X char buf[256], oldbuf[256]; X X while (!CHECKBREAK() && gets(buf)) { X if ( firstline || strcmp(buf, oldbuf)) { X strcpy(oldbuf, buf); X puts(buf); X } X firstline=0; X } X return 0; X} X X X#define RXFB_RESULT 17 X Xstatic struct rexxmsg { X struct Message cm_Node; X LONG RFU1; X LONG RFU2; X LONG rm_Action; X LONG rm_Result1; X LONG rm_Result2; X char *cm_Args[16]; X LONG RFU7; X LONG RFU8; X LONG RFU9; X LONG RFU10; X LONG RFU11; X LONG RFU12; X} mymsg; X Xdo_rxsend( char *avline ) X{ X int i; X long result; X struct MsgPort *port, *reply; X long len; X char buf[20], *resptr; X X if (!(port = FindPort(av[1]))) X { fprintf(stderr, "No port %s!\n", av[1]); return 20; } X mymsg.cm_Node.mn_Node.ln_Type = NT_MESSAGE; X mymsg.cm_Node.mn_Length = sizeof(struct rexxmsg); X mymsg.rm_Action = (options&1 ? 1L << RXFB_RESULT : 0); X if (!(reply = CreatePort(NULL, 0L))) { X fprintf(stderr, "No reply port\n"); X return 20; X } X mymsg.cm_Node.mn_ReplyPort = reply; X X if( options&2 ) X av[2]=compile_av( av,2,ac,' ',0), ac=3; X for ( i=2; i<ac; i++) { X mymsg.cm_Args[0] = av[i]; X mymsg.rm_Result2 = 0; /* clear out the last result. */ X PutMsg(port, &mymsg.cm_Node); X WaitPort(reply); X X if (options&1) { X if( (result=mymsg.rm_Result2)<1000000 ) { /* so does it AREXX */ X sprintf(buf,"%d",result); X set_var(LEVEL_SET,v_result,buf); X } else { X resptr=(char *)(result-4); X len=*(long *)resptr; X memmove(resptr,resptr+4,len); /* Null terminate */ X resptr[len]=0; X set_var(LEVEL_SET,v_result,resptr); X FreeMem(resptr, len+4 ); X } X } else X unset_var( LEVEL_SET, v_result ); X } X if( options&2 ) X free( av[2] ); X X if (reply) DeletePort(reply); X return 0; X} X Xstatic char *rxreturn; X Xdo_rxrec( void ) X{ X struct MsgPort *port; X struct rexxmsg *msg; X char *portname, *str; X X if (ac > 1) X portname=av[1]; X else X portname="rexx_csh"; X X port=CreatePort(portname, 0L); X if (port==NULL) { X fprintf(stderr, "Can't have MsgPort %s\n", portname); X return 20; X } X for (;;) { X WaitPort(port); X while (msg=(struct rexxmsg *)GetMsg(port)) { X if ( ! Strcmp(msg->cm_Args[0], "bye")) { X ReplyMsg((struct Message *)msg); X DeletePort(port); X return 0; X } X rxreturn=NULL; X exec_command(msg->cm_Args[0]); X if (msg->rm_Action & (1L << RXFB_RESULT)) { X if( rxreturn ) { X str= SAllocMem( strlen( rxreturn )+5 , 0 ); X *(long *)str=strlen( rxreturn ); X strcpy( str+4, rxreturn ); X msg->rm_Result2=(long)str; X } else { X str = get_var(LEVEL_SET, v_lasterr); X msg->rm_Result2=(str) ? atoi(str) : 20; X } X } X ReplyMsg((struct Message *)msg); X } X } X} X Xint Xdo_waitport( void ) X{ X int count=4*10; X struct MsgPort *port=NULL; X X if( ac==3 ) X { count=2*myatoi(av[2],0, 32000); if( atoierr ) return 20; } X X while( --count>=0 && !(port=FindPort(av[1])) && !dobreak() ) X Delay(12); X X return port ? 0 : 20; X} X Xint Xdo_rxreturn( void ) X{ X rxreturn=compile_av( av, 1, ac, ' ', 1 ); X return 0; X} X Xdo_ascii( void ) X{ X int x=1, y, c, c1, t; X char *fmt1=" %3d %c%c |", *fmt2=" %4d"; X X if( options&1 ) fmt1=" %3o %c%c |", fmt2="%4o"; X if( options&2 ) fmt1=" %3x %c%c |", fmt2="%4x"; X if( ac==x ) X for( y=0; y<32 && !dobreak(); y++ ) { X printf("|"); X for( x=0; x<8; x++ ) { X c1=c=y+32*x; t=' '; X if( c<32 ) t='^', c1+=64; X printf(fmt1,c, t, c1<128 || c1>=160?c1:'.'); X } X printf("\n"); X } X else X for( ; x<ac && !dobreak(); x++ ) { X for( y=0; y<strlen(av[x]); y++ ) X printf(fmt2,av[x][y]); X printf("\n"); X } X return 0; X} X Xvoid Xappendslash( char *path ) X{ X int c; X X if( (c=path[strlen(path)-1]) !='/' && c!=':' ) X strcat(path,"/"); X} X Xstatic void Xwhereis( char *path, char *file ) X{ X char **eav, buf[100]; X int eac, j; X X buf[0]=0; X if( path ) { X strcpy(buf,path); X appendslash(buf); X } X strcat(buf,".../"); X strcat(buf,file); X if( !index( file, '*' ) && !index( file, '?') ) X strcat(buf,"*"); X if(eav=expand(buf,&eac)) { X for( j=0; j<eac && !dobreak(); j++ ) X printf("%s\n",eav[j]); X free_expand(eav); X } X} X Xdo_whereis( void ) X{ X char buf[200], *prev, *devs; X int i; X X if( index( av[1],':') || index( av[1],'/' ) ) X { fprintf(stderr,"No paths please\n"); return 20; }; X X if( options&1 ) { X Myprocess->pr_WindowPtr = (APTR)(-1); X get_drives( devs=buf ); X do { X prev=devs; devs=index(devs,0xA0); X if( devs ) *devs++=0; X whereis( prev, av[1] ); X } while( devs ); X Myprocess->pr_WindowPtr = (APTR) o_noreq; X } else if( ac==2 ) { X whereis( NULL, av[1] ); X } else { X for( i=2; i<ac; i++ ) { X strcpy(buf,av[i]); X appendslash( buf ); X whereis( buf, av[1] ); X } X } X return 0; X} X Xdo_usage( void ) X{ X int i; X X if( ac==1 ) { X printf("Usage: usage [command...command]\n"); X printf("[ ]=option [ | ]=choice { }=repetition name...name=1 or more names\n"); X } else X for( i=1; i<ac; i++ ) X show_usage( av[i] ); X return 0; X} X Xint NumMenus; X Xdo_menu( void ) X{ X if( o_nowindow ) X return 5; X X if( options&1 ) X remove_menu(); X X if( ac==2 ) X show_usage( NULL ); X else if( NumMenus<MAXMENUS && ac!=1) X install_menu( av+1, ac-1 ); X X set_menu(); X return 0; X} X X#define NUMITE 40 X#define TITWID 90 X#define ITEWID 148 X Xstatic struct Menu DefaultMenu= {0, 0,0,TITWID,10, MENUENABLED,0,0}; Xstatic struct IntuiText DefaultIntuiText= {0,1,JAM2, 1,1,NULL,0,0}; Xstatic struct MenuItem DefaultMenuItem= X {0, 0,0,ITEWID,0, HIGHCOMP|ITEMTEXT|ITEMENABLED,0,0,0,0,0,0}; X Xstruct Menu Menus[10]; Xchar *MenuCommand[MAXMENUS][MAXITEMS]; X Xextern char *rindex(); X Xstatic void Xinstall_menu( char *mav[], int mac ) X{ X struct TextAttr *ta; X struct Menu *m; X struct MenuItem *mi, **pmi; X struct IntuiText *it; X int y, i, fonthei; X char *p, *com; X X if( o_nowindow || !Win ) X return; X X if( mac>=MAXITEMS ) X mac=MAXITEMS-1; X X ClearMenuStrip( Win ); X Delay(3); X X if( NumMenus ) X Menus[NumMenus-1].NextMenu=Menus+NumMenus; X m =&Menus[NumMenus]; X *m =DefaultMenu; X m->LeftEdge = NumMenus*TITWID; X m->MenuName = strcpy(salloc(strlen(mav[0])+1),mav[0]); X if( strlen(m->MenuName)>TITWID/8 ) X m->MenuName[TITWID/8+1]=0; X DefaultIntuiText.ITextFont=ta=Win->WScreen->Font; X DefaultMenuItem.Height=2+(fonthei=ta->ta_YSize); X X y=0; X pmi=&m->FirstItem; X for( i=1; i<mac; i++) { X it =(void *)salloc(sizeof(struct IntuiText)); X *it=DefaultIntuiText; X mi =(void *)salloc(sizeof(struct MenuItem )); X *mi=DefaultMenuItem; X X com=NULL; X if( p=index(mav[i],',')) { X *p=0; com=++p; X if( p=index(com,',')) { X *p=0; X mi->Command=p[1]; X mi->Flags |=COMMSEQ; X } X } X X if( !com || !*com) { X com=strcpy(salloc(strlen(mav[i])+2),mav[i]); X MenuCommand[NumMenus][i-1]=com; X com+=strlen(com); X *com++=13; X *com=0; X } else { X MenuCommand[NumMenus][i-1]=strcpy(salloc(strlen(com)+1),com); X } X X it->IText=(UBYTE *)strcpy(salloc(strlen(mav[i])+2),mav[i]); X X *pmi= mi; X pmi = &mi->NextItem; X mi->TopEdge = y; X mi->ItemFill= (APTR)it; X X y+=DefaultMenuItem.Height; X } X X NumMenus++; XMError: X return; X} X X Xvoid Xremove_menu() X{ X if( NumMenus>0 ) { X struct MenuItem *mi, *nextmi; X int i,j; X X for( i=0; i<NumMenus; i++ ) { X for( mi=Menus[i].FirstItem,j=0 ; mi; mi=nextmi,j++ ) { X free( ((struct IntuiText *)mi->ItemFill)->IText ); X free( ((struct IntuiText *)mi->ItemFill) ); X nextmi=mi->NextItem; X free(mi); X free(MenuCommand[i][j]); X } X } X X NumMenus=0; X set_menu(); X } X} X X Xvoid Xset_menu() X{ X if( o_nowindow || !Win ) X return; X X if( NumMenus>0 ) X SetMenuStrip( Win, Menus ); X else X ClearMenuStrip( Win ); X X Delay(3); X} X Xdo_getenv( void ) X{ X char buf[256], *val=buf, *getenv(); X X if( ac!=3 && ac!=2 ) { X show_usage( NULL ); X return 20; X } X if( !Getenv(av[ac-1],buf,256)) X val=""; X X if( ac==2 ) X printf( "%s\n", val ); X else X set_var( LEVEL_SET, av[1], val ); X return 0; X} X X Xdo_setenv( void ) X{ X if( ac!=3 ) { X show_usage( NULL ); X return 20; X } else X setenv( av[1], av[2] ); X return 0; X} X Xchar ** Xread_name( char *name, int *ac ) X{ X FILE *file; X char **av=NULL; X X *ac=0; X if( file=name ? fopen( name, "r") : stdin ) { X av=read_file( file, ac ); X if( name ) fclose( file ); X } else X pError( name ); X return av; X} X X Xchar ** Xread_file( FILE *file, int *ac ) X{ X int buflen=4096, lines=0, i, offs; X char *buf, *ptr, *got=NULL, **lineptr; X X if( !(buf=ptr=malloc( buflen ))) X goto error; X do { X while( ptr+400 < buf+buflen && (got=fgets( ptr, 400, file ) ) && X !dobreak()) { X ptr+=strlen(ptr)-1, lines++; X *ptr++=0; X } X if( ptr+256 < buf+buflen ) { X offs=ptr-buf; X if( !(buf=realloc( buf, buflen*=2 ) ) ) X goto error; X ptr=buf+offs; X } X } while( got && !dobreak()); X if( !(lineptr=(char **)malloc( (lines+1)*sizeof( char * )))) X goto error; X *lineptr++=buf; X for( ptr=buf, i=0; i<lines; i++ ) { X lineptr[i]=ptr; X ptr+=strlen(ptr)+1; X } X *ac=lines; X return lineptr; X Xerror: X if( buf ) free( buf ); X fprintf( stderr, "Out of memory\n" ); X *ac=0; X return NULL; X} X Xvoid Xfree_file( ptr ) X char **ptr; X{ X if( ptr-- ) { X if( *ptr ) X free( *ptr ); X free(ptr); X } X} X X Xdo_qsort( void ) X{ X char **lineptr; X int lines, i; X X if( ac==1 ) { X lineptr=read_file( stdin, &lines); X DirQuickSort( lineptr, lines, cmp, options&1, 0 ); X prepscroll(0); X for( i=0; i<lines && !dobreak(); i++ ) { X quickscroll(); X puts( lineptr[i] ); X } X free_file( lineptr ); X } X return 0; X} X Xextern int w_width; X Xdo_truncate( void ) X{ X char buf[256]; X int w=newwidth(), c; X char *ptr; X X if( ac==2 ) X w=atoi( av[1] ); X X prepscroll(0); X while( gets(buf) && !dobreak() ) { X for( c=0, ptr=buf; *ptr && c<w; ptr++ ) X if( *ptr=='\t' ) X c+=8-(c&7); X else if( *ptr==27 ) { X while( *ptr<'@' ) X ptr++; X } else X c++; X *ptr=0; X quickscroll(); X puts(buf); X } X return 0; X} X Xint Xdo_readfile( void ) X{ X char **rav, *str=NULL; X int rac; X X if( rav= read_name( ac>2 ? av[2] : NULL, &rac ) ) { X if( rac>255 ) rac=255; X if( str= compile_av( rav, 0, rac, 0xA0, 0 ) ) X set_var( LEVEL_SET, av[1], str ); X free_file( rav ); X } X return str ? 0 : 20; X} X Xint Xdo_split( void ) X{ X int i; X char *val, *gap, *oldval; X X if( !(val=get_var( LEVEL_SET, av[1] ))) X { fprintf( stderr, "Variable %s undefined\n", av[0] ); return 20; } X oldval=val=strcpy(salloc(strlen(val)+1),val); X for( i=2; i<ac-1; i++ ) { X if( gap=index(val,0xA0 )) *gap=0; X set_var( LEVEL_SET, av[i], val ); X val=""; X if( gap ) *gap=0xA0, val=gap+1; X } X set_var( LEVEL_SET, av[ac-1], val ); X free(oldval); X return 0; X} X Xchar * Xcopyof( char *str ) X{ X return strcpy(salloc(strlen(str)+1),str); X} X Xint Xdo_class( char *avline ) X{ X CLASS *new; X X if( options&1 ) { X avline=next_word(avline); X for( new=CRoot,CRoot=NULL; new; new=new->next ) X Free(new); X } X X if( ac==1 ) { X for( new=CRoot; new; new=new->next ) X printf("%s\n",new->name); X return 0; X } X X avline=next_word(avline); X if(!(new=malloc( strlen(avline)+5))) X ierror( NULL, 512 ); X else { X new->next=NULL; X strcpy( new->name,avline ); X if( CRoot ) X LastCRoot->next=new; X else X CRoot=new; X LastCRoot=new; X } X return 0; X} X Xdo_getcl( void ) X{ X char *s=getclass(av[1]); X if( s ) printf("%s\n",s); X return 0; X} X Xdo_action( char *argline ) X{ X char *args, err; X int abort=options&1; X X args=compile_av( av,3,ac,' ',0 ); X err=doaction(av[2],av[1],args); X if( !abort ) X if( err==10 ) fprintf(stderr,"Can't identify %s\n", av[2] ); X else if(err==11) fprintf(stderr,"Can't '%s' this file\n",av[1] ); X return abort ? !err : err; X} END_OF_FILE if test 28599 -ne `wc -c <'comm3.c'`; then echo shar: \"'comm3.c'\" unpacked with wrong size! fi # end of 'comm3.c' fi if test -f 'csh.doc.aa' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'csh.doc.aa'\" else echo shar: Extracting \"'csh.doc.aa'\" \(26142 characters\) sed "s/^X//" >'csh.doc.aa' <<'END_OF_FILE' X X INSTRUCTIONS FOR SHELL VERSION: 5.10 11-Apr-1991 X ================================================= X X Contents X -------- X X O. Installation X I. Description X II. Overview of Major features X III. Restrictions X IV. PIPES X V. Command Pre-processor X VI. Command Line Editing X VII. Function Keys X VIII. Shell Commands X IX. Special Set Variables X X. Functions X XI. Miscellaneous X XII. Example source files X XIII. Default values X XIV. Object oriented features X XV. Keymaps X X X XO. Installation X---------------- X XYou can simply invoke csh from the command line or at the end of your Xstartup-sequence, because csh is, from the AmigaDOS standpoint, not a true Xshell like l:shell-seg. Nevertheless, csh is 'pure', so if your archiver Xforgot to set the 'p' bit, do it right now. X XProposed final setup: If you want to make csh resident, do the following: X XKickstart 1.3 X1. Copy csh anywhere on your (hard)disk, e.g. dh1:tools X2. Make sure your s:startup-sequence contains: X Resident CLI L:Shell-Seg SYSTEM PURE ADD X Resident dh1:tools/csh ADD X NewCLI FROM s:csh-startup X EndCLI X3. Put the following in s:csh-startup X csh -r s:firstlogin.sh X4. In s:firstlogin.sh, put any commands to be called only once, like setmap, X assign, setclock. This is a shell script, use # for comments, and don't X use .key type commands. At the end of this file, add X source s:login.sh X5. In s:login.sh, you put any commands that need to be invocated on every X invocation, like 'alias', 'set' and so on. X6. Put the following the s:cli-startup and s:shell-startup, so csh will be X started in any window opened by NewCLI or from workbench. X csh s:login.sh X XKickstart 2.0 X1. Copy csh anywhere on your (hard)disk, e.g. dh1:tools X2. Make sure your s:startup-sequence contains: X Resident dh1:tools/csh ADD X csh s:firstlogin.sh X3. Proceed from step 4 in kickstart 1.3 X X XAdditionally, I recommend to assign CSH: somewhere and put your docs and Xcshell scripts there. You can do the assign from inside the shell, it's not Xneeded at startup. X X XI. DESCRIPTION X--------------- X XThis version of Shell is the successor of: X Shell V2.04 (C)Copyright 1986, Matthew Dillon, All Rights Reserved X Shell V2.04M-V2.07M by Steve Drew X Shell V2.08MI, V3.xxA and V4.xxA by Carlo Borreo & Cesare Dieni X Shell V5.xxL by Urban Mueller X XIf you have any wishes, bug reports or beer bottles, send them to: X X FIDONET : AUGL BBS, 2:302/906 X INTERNET: umueller@iiic.ethz.ch Xor X Urban Mueller X Schulhausstrasse 83 X CH-6312 Steinhausen X SWITZERLAND X XAny sign of intelligent life welcome! X XPlease check the 'restrictions' and 'known bugs' paragraphs before reporting Xany bugs. The support BBS is AUGL, +41 75 8 20 19, +41 75 8 20 18, +41 75 2 X15 87 (all lines USRobotics HST) login='cshell', password='support' X XFor versions prior to 5.00 send suggestions/criticism/anything else to Carlo XBorreo or Cesare Dieni at: X X BITNET: PERUGIA@ICNUCEVM.BITNET X FIDONET: 2:332/602.0@FIDONET Xor X Carlo Borreo Cesare Dieni X Via G. Berio 34 Via G. Taddei 3 X I-18100 Imperia I-56100 Pisa X Italy Italy X XYou may distribute this program unmodified and for non-profit only. X X*** YOU MAY NOT MODIFY THIS PROGRAM AND REDISTRIBUTE IT *** X XIf everyone writes his own version of Shell and distributes it, we would be Xcovered by Shell versions. If you make a modification to Shell that you Xwould like to share with other users, please send us a DIFF output, or a Xdescription of what you need. X XCREDITS X------- X XArexx is a program by William Hawes. XCygnus Ed Professional (C) 1988 CygnusSoft Software. X XMany thanks to all who gave me feedback, namely Eddy Carroll, Patrizio XRusconi, Allard Siemelink, Magnus Heldestad, Roddi Walker, Roy Haverman, XSteve Koren, Randell Jesup and all I forgot to mention. X X XII. OVERVIEW X------------ X XShell provides a convenient AmigaDos alternative command interface. All its Xcommands are internal and thus does not rely on the c: commands for any Xfunctionality. X XMajor features include: X - command line editing X - simple history X - piping X - aliases with arguments X - variables & variable handling (embedded variables) X - file name expansion via wild carding ('?', '*' and more) X - conditionals (if/else etc..) X - source files (w/ gotos and labels) X - tab file name completion X - object oriented features (file classes, actions) X - many built in commands to speed things up X - full functionality on VT terminals X - freely programmable command line editing X XShell runs on minimum stack, for recursive aliases and source files better Xincrease stack to 8K or more. X XIf you use CShell for the first time, remember the following: X - CShell internal commands must be lowercase & can be abbreviated X - AmigaDOS command 'Execute' causes some trouble. You cannot redirect X it, you must not rename it, and you get no return code. X You can also use 'source' to start your scripts, but you'll have X to rewrite them a bit. Besides the '.key'-type commands, 'source' X is downward compatible with 'Execute'. X - You can always get more information on a command if csh.doc is X in the current directoy or in csh: (you will be able to modify X this) and you enter 'man <command>' X X XIII. RESTRICTIONS X----------------- X XThe following applies only to Kickstart 2.0, and only to V36: The INTERNAL Xcommands cannot be started. The same is true for the commands in C: if they Xwere made resident using the AmigaDOS 'Resident' command (with cshell's X'resident' they work). Thus, you should disable the INTERNAL residents using Xthe -i0 startup option if you have a V36 Kickstart. X XUnder 1.3, you can't start AmigaDOS residents directly. But you can use the X-r startup option, which will copy the AmigaDOS resident list to the arp Xresident list once (and make those residents unremovable). I'll try to find Xa better solution. X XThe best choice under both kickstarts is to make only csh itself AmigaDOS Xresident, all other commands, if any, ARP resident. Under 1.3, you can start Xthe shell (as any other commands) from the resident list only after you did X'resident CLI l:Shell-seg' and 'newcli'. X XThe c:Execute command cannot be redirected, does not return error codes, and Xmight cause other problems. It will not work at all if it has been renamed. X XThe VDK: handler and Frank Seidel's BootRam-Handler have a bug with setting Xfile dates, so when using the copy command you should try the -d and -p Xswitches, otherwise your file date will be bad. (This is not a shell bug) X XIf using with conman it you may consider starting shell with the -a switch to Xturn off shell's command line editing and use conmans instead. You'll lose, Xhowever, many shell features like TAB file name completion. X XCB-handler (a tool that installs a scrollbar in the CLI window) is not 100% Xcompatible with cshell. The log will not always represent the real screen Xcontents. X X XIV. NOTES ON PIPES X------------------ X X PIPES X PIPES have been implemented using temporary T: files. Thus, you X should be careful when specifying a 't:*' expansion as it might X include the temporary files. These files are deleted on completion X of the pipe segment. X X The file names used are completely unique, even with multiple shell X running simultaneously. X X My favorite new feature is the fact that you can now redirect to X and from, and pipe internal commands. 'echo charlie >ram:x', for X instance. Another favorite: X X echo "echo mem | csh" | csh X X No BCPL program should be output-append redirected (>>). X X XV. COMMAND PRE-PROCESSOR X------------------------- X X PREPROCESSING X Preprocessing is done on the command line before it is passed on to X an internal or external routine: X X ^c where c is a character is converted to that control character. X Thus, say '^l' for control-l. X X \233 insert character code 233 octal. Do not use values between X 200o and 232o, as they have special meanings. \240 is the X word separator. X X $name where name is a variable name. Variable names can consist of X 0-9, a-z, A-Z, and underscore (_). The contents of the X specified variable is used. If the variable doesn't exist, X the specifier is used. That is, if the variable 'i' contains X 'charlie', then '$i' -> 'charlie'. If the variable 'i' doesn't X exist, then '$i'->'$i' . X X ; delimits commands. echo charlie ; echo ben. X X ' ' (a space). Spaces delimit arguments. X X "string" a quoted string. Trailing quotes are optional. For instance, X if you want to echo five spaces and an 'a': X X echo a -> a X echo " a" -> a X X \c overide the meaning of special characters. '\^a' is a X circumflex and an a rather than control-a. To get a backslash, X you must say '\\'. X X also used to overide alias searching for commands. X X >file specify output redirection. All output from the command is X placed in the specified file. X X >>file specify append redirection (Does not work with BCPL programs). X X <file specify input redirection. The command takes input from the X file rather than the keyboard (note: not all commands require X input; it makes no sense to say 'echo <charlie' since X the 'echo' command only outputs its arguments). X X | PIPE specifier. The output from the command on the left becomes X the input to the command on the right. The current SHELL X implimentation uses temporary files to store the data. X X !! execute the previously executed command. X !nn (nn is a number). Insert the history command numbered n (see X the HISTORY command) X !partial search backwards through the history list for a command which X looks the same as 'partial', and execute it. X X # enter comment. The rest of the line is discarded (note: \# X will, of course, overide the comment character's special X meaning) X X {e hi;e ho} executes two commands as one, so they can be redirected X as one, so they can be redirected together (see ALIAS X command). The traling curly brace is optional. X X $(foo) insert the stdout of the command 'foo' at this position of X the command line. Every line of the output will count as one X argument. The closing parenthesis is optional. X X `foo` insert the stdout of the command 'foo' at this position of X the command line. Every blank separated word will count as X one argument. The trailing backtick is optional. X X Please note the subtle differences between X alias count {echo one;echo two} X alias count "echo one;echo two X The first form will create an alias that contains a local alias. The X other will create a plain alias. Also, things within braces will not X be parsed more than once, therefore a backslash needs not be pre- X ceeded by a pair of backslashes. Thus the commands look the same as X if they were to be typed in at the prompt. To echo lots of '#', X either use: X forever {echo \# X forever "echo \\\# X A block can spread over several line. Refer to the SOURCE command. X X XVI. COMMAND LINE EDITING X------------------------ X X o Command line can be up to 255 chars. X o Inserts and deletes are handled correctly over multiple screen X lines. X o Shell will keep track of the line width should the window get X resized. X X EDITING X X -- MOVING -- X Left Arrow One character left X Right Arrow One character right X Shift-Left Arrow One word left X Shift-Right Arrow One word right X ESC-Left Arrow Beginning of line (^A) (^Z) X ESC-Right Arrow End of line (^E) X -- DELETING -- X Backspace Previous character X Del Character under cursor X ESC-Backspace Previous word (^W) X ESC-Del Next word X ESC-x-Backspace To start of line (^B) X ESC-x-Del To end of line (^K) X ESC-d Entire line (^X) X -- HISTORY -- X Up Arrow Recall previous commands X Down Arrow Recall commands X Shift-Up Arow Get history from partial (or number) X Shift-Down Arrow Go below last command of history X ESC-Up Arrow Get start of history X ESC-Down Arrow Get end of history X ESC-! Get history from partial (or number) X ^T Insert tail (all but first word) of previous line X ^P Duplicate previous word (useful for mv) X -- COMPLETION -- X TAB Inserts first matching file name X Shift-TAB Inserts longest common substring X ESC-TAB Inserts all matching file names X ESC-c Does a quick cd on left word (TAB for cycling) X ESC-~ Inserts the last current directory X -- EXECUTING LINE -- X Return Executes line X ESC-Return Executes this line of history & brings up next one X ^N Next line. Don't exec this one but store history X ^\ EOF (directly exits) X -- MISCELLANEOUS -- X ^L Retype current line. X ^O Echo a ^O X ^R Repeat last command (don't play with this) X ^U Undo/Redo last edit X ESC-i Toggle Insert/Overwrite X f1-f10 Execute command if variable exists. X F1-F10 More commands (Shifted f keys). X Help Invokes help command X XWhenever the cursor is placed on or directly after an incomplete file name Xand you press TAB, CShell inserts for the first filename (sorted Xalphabetically) that matches the name part already typed. Any wildcards Xare allowed here, if none are given, '*' is appended. Immediately pressing XTAB again brings up the next file name that matched the substring. XShift-TAB will only insert the as much as is common to all files that Xmatched you abbreviation. If pressed again, behaves just like TAB. XESC-Tab inserts the name of the directory where you would have ended up Xwith a quick cd to that substring. X XNote that ^D now means 'quit batchfile' like under AmigaDOS and is no Xlonger used for quitting CShell. If you want it back, enter 'keymap 0 4=41' X XThe CTRL keys FGVY are unset, feel free to map them to any function (see Xchapter XV). You can also remap all preset keys. X XVII. FUNCTION KEYS X------------------ X X FUNKEY X Function keys now insert text to the current position on the command X line. They maybe terminated with a ^M (return). f1 would be non shifted X where as F1 is shifted. X Most of functions key have a default definition, but it may be changed. X X $ set f1 dir df0:^M X X will add the text 'dir df0:<return>' to the current line. X X $ set f1 dir X X would only add 'dir' you could then enter ' df0:<return>' X X XVIII. SHELL COMMANDS X-------------------- X X STARTUP OPTIONS X First to start shell from a CLI: X X shell [-abcfiknstv] [-c command;command] X shell [-abcfiknstv] [batchfile1 ... batchfileN] X X -a AUX: mode. No command line editing and text highlighting X -b starts shell in background, which means only task priority -1. X -c allows execution of one command line and then exits out X of shell. This is useful for running an internal shell X commands in the background or from an external application: X Run csh -c "dir df0:; copy -r df0: df1: >nil:; echo Done" X -f starts shell in foreground, which means only task priority 1. X you might reset this prioritiy to 0 at the end of your .login X -i0 disables INTERNAL residents. for V36 kickstarts. X -k sets _nobreak before doing anything X -n suppresses starting of s:.login X -r copies the amiga resident list to the arp resident list. You X can't remove them anymore. No copying when under kick 2.0 or X if arp residents present. X -s globally enables the star '*' as alias for #? in AmigaDOS 2.0 X -t terminal mode. You can use command line editing and text high- X lighting on a VT100 compatible terminal. X -v sets _verbose to 'hs' before doing anything. X X Under 1.3, the best thing you can do is to make csh resident using X the AmigaDOS Resident command in the startup-sequence, then start X it with the option -r, so you can start another resident csh from X inside csh. NOTE: Residents copied using -r cannot be removed! I X advise you to use the internal resident command for all but csh X itself. X X COMMAND EXECUTION X X Internal shell commands are case sensitive and may be abreviated. X X The first argument is the command-name... here is (in order) how Shell X tries to execute it: X X 1) The alias list is searched for an alias with an exactly X matching name. X 2) Internal commands list is scanned for a command even partially X matching name (so you can, for instance, say resi for resident; X however, you should specify enough of a command to be unique). X 3) Then, the list of functions is scanned for a command that X matches completely. If one is found, the result of the function X is echoed to stdout. X 4) Now the command is assumed to be external. Arguments with spaces X or empty strings will be surrounded by quotes. X 5) If the file is a directory, a 'cd <file>' will be performed to X it. X 6) AmigaDOS and ARP resident list are scanned for it (you can use X Shell's 'resident' command to add/remove a file in the ARP list). X 7) If the file is in the current directory and it's executable, it X is started. X 8) Then it is searched in the AmigaDOS path and c: (NOTE: Path X assigns to C: under Kickstart 2.0 don't work; use 'path') X 9) Now, the shell path ($_path) is searched. If it's found and X executable, it's be started. If it has the 's' bit set, it will X be 'c:Execute'd. X 10) If there exists a file with the suffix '.sh' and the same root X in the current directory or in the shell path, it is 'source'd. X 11) Then the variable _rxpath is examined. If there exists a file X with the suffix '.rexx' and the same root in the current direc- X tory or in '$_rxpath', 'RX <file>' will be performed. X 12) If all failed, an 'exec' action is sent to the file. See chapter X XIV for more info on classes and actions. X X To enforce that the external 'dir'-command is used, enter 'Dir'. Tt X is a good habit to uppercase the first letter of all external com- X mands, even if this is not necessary. X X AUTOMATIC SOURCING may be accomplished by naming shell scripts with X a .sh suffix. Thus, if you say 'stuff' and the file 'stuff.sh' X exists in your current or anywhere in Shell search path (NOTE: won't X be found in the AmigaDOS path), it will be SOURCED with all arguments X you have given placed in the $_passed variable. This is equivalent X to typing 'source stuff.sh' X X WILD CARD EXPANSION X Most shell commands will accept multiple arguments that can X be as a result of wild card expansion. Also when calling X an external command shell will first expand any wild cards X to separate arguments. If you wish to have the external command X handle it's own wild carding you will need to insert quotes X around the special wild card characters or use an alias (see X explanation of 'alias') X X eg. X arc a new.arc *.txt - shell will expand and pass to arc X arc a new.arc "*.txt" - let arc expand the wild cards. X alias arc "*a Arc $a" - now shell will never expand X X Wildcards allowed: X X ? match any single character X * match any string X .../* recursive search down ALL sub directories from current level X ~ exclude pattern matching specifier X ! synonym for ~, supported for compatibility X & prefixed to patterns, ask confirmation for each file X [] character class X ~ the previous current directory (if separated) X Note that a pattern must contain a '?' or a '*', otherwise the other X special characters are not recognized. Furthermore, you cannot spe- X cify a single '?' as a pattern in the first argument to a command, X as this will be passed on to the command in order to show its usage. X X Examples: X X df0:.../* all files in all directories on df0: X df0:.../!*.info full directory tree of df0: but exclude X any ugly .info files. X !*.o !*.c will result in ALL files matching since what X doesn't match the !*.o will match the !*.c X df1:&* all files in root of df1:, but ask X confirmation for each X *.[co] all files ending in .c or .o X ~*.[co] all files NOT ending in .c nor in .o X ~ the previous current directory X ~/*.c all .c files in the previous current directory X ~// the parent of the previous current directory X . the current directory X ./foo.c the same as foo.c X .. the parent of the current directory X ../foo.c the file foo.c in the parent directory X X Note that some commands prevent wild card expansion. These are: X - dir, rpn, whereis, window X Those commands will expand the wild cards themselves. This is why X dir @without( *.? , *.o ) X will not work. Instead use: X set arg @without( *.? , *.o );dir $arg X X There is one exception to the rules given above: A single '?' as X the first argument will *not* expand in order to allow you to get X the usage of CLI and csh commands easily. X X The following symbols are not yet supported by wild card X expansions, but are accepted in search -w: X X ( | ) OR matching X # 0 or more times the pattern following X X Examples: X X "k#a" matches ka, kaa, kaaa, etc. X "hel(lo|p)" matches hello or help. X X XLIST OF COMMANDS: X----------------- X X ABORTLINE X Usage : abortline X Example : echo a;abort;echo b X Results : a X X Causes the rest of the line to be aborted. Intended for use in X conjunction with exception handling. X X ACTION X Usage : action [-a] actionname file [arguments] X X Sends an action to a file. See chapter XIV CLASSES X Options: X -a (abort) returns 0 if failed and 1 if successful. Otherwise, X normal error codes (10 or 11) are returned X X ADDBUFFERS X Usage : addbuffers drive buffers [drive buffers ...] X Example : addbuffers df0: 24 X X Just like AmigaDOS addbuffer command, causes new buffers to be X allocated for disk I/O. Each buffer costs 512 bytes of memory, X CHIP memory if a disk drive. X X ALIAS X Usage : alias [name [command string] ] X Example : alias vt "echo Starting VT100;run sys:tools/vt100" X X Sets a name to be a string. You can alias a single name to a set X of commands if you enclose them in quotes as above. By simply X typing vt, the command line above would be executed. X Aliases may call each other, but direct recursion is prohibited, X so the following works: alias ls "ls -s" X To prevent alias replacement, enter: \ls X X By typing "alias name", you will get the alias for that name, while X with "alias" you get a list of all alias. X X ARGUMENT PASSING TO AN ALIAS: X X Usage : alias name "%var[%var...] [ command_string ]" X alias name "*var[%var...] [ command_string ]" X Example : alias xx "%q%w echo hi $q, you look $w X xx Steve great today X Results : hi Steve, you look great today X X The second form of the alias command allows passing of arguments X to any position within the command string via use of a variable X name. To pass arguments to the end of a command string this method X is actually not necessary. These variables are local, so they don't X destroy another variable with the same name. X If you specify multiple arguments, every argument will be assigned X one word, and the last argument will be assigned the rest of the X command line. X X Using a '*' instead of the first '%' prevents wild card expansion: X alias zoo "*a zoo $a X To expand the wild cards after you got them, use X exec set a $a X X IMPLICIT ALIASES: X X Usage : {command;command} X {%var command;command} arg arg X Example : {%tmp echo $tmp $tmp} hello X Results : hello hello X X Curly braces define a temporary aliases. They can be redirected as X a whole, can have arguments and local variables. They count as X one argument, even if there are blanks inside (as with quotes), and X they may be nested. Complex alias definitions can use the braces X instead of quotes, although this will add some calling overhead. X The closing curly brace is optional if at the end of line. X Example: X X alias assert {e "Are you sure? ";input -s sure X X ASCII X Usage : ascii X ascii string X X If called without arguments, ascii outputs a complete ascii table. X Given a string, shows each character in ascii. Options: X -h shows numbers in hexadecimal X -o shows numbers in octal X X ASET X Usage : aset name value X Example : aset INCLUDE include: X X Set a variable in a way that is compatible with ARP/old Aztec set X command; this is completely different from ENV: Shell variable. X X ASSIGN X Usage : assign X assign logical X assign [-lnp] logical1 physical1 [logical2 physical2 ... ] X X The first form shows all assigns. X The second form kills one assign. X The third form assigns logical1 to physical1 and so on. Options: X -l creates a late-binding assign under kick 2.0, normal otherwise X -n creates a non-binding assign under kick 2.0, normal otherwise X -p creates a path-assign under kick 2.0, cancelled otherwise X For definition of late/nonbinding, refer to your AmigaDOS manual. X X BASENAME X Usage : basename var path X Example : basename x df0:c/Dir # sets x to "Dir" X X Sets var specified to basename of path. X X CAT X Usage : cat [-n][file file....] X Example : cat foo.txt X X Type the specified files onto the screen. If no file is specified, X STDIN in used (note: ^\ is EOF). CAT is meant to output text files X only. Specifying -n option you will get numbered lines. X X CD X Usage : cd [path] X cd -g device1 [device2 [device3 ...]] X X Change your current working directory. You may specify '..' to go X back one directory (this is a CD specific feature, and does not X work with normal path specifications). X X In most cases, you'll no more have to use the CD command. Just type X the desired directory at the prompt (very handy in conjunction with X file name completion). Typing a ~ alone on a command line cd's X to prevous current directory. X X There are two situations left when you still need it: X X Entering 'cd *tem' will cd to the first name matched. X X The second form generates a list (an ascii file) of all direc- X tories on the given devices. It will be stored in the file given X in $_qcd (default: 'csh:csh-qcd'). Note that this ascii file will X not be merged but overwritten. Once you have generated this file, X you can cd to any directory on your harddisk(s) even if it's not X in the current directory. X If you have two directories of the same name and you use one of X them more, move the more important one to the beginning of the X qcd file. You might also sort the file. X It is legal to type just an abbreviation of the directory name X you want to cd to. No asterisk '*' necessary. If you end up in X the wrong directory, cd to the same directory again (best done END_OF_FILE if test 26142 -ne `wc -c <'csh.doc.aa'`; then echo shar: \"'csh.doc.aa'\" unpacked with wrong size! fi # end of 'csh.doc.aa' fi echo shar: End of archive 4 \(of 6\). cp /dev/null ark4isdone 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.