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 / comm3.c < prev    next >
C/C++ Source or Header  |  1991-02-20  |  27KB  |  1,484 lines

  1. /*
  2.  * COMM3.C
  3.  *
  4.  * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  5.  * Version 5.00L by Urban Mueller 17-Feb-91
  6.  *
  7.  */
  8.  
  9. #include "shell.h"
  10.  
  11. /* comm3.c */
  12. static void doassign(char *log, char *phy);
  13. static void assignlist(void);
  14. static int strings_in_file(char *s);
  15. static int htype_a_file(char *s);
  16. static void install_menu(char **mav, int mac);
  17. static int line_filter( char *(*line)(char *) );
  18.  
  19. static int
  20. myfgets( char *buf, FILE *in )
  21. {
  22.     int l;
  23.     char *ret;
  24.     if( ret=fgets(buf,253,in) ) {
  25.         l=strlen(buf);
  26.         if( buf[l-1]!='\n' )
  27.             buf[l]='\n', buf[l+1]=0;
  28.     }
  29.     return ret!=NULL && !dobreak();
  30. }
  31.  
  32. do_tee( void )
  33. {
  34.     char buf[256];
  35.     FILE *out;
  36.  
  37.     prepscroll( ac==1 );
  38.     if( ac>2 ) { ierror( av[2], 500 ); return 20; }
  39.     if( ac==1 ) out=stderr;
  40.     else if( !(out=fopen( av[1], "w" ))) { pError( av[1] ); return 20; }
  41.     while (myfgets(buf,stdin)) {
  42.         fputs(buf, stdout);
  43.         quickscroll();
  44.         fprintf(out, "%s", buf);
  45.     }
  46.     if( ac!=1 ) fclose( out );
  47.     return 0;
  48. }
  49.  
  50. do_head( char *garbage, int com )
  51. {
  52.     int i, n;
  53.     FILE *f;
  54.     char buf[256];
  55.  
  56.     if (ac>2) {
  57.         n=(int)(long)Atol(av[2]);
  58.         if (IoErr()) {
  59.             ierror(av[2],511);
  60.             return 20;
  61.         }
  62.     } else n=10;
  63.  
  64.     f=fopen(av[1], "r");
  65.     if (f==NULL) {
  66.         pError(av[1]);
  67.         return 20;
  68.     }
  69.     if (com) {    /* tail specific part */
  70.         i=0;
  71.         while (fgets(buf, 256, f) && ! dobreak()) i++;
  72.         rewind(f);
  73.         if (n>i) n=i;
  74.         i=i-n;
  75.         while (i-- && fgets(buf, 256, f) && ! dobreak()) ;
  76.     }
  77.     for (i=1; i<=n && fgets(buf, 256, f) && ! dobreak(); i++)
  78.         printf("%s", buf);
  79.     fclose(f);
  80.     return 0;
  81. }
  82.  
  83. static int
  84. exword( char **src, char *buf )
  85. {
  86.     *buf=0;
  87.     if( **src==0 ) return 0;
  88.     while( **src && **src!=',' )
  89.         *buf++=*(*src)++;
  90.     *buf=0; (*src)++;
  91.     return 1;
  92. }
  93.  
  94. static char helpfound=0;
  95.  
  96. void
  97. man( FILE *f, char *s)
  98. {
  99.     char buf[140], entry[100];
  100.     int len=sprintf(entry, "    %s", s);
  101.  
  102.     prepscroll(0);
  103.     rewind(f);
  104.     do                                  /* look for required argument */
  105.         if (fgets(buf, 140, f) == NULL)
  106.             return;
  107.     while ( Strncmp(entry, buf, len) );
  108.     helpfound=1;
  109.     do {                                /* display help */
  110.         quickscroll();
  111.         printf("%s", buf);
  112.         if (fgets(buf, 140, f) == NULL) return;
  113.     } while ( ( !isalphanum(*buf) ) && strncmp(buf, "    ", 4) && !dobreak() );
  114. }
  115.  
  116.  
  117. do_man( void )
  118. {
  119.     FILE *f;
  120.     int i;
  121.     char buf[200], name[60], *src, *var;
  122.  
  123.     buf[0]=0;
  124.     if( var=get_var(LEVEL_SET,"_man" ) )
  125.         strcpy(buf,var);
  126.  
  127.     if (ac==1) ac=2, av[1]="MAN";
  128.     for (i=1; i<ac; i++) {
  129.         src=buf, helpfound=0;
  130.         while( exword( &src, name) )
  131.             if( f=fopen(name, "r") ) {
  132.                 man(f, av[i]);
  133.                 fclose(f);
  134.             }
  135.         if( !helpfound )
  136.             fprintf(stderr, "Help not found for %s\n", av[i]);
  137.     }
  138.     return 0;
  139. }
  140.  
  141. do_assign( void )
  142. {
  143.     int i;
  144.  
  145.     if     (  ac==1  ) assignlist();
  146.     else if(  ac==2  ) doassign(av[1], NULL);
  147.     else if( !(ac&1) ) ierror(NULL, 500);
  148.     else
  149.         for( i=1; i<ac; i+=2 )
  150.             doassign( av[i],av[i+1] );
  151.     return 0;
  152. }
  153.  
  154. static char *assign_errors[4]={
  155.     "",
  156.     "Name %s is not valid\n",
  157.     "Weird error\n",
  158.     "Can't cancel %s\n"
  159.     };
  160.  
  161.  
  162. static void
  163. doassign(char *log, char *phy)
  164. {
  165.     int last=strlen(log) - 1;
  166.  
  167.     if (log[last] != ':') fprintf(stderr, "Bad name %s\n", log);
  168.     else {
  169.         log[last] = 0;
  170.         if( options && phy && o_kick20 ) {
  171.             int succ=0;
  172.             if     ( options&1 ) succ=AssignLate( log,phy );
  173.             else if( options&2 ) succ=AssignPath( log,phy );
  174.             if( !succ )
  175.                 pError( log );
  176.         } else 
  177.             fprintf(stderr,assign_errors[Assign(log, phy)],phy);
  178.     }
  179. }
  180.  
  181. static void
  182. assignlist()
  183. {
  184.     struct DirectoryEntry *de_head=NULL, *de;
  185.     char buf[256];
  186.     BPTR lock;
  187.     int ctr=0;
  188.  
  189.     AddDADevs(&de_head, DLF_DEVICES | DLF_VOLUMES | DLF_DIRS);
  190.     printf("Devices:\n");
  191.     for (de=de_head; de && de->de_Type==DLX_DEVICE; de=de->de_Next) {
  192.         printf("%-8s",de->de_Name);
  193.         if (ctr++ == 5) { ctr=0; printf("\n"); }
  194.     }
  195.     printf("\n\nVolumes:\n");
  196.     for (    ;
  197.         de && (de->de_Type==DLX_VOLUME || de->de_Type==DLX_UNMOUNTED);
  198.         de=de->de_Next
  199.     )
  200.     printf( "%-16s %s\n",
  201.         de->de_Name,
  202.         de->de_Type == DLX_VOLUME ? "[Mounted]" : ""
  203.     );
  204.     printf("\nDirectories:\n");
  205.     for (; de && de->de_Type==DLX_ASSIGN; de=de->de_Next) {
  206.         if (lock=Lock(de->de_Name, ACCESS_READ)) {
  207.             PathName(lock, buf, 256L);
  208.             UnLock(lock);
  209.         }
  210.         else
  211.             strcpy(buf,"Unexisting lock");
  212.         printf("%-20s%s\n",de->de_Name,buf);
  213.     }
  214.     FreeDAList(de_head);
  215. }
  216.  
  217. do_join( void )
  218. {
  219.     BPTR sou, dest;
  220.     char *buffer;
  221.     int i;
  222.     long n;
  223.     char *namedest=av[--ac];
  224.  
  225.     if (options==0 && exists(namedest)) { ierror(namedest,203); return 20; }
  226.     if ( (buffer=malloc(8192)) == NULL ) { ierror(NULL,103); return 20; }
  227.     if ( (dest=Open(namedest, MODE_NEWFILE)) == NULL )
  228.         { pError(namedest); goto fail1; }
  229.     for (i=1; i<ac; i++) {
  230.         if ( (sou=Open(av[i], MODE_OLDFILE)) == NULL ) pError(av[i]);
  231.         else
  232.             while( (n=Read(sou, buffer, 8192L)) > 0 )
  233.                 if (Write(dest, buffer, n) != n)
  234.                     { pError(namedest); Close(sou); goto fail2; }
  235.         Close(sou);
  236.     }
  237. fail2:
  238.     Close(dest);
  239. fail1:
  240.     free(buffer);
  241.     return 0;
  242. }
  243.  
  244. #define BUFDIM 512L
  245. #define MAXSTR 256
  246.  
  247. int minstr;
  248.  
  249. static int
  250. strings_in_file(char *s)
  251. {
  252.     char c;
  253.     char readbuf[BUFDIM+1], strbuf[MAXSTR+1];
  254.     int i, strctr=0;
  255.     BPTR fh;
  256.     int out, n;
  257.  
  258.     prepscroll(0);
  259.     if ( fh=Open(s, MODE_OLDFILE) ) {
  260.         fprintf(stderr, "Strings in %s (len>=%d):\n",s,minstr);
  261.         while ( (n=(int)Read(fh, readbuf, BUFDIM)) > 0 && !CHECKBREAK() )
  262.             for (i=0; i<n; i++) {
  263.                 c=readbuf[i];
  264.                 if (c<0x20 || c>0x7f) {
  265.                     out=(strctr>=minstr);
  266.                     if (!out) strctr=0;
  267.                 } else {
  268.                     strbuf[strctr++]=c;
  269.                     out=(strctr>=BUFDIM);
  270.                 }
  271.                 if (out) {
  272.                     strbuf[strctr]='\0';
  273.                     puts(strbuf);
  274.                     quickscroll();
  275.                     strctr=0;
  276.                 }
  277.             }
  278.         Close(fh);
  279.     } else
  280.         pError(s);
  281.     return 0;
  282. }
  283.  
  284. do_strings( void )
  285. {
  286.     minstr=myatoi(av[--ac],1,255);
  287.     all_args( strings_in_file, 0);
  288.     return 0;
  289. }
  290.  
  291. BPTR myfile[MAXMYFILES];
  292.  
  293. do_open( void )
  294. {
  295.     long mode;
  296.     int n;
  297.  
  298.     switch (toupper(av[2][0])) {
  299.         case 'R': mode=MODE_OLDFILE; break;
  300.         case 'W': mode=MODE_NEWFILE; break;
  301.         default : ierror(NULL,500); return 1;
  302.     }
  303.     n=myatoi(av[3],0,MAXMYFILES-1); if (atoierr) return 20;
  304.     if (myfile[n]) myclose(n);
  305.     myfile[n]=Open(av[1],mode);
  306.     return myfile[n]==NULL;
  307. }
  308.  
  309. do_close( void )
  310. {
  311.     int i, n;
  312.  
  313.     if (ac==1)
  314.         for (i=1; i<MAXMYFILES; i++)
  315.             myclose(i);
  316.     for (i=1; i<ac; i++) {
  317.         n=myatoi(av[i],0,MAXMYFILES-1); if (atoierr) return 20;
  318.         myclose(n);
  319.     }
  320.     return 0;
  321. }
  322.  
  323. void
  324. myclose(int n)
  325. {
  326.     if (myfile[n]) { Close(myfile[n]); myfile[n]=NULL; }
  327. }
  328.  
  329. do_fileslist( void )
  330. {
  331.     int i, flag=0;
  332.  
  333.     printf("Open files:");
  334.     for (i=0; i<MAXMYFILES; i++)
  335.         if (myfile[i]) { printf(" %d",i); flag=1; }
  336.     if (!flag) printf(" None!");
  337.     printf("\n");
  338.     return 0;
  339. }
  340.  
  341. BPTR
  342. extOpen( char *name, long mode )
  343. {
  344.     if (name[0]=='.') return myfile[atoi(name+1)];
  345.     return Open(name,mode);
  346. }
  347.  
  348. void
  349. extClose(BPTR fh)
  350. {
  351.     int i;
  352.  
  353.     for (i=0; i<MAXMYFILES; i++)
  354.         if (myfile[i]==fh) return;
  355.     Close(fh);
  356. }
  357.  
  358. do_basename( void )
  359. {
  360.     set_var(LEVEL_SET, av[1], BaseName(av[2]));
  361.     return 0;
  362. }
  363.  
  364. do_tackon( void )
  365. {
  366.     char buf[256];
  367.  
  368.     strcpy(buf, av[2]);
  369.     TackOn(buf, av[3]);
  370.     set_var(LEVEL_SET, av[1], buf);
  371.     return 0;
  372. }
  373.  
  374. extern char shellres[];
  375.  
  376. do_resident( void )
  377. {
  378.     int i=1;
  379.     struct ResidentProgramNode *p;
  380.     char buf[256];
  381.  
  382.     if (options==0 && ac>1) options=1;
  383.     switch (options) {
  384.     case 0:
  385.         ObtainSemaphore (& (ArpBase->ResPrgProtection) );
  386.         if (p=ArpBase->ResidentPrgList) {
  387.             printf("Name             Users Access\n");
  388.             for (; p; p=p->rpn_Next)
  389.                 printf("%-17s%5d%6d\n",
  390.                     p->rpn_Name, p->rpn_Usage, p->rpn_AccessCnt);
  391.         } else
  392.             printf("No resident program(s)\n");
  393.         ReleaseSemaphore(& (ArpBase->ResPrgProtection) );
  394.         break;
  395.     case 1:
  396.         for (; i<ac; i++)
  397.             if (loadres(av[i]))
  398.                 printf("OK! %s is now resident\n", BaseName(av[i]));
  399.             else
  400.                 pError(av[i]);
  401.         break;
  402.     case 2:
  403.         for (; i<ac; i++)
  404.             if (RemResidentPrg(av[i])) ierror(av[i],202);
  405.             else printf("Removed %s\n",av[i]);
  406.         break;
  407.     case 4:
  408.         for (; i<ac; i++) {
  409.             if( !o_resident ) {
  410.                 Setenv(shellres,"1");
  411.                 o_resident=1;
  412.             }
  413.             sprintf(buf,"res_%s",av[i]);
  414.             Setenv(buf,"1");
  415.         }
  416.         break;
  417.     default:
  418.         ierror(NULL,500);
  419.         break;
  420.     }
  421.     return 0;
  422. }
  423.  
  424. int
  425. loadres(char *s)
  426. {
  427.     BPTR seg;
  428.  
  429.     if (seg=(BPTR)LoadPrg(s)) AddResidentPrg(seg,BaseName(s));
  430.     return (seg != NULL);
  431. }
  432.  
  433. struct ProcessControlBlock pcb={
  434.     4000,        /* pcb_StackSize    */
  435.     0,            /* pcb_Pri            */
  436.     };
  437. /* remaining field are NULL */
  438.     
  439. do_truerun(char *avline, int backflag)
  440. {
  441.     char name[200], *args;
  442.  
  443.     if (backflag) {
  444.         pcb.pcb_Control=NULL;
  445.         pcb.pcb_Input=pcb.pcb_Output=Open("NIL:",MODE_OLDFILE);
  446.     } else {
  447.         pcb.pcb_Control=NULL;
  448.         pcb.pcb_Input=pcb.pcb_Output =NULL;
  449.     }
  450.     args=next_word(next_word(avline));
  451.  
  452.     if(ASyncRun(av[1],args,&pcb)<0)
  453.         if (dofind(av[1], "", name,v_path))
  454.             ASyncRun(name,args,&pcb);
  455.         else
  456.             ierror(av[1],205);
  457.     return 0;
  458. }
  459.  
  460. int
  461. exists( char *name )
  462. {
  463.     BPTR lock;
  464.  
  465.     if (lock=Lock(name,ACCESS_READ)) {
  466.         UnLock(lock);
  467.         return 1;
  468.     }
  469.     return 0;
  470. }
  471.  
  472. do_aset( void )
  473. {
  474.     Setenv(av[1],av[2]);
  475.     return 0;
  476. }
  477.  
  478. #define HTYPELINE 16L
  479.  
  480. static int
  481. htype_a_file( char *s )
  482. {
  483.     BPTR fh;
  484.     long n, filesize=0;
  485.     char buf[HTYPELINE+1];
  486.     char out[80], *put;
  487.     int i;
  488.  
  489.     if ( (fh=Open(s,MODE_OLDFILE))==NULL ) { pError(s); return 20; }
  490.     prepscroll(0);
  491.     while ( (n=Read(fh,buf,HTYPELINE))>0 && !dobreak()) {
  492.         put=out;
  493.         put+=sprintf(put,"%06lx: ",filesize);
  494.         filesize+=n;
  495.         for (i=0; i<n; i++) {
  496.             put+=sprintf( put,(i&3) ? "%02x" : " %02x",buf[i]);
  497.             if ((buf[i]&127)<0x20) buf[i]='.';
  498.         }
  499.         for ( ; i<HTYPELINE; i++) {
  500.             put+=sprintf( put, (i&3) ? "  " : "   ");
  501.             buf[i]=' ';
  502.         }
  503.         buf[i]=0;
  504.         sprintf(put,"    %s",buf);
  505.         puts(out);
  506.         quickscroll();
  507.     }
  508.     Close(fh);
  509.     return 0;
  510. }
  511.  
  512. do_htype( void )
  513. {
  514.     all_args( htype_a_file, 0);
  515.     return 0;
  516. }
  517.  
  518. do_stack( void )
  519. {
  520.     long n;
  521.  
  522.     if (ac>1) {
  523.         n=Atol(av[1]);
  524.         if (!IoErr()) Mycli->cli_DefaultStack=(long)(n >> 2L);
  525.     }
  526.     else printf("current stack size is %ld bytes\n",
  527.                 (long)Mycli->cli_DefaultStack << 2L);
  528.     return 0;
  529. }
  530.  
  531. do_fault( void )
  532. {
  533.     struct PERROR *p;
  534.     int i, n;
  535.  
  536.     for (i=1; i<ac; i++) {
  537.         n=myatoi(av[i],0,32767);
  538.         if (!atoierr) {
  539.             for (p=Perror; p->errnum && p->errnum!=n; p++);
  540.             if (p->errnum)
  541.                 printf("Fault %d: %s\n",n,p->errstr);
  542.             else
  543.                 printf("Fault %d not recognized\n",n);
  544.         }
  545.     }
  546.     return 0;
  547. }
  548.  
  549. struct rpncommand {
  550.     char *str;
  551.     int parsin, parsout;
  552.     };
  553.  
  554. static struct rpncommand rpn[]={
  555.     "+",    2,    1,
  556.     "-",    2,    1,
  557.     "*",    2,    1,
  558.     "/",    2,    1,
  559.     "%",    2,    1,
  560.     "&",    2,    1,
  561.     "|",    2,    1,
  562.     "~",    1,    1,
  563.     ">",    2,    1,
  564.     "<",    2,    1,
  565.     "==",    2,    1,
  566.     "!",    1,    1,
  567.     "MAX",    2,    1,
  568.     "MIN",    2,    1,
  569.     "DUP",    1,    2,
  570.     "DROP",    1,    0,
  571.     "SWAP",    2,    2,
  572.     "HELP",    0,    0,
  573.     NULL,    0,    1,    /* this looks for a number */
  574. };
  575.  
  576. static long stack[50];
  577. static int sp;
  578.  
  579.  
  580. eval_rpn( char **av, int ac, int flag )
  581. {
  582.     char *zero="Division by zero\n";
  583.     struct rpncommand *temp;
  584.     long n0, n1, t;
  585.     int j, i=0, oldsp=sp;
  586.  
  587.     for (; i<ac; i++) {
  588.         for (j=0; rpn[j].str && Strcmp(rpn[j].str,av[i]); j++) ;
  589.         n0=stack[sp-1];
  590.         n1=stack[sp-2];
  591.         sp -= (rpn[j].parsin);
  592.         if (sp<0) { fprintf(stderr, "RPN: Empty stack\n"); goto error; }
  593.         switch (j) {
  594.           case 0:    n0 += n1;            break;
  595.           case 1:    n0 = n1-n0;            break;
  596.           case 2:    n0 *= n1;            break;
  597.           case 3:    if(n0) n0=n1/n0; else fprintf(stderr,zero); break;
  598.           case 4:    if(n0) n0=n1%n0; else fprintf(stderr,zero); break;
  599.           case 5:    n0 &= n1;            break;
  600.           case 6:    n0 |= n1;            break;
  601.           case 7:    n0 =  ~n0    ;        break;
  602.           case 8:    n0 = (n1 > n0);        break;
  603.           case 9:    n0 = (n1 < n0);        break;
  604.           case 10:    n0 = (n0 == n1);    break;
  605.           case 11:    n0 = !n0;            break;
  606.           case 12:    n0=n1>n0 ? n1 : n0;    break;
  607.           case 13:    n0=n1<n0 ? n1 : n0;    break;
  608.           case 14:    n1=n0;                break;
  609.           case 15:    t=n0; n0=n1; n1=t;    break;
  610.           case 16:                        break;
  611.           case 17:    printf("In Commands Out\n");
  612.             for (temp=rpn; temp->str; temp++)
  613.                 printf(" %d %-10s%d\n",
  614.                 temp->parsin,temp->str,temp->parsout);
  615.             break;
  616.           default:    n0=Atol(av[i]);
  617.                 if (IoErr()) {
  618.                     fprintf(stderr, "Bad RPN cmd: %s\n",av[i]);
  619.                     goto error;
  620.                 }
  621.                 break;
  622.           }
  623.         stack[sp]=n0;
  624.         stack[sp+1]=n1;
  625.         sp += rpn[j].parsout;
  626.     }
  627.     if( flag && sp-1) fprintf( stderr, "RPN: Stack not empty\n" );
  628.  
  629. exit:
  630.     t=sp; sp=oldsp;
  631.     if( flag )
  632.         return stack[t-1]; /* return top value */
  633.     else 
  634.         return t-sp;
  635.  
  636. error:
  637.     sp=oldsp;
  638.     return 0;
  639. }
  640.  
  641.  
  642. do_rpn(char *garbage,int ifflag) /* ifflag!=0 if called from if */
  643. {
  644.     int i=1;
  645.     long t;
  646.  
  647.     t=eval_rpn( av+i, ac-i, ifflag );
  648.     if (ifflag) return t;              /* called from if: return top value */
  649.     for (i=sp+t-1;i>=sp;i--) printf("%ld\n", stack[i]);/* else print stack */
  650.  
  651.     return t ? 0 : 20;
  652. }
  653.  
  654. do_path( void )
  655. {
  656.     ULONG ll, ll1, *lp, new, *newp;
  657.     char buf[256];
  658.     char buf2[256];
  659.     BPTR lock;
  660.     int i;
  661.  
  662.     if( options&1 ) {
  663.         Forbid();
  664.         for( ll= Mycli->cli_CommandDir; ll; ll= ll1 ) {
  665.             lp=(ULONG *)(4*ll);
  666.             ll1=*lp;
  667.             DosFreeMem( lp );
  668.         }
  669.         Mycli->cli_CommandDir=0;
  670.         Permit();
  671.     } else if( ac==1 ) {     /* Should Forbid() here, but puts() Permit()s */
  672.         puts("Current dir"); /* and failure here is not really harmful...  */
  673.         for( ll= Mycli->cli_CommandDir; ll; ll= *lp ) {
  674.             lp=(ULONG *)(4*ll);
  675.             PathName(lp[1], buf, 256L);
  676.             puts(buf);
  677.         }
  678.         puts("C:");
  679.         return 0;
  680.     }
  681.     Forbid();
  682.     for( i=1; i<ac; i++ ) {
  683.         if( !(lock=Lock(av[i],ACCESS_READ)) ) {
  684.             pError(av[i]);
  685.             continue;
  686.         }
  687.         PathName(lock, buf, 256L);
  688.         for( ll= Mycli->cli_CommandDir, lp=NULL; ll; ll= *lp ) {
  689.             lp=(ULONG *)(4*ll);
  690.             PathName(lp[1],buf2,256L);
  691.             if( !Strcmp(buf,buf2) ) {
  692.                 UnLock(lock);
  693.                 break;
  694.             }
  695.         }
  696.         if( !ll ) {
  697.             newp=DosAllocMem( 8 );
  698.             newp[1]=lock;
  699.             new =(ULONG)newp/4;
  700.             if( lp )
  701.                 *lp=new;
  702.             else
  703.                 Mycli->cli_CommandDir=new;
  704.         }
  705.     }
  706.     Permit();
  707.     return 0;
  708. }
  709.  
  710. do_pri( void )
  711. {
  712.     int t, pri;
  713.     struct Process *proc;
  714.  
  715.     t=(int)(long)FindCLI(0L);
  716.     t=myatoi(av[1],0,t); if (atoierr) return 20;
  717.     pri=myatoi(av[2],-128,127); if (atoierr) return 20;
  718.     Forbid();
  719.     proc=(t==0 ? Myprocess : FindCLI((long)t));
  720.     if (proc==NULL) fprintf(stderr, "process not found\n");
  721.     else SetTaskPri((struct Task *)proc, (long)pri);
  722.     Permit();
  723.     return 0;
  724. }
  725.  
  726. do_strleft( void )
  727. {
  728.     int n;
  729.  
  730.     n=posatoi(av[3]); if (atoierr) return 20;
  731.     set_var_n(LEVEL_SET, av[1], av[2], n);
  732.     return 0;
  733. }
  734.  
  735. do_strright( void )
  736. {
  737.     int n, len=strlen(av[2]);
  738.  
  739.     n=posatoi(av[3]); if (atoierr) return 20;
  740.     if( n>len ) n=len;
  741.     set_var(LEVEL_SET, av[1], av[2]+len-n );
  742.     return 0;
  743. }
  744.  
  745. do_strmid( void )
  746. {
  747.     int n1, n2=999999, len=strlen(av[2]);
  748.  
  749.     n1=myatoi(av[3],1,999999)-1; if (atoierr) return 20;
  750.     if (n1>len) n1=len;
  751.     if (ac>4) {
  752.         n2=posatoi(av[4]); if (atoierr) return 20;
  753.     }
  754.     set_var_n(LEVEL_SET, av[1], av[2]+n1, n2);
  755.     return 0;
  756. }
  757.  
  758. do_strlen( void )
  759. {
  760.     char buf[16];
  761.  
  762.     sprintf(buf,"%d",strlen(av[2]));
  763.     set_var(LEVEL_SET, av[1], buf);
  764.     return 0;
  765. }
  766.  
  767. int atoierr;
  768.  
  769. myatoi(s,min,max)
  770. char *s;
  771. {
  772.     int n;
  773.  
  774.     n=Atol(s);
  775.     if (atoierr=IoErr())
  776.         ierror(s,511);
  777.     else if (n<min || n>max) {
  778.         atoierr=1; n=min;
  779.         fprintf( stderr, "%s(%d) not in (%d,%d)\n",s,n,min,max );
  780.     }
  781.     return n;
  782. }
  783.  
  784. unlatoi(char *s)
  785. {
  786.     int n=Atol(s);
  787.     if (atoierr=IoErr())
  788.         ierror(s,511), n=0;
  789.     return n;
  790. }
  791.  
  792. posatoi(char *s)
  793. {
  794.     int n=Atol(s);
  795.     if (atoierr=IoErr())
  796.         ierror(s,511);
  797.     else if (n<0 )
  798.         atoierr=1, n=0, fprintf( stderr, "%s must be positive\n",s );
  799.     return n;
  800. }
  801.  
  802.  
  803. do_fltlower( void )
  804. {
  805.     return line_filter( strlwr );
  806. }
  807.  
  808. do_fltupper( void )
  809. {
  810.     return line_filter( strupr );
  811. }
  812.  
  813. #if 0
  814. char *
  815. stripcr( char *get )
  816. {
  817.     char *old=get, *put;
  818.  
  819.     for( put=get; *get; get++ )
  820.         if( *get!=13 )
  821.             *put++=*get;
  822.     *put++=0;
  823.     return old;
  824. }
  825.  
  826. do_fltstripcr( void )
  827. {
  828.     return line_filter( stripcr );
  829. }
  830. #endif
  831.  
  832. int
  833. line_filter( char *(*func)( char * ) )
  834. {
  835.     char buf[256];
  836.  
  837.     while (!CHECKBREAK() && gets(buf))
  838.         puts((*func)(buf));
  839.     return 0;
  840. }
  841.  
  842. do_linecnt( void )
  843. {
  844.     int count=0;
  845.     char buf[256];
  846.  
  847.     while (!CHECKBREAK() && gets(buf)) ++count;
  848.     printf("%d lines\n",count);
  849.     return 0;
  850. }
  851.  
  852. do_uniq( void )
  853. {
  854.     int firstline=1;
  855.     char buf[256], oldbuf[256];
  856.  
  857.     while (!CHECKBREAK() && gets(buf)) {
  858.         if ( firstline || strcmp(buf, oldbuf)) {
  859.             strcpy(oldbuf, buf);
  860.             puts(buf);
  861.         }
  862.         firstline=0;
  863.     }
  864.     return 0;
  865. }
  866.  
  867.  
  868. #define RXFB_RESULT  17
  869.  
  870. static struct rexxmsg {
  871.     struct Message cm_Node;
  872.     LONG   RFU1;
  873.     LONG   RFU2;
  874.     LONG   rm_Action;
  875.     LONG   rm_Result1;
  876.     LONG   rm_Result2;
  877.     char   *cm_Args[16];
  878.     LONG   RFU7;
  879.     LONG   RFU8;
  880.     LONG   RFU9;
  881.     LONG   RFU10;
  882.     LONG   RFU11;
  883.     LONG   RFU12;
  884. } mymsg;
  885.  
  886. do_rxsend( char *avline )
  887. {
  888.     int i;
  889.     long result;
  890.     struct MsgPort *port, *reply;
  891.     long len;
  892.     char buf[20], *resptr;
  893.  
  894.     if (!(port = FindPort(av[1])))
  895.         { fprintf(stderr, "No port %s!\n", av[1]); return 20; }
  896.     mymsg.cm_Node.mn_Node.ln_Type = NT_MESSAGE;
  897.     mymsg.cm_Node.mn_Length = sizeof(struct rexxmsg);
  898.     mymsg.rm_Action = (options&1 ? 1L << RXFB_RESULT : 0);
  899.     if (!(reply = CreatePort(NULL, 0L))) {
  900.         fprintf(stderr, "No reply port\n");
  901.         return 20;
  902.     }
  903.     mymsg.cm_Node.mn_ReplyPort = reply;
  904.  
  905.     if( options&2 )
  906.         av[2]=compile_av( av,2,ac,' ',0), ac=3;
  907.     for ( i=2; i<ac; i++) {
  908.         mymsg.cm_Args[0] = av[i];
  909.         mymsg.rm_Result2 = 0;        /* clear out the last result. */
  910.         PutMsg(port, &mymsg.cm_Node);
  911.         WaitPort(reply);
  912.  
  913.         if (options&1) {
  914.             if( (result=mymsg.rm_Result2)<1000000 ) { /* so does it AREXX */
  915.                 sprintf(buf,"%d",result);              
  916.                 set_var(LEVEL_SET,v_result,buf);
  917.             } else {
  918.                 resptr=(char *)(result-4);
  919.                 len=*(long *)resptr;
  920.                 memmove(resptr,resptr+4,len);  /* Null terminate */
  921.                 resptr[len]=0;      
  922.                 set_var(LEVEL_SET,v_result,resptr);
  923.                 FreeMem(resptr, len+4 );
  924.             }
  925.         } else 
  926.             unset_var( LEVEL_SET, v_result );
  927.     }
  928.     if( options&2 )
  929.         free( av[2] );
  930.  
  931.     if (reply) DeletePort(reply);
  932.     return 0;
  933. }
  934.  
  935. static char *rxreturn;
  936.  
  937. do_rxrec( void )
  938. {
  939.     struct MsgPort *port;
  940.     struct rexxmsg *msg;
  941.     char *portname, *str;
  942.  
  943.     if (ac > 1)
  944.         portname=av[1];
  945.     else
  946.         portname="rexx_csh";
  947.  
  948.     port=CreatePort(portname, 0L);
  949.     if (port==NULL) {
  950.         fprintf(stderr, "Can't have MsgPort %s\n", portname);
  951.         return 20;
  952.     }
  953.     for (;;) {
  954.         WaitPort(port);
  955.         while (msg=(struct rexxmsg *)GetMsg(port)) {
  956.             if ( ! Strcmp(msg->cm_Args[0], "bye")) {
  957.                 ReplyMsg((struct Message *)msg);
  958.                 DeletePort(port);
  959.                 return 0;
  960.             }
  961.             rxreturn=NULL;
  962.             exec_command(msg->cm_Args[0]);
  963.             if (msg->rm_Action & (1L << RXFB_RESULT)) {
  964.                 if( rxreturn ) {
  965.                     str= AllocMem( strlen( rxreturn )+5 , 0 );
  966.                     *(long *)str=strlen( rxreturn );
  967.                     strcpy( str+4, rxreturn );
  968.                     msg->rm_Result2=(long)str;
  969.                 } else {
  970.                     str = get_var(LEVEL_SET, v_lasterr);
  971.                     msg->rm_Result2=(str) ? atoi(str) : 20;
  972.                 }
  973.             }
  974.             ReplyMsg((struct Message *)msg);
  975.         }
  976.     }
  977. }
  978.  
  979. int
  980. do_waitport( void )
  981. {
  982.     int count=4*10;
  983.     struct MsgPort *port;
  984.  
  985.     if( ac==3 ) 
  986.         { count=2*myatoi(av[2],0, 32000); if( atoierr ) return 20; }
  987.  
  988.     while( --count>=0 && !(port=FindPort(av[1])) && !dobreak() )
  989.         Delay(12);
  990.  
  991.     return port ? 0 : 20;
  992. }
  993.  
  994. int
  995. do_rxreturn( void )
  996. {
  997.     rxreturn=compile_av( av, 1, ac, ' ', 1 );
  998.     return 0;
  999. }
  1000.  
  1001. do_ascii( void )
  1002. {
  1003.     int x=1, y, c, c1, t;
  1004.     char *fmt1=" %3d %c%c |", *fmt2=" %4d";
  1005.  
  1006.     if( options&1 ) fmt1=" %3o %c%c |", fmt2="%4o";
  1007.     if( options&2 ) fmt1=" %3x %c%c |", fmt2="%4x";
  1008.     if( ac==x )
  1009.         for( y=0; y<32 && !dobreak(); y++ ) {
  1010.             printf("|");
  1011.             for( x=0; x<8; x++ ) {
  1012.                 c1=c=y+32*x; t=' ';
  1013.                 if( c<32 ) t='^', c1+=64;
  1014.                 printf(fmt1,c, t, c1<128 || c1>=160?c1:'.');
  1015.             }
  1016.             printf("\n");
  1017.         }
  1018.     else 
  1019.         for( ; x<ac && !dobreak(); x++ ) {
  1020.             for( y=0; y<strlen(av[x]); y++ )
  1021.                 printf(fmt2,av[x][y]);
  1022.             printf("\n");
  1023.         }
  1024.     return 0;
  1025. }
  1026.  
  1027. void
  1028. appendslash( char *path )
  1029. {
  1030.     int c;
  1031.  
  1032.     if( (c=path[strlen(path)-1]) !='/' && c!=':' )
  1033.         strcat(path,"/");
  1034. }
  1035.  
  1036. static void
  1037. whereis( char *path, char *file )
  1038. {
  1039.     char **eav, buf[100];
  1040.     int  eac, j;
  1041.  
  1042.     buf[0]=0;
  1043.     if( path ) {
  1044.         strcpy(buf,path);
  1045.         appendslash(buf);
  1046.     }
  1047.     strcat(buf,".../");
  1048.     strcat(buf,file);
  1049.     if( !index( file, '*' ) && !index( file, '?') )
  1050.         strcat(buf,"*");
  1051.     if(eav=expand(buf,&eac)) {
  1052.         for( j=0; j<eac && !dobreak(); j++ )
  1053.             printf("%s\n",eav[j]);
  1054.         free_expand(eav);
  1055.     }
  1056. }
  1057.  
  1058. do_whereis( void )
  1059. {
  1060.     char buf[200], *prev, *devs;
  1061.     int i;
  1062.  
  1063.     if( index( av[1],':') || index( av[1],'/' ) )
  1064.         { fprintf(stderr,"No paths please\n"); return 20; };
  1065.  
  1066.     if( options&1 ) {
  1067.         Myprocess->pr_WindowPtr = (APTR)(-1);
  1068.         get_drives( devs=buf );
  1069.         do {
  1070.             prev=devs; devs=index(devs,0xA0);
  1071.             if( devs ) *devs++=0; 
  1072.             whereis( prev, av[1] );
  1073.         } while( devs );
  1074.         Myprocess->pr_WindowPtr = (APTR) o_noreq;
  1075.     } else if( ac==2 ) {
  1076.         whereis( NULL, av[1] );
  1077.     } else {
  1078.         for( i=2; i<ac; i++ ) {
  1079.             strcpy(buf,av[i]);
  1080.             appendslash( buf );
  1081.             whereis( buf, av[1] );
  1082.         }
  1083.     }
  1084.     return 0;
  1085. }
  1086.  
  1087. do_usage( void )
  1088. {
  1089.     int i;
  1090.  
  1091.     if( ac==1 ) {
  1092.         printf("Usage: usage [command...command]\n");
  1093.         printf("[ ]=option   [ | ]=choice   { }=repetition   name...name=1 or more names\n");
  1094.     } else 
  1095.         for( i=1; i<ac; i++ )
  1096.             show_usage( av[i] );
  1097.     return 0;
  1098. }
  1099.  
  1100. int NumMenus;
  1101.  
  1102. do_menu( void )
  1103. {
  1104.     if( o_nowindow )
  1105.         return 5;
  1106.  
  1107.     if( options&1 )
  1108.         remove_menu();
  1109.  
  1110.     if( ac==2 )
  1111.         show_usage( NULL );
  1112.     else if( NumMenus<MAXMENUS && ac!=1)
  1113.         install_menu( av+1, ac-1 );
  1114.  
  1115.     set_menu();
  1116.     return 0;
  1117. }
  1118.  
  1119. #define NUMITE 40
  1120. #define TITWID 90
  1121. #define ITEWID 148
  1122.  
  1123. static struct Menu DefaultMenu= {0, 0,0,TITWID,10, MENUENABLED,0,0};
  1124. static struct IntuiText DefaultIntuiText= {0,1,JAM2, 1,1,NULL,0,0};
  1125. static struct MenuItem DefaultMenuItem=
  1126.   {0, 0,0,ITEWID,0, HIGHCOMP|ITEMTEXT|ITEMENABLED,0,0,0,0,0,0};
  1127.  
  1128. struct Menu Menus[10];
  1129. char *MenuCommand[MAXMENUS][MAXITEMS];
  1130.  
  1131. extern char *rindex();
  1132.  
  1133. static void
  1134. install_menu( char *mav[], int mac )
  1135. {
  1136.     struct TextAttr *ta;
  1137.     struct Menu *m;
  1138.     struct MenuItem *mi, **pmi;
  1139.     struct IntuiText *it;
  1140.     int y, i, fonthei;
  1141.     char *p, *com;
  1142.  
  1143.     if( o_nowindow || !Win )
  1144.         return;
  1145.  
  1146.     if( mac>=MAXITEMS )
  1147.         mac=MAXITEMS-1;
  1148.  
  1149.     ClearMenuStrip( Win );
  1150.     Delay(3);
  1151.  
  1152.     if( NumMenus )
  1153.         Menus[NumMenus-1].NextMenu=Menus+NumMenus;
  1154.     m  =&Menus[NumMenus];
  1155.     *m =DefaultMenu;
  1156.     m->LeftEdge  = NumMenus*TITWID;
  1157.     m->MenuName  = strcpy(malloc(strlen(mav[0])+1),mav[0]);
  1158.     if( strlen(m->MenuName)>TITWID/8 )
  1159.         m->MenuName[TITWID/8+1]=0;
  1160.     DefaultIntuiText.ITextFont=ta=Win->WScreen->Font;
  1161.     DefaultMenuItem.Height=2+(fonthei=ta->ta_YSize);
  1162.  
  1163.     y=0;
  1164.     pmi=&m->FirstItem;
  1165.     for( i=1; i<mac; i++) {
  1166.         it =(void *)malloc(sizeof(struct IntuiText));
  1167.         *it=DefaultIntuiText;
  1168.         mi =(void *)malloc(sizeof(struct MenuItem ));
  1169.         *mi=DefaultMenuItem;
  1170.  
  1171.         com=NULL;
  1172.         if( p=index(mav[i],',')) {
  1173.             *p=0; com=++p;
  1174.             if( p=index(com,',')) {
  1175.                 *p=0;
  1176.                 mi->Command=p[1];
  1177.                 mi->Flags |=COMMSEQ;
  1178.             }
  1179.         }
  1180.  
  1181.         if( !com || !*com) {
  1182.             com=strcpy(malloc(strlen(mav[i])+2),mav[i]);
  1183.             MenuCommand[NumMenus][i-1]=com;
  1184.             com+=strlen(com);
  1185.             *com++=13;
  1186.             *com=0;
  1187.         } else {
  1188.             MenuCommand[NumMenus][i-1]=strcpy(malloc(strlen(com)+1),com);
  1189.         }
  1190.  
  1191.         it->IText=(UBYTE *)strcpy(malloc(strlen(mav[i])+2),mav[i]);
  1192.  
  1193.         *pmi= mi;
  1194.         pmi = &mi->NextItem;
  1195.         mi->TopEdge = y;
  1196.         mi->ItemFill= (APTR)it;
  1197.  
  1198.         y+=DefaultMenuItem.Height;
  1199.     }
  1200.  
  1201.     NumMenus++;
  1202. MError:
  1203.     return;
  1204. }
  1205.  
  1206.  
  1207. void
  1208. remove_menu()
  1209. {
  1210.     if( NumMenus>0 ) {
  1211.         struct MenuItem *mi, *nextmi;
  1212.         int i,j;
  1213.  
  1214.         for( i=0; i<NumMenus; i++ ) {
  1215.             for( mi=Menus[i].FirstItem,j=0 ; mi; mi=nextmi,j++ ) {
  1216.                 free( ((struct IntuiText *)mi->ItemFill)->IText );
  1217.                 free( ((struct IntuiText *)mi->ItemFill) );
  1218.                 nextmi=mi->NextItem;
  1219.                 free(mi);
  1220.                 free(MenuCommand[i][j]);
  1221.             }
  1222.         }
  1223.  
  1224.         NumMenus=0;
  1225.         set_menu();
  1226.     }
  1227. }
  1228.  
  1229.  
  1230. void
  1231. set_menu()
  1232. {
  1233.     if( o_nowindow || !Win )
  1234.         return;
  1235.  
  1236.     if( NumMenus>0 )
  1237.         SetMenuStrip( Win, Menus );
  1238.     else 
  1239.         ClearMenuStrip( Win );
  1240.  
  1241.     Delay(3);
  1242. }
  1243.  
  1244. do_getenv( void )
  1245. {
  1246.     char buf[256], *val=buf, *getenv();
  1247.  
  1248.     if( ac!=3 && ac!=2 ) {
  1249.         show_usage( NULL );
  1250.         return 20;
  1251.     }
  1252.     if( !Getenv(av[ac-1],buf,256))
  1253.         val="";
  1254.  
  1255.     if( ac==2 )
  1256.         printf( "%s\n", val );
  1257.     else 
  1258.         set_var( LEVEL_SET, av[1], val );
  1259.     return 0;
  1260. }
  1261.  
  1262.  
  1263. do_setenv( void )
  1264. {
  1265.     if( ac!=3 ) {
  1266.         show_usage( NULL );
  1267.         return 20;
  1268.     } else {
  1269. #ifndef AZTEC_C
  1270.         char buf[300];
  1271.         sprintf(buf, "%s=%s", av[1], av[2] );
  1272.         putenv( buf );
  1273. #else
  1274.         setenv( av[1], av[2] );
  1275. #endif
  1276.     }
  1277.     return 0;
  1278. }
  1279.  
  1280. char **
  1281. read_name( char *name, int *ac )
  1282. {
  1283.     FILE *file;
  1284.     char **av=NULL;
  1285.  
  1286.     *ac=0;
  1287.     if( file=name ? fopen( name, "r") : stdin ) {
  1288.         av=read_file( file, ac );
  1289.         if( name ) fclose( file );
  1290.     } else 
  1291.         pError( name );
  1292.     return av;
  1293. }
  1294.  
  1295.  
  1296. char **
  1297. read_file( FILE *file, int *ac )
  1298. {
  1299.     int buflen=4096, lines=0, i, offs;
  1300.     char *buf, *ptr, *got, **lineptr;
  1301.  
  1302.     if( !(buf=ptr=malloc( buflen )))
  1303.         goto error;
  1304.     do {
  1305.         while( ptr+400 < buf+buflen && (got=fgets( ptr, 400, file ) ) &&
  1306.                !dobreak()) {
  1307.             ptr+=strlen(ptr)-1, lines++;
  1308.             *ptr++=0;
  1309.         }
  1310.         if( ptr+256 < buf+buflen ) {
  1311.             offs=ptr-buf;
  1312.             if( !(buf=realloc( buf, buflen*=2 ) ) )
  1313.                 goto error;
  1314.             ptr=buf+offs;
  1315.         }
  1316.     } while( got && !dobreak());
  1317.     if( !(lineptr=(char **)malloc( (lines+1)*sizeof( char * ))))
  1318.         goto error;
  1319.     *lineptr++=buf;
  1320.     for( ptr=buf, i=0; i<lines; i++ ) {
  1321.         lineptr[i]=ptr;
  1322.         ptr+=strlen(ptr)+1;
  1323.     }
  1324.     *ac=lines;
  1325.     return lineptr;
  1326.  
  1327. error:
  1328.     if( buf ) free( buf );
  1329.     fprintf( stderr, "Out of memory\n" );
  1330.     *ac=0;
  1331.     return NULL;
  1332. }
  1333.  
  1334. void
  1335. free_file( ptr )
  1336.     char **ptr;
  1337. {
  1338.     if( ptr-- ) {
  1339.         if( *ptr )
  1340.             free( *ptr );
  1341.         free(ptr);
  1342.     }
  1343. }
  1344.  
  1345.  
  1346. do_qsort( void )
  1347. {
  1348.     char **lineptr;
  1349.     int  lines, i;
  1350.  
  1351.     if( ac==1 ) {
  1352.         lineptr=read_file( stdin, &lines);
  1353.         QuickSort( lineptr, lines );
  1354.         prepscroll(0);
  1355.         for( i=0; i<lines && !dobreak(); i++ ) {
  1356.             quickscroll();
  1357.             puts( lineptr[i] );
  1358.         }
  1359.         free_file( lineptr );
  1360.     }
  1361.     return 0;
  1362. }
  1363.  
  1364. extern int w_width;
  1365.  
  1366. do_truncate( void )
  1367. {
  1368.     char buf[256];
  1369.     int  w=newwidth(), c;
  1370.     char *ptr;
  1371.  
  1372.     if( ac==2 )
  1373.         w=atoi( av[1] );
  1374.  
  1375.     prepscroll(0);
  1376.     while( gets(buf) && !dobreak() ) {
  1377.         for( c=0, ptr=buf; *ptr && c<w; ptr++ )
  1378.             if( *ptr=='\t' )
  1379.                 c+=8-(c&7);
  1380.             else if( *ptr==27 ) {
  1381.                 while( *ptr<'@' )
  1382.                     ptr++;
  1383.             } else 
  1384.                 c++;
  1385.         *ptr=0;
  1386.         quickscroll();
  1387.         puts(buf);
  1388.     }
  1389.     return 0;
  1390. }
  1391.  
  1392. int
  1393. do_readfile( void )
  1394. {
  1395.     char **rav, *str=NULL;
  1396.     int rac;
  1397.  
  1398.     if( rav= read_name( ac>2 ? av[2] : NULL, &rac ) ) {
  1399.         if( rac>255 ) rac=255;
  1400.         if( str= compile_av( rav, 0, rac, 0xA0, 0 ) )
  1401.             set_var( LEVEL_SET, av[1], str );
  1402.         free_file( rav );
  1403.     }
  1404.     return str ? 0 : 20;
  1405. }
  1406.  
  1407. int
  1408. do_split( void )
  1409. {
  1410.     int i;
  1411.     char *val, *gap, *oldval;
  1412.  
  1413.     if( !(val=get_var( LEVEL_SET, av[1] )))
  1414.         { fprintf( stderr, "%s undefined\n", av[0] ); return 20; }
  1415.     oldval=val=strcpy(malloc(strlen(val)+1),val);
  1416.     for( i=2; i<ac-1; i++ ) {
  1417.         if( gap=index(val,0xA0 )) *gap=0;
  1418.         set_var( LEVEL_SET, av[i], val );
  1419.         val="";
  1420.         if( gap ) *gap=0xA0, val=gap+1;
  1421.     }
  1422.     set_var( LEVEL_SET, av[ac-1], val );
  1423.     free(oldval);
  1424.     return 0;
  1425. }
  1426.  
  1427. char *
  1428. copyof( char *str )
  1429. {
  1430.     return strcpy(malloc(strlen(str)+1),str);
  1431. }
  1432.  
  1433. int
  1434. do_class( char *avline )
  1435. {
  1436.     CLASS *new;
  1437.  
  1438.     if( options&1 ) {
  1439.         avline=next_word(avline);
  1440.         for( new=CRoot,CRoot=NULL; new; new=new->next )
  1441.             Free(new);
  1442.     }
  1443.  
  1444.     if( ac==1 ) {
  1445.         for( new=CRoot; new; new=new->next )
  1446.             printf("%s\n",new->name);
  1447.         return 0;
  1448.     }
  1449.  
  1450.     avline=next_word(avline);
  1451.     if(!(new=malloc( strlen(avline)+5)))
  1452.         ierror( NULL, 512 );
  1453.     else {
  1454.         new->next=NULL;
  1455.         strcpy( new->name,avline );
  1456.         if( CRoot )
  1457.             LastCRoot->next=new;
  1458.         else 
  1459.             CRoot=new;
  1460.         LastCRoot=new;
  1461.     }
  1462.     return 0;
  1463. }
  1464.  
  1465. do_getcl( void )
  1466. {
  1467.     char *s=getclass(av[1]);
  1468.     if( s ) printf("%s\n",s);
  1469.     return 0;
  1470. }
  1471.  
  1472. do_action( char *argline )
  1473. {
  1474.     char *args, err;
  1475.     int abort=options&1;
  1476.  
  1477.     args=compile_av( av,3,ac,' ',0 );
  1478.     err=doaction(av[2],av[1],args);
  1479.     if( !abort )
  1480.         if( err==10 )    fprintf(stderr,"Can't identify %s\n", av[2] );
  1481.         else if(err==11) fprintf(stderr,"Can't '%s' this file\n",av[1] );
  1482.     return abort ? !err : err;
  1483. }
  1484.