home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
488.lha
/
csh_v5.0
/
src
/
csh500src.lzh
/
sub.c
< prev
Wrap
C/C++ Source or Header
|
1991-02-23
|
21KB
|
1,079 lines
/*
* SUB.C
*
* (c)1986 Matthew Dillon 9 October 1986
*
* Version 2.07M by Steve Drew 10-Sep-87
* Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
* Version 5.00L by Urban Mueller 17-Feb-91
*
*/
#include "shell.h"
#include "proto.h"
static void del_history( void );
static int hasspace( char *s );
static int dnext( struct DPTR *dp, char **pname, int *stat);
static char *svfile( char *s1, char *s2, FIB *fib);
static int exall( BPTR lock, char *path );
static void quicksort( char **av, int n );
#define HM_STR 0 /* various HISTORY retrieval modes */
#define HM_REL 1
#define HM_ABS 2
void
seterr( void )
{
char buf[32], *val;
int stat=0;
sprintf(buf, "%d", Lastresult);
set_var(LEVEL_SET, v_lasterr, buf);
if( val=get_var(LEVEL_SET, v_stat))
stat = atoi(val);
if (stat < Lastresult) set_var(LEVEL_SET, v_stat, buf);
}
#define ISSPACE(c) ((c)==' ' || (c)==9 || (c)==0xA0)
char *
next_word( char *str )
{
while (*str && ! ISSPACE(*str)) ++str;
while (*str && ISSPACE(*str)) ++str;
return str;
}
static int
hasspace( char *s )
{
for ( ; *s; s++)
if (ISSPACE(*s)) return 1;
return 0;
}
char *
compile_av(char **av, int start, int end, char delim, int quote)
{
char *cstr, *p;
int len, i;
len = 1;
for (i = start; i < end; ++i) len += strlen(av[i]) + 3;
p = cstr = malloc(len);
*cstr = '\0';
for (i = start; i < end; ++i) {
if (debug) fprintf (stderr, "AV[%2d] :%s:\n", i, av[i]);
if (quote && hasspace(av[i]))
p += sprintf(p, "\"%s\"", av[i]);
else
p += sprintf(p, "%s", av[i]);
if (i+1 < end) *p++=delim;
}
*p='\0';
return cstr;
}
/*
* FREE(ptr) --frees without actually freeing, so the data is still good
* immediately after the free.
*/
void
Free( void *ptr )
{
static char *old_ptr;
if (old_ptr) free (old_ptr);
old_ptr = ptr;
}
/*
* Add new string to history (H_head, H_tail, H_len,
* S_histlen
*/
void
add_history( char *str )
{
struct HIST *hist;
char *get;
for( get=str; *get; get++ )
if( (*get&127)<' ')
*get=' ';
if (H_head != NULL && !strcmp(H_head->line, str))
return;
while (H_len > S_histlen)
del_history();
hist = (struct HIST *)malloc (sizeof(struct HIST));
if (H_head == NULL) {
H_head = H_tail = hist;
hist->next = NULL;
} else {
hist->next = H_head;
H_head->prev = hist;
H_head = hist;
}
hist->prev = NULL;
hist->line = malloc (strlen(str) + 1);
strcpy (hist->line, str);
++H_len;
}
static void
del_history()
{
if (H_tail) {
--H_len;
++H_tail_base;
free (H_tail->line);
if (H_tail->prev) {
H_tail = H_tail->prev;
free (H_tail->next);
H_tail->next = NULL;
} else {
free (H_tail);
H_tail = H_head = NULL;
}
}
}
char *
get_history( char *ptr, int echo )
{
struct HIST *hist;
int len;
int mode = HM_REL;
int num = 1;
char *str;
char *result = NULL;
if (ptr[1] >= '0' && ptr[1] <= '9') {
mode = HM_ABS;
num = atoi(&ptr[1]);
goto skip;
}
switch (ptr[1]) {
case '!':
break;
case '-':
num += atoi(&ptr[2]);
break;
default:
mode = HM_STR;
str = ptr + 1;
break;
}
skip:
switch (mode) {
case HM_STR:
len = strlen(str);
for (hist = H_head; hist; hist = hist->next) {
if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
result = hist->line;
break;
}
}
break;
case HM_REL:
for (hist = H_head; hist && num--; hist = hist->next);
if (hist)
result = hist->line;
break;
case HM_ABS:
len = H_tail_base;
for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
if (hist)
result = hist->line;
break;
}
if( echo )
fprintf(stderr, result ? "%s\n" : "History failed\n", result);
if( !result ) result="";
return result;
}
void
replace_head( char *str )
{
if (str && strlen(str) && H_head) {
free (H_head->line);
H_head->line = malloc (strlen(str)+1);
strcpy (H_head->line, str);
}
}
#if 0
#define CDLEN 20
static int cd_len=CDLEN, cd_read, cd_write, cd_current;
static char *cd_hist[CDLEN];
add_cdhist( char *str )
{
if( !str )
return;
if( cd_hist[cd_write] )
free(cd_hist[cd_write]);
cd_hist[cd_write++]=str;
cd_write%=cd_len;
cd_current=cd_write;
}
char *
back_cdhist( void )
{
if( cd_current!=cd_write ) cd_current= --cd_current % cd_len;
return cd_hist[cd_current];
}
char *
forw_cdhist( void )
{
if( cd_current!=cd_read ) cd_current= ++cd_current % cd_len;
return cd_hist[cd_current];
}
#endif
void
pError(char *str )
{
int ierr = (long)IoErr();
ierror(str, ierr);
}
ierror( char *str, int err )
{
struct PERROR *per = Perror;
if (err) {
for (; per->errstr; ++per) {
if (per->errnum == err) {
fprintf (stderr, "%s%s%s\n",
per->errstr,
(str) ? ": " : "",
(str) ? str : "");
return err;
}
}
fprintf (stderr, "Unknown DOS error %d %s\n", err, (str) ? str : "");
}
return err;
}
/*
* Disk directory routines
*
* dptr = dopen(name, stat)
* struct DPTR *dptr;
* char *name;
* int *stat;
*
* dnext(dptr, name, stat)
* struct DPTR *dptr;
* char **name;
* int *stat;
*
* dclose(dptr) -may be called with NULL without harm
*
* dopen() returns a struct DPTR, or NULL if the given file does not
* exist. stat will be set to 1 if the file is a directory. If the
* name is "", then the current directory is openned.
*
* dnext() returns 1 until there are no more entries. The **name and
* *stat are set. *stat = 1 if the file is a directory.
*
* dclose() closes a directory channel.
*
*/
extern long IoError;
struct DPTR *
dopen( char *name, int *stat)
{
struct DPTR *dp;
*stat = 0;
dp = (struct DPTR *)malloc(sizeof(struct DPTR));
if (*name == '\0')
dp->lock = DupLock(Myprocess->pr_CurrentDir);
else
dp->lock = Lock (name,ACCESS_READ);
if (dp->lock == NULL) {
IoError=IoErr();
free (dp);
return NULL;
}
dp->fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
if (!Examine (dp->lock, dp->fib)) {
pError (name);
dclose (dp);
return NULL;
}
if (dp->fib->fib_DirEntryType >= 0) *stat = 1;
return dp;
}
static int
dnext( struct DPTR *dp, char **pname, int *stat)
{
if (dp == NULL) return (0);
if (ExNext (dp->lock, dp->fib)) {
*stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
*pname = dp->fib->fib_FileName;
return 1;
}
return 0;
}
int
dclose( struct DPTR *dp )
{
if (dp == NULL)
return 1;
if (dp->fib)
FreeMem (dp->fib,(long)sizeof(*dp->fib));
if (dp->lock)
UnLock (dp->lock);
free (dp);
return 1;
}
int
isdir( char *file )
{
struct DPTR *dp;
int stat;
stat = 0;
if (dp = dopen (file, &stat))
dclose(dp);
return (stat == 1);
}
void
free_expand( char **av )
{
char **get = av;
if (av) {
while (*get)
free (*get++-sizeof(struct file_info));
free (av);
}
}
/*
* EXPAND(base,pac)
* base - char * (example: "df0:*.c")
* pac - int * will be set to # of arguments.
*
* 22-May-87 SJD. Heavily modified to allow recursive wild carding and
* simple directory/file lookups. Returns a pointer to
* an array of pointers that contains the full file spec
* eg. 'df0:c/sear*' would result in : 'df0:C/Search'
*
* Now no longer necessary to Examine the files a second time
* in do_dir since expand will return the full file info
* appended to the file name. Set by formatfile().
* eg. fullfilename'\0'rwed NNNNNN NNNN DD-MMM-YY HH:MM:SS
*
* Caller must call free_expand when done with the array.
*
* base bname = ename =
* ------ ------- -------
* "*" "" "*"
* "!*.info" "" "*.info" (wild_exclude set)
* "su*d/*" "" "*" (tail set)
* "file.*" "" "file.*"
* "df0:c/*" "df0:c" "*"
* "" "" "*"
* "df0:.../*" "df0:" "*" (recur set)
* "df0:sub/.../*" "df0:sub" "*" (recur set)
*
* ---the above base would be provided by execom.c or do_dir().
* ---the below base would only be called from do_dir().
*
* "file.c" "file.c" "" if (dp == 0) fail else get file.c
* "df0:" "df0:" "*"
* "file/file" "file/file" "" (dp == 0) so fail
* "df0:.../" "df0:" "*" (recur set)
*
*/
int expand_err;
char **
expand( char *base, int *pac )
{
char *ptr;
char **eav = (char **)malloc(sizeof(char *) * (2));
short eleft, eac;
char *name;
char *bname, *ename, *tail;
int stat, recur, scr, bl;
struct DPTR *dp;
expand_err = *pac = recur = eleft = eac = 0;
base = strcpy(malloc(strlen(base)+1), base);
for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
if (!*ptr) /* no wild cards */
--ptr;
else
for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
if (ptr < base) {
bname = strcpy (malloc(1), "");
} else {
scr = ptr[1];
ptr[1] = '\0';
if (!strcmp(ptr-3,".../")) {
recur = 1;
*(ptr-3) = '\0';
}
bname = strcpy (malloc(strlen(base)+2), base);
ptr[1] = scr;
}
bl = strlen(bname);
ename = ++ptr;
for (; *ptr && *ptr != '/'; ++ptr);
scr = *ptr;
*ptr = '\0';
if (scr) ++ptr;
tail = ptr;
if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
free (bname);
free (base);
free (eav);
expand_err=1;
return (NULL);
}
if (!stat) { /* eg. 'dir file' */
char *p,*s;
for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
if (s != bname) ++s;
*s ='\0';
eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
goto done;
}
if (!*ename) ename = "*"; /* eg. dir df0: */
if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
bname[bl] = '/';
bname[++bl] = '\0';
}
while ((dnext (dp, &name, &stat)) && !breakcheck()) {
int match = compare_ok(ename,name,0);
if (match && !(!recur && *tail)) {
if (eleft < 2) {
char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
memmove (scrav, eav, (eac + 1) << 2);
free (eav);
eav = scrav;
eleft = 10;
}
eav[eac++] = svfile(bname,name,dp->fib);
--eleft;
}
if ((*tail && match) || recur) {
int alt_ac;
char *search, **alt_av, **scrav;
BPTR lock;
if (!stat) /* expect more dirs, but this not a dir */
continue;
lock = CurrentDir (dp->lock);
search = malloc(strlen(ename)+strlen(name)+strlen(tail)+6);
strcpy (search, name);
strcat (search, "/");
if (recur) {
strcat(search, ".../");
strcat(search, ename);
}
strcat (search, tail);
scrav = alt_av = expand (search, &alt_ac);
free(search);
CurrentDir (lock);
if (scrav) {
while (*scrav) {
int l;
if (eleft < 2) {
char **scrav = (char **)malloc(sizeof(char *)*(eac+10));
memmove ( scrav, eav, (eac + 1) << 2);
free (eav);
eav = scrav;
eleft = 10;
}
l = strlen(*scrav);
eav[eac] = malloc(bl+l+1+sizeof(struct file_info));
memcpy( eav[eac], *scrav-sizeof(struct file_info),
sizeof(struct file_info));
eav[eac]+=sizeof(struct file_info);
strcpy( eav[eac], bname);
strcat( eav[eac], *scrav);
free (*scrav-sizeof(struct file_info));
++scrav;
--eleft, ++eac;
}
free (alt_av);
}
}
}
done:
dclose (dp);
*pac = eac;
eav[eac] = NULL;
free (bname);
free (base);
if (eac)
return (eav);
free (eav);
return (NULL);
}
char *
strupr( char *s )
{
char *old=s;
while (*s) *s=toupper(*s), s++;
return old;
}
char *
strlwr( char *s )
{
char *old=s;
while (*s) *s=tolower(*s), s++;
return old;
}
/*
* Compare a wild card name with a normal name
*/
int
compare_ok( char *wild, char *name, int casedep)
{
int queryflag;
char buf[260], wildbuf[260], *lowname;
if (queryflag=(*wild=='&')) wild++;
if (*wild=='!') *wild='~';
if (! casedep) {
strupr(wild);
strcpy(buf,name);
strupr(buf);
lowname=buf;
} else
lowname=name;
PreParse(wild, wildbuf);
if ( ! PatternMatch(wildbuf,lowname)) return 0;
if (queryflag) {
printf("Select %s%-16s%s [y/n] ? ",o_hilite,name,o_lolite);
gets(buf);
return (toupper(*buf)=='Y');
}
return 1;
}
static char *
svfile( char *s1, char *s2, FIB *fib)
{
int len=strlen(s1)+strlen(s2)+1;
char *p = malloc (len+sizeof(struct file_info));
struct file_info *info;
info=(struct file_info *)p;
p+=sizeof(struct file_info);
strcpy(p, s1);
strcat(p, s2);
info->flags = fib->fib_Protection;
if( fib->fib_DirEntryType<0 ) {
info->size = fib->fib_Size;
info->blocks= fib->fib_NumBlocks;
} else {
info->size = -1;
info->blocks= 0;
}
if( fib->fib_Comment[0] )
info->flags|= 1<<30;
info->date=fib->fib_Date;
info->class[0]=1;
return p;
}
static FILE *out;
static int NumDirs;
void
expand_all( char *name, FILE *file )
{
BPTR lock;
char path[300];
FIB *fib;
out=file;
printf( " %s\n", name );
NumDirs=0;
if(fib=AllocMem(sizeof(struct FileInfoBlock),0)) {
if( lock=Lock( name, ACCESS_READ )) {
strcpy( path, name );
exall( lock, path );
printf( "\n", NumDirs );
}
FreeMem(fib,sizeof(struct FileInfoBlock));
}
}
static int
exall( BPTR lock, char *path )
{
BPTR old, sublock;
int len;
struct FileInfoBlock *fib;
old=CurrentDir( lock );
if( !(fib=AllocMem(sizeof(struct FileInfoBlock),0)) )
return 1;
len=strlen( path );
Examine( lock, fib );
while( ExNext( lock, fib ) ) {
if( fib->fib_DirEntryType>=0 )
if( sublock=Lock( fib->fib_FileName, ACCESS_READ )) {
if( !len || path[len-1]==':' )
sprintf(path+len,"%s", fib->fib_FileName);
else
sprintf(path+len,"/%s", fib->fib_FileName);
fprintf( out, "%s\n", path );
fprintf( stdout, " Directories: %d\015", ++NumDirs );
fflush ( stdout );
if(exall( sublock, path ))
break;
path[len]=0;
}
}
FreeMem( fib, sizeof(struct FileInfoBlock));
CurrentDir( old );
return dobreak();
}
/* Sort routines */
int reverse;
int
cmp( char *s1, char *s2)
{
int r=Strcmp(s1, s2);
return reverse ? -r : r;
}
int
sizecmp( char *s1, char *s2)
{
int r= ((struct file_info *)(s2-sizeof(struct file_info)))->size -
((struct file_info *)(s1-sizeof(struct file_info)))->size;
return reverse ? -r : r;
}
int
datecmp( char *s1, char *s2 )
{
int r;
struct DateStamp
*d1=&((struct file_info *)(s1-sizeof(struct file_info)))->date,
*d2=&((struct file_info *)(s2-sizeof(struct file_info)))->date;
if( !(r= d2->ds_Days - d1->ds_Days))
if( !(r=d2->ds_Minute - d1->ds_Minute ) )
r=d2->ds_Tick - d1->ds_Tick;
return reverse ? -r : r;
}
static void
enterclass( FILEINFO *info )
{
char *class, *iclass=info->class, *t;
if( *iclass==1 ) {
if( class=getclass( (char *)(info+1))) {
strncpy( iclass, class, 11 );
iclass[11]=0;
if( t=index(iclass,0xA0))
*t=0;
} else
iclass[0]=0;
}
}
int
classcmp( char *s1, char *s2 )
{
int r;
FILEINFO *info1=(FILEINFO *)s1-1, *info2=(FILEINFO *)s2-1;
enterclass( info1 );
enterclass( info2 );
r= Strcmp( info1->class, info2->class );
if( !r ) r=Strcmp(s1, s2);
return reverse ? -r : r;
}
void
QuickSort( char *av[], int n)
{
DirQuickSort( av, n, cmp, 0 );
}
static int (*compare)(char *, char *);
void
DirQuickSort( char *av[], int n, int (*func)(char *,char *), int rev)
{
reverse=rev; compare=func;
quicksort( av, n-1 );
}
static void
quicksort( char **av, int n )
{
char **i, **j, *x, *t;
if( n>0 ) {
i=av; j=av+n; x=av[ n>>1 ];
do {
while( (*compare)(*i,x)<0 ) i++;
while( (*compare)(x,*j)<0 ) --j;
if( i<=j )
{ t=*i; *i=*j; *j=t; i++; j--; }
} while( i<=j );
if( j-av < av+n-i ) {
quicksort( av, j-av );
quicksort( i , av+n-i);
} else {
quicksort( i , av+n-i);
quicksort( av, j-av );
}
}
}
int
filesize( char *name )
{
BPTR lock;
struct FileInfoBlock *fib;
int len=0;
if( lock = Lock (name,ACCESS_READ)) {
if( fib=(struct FileInfoBlock *)AllocMem(sizeof(*fib),MEMF_PUBLIC)) {
if (Examine (lock, fib))
len=fib->fib_Size;
FreeMem( fib, sizeof(*fib));
}
UnLock(lock);
}
return len;
}
#ifndef MIN
#define MIN(x,y) ((x)<(y)?(x):(y))
#endif
char **
and( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
{
char **av=(char **)malloc(MIN(ac1,ac2)*sizeof(char *) ), *str;
int i, j, k=0;
for( i=0; i<ac1; i++ )
for( j=0, str=base ? BaseName(av1[i]) : av1[i]; j<ac2; j++ )
if( !Strcmp(str, base ? BaseName(av2[j]) : av2[j]))
av[k++]=av1[i];
*ac=k;
return av;
}
char **
without( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
{
char **av=(char **)malloc(ac1*sizeof(char *) ), *str;
int i, j, k=0;
for( i=0; i<ac1; i++ ) {
for( j=0, str=base ? BaseName(av1[i]) : av1[i]; j<ac2; j++ )
if( !Strcmp(str, base ? BaseName(av2[j]) : av2[j] ) )
break;
if( j==ac2 )
av[k++]=av1[i];
}
*ac=k;
return av;
}
char **
or( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
{
char **av=(char **)malloc((ac1+ac2)*sizeof(char *) ), *str;
int i, j, k=0;
for( i=0; i<ac1; i++ )
av[k++]=av1[i];
for( i=0; i<ac2; i++ ) {
for( j=0, str=base ? BaseName(av2[i]) : av2[i]; j<ac1; j++ )
if( !Strcmp(str, base ? BaseName(av1[j]) : av1[j] ) )
break;
if( j==ac1 )
av[k++]=av2[i];
}
*ac=k;
return av;
}
void
clear_archive_bit( char *name )
{
struct DPTR *dp;
int stat;
if(dp = dopen(name,&stat) ) {
SetProtection( name, dp->fib->fib_Protection&~FIBF_ARCHIVE);
dclose( dp );
}
}
char *
itoa( int i )
{
static char buf[20];
char *pos=buf+19;
int count=4, flag=0;
if( i<0 )
flag=1, i=-i;
do {
if( !--count )
count=3, *--pos='\'';
*--pos= i%10+'0';
} while( i/=10 );
if( flag )
*--pos='-';
return pos;
}
char *
itok( int i )
{
static char buf[16], which;
char *exp=" KMG", *ptr= buf+(which=8-which);
do
i=(i+512)/1024, exp++;
while( i>1024 );
sprintf( ptr,"%d%c",i,*exp);
return ptr;
}
char *
next_a0( char *str )
{
while( *str && *str!=0xA0 && *str!='=' && *str!=',') str++;
return *str ? str+1 : NULL;
}
static int
gethex( char *str, int l )
{
int i, val=0, n, c;
if( *str=='.' ) return l==2 ? 256 : 0;
for( i=0; i<l || !l; i++ ) {
c=*str++;
if ( c>='0' && c<='9' ) n=c-'0';
else if( c>='a' && c<='f' ) n=c-'a'+10;
else if( c>='A' && c<='F' ) n=c-'A'+10;
else break;;
val=16*val+n;
}
return (l && i!=l) ? -1 : val;
}
strwrdcmp( char *str, char *wrd )
{
int len1=strlen(str);
char *ind=index(wrd,0xA0);
if( ind )
return len1!=ind-wrd || Strncmp(str,wrd,len1);
else
return Strcmp(str,wrd);
}
int
wrdlen( char *str )
{
char *old=str;
while( *str && *str!=0xA0 ) str++;
return str-old;
}
char *classfile;
char *
getclass(char *file)
{
CLASS *cl;
char *class, *str, *arg, *get, *buf;
int offs, byte, len, fail;
BPTR fh;
if( classfile ) {
char buf[80];
sprintf(buf,"source %s",classfile);
execute(buf);
classfile=0;
}
if( isdir(file) ) return "dir";
if( !(buf=calloc(1024,1))) return NULL;
if( !(fh=Open(file,MODE_OLDFILE))) return NULL;
len=Read( fh,buf,1023);
Close(fh);
for( cl=CRoot; cl; cl=cl->next ) {
class=cl->name;
if(!(str=next_a0(cl->name))) continue;
while( str ) {
if(!(arg=next_a0( str ))) goto nextclass;
switch( *str ) {
case 's':
if( (offs=strlen(file)-wrdlen(arg))<0 ) break;
if( !strwrdcmp(file+offs,arg)) goto found;
break;
case 'n':
if( !strwrdcmp(BaseName(file),arg) ) goto found;
break;
case 'd':
goto found;
case 'o':
offs=gethex(arg,0);
if( !(arg=index(arg,','))) goto nextclass;
if( offs>len-10 ) break;
for( get=buf+offs, ++arg; (byte=gethex(arg,2))>=0; arg+=2 )
if( *get++!=byte && byte!=256 )
goto nexttry;
goto found;
case 'c':
if( !len )
goto nexttry;
for( get=buf, fail=0; get<buf+len; get++ )
if( *get<9 || *get>13 && *get<32 || *get>127 )
fail++;
if( fail*8>len )
goto nexttry;
goto found;
case 'a':
goto nextclass;
default:
goto nextclass;
}
nexttry: str=next_a0(arg);
}
nextclass: ;
}
free(buf);
return NULL;
found:
free(buf);
return class;
}
char *
getaction( char *class, char *action )
{
CLASS *cl;
char *cur, *ind;
int len;
for( len=0; class[len] && class[len]!=0xA0; len++ ) ;
for( cl=CRoot; cl; cl=cl->next ) {
if( strncmp( cur=cl->name,class,len+1 ))
continue;
do
cur=index( cur,0xA0 );
while( cur && *++cur!='a');
if( cur && (cur=index( ++cur,0xA0 ))) {
do {
if( !(ind=index( ++cur,'=' )))
return NULL;
len=ind-cur;
if( len==strlen(action) && !strncmp(action,cur,len))
return ++ind;
} while( cur=index(cur,0xA0) );
}
}
return NULL;
}
int
doaction( char *file, char *action, char *args )
{
char *class, *com, *c, *copy;
if( !(class=getclass(file)))
return 10;
if( !(com=getaction(class,action)))
return 11;
if( c=index(com,0xA0) )
*c=0;
copy=malloc( strlen(com)+strlen(file)+strlen(args)+5 );
sprintf(copy,"%s %s %s",com,file,args);
execute(copy);
free(copy);
if( c )
*c=0xA0;
return 0;
}