home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / shell / csh531s.lha / comm3.c < prev    next >
C/C++ Source or Header  |  1993-06-15  |  45KB  |  2,311 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.  * Version 5.20L by Andreas M. Kirchwitz (Fri, 13 Mar 1992)
  7.  *
  8.  */
  9.  
  10. #include "shell.h"
  11.  
  12. /* comm3.c */
  13. static void doassign(char *log, char *phy);
  14. static void assignlist(void);
  15. static int strings_in_file(long mask, char *s, char *path);
  16. static int htype_a_file   (long mask, char *s, char *path);
  17. static void install_menu(char **mav, int mac);
  18. static int line_filter( char *(*line)(char *) );
  19.  
  20.  
  21. /* Casting conveniences */
  22. #define BPTR_TO_C(strtag, var)  ((struct strtag *)(BADDR( (ULONG) var)))
  23. #define PROC(task)              ((struct Process *)task)
  24. #define CLI(proc)               (BPTR_TO_C(CommandLineInterface, proc->pr_CLI))
  25.  
  26.  
  27. int do_ln(void)
  28. {
  29.     char *linkname;
  30.     long link_type;
  31.     long dest_data;
  32.     BOOL success;
  33.  
  34.     if( ac!=2 && ac!=3 ) {
  35.         show_usage( NULL );
  36.         return 20;
  37.     }
  38.  
  39.     if (ac==2)
  40.         linkname = FilePart(av[1]);
  41.     else
  42.         linkname = av[2];
  43.  
  44.     if (options&1) {
  45.         link_type = LINK_SOFT;
  46.         dest_data = (long)av[1];
  47.     }
  48.     else {
  49.         link_type = LINK_HARD;
  50.         if (!( dest_data = (long)Lock(av[1],ACCESS_READ) )) {
  51.             pError(av[1]);
  52.             return 20;
  53.         }
  54.     }
  55.  
  56.     success = MakeLink(linkname,dest_data,link_type);
  57.  
  58.     if (link_type==LINK_HARD)
  59.         UnLock((BPTR)dest_data);
  60.  
  61.     if (!success) {
  62.         pError(linkname);
  63.         return 20;
  64.     }
  65.  
  66.     return 0;
  67. }
  68.  
  69.  
  70. do_tee( void )
  71. {
  72.     char buf[256];
  73.     FILE *out;
  74.  
  75.     prepscroll( ac==1 );
  76.     if( ac>2 ) { ierror( av[2], 500 ); return 20; }
  77.     if( ac==1 ) out=stderr;
  78.     else if( !(out=fopen( av[1], "w" ))) { pError( av[1] ); return 20; }
  79.     while (safegets(buf,stdin)) {
  80.         puts(buf);
  81.         quickscroll();
  82.         fprintf(out,"%s\n",buf);
  83.     }
  84.     if( ac!=1 ) fclose( out );
  85.     return 0;
  86. }
  87.  
  88. do_head( char *garbage, int com )
  89. {
  90.     FILE *f;
  91.     int i, n = 10;
  92.     char buf[256];
  93.  
  94.     if (ac==1) {                    /* use stdin */
  95.         f = stdin;
  96.     }
  97.     else {
  98.         f=fopen(av[1],"r");
  99.         if (f==NULL) {
  100.             if (ac==2 && isnum(av[1])) {    /* use stdin */
  101.                 f = stdin;
  102.                 n = atol(av[1]);
  103.             }
  104.             else {
  105.                 pError(av[1]);
  106.                 return 20;
  107.             }
  108.         }
  109.     }
  110.  
  111.     if (ac>2) {
  112.         if (!isnum(av[2])) {   /* AMK: IoErr() replaced by isnum() */
  113.             ierror(av[2],511);
  114.             return 20;
  115.         }
  116.         n=(int)atol(av[2]);
  117.     }
  118.  
  119.     if (com) {    /* tail specific part */
  120.         i=0;
  121.         while (fgets(buf, 256, f) && ! dobreak()) i++;
  122.         rewind(f);
  123.         if (n>i) n=i;
  124.         i=i-n;
  125.         while (i-- && fgets(buf, 256, f) && ! dobreak()) ;
  126.     }
  127.  
  128.     for (i=1; i<=n && fgets(buf, 256, f) && ! dobreak(); i++)
  129.         printf("%s", buf);
  130.  
  131.     if (f!=stdin)
  132.         fclose(f);
  133.  
  134.     return 0;
  135. }
  136.  
  137. #if 0
  138. do_head( char *garbage, int com )
  139. {
  140.     int i, n;
  141.     FILE *f;
  142.     char buf[256];
  143.  
  144.     if (ac>2) {
  145.         if (!isnum(av[2])) {   /* AMK: IoErr() replaced by isnum() */
  146.             ierror(av[2],511);
  147.             return 20;
  148.         }
  149.         n=(int)atol(av[2]);
  150.     } else n=10;
  151.  
  152.     f=fopen(av[1], "r");
  153.     if (f==NULL) {
  154.         pError(av[1]);
  155.         return 20;
  156.     }
  157.     if (com) {    /* tail specific part */
  158.         i=0;
  159.         while (fgets(buf, 256, f) && ! dobreak()) i++;
  160.         rewind(f);
  161.         if (n>i) n=i;
  162.         i=i-n;
  163.         while (i-- && fgets(buf, 256, f) && ! dobreak()) ;
  164.     }
  165.     for (i=1; i<=n && fgets(buf, 256, f) && ! dobreak(); i++)
  166.         printf("%s", buf);
  167.     fclose(f);
  168.     return 0;
  169. }
  170. #endif
  171.  
  172. static int
  173. exword( char **src, char *buf )
  174. {
  175.     *buf=0;
  176.     if( **src==0 ) return 0;
  177.     while( **src && **src!=0xA0 )
  178.         *buf++=*(*src)++;
  179.     *buf=0;
  180.     if( **src ) (*src)++;
  181.     return 1;
  182. }
  183.  
  184. static char helpfound=0;
  185.  
  186. void
  187. man (FILE *f, char *s)
  188. {
  189.     char buf[140], entry[100];
  190.     int  len = sprintf (entry, "    %s", s);
  191.     char *example = "    ";
  192.  
  193.     prepscroll (0);
  194.     rewind (f);
  195.     do {                        /* look for required argument */
  196.         if (fgets (buf, sizeof(buf), f)==NULL || dobreak())
  197.             return;                /* GMD */
  198.     } while (strnicmp (entry, buf, len)) ;
  199.     helpfound = 1;
  200.  
  201.     do {                /* display help */
  202.         if (dobreak())
  203.             return;
  204.         quickscroll ();
  205.         printf ("%s", buf);
  206.         if (fgets (buf, sizeof(buf), f) == NULL)
  207.             return;
  208.     } while ((!isalphanum (*buf)) && strncmp (buf, example, strlen(example))) ;
  209. }
  210.  
  211.  
  212. do_man( void )
  213. {
  214.     FILE *f;
  215.     int i;
  216.     char buf[200], name[60], *src, *var, docfound=0;
  217.  
  218.     buf[0]=0;
  219.     if( var=get_var(LEVEL_SET,"_man" ) )
  220.         strcpy(buf,var);
  221.  
  222.     if (ac==1) ac=2, av[1]="MAN";
  223.     for (i=1; i<ac; i++) {
  224.         src=buf, helpfound=0;
  225.         while( exword( &src, name) )
  226.             if( f=fopen(name, "r") ) {
  227.                 docfound=1;
  228.                 man(f, av[i]);
  229.                 fclose(f);
  230.                 if( helpfound )
  231.                     break;
  232.             }
  233.         if( !docfound )
  234.             fprintf(stderr,"%s not found\n",buf);
  235.         else if( !helpfound )
  236.             fprintf(stderr, "Help not found for %s\n", av[i]);
  237.     }
  238.     return 0;
  239. }
  240.  
  241. do_assign( void )
  242. {
  243.     int i;
  244.  
  245.     if     (  ac==1  ) assignlist();
  246.     else if(  ac==2  ) doassign(av[1], NULL);
  247.     else if( !(ac&1) ) ierror(NULL, 500);
  248.     else
  249.         for( i=1; i<ac; i+=2 )
  250.             doassign( av[i],av[i+1] );
  251.     return 0;
  252. }
  253.  
  254. /* AMK: rewritten code, removed bug when strlen(log) was 0 */
  255. static void
  256. doassign(char *log, char *phy)
  257. {
  258.     int last=strlen(log);
  259.  
  260.     if (last<2 || log[last-1] != ':') fprintf(stderr, "Bad name %s\n", log);
  261.     else {
  262.         int succ=0;
  263.  
  264.         log[last-1] = 0;
  265.  
  266.         if (!phy)
  267.             succ=AssignLock(log,NULL);
  268.         else if (options&1) {   /* add assign, CLI: assign ADD */
  269.             BPTR lock;
  270.             if( lock=Lock(phy,ACCESS_READ) )
  271.                 if( !(succ=AssignAdd(log,lock)))
  272.                     UnLock(lock);
  273.         }
  274.  
  275.         /* late-binding assign, CLI: assign DEFER */
  276.         else if (options&2 || options&8)
  277.             succ=AssignLate(log,phy);
  278.  
  279.         /* non-binding assign, CLI: assign PATH */
  280.         else if (options&4 || options&16)
  281.             succ=AssignPath(log,phy);
  282.         else if (!options) {
  283.             BPTR lock;
  284.             if( lock=Lock(phy,ACCESS_READ) )
  285.                 if( !(succ=AssignLock(log,lock)))
  286.                     UnLock(lock);
  287.         }
  288.  
  289.         if( !succ )
  290.             pError( log );
  291.     }
  292. }
  293.  
  294.  
  295. static void
  296. assignlist()
  297. {
  298.     char *ptr;
  299.     struct DosList *dl;
  300.     struct AssignList *path;
  301.     ULONG flags;
  302.     char fmt[256],devname[256];
  303.     char **dev_list;
  304.     long dev_num,i,cnt;
  305.  
  306.     dev_list = NULL;
  307.     dev_num  = 0;
  308.     flags    = LDF_VOLUMES|LDF_READ;
  309.  
  310.     if (dl=LockDosList(flags)) {
  311.         while (dl=NextDosEntry(dl,flags)) {
  312.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  313.             sprintf(fmt,"%s%s",devname,
  314.                     dl->dol_misc.dol_volume.dol_LockList?"":" [Mounted]");
  315.             add_array_list(&dev_list,&dev_num,fmt);
  316.         }
  317.         UnLockDosList(flags);
  318.     }
  319.  
  320.     QuickSort(dev_list,dev_num);
  321.     printf("Volumes:\n");
  322.     for(i=0; i<dev_num; i++)
  323.         printf("%s\n",dev_list[i]);
  324.     free_array_list(dev_list,dev_num);
  325.  
  326.     if (dobreak())
  327.         return;
  328.  
  329.     dev_list = NULL;
  330.     dev_num  = 0;
  331.     flags    = LDF_ASSIGNS|LDF_READ;
  332.  
  333.     if (dl=LockDosList(flags)) {
  334.         while (dl=NextDosEntry(dl,flags)) {
  335.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  336.  
  337.             sprintf(fmt,"%-14s ",devname);
  338.             ptr = fmt+strlen(fmt);
  339.  
  340.             switch (dl->dol_Type) {
  341.                 case DLT_DIRECTORY :
  342.                     if(dl->dol_Lock)
  343.                         NameFromLock(dl->dol_Lock,ptr,200L);
  344.                     else
  345.                         strcpy(ptr,"Nonexisting lock");
  346. /* --- */
  347.                     if (path=dl->dol_misc.dol_assign.dol_List) {
  348.                         char **ass_list=NULL;
  349.                         long ass_num=0,str_len=0;
  350.                         char *ass_str;
  351.  
  352.                         add_array_list(&ass_list,&ass_num,fmt);
  353.                         str_len += strlen(fmt);
  354.  
  355.                         for (; path; path=path->al_Next) {
  356.                             sprintf(fmt,"%-13s+ ","");
  357.                             ptr = fmt+strlen(fmt);
  358.                             if (dl->dol_Lock)
  359.                                 NameFromLock(path->al_Lock,ptr,200L);
  360.                             else
  361.                                 strcpy(ptr,"Nonexisting lock");
  362.                             add_array_list(&ass_list,&ass_num,fmt);
  363.                             str_len += strlen(fmt)+1;
  364.                         }
  365.  
  366.                         if (ass_str=malloc(str_len+1)) {
  367.                             char *p=ass_str;
  368.                             for(i=0; i<ass_num; i++) {
  369.                                 strcpy(p,ass_list[i]);
  370.                                 p += strlen(p);
  371.                                 if ((i+1)<ass_num) {
  372.                                     *p++ = '\n';
  373.                                     *p   = '\0';
  374.                                 }
  375.                             }
  376.                             add_array_list(&dev_list,&dev_num,ass_str);
  377.                             free(ass_str);
  378.                         }
  379.  
  380.                         free_array_list(ass_list,ass_num);
  381.                     }
  382.                     else
  383.                         add_array_list(&dev_list,&dev_num,fmt);
  384. /* --- */
  385. #if 0
  386.                     add_array_list(&dev_list,&dev_num,fmt);
  387.  
  388.                     for(path=dl->dol_misc.dol_assign.dol_List; path; path=path->al_Next) {
  389.                         sprintf(fmt,"%-13s+ ","");
  390.                         ptr = fmt+strlen(fmt);
  391.                         if (dl->dol_Lock)
  392.                             NameFromLock(path->al_Lock,ptr,200L);
  393.                         else
  394.                             strcpy(ptr,"Nonexisting lock");
  395.                         add_array_list(&dev_list,&dev_num,fmt);
  396.                     }
  397. #endif
  398.                     break;
  399.                 case DLT_LATE      :
  400.                     sprintf(ptr,"<%s>",dl->dol_misc.dol_assign.dol_AssignName);
  401.                     add_array_list(&dev_list,&dev_num,fmt);
  402.                     break;
  403.                 case DLT_NONBINDING:
  404.                     sprintf(ptr,"[%s]",dl->dol_misc.dol_assign.dol_AssignName);
  405.                     add_array_list(&dev_list,&dev_num,fmt);
  406.                     break;
  407.                 default:
  408.                     strcpy(ptr,"Unknown assign");
  409.                     add_array_list(&dev_list,&dev_num,fmt);
  410.                     break;
  411.             }
  412.         }
  413.         UnLockDosList(flags);
  414.     }
  415.  
  416.     QuickSort(dev_list,dev_num);
  417.     printf("\nDirectories:\n");
  418.     for(i=0; !dobreak() && i<dev_num; i++)
  419.         printf("%s\n",dev_list[i]);
  420.     free_array_list(dev_list,dev_num);
  421.  
  422.     if (dobreak())
  423.         return;
  424.  
  425.     dev_list = NULL;
  426.     dev_num  = 0;
  427.     flags    = LDF_DEVICES|LDF_READ;
  428.  
  429.     if (dl=LockDosList(flags)) {
  430.         while (dl=NextDosEntry(dl,flags)) {
  431.             if (dl->dol_Task) {
  432.                 BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  433.                 add_array_list(&dev_list,&dev_num,devname);
  434.             }
  435.         }
  436.         UnLockDosList(flags);
  437.     }
  438.  
  439.     QuickSort(dev_list,dev_num);
  440.     printf("\nDevices (with FileSystem):\n");
  441.     for(i=0,cnt=0; i<dev_num; i++) {
  442.         if (IsFileSystem(dev_list[i])) {
  443.             if (cnt>0 && cnt%5==0)
  444.                 printf("\n");
  445.             printf("%s ",dev_list[i]);
  446.             ++cnt;
  447.         }
  448.     }
  449.     printf("\n");
  450.     free_array_list(dev_list,dev_num);
  451.  
  452.     if (dobreak())
  453.         return;
  454.  
  455.     dev_list = NULL;
  456.     dev_num  = 0;
  457.     flags    = LDF_DEVICES|LDF_READ;
  458.  
  459.     if (dl=LockDosList(flags)) {
  460.         while (dl=NextDosEntry(dl,flags)) {
  461.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  462.             add_array_list(&dev_list,&dev_num,devname);
  463.         }
  464.         UnLockDosList(flags);
  465.     }
  466.  
  467.     QuickSort(dev_list,dev_num);
  468.     printf("\nDevices:\n");
  469.     for(i=0; i<dev_num; i++) {
  470.         if (i>0 && i%5==0)
  471.             printf("\n");
  472.         printf("%s ",dev_list[i]);
  473.     }
  474.     printf("\n");
  475.     free_array_list(dev_list,dev_num);
  476.  
  477. return;
  478. #if 0
  479.     printf("\nDirectories:\n");
  480.     for( ; arr[i] && !dobreak(); i++ ) {
  481.         log=arr[i]+1; ptr=log+strlen(log)+1;
  482.         switch( *(log-1)) {
  483.         case 3:
  484.             printf("%-20s%s\n", log, ptr);
  485.             for(;;) {
  486.                 ptr+=strlen(ptr)+1;
  487.                 if( !*ptr ) break;
  488.                     printf("%-19s+%s\n", "", ptr);
  489.             }
  490.             break;
  491.         case 4: printf("%-20s<%s>\n", log, ptr); break;
  492.         case 5: printf("%-20s[%s]\n", log, ptr); break;
  493.         }
  494.     }
  495. #endif
  496. }
  497.  
  498.  
  499.  
  500. do_join( void )
  501. {
  502.     BPTR sou, dest;
  503.     char *buffer;
  504.     int i;
  505.     long n;
  506.     char *namedest=av[--ac];
  507.  
  508.     if (options==0 && exists(namedest)) { ierror(namedest,203); return 20; }
  509.     if ( (buffer=malloc(8192)) == NULL ) { ierror(NULL,103); return 20; }
  510.     if ( (dest=Open(namedest, MODE_NEWFILE)) == NULL )
  511.         { pError(namedest); goto fail1; }
  512.     for (i=1; i<ac; i++) {
  513.         if ( (sou=Open(av[i], MODE_OLDFILE)) == NULL ) pError(av[i]);
  514.         else
  515.             while( (n=Read(sou, buffer, 8192L)) > 0 )
  516.                 if (Write(dest, buffer, n) != n)
  517.                     { pError(namedest); Close(sou); goto fail2; }
  518.         Close(sou);
  519.     }
  520. fail2:
  521.     Close(dest);
  522. fail1:
  523.     free(buffer);
  524.     return 0;
  525. }
  526.  
  527. #define BUFDIM 512L
  528. #define MAXSTR 256
  529.  
  530. int minstr;
  531.  
  532. static int
  533. strings_in_file(long mask, char *s, char *path)
  534. {
  535.     char c;
  536.     char readbuf[BUFDIM+1], strbuf[MAXSTR+1];
  537.     int i, strctr=0;
  538.     BPTR fh;
  539.     int out, n, inter=IsInteractive(Output());
  540.     BOOL hdout = TRUE;
  541.     BOOL usestdin = (s==NULL);
  542.  
  543.     prepscroll(0);
  544.  
  545.     if (usestdin)
  546.         fh = Input();
  547.     else
  548.         fh=Open(s,MODE_OLDFILE);
  549.  
  550.     if (fh) {
  551.         while ( (n=(int)Read(fh, readbuf, BUFDIM))>0 && !CHECKBREAK() )
  552.             for (i=0; i<n && !CHECKBREAK(); i++) {   /* GMD: speed up ^C reaction */
  553.                 c=readbuf[i];
  554.                 if (c<0x20 || c>0x7f) {
  555.                     out=(strctr>=minstr);
  556.                     if (!out) strctr=0;
  557.                 } else {
  558.                     strbuf[strctr++]=c;
  559.                     out=(strctr>=BUFDIM);
  560.                 }
  561.                 if (out) {
  562.                     strbuf[strctr]='\0';
  563.                     if (options&2) {
  564.                         printf("%s: |%s|\n",path?path:"STDIN",strbuf);
  565.                     }
  566.                     else {
  567.                         if (hdout) {
  568.                             printf("Strings in %s (len>=%d):\n",path?path:"STDIN",minstr);
  569.                             hdout=FALSE;
  570.                         }
  571.                         puts(strbuf);
  572.                     }
  573.                     if (inter) fflush(stdout);
  574.                     quickscroll();
  575.                     strctr=0;
  576.                 }
  577.             }
  578.         /* only close file if not standard input */
  579.         if (!usestdin)
  580.             Close(fh);
  581.     } else
  582.         pError(s);
  583.     return 0;
  584. }
  585.  
  586. do_strings( void )
  587. {
  588.     if (isnum(av[ac-1])) {
  589.         minstr = myatoi(av[--ac],1,255);
  590.         if (atoierr) {
  591.             fprintf(stderr,"Need a valid string length param (1-255)!\n");
  592.             return 0;
  593.         }
  594.     }
  595.     else
  596.         minstr = 4;
  597.  
  598.     if (ac<2)
  599.         strings_in_file(0, NULL, NULL);
  600.     else
  601.         all_args( strings_in_file, 0);
  602.  
  603.     return 0;
  604. }
  605.  
  606. BPTR myfile[MAXMYFILES];
  607.  
  608. do_open( void )
  609. {
  610.     long mode;
  611.     int n;
  612.  
  613.     switch (toupper(av[2][0])) {
  614.         case 'R': mode=MODE_OLDFILE; break;
  615.         case 'W': mode=MODE_NEWFILE; break;
  616.         default : ierror(NULL,500); return 1;
  617.     }
  618.     n=myatoi(av[3],0,MAXMYFILES-1); if (atoierr) return 20;
  619.     if (myfile[n]) myclose(n);
  620.     myfile[n]=Open(av[1],mode);
  621.     return myfile[n]==NULL;
  622. }
  623.  
  624. do_close( void )
  625. {
  626.     int i, n;
  627.  
  628.     if (ac==1)
  629.         for (i=1; i<MAXMYFILES; i++)
  630.             myclose(i);
  631.     for (i=1; i<ac; i++) {
  632.         n=myatoi(av[i],0,MAXMYFILES-1); if (atoierr) return 20;
  633.         myclose(n);
  634.     }
  635.     return 0;
  636. }
  637.  
  638. void
  639. myclose(int n)
  640. {
  641.     if (myfile[n]) { Close(myfile[n]); myfile[n]=NULL; }
  642. }
  643.  
  644. do_fileslist( void )
  645. {
  646.     int i, flag=0;
  647.  
  648.     printf("Open files:");
  649.     for (i=0; i<MAXMYFILES; i++)
  650.         if (myfile[i]) { printf(" %d",i); flag=1; }
  651.     if (!flag) printf(" None!");
  652.     printf("\n");
  653.     return 0;
  654. }
  655.  
  656. BPTR
  657. extOpen( char *name, long mode )
  658. {
  659.     if (name[0]=='.' && name[1]>='0' && name[1]<='9')
  660.         return myfile[atoi(name+1)];
  661.     return Open(name,mode);
  662. }
  663.  
  664.  
  665. void
  666. extClose(BPTR fh)
  667. {
  668.     int i;
  669.  
  670.     for (i=0; i<MAXMYFILES; i++)
  671.         if (myfile[i]==fh) return;
  672.     Close(fh);
  673. }
  674.  
  675. do_basename( void )
  676. {
  677.     char *res;
  678.     int  i;
  679.  
  680.     for( i=2; i<ac; i++ )
  681.         av[i]=FilePart(av[i]);
  682.     set_var(LEVEL_SET, av[1], res=compile_av(av,2,ac,0xA0,0));
  683.     free(res);
  684.     return 0;
  685. }
  686.  
  687. do_tackon( void )
  688. {
  689.     char buf[256];
  690.  
  691.     strcpy(buf, av[2]);
  692.     AddPart(buf, av[3], 256L);
  693.     set_var(LEVEL_SET, av[1], buf);
  694.     return 0;
  695. }
  696.  
  697. extern char shellres[];
  698.  
  699. do_resident( void )
  700. {
  701.     struct Segment *seg;
  702.     char buf[256],devname[256];
  703.     char **dev_list1=NULL,**dev_list2=NULL;
  704.     long dev_num1=0,dev_num2=0,i;
  705.  
  706.     if (options==0 && ac>1) options=1;
  707.     switch (options) {
  708.     case 0:
  709.         Forbid();
  710.         seg = (struct Segment *)BADDR(((struct DosInfo *)BADDR(DOSBase->dl_Root->rn_Info))->di_NetHand);
  711.         while (seg) {
  712.             BtoCStr(devname,MKBADDR(seg->seg_Name),254L);  /* 256 - '\0' + ':' */
  713.             if (seg->seg_UC >= 0) {
  714.                 sprintf(buf,"%-18s%4.1ld",devname,seg->seg_UC-1);
  715.                 add_array_list(&dev_list1,&dev_num1,buf);
  716.             }
  717.             else {
  718.                 switch (seg->seg_UC) {
  719.                 case CMD_INTERNAL:
  720.                     sprintf(buf,"%-18s%s",devname,"INTERNAL");
  721.                     add_array_list(&dev_list2,&dev_num2,buf);
  722.                     break;
  723.                 case CMD_SYSTEM:
  724. /* don't print this */ /*
  725.                     sprintf(buf,"%-18s%s",devname,"SYSTEM");
  726.                     add_array_list(&dev_list2,&dev_num2,buf);
  727. */
  728.                     break;
  729.                 case CMD_DISABLED:
  730.                     sprintf(buf,"%-18s%s",devname,"DISABLED");
  731.                     add_array_list(&dev_list2,&dev_num2,buf);
  732.                     break;
  733.                 default:
  734.                     sprintf(buf,"%-18s%s",devname,"UNKNOWN");
  735.                     add_array_list(&dev_list2,&dev_num2,buf);
  736.                     break;
  737.                 }
  738.             }
  739.             seg = (struct Segment *)BADDR(seg->seg_Next);
  740.         }
  741.         Permit();
  742.         printf("NAME              USE COUNT\n\n");
  743.  
  744.         QuickSort(dev_list1,dev_num1);
  745.         for(i=0; !dobreak() && i<dev_num1; i++)
  746.             printf("%s\n",dev_list1[i]);
  747.         free_array_list(dev_list1,dev_num1);
  748.  
  749.         for(i=0; !dobreak() && i<dev_num2; i++)
  750.             printf("%s\n",dev_list2[i]);
  751.         free_array_list(dev_list2,dev_num2);
  752.  
  753.         break;
  754.     case 1:
  755.         for (i=1; i<ac; i++)
  756.             if (loadres(av[i]))
  757.                 printf("OK! %s is now resident\n", FilePart(av[i]));
  758.             else
  759.                 pError(av[i]);
  760.         break;
  761.     case 2:
  762.         for (i=1; i<ac; i++) {
  763.             Forbid();
  764.             if (seg=FindSegment(av[i],NULL,0L)) {
  765.                 if (RemSegment(seg)) {
  766.                     Permit();
  767.                     printf("Removed %s\n",av[i]);
  768.                 }
  769.                 else {
  770.                     Permit();
  771.                     ierror(av[i],ERROR_OBJECT_IN_USE);
  772.                 }
  773.             }
  774.             else {
  775.                 Permit();
  776.                 ierror(av[i],ERROR_OBJECT_NOT_FOUND);
  777.             }
  778.         }
  779.         break;
  780.     case 4:
  781.         for (i=1; i<ac; i++) {
  782.             if( !o_resident ) {
  783.                 /* AMK: OS20-SetVar replaces ARP-Setenv */
  784.                 SetVar(shellres,"1",-1L,GVF_GLOBAL_ONLY|GVF_BINARY_VAR);
  785.                 o_resident=1;
  786.             }
  787.             sprintf(buf,"res_%s",FilePart(av[i]));
  788.             /* AMK: OS20-SetVar replaces ARP-Setenv */
  789.             SetVar(buf,av[i],-1L,GVF_GLOBAL_ONLY|GVF_BINARY_VAR);
  790.         }
  791.         break;
  792.     default:
  793.         ierror(NULL,500);
  794.         break;
  795.     }
  796.     return 0;
  797. }
  798.  
  799. int
  800. loadres(char *s)
  801. {
  802.     BPTR seg;
  803.     BOOL okay = FALSE;
  804.  
  805.     if (seg=NewLoadSeg(s,NULL))
  806.         okay=AddSegment(FilePart(s),seg,1L);
  807.  
  808.     return (okay);
  809. }
  810.  
  811. extern BPTR redir_out, redir_in;
  812.  
  813. struct TagItem tags[]={
  814.     {SYS_Input,  0},
  815.     {SYS_Output, 0},
  816.     {SYS_Asynch, 1},
  817.     {TAG_DONE,   0} };
  818.  
  819. do_truerun(char *avline, int backflag)
  820. {
  821.     BPTR input, output;
  822.     char *args;
  823.     int err;
  824.  
  825.     if (backflag) {
  826.         input = Open("NIL:",MODE_NEWFILE);
  827.         output= Open("NIL:",MODE_NEWFILE);
  828.     } else {
  829.         input = redir_in ?redir_in : Open("NIL:"    , MODE_NEWFILE);
  830.         output= redir_out?redir_out: Open("CONSOLE:", MODE_NEWFILE);
  831.     }
  832.  
  833.     args=compile_av(av,1,ac,' ',1);
  834.  
  835.     tags[0].ti_Data= input;
  836.     tags[1].ti_Data= output;
  837.  
  838.     err=System( args, tags );
  839.  
  840.     if( err!=0 ) {
  841.         Close( tags[0].ti_Data );
  842.         Close( tags[1].ti_Data );
  843.         pError(av[1]);
  844.     }
  845.     free(args);
  846.  
  847.     return 0;
  848. }
  849.  
  850. #if 0
  851. extern BPTR redir_out, redir_in;
  852.  
  853. static struct ProcessControlBlock pcb={
  854.     4000,        /* pcb_StackSize    */
  855.     0,        /* pcb_Pri        */
  856.     };
  857. /* remaining fields are NULL */
  858.  
  859. do_truerun(char *avline, int backflag)
  860. {
  861.     char name[100], *args, buf[10];
  862.     int cli;
  863.  
  864.     args=next_word(next_word(avline));
  865.     if (backflag) {
  866.         pcb.pcb_Control= 0;
  867.         pcb.pcb_Input  = Open("NIL:",MODE_OLDFILE);
  868.         pcb.pcb_Output = Open("NIL:",MODE_OLDFILE);
  869.     } else {
  870.         pcb.pcb_Control= 0;
  871.         pcb.pcb_Input  = redir_in;
  872.         pcb.pcb_Output = redir_out;
  873.  
  874.     }
  875.  
  876.     if((cli=ASyncRun(av[1],args,&pcb))<0)
  877.         if (dofind(av[1], "", name,v_path))
  878.             cli=ASyncRun(name,args,&pcb);
  879.  
  880.     if( cli<0 && cli>=-11 ) {
  881.         if( redir_out ) extClose( redir_out );
  882.         if( redir_in  ) extClose( redir_in  );
  883.     }
  884.  
  885.     sprintf(buf,"%d",cli);
  886.     set_var(LEVEL_SET,"_newproc",buf);
  887.  
  888.     if( cli<0 ) {
  889.         ierror(av[1],205);
  890.         return 20;
  891.     }
  892.     return 0;
  893. }
  894. #endif
  895.  
  896. int
  897. exists( char *name )
  898. {
  899.     BPTR lock;
  900.     char *nam=FilePart(name);
  901.     int ret=0;
  902.  
  903.     Myprocess->pr_WindowPtr = (APTR)(-1);
  904.     if ( strlen(nam)<=MAXFILENAME && (lock=Lock(name,ACCESS_READ))) {
  905.         UnLock(lock);
  906.         ret=1;
  907.     }
  908.     Myprocess->pr_WindowPtr = (APTR) o_noreq;
  909.     return ret;
  910. }
  911.  
  912. int
  913. mounted( char *dev )
  914. {
  915.     struct DosList *dl;
  916.     ULONG flags = LDF_ALL|LDF_READ;
  917.     int gotcha = FALSE;
  918.     char devname[256];
  919.  
  920.     if (dl=LockDosList(flags)) {
  921.         while ((!gotcha) && (dl=NextDosEntry(dl,flags))) {
  922.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  923.             if (stricmp(devname,dev)==0)
  924.                 gotcha = TRUE;
  925.         }
  926.         UnLockDosList(flags);
  927.     }
  928.  
  929.     return (gotcha);
  930. }
  931.  
  932. #define HTYPELINE 16L
  933.  
  934. static int
  935. htype_a_file(long mask, char *s, char *path)
  936. {
  937.     BPTR fh;
  938.     long n, filesize=0;
  939.     UBYTE buf[HTYPELINE+1];
  940.     char out[80], *put;
  941.     int i, inter=IsInteractive(Output());
  942.     BOOL usestdin = (s==NULL);
  943.  
  944.     if (usestdin)
  945.         fh = Input();
  946.     else
  947.         fh = Open(s,MODE_OLDFILE);
  948.  
  949.     if (fh==NULL) { pError(s); return 20; }
  950.     prepscroll(0);
  951.     while ( (n=Read(fh,(char *)buf,HTYPELINE))>0 && !dobreak()) {
  952.         put=out;
  953.         put+=sprintf(put,"%06lx: ",filesize);
  954.         filesize+=n;
  955.         for (i=0; i<n; i++) {
  956.             put+=sprintf( put,(i&3) ? "%02x" : " %02x",buf[i]);
  957.             if ((buf[i]&127)<0x20) buf[i]='.';
  958.         }
  959.         for ( ; i<HTYPELINE; i++) {
  960.             put+=sprintf( put, (i&3) ? "  " : "   ");
  961.             buf[i]=' ';
  962.         }
  963.         buf[i]=0;
  964.         sprintf(put,"    %s",buf);
  965.         puts(out);
  966.         if( inter ) fflush(stdout);
  967.         quickscroll();
  968.     }
  969.     /* only close file if not standard input */
  970.     if (!usestdin)
  971.         Close(fh);
  972.     return 0;
  973. }
  974.  
  975. do_htype( void )
  976. {
  977.     if (ac<2)
  978.         htype_a_file(0, NULL, NULL);
  979.     else
  980.         all_args( htype_a_file, 0);
  981.     return 0;
  982. }
  983.  
  984. do_stack( void )
  985. {
  986.     long n;
  987.  
  988.     if (ac>1) {
  989.         if (isnum(av[1])) {   /* AMK: IoErr() replaced by isnum() */
  990.             n=atol(av[1]);
  991.             Mycli->cli_DefaultStack=(long)(n >> 2L);
  992.         }
  993.         else {
  994.             ierror(av[1],511);   /* AMK: message if error */
  995.             return 20;
  996.         }
  997.     }
  998.     else {
  999.         if (options&1)
  1000.             printf("%ld\n",(long)Mycli->cli_DefaultStack << 2L);
  1001.         else
  1002.             printf("current stack size is %ld bytes\n",
  1003.                     (long)Mycli->cli_DefaultStack << 2L);
  1004.     }
  1005.     return 0;
  1006. }
  1007.  
  1008. do_fault( void )
  1009. {
  1010.     PERROR *p;
  1011.     int i, n;
  1012.  
  1013.     for (i=1; i<ac; i++) {
  1014.         n=myatoi(av[i],0,32767);
  1015.         if (!atoierr) {
  1016.             for (p=Perror; p->errnum && p->errnum!=n; p++);
  1017.             if (p->errnum)
  1018.                 printf("Fault %d: %s\n",n,p->errstr);
  1019.             else
  1020.                 printf("Fault %d not recognized\n",n);
  1021.         }
  1022.     }
  1023.     return 0;
  1024. }
  1025.  
  1026. struct rpncommand {
  1027.     char *str;
  1028.     int parsin, parsout;
  1029.     };
  1030.  
  1031. static struct rpncommand rpn[]={
  1032.     "+",    2,    1,
  1033.     "-",    2,    1,
  1034.     "*",    2,    1,
  1035.     "/",    2,    1,
  1036.     "%",    2,    1,
  1037.     "&",    2,    1,
  1038.     "|",    2,    1,
  1039.     "~",    1,    1,
  1040.     ">",    2,    1,
  1041.     "<",    2,    1,
  1042.     "==",    2,    1,
  1043.     "!",    1,    1,
  1044.     "MAX",    2,    1,
  1045.     "MIN",    2,    1,
  1046.     "DUP",    1,    2,
  1047.     "DROP",    1,    0,
  1048.     "SWAP",    2,    2,
  1049.     "HELP",    0,    0,
  1050.     NULL,    0,    1,    /* this looks for a number */
  1051. };
  1052.  
  1053. static long stack[50];
  1054. static int sp;
  1055.  
  1056.  
  1057. eval_rpn( char **av, int ac, int flag )
  1058. {
  1059.     char *zero="Division by zero\n";
  1060.     struct rpncommand *temp;
  1061.     long n0, n1, t;
  1062.     int j, i=0, oldsp=sp;
  1063.  
  1064.     for (; i<ac; i++) {
  1065.         for (j=0; rpn[j].str && stricmp(rpn[j].str,av[i]); j++) ;
  1066.         n0=stack[sp-1];
  1067.         n1=stack[sp-2];
  1068.         sp -= (rpn[j].parsin);
  1069.         if (sp<0) { fprintf(stderr, "RPN: Empty stack\n"); goto error; }
  1070.         switch (j) {
  1071.           case 0:    n0 += n1;            break;
  1072.           case 1:    n0 = n1-n0;            break;
  1073.           case 2:    n0 *= n1;            break;
  1074.           case 3:    if(n0) n0=n1/n0; else fprintf(stderr,zero); break;
  1075.           case 4:    if(n0) n0=n1%n0; else fprintf(stderr,zero); break;
  1076.           case 5:    n0 &= n1;            break;
  1077.           case 6:    n0 |= n1;            break;
  1078.           case 7:    n0 =  ~n0    ;        break;
  1079.           case 8:    n0 = (n1 > n0);        break;
  1080.           case 9:    n0 = (n1 < n0);        break;
  1081.           case 10:    n0 = (n0 == n1);    break;
  1082.           case 11:    n0 = !n0;            break;
  1083.           case 12:    n0=n1>n0 ? n1 : n0;    break;
  1084.           case 13:    n0=n1<n0 ? n1 : n0;    break;
  1085.           case 14:    n1=n0;                break;
  1086.           case 15:    t=n0; n0=n1; n1=t;    break;
  1087.           case 16:                        break;
  1088.           case 17:    printf("In Commands Out\n");
  1089.             for (temp=rpn; temp->str; temp++)
  1090.                 printf(" %d %-10s%d\n",
  1091.                 temp->parsin,temp->str,temp->parsout);
  1092.             break;
  1093.           default:    n0=atol(av[i]);
  1094.                 if (!isnum(av[i])) {   /* AMK: IoErr() replaced by isnum() */
  1095.                     fprintf(stderr, "Bad RPN cmd: %s\n",av[i]);
  1096.                     goto error;
  1097.                 }
  1098.                 break;
  1099.           }
  1100.         stack[sp]=n0;
  1101.         stack[sp+1]=n1;
  1102.         sp += rpn[j].parsout;
  1103.     }
  1104.     if( flag && sp-1)
  1105.         fprintf( 
  1106.           stderr,
  1107.           "RPN: Stack not empty\n"
  1108.         );
  1109.  
  1110.     t=sp; sp=oldsp;
  1111.     if( flag )
  1112.         return stack[t-1]; /* return top value */
  1113.     else 
  1114.         return t-sp;
  1115.  
  1116. error:
  1117.     sp=oldsp;
  1118.     return 0;
  1119. }
  1120.  
  1121.  
  1122. do_rpn(char *garbage,int ifflag) /* ifflag!=0 if called from if */
  1123. {
  1124.     int i=1;
  1125.     long t;
  1126.  
  1127.     t=eval_rpn( av+i, ac-i, ifflag );
  1128.     if (ifflag) return t;              /* called from if: return top value */
  1129.     for (i=sp+t-1;i>=sp;i--) printf("%ld\n", stack[i]);/* else print stack */
  1130.  
  1131.     return t ? 0 : 20;
  1132. }
  1133.  
  1134.  
  1135.  
  1136. void *DosAllocMem(long size)
  1137. {
  1138.     return( AllocVec(size,MEMF_CLEAR|MEMF_PUBLIC) );
  1139. }
  1140.  
  1141.  
  1142.  
  1143. void DosFreeMem(void *block)
  1144. {
  1145.     FreeVec(block);
  1146. }
  1147.  
  1148.  
  1149.  
  1150. do_path( void )
  1151. {
  1152.     struct Process *proc;
  1153.     BPTR lock,dup_lock;
  1154.     long mycli,clinum,mincli,maxcli;
  1155.     struct PathList *pl,*new_pl,*old,*last;
  1156.     char buf[256];
  1157.     int i;
  1158.  
  1159.     if( options&1 ) {
  1160.         Forbid();
  1161.         mincli = 1;
  1162.         maxcli = MaxCli();
  1163.         mycli  = Myprocess->pr_TaskNum;
  1164.         if (!(options&2))
  1165.             mincli = maxcli = mycli;
  1166.         for (clinum = mincli; clinum<=maxcli; clinum++) {
  1167.             if (proc=FindCliProc(clinum)) {
  1168.                 pl = (struct PathList *)BADDR(CLI(proc)->cli_CommandDir);
  1169.                 while (pl) {
  1170.                     if (pl->pl_PathLock) {
  1171.                         UnLock(pl->pl_PathLock);
  1172.                     }
  1173.                     old = pl;
  1174.                     pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1175.                     DosFreeMem( old );
  1176.                 }
  1177.                 CLI(proc)->cli_CommandDir=NULL;
  1178.             }
  1179.         }
  1180.         Permit();
  1181.     } else if( ac==1 ) {
  1182.         char **dev_list=NULL;
  1183.         long dev_num=0,i;
  1184.         puts("Current dir");
  1185.         Forbid();
  1186.         pl = (struct PathList *)BADDR(Mycli->cli_CommandDir);
  1187.         while (pl) {
  1188.             if (pl->pl_PathLock) {
  1189.                 NameFromLock(pl->pl_PathLock,buf,255L);
  1190.                 add_array_list(&dev_list,&dev_num,buf);
  1191.             }
  1192.             pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1193.         }
  1194.         Permit();
  1195.  
  1196.         for(i=0; !dobreak() && i<dev_num; i++)
  1197.             printf("%s\n",dev_list[i]);
  1198.         free_array_list(dev_list,dev_num);
  1199.  
  1200.         if (!dobreak())
  1201.             puts("C:");
  1202.         return 0;
  1203.     }
  1204.     for( i=1; i<ac; i++ ) {
  1205.         if( !(lock=Lock(av[i],ACCESS_READ)) ) {
  1206.             ierror(av[i],205);
  1207.             continue;
  1208.         }
  1209.         if( !isdir(av[i])) {
  1210.             ierror(av[i],212);
  1211.             UnLock(lock);
  1212.             continue;
  1213.         }
  1214.         Forbid();
  1215.         mincli = 1;
  1216.         maxcli = MaxCli();
  1217.         mycli  = Myprocess->pr_TaskNum;
  1218.         if (!(options&2))
  1219.             mincli = maxcli = mycli;
  1220.         for (clinum = mincli; clinum<=maxcli; clinum++) {
  1221.             if (proc=FindCliProc(clinum)) {
  1222.                 if (options&2)
  1223.                     dup_lock = DupLock(lock);
  1224.                 else
  1225.                     dup_lock = lock;
  1226.                 last = pl = (struct PathList *)BADDR(CLI(proc)->cli_CommandDir);
  1227.                 while (pl && dup_lock) {
  1228.                     last = pl;
  1229.                     if (pl->pl_PathLock) {
  1230.                         if (SameLock(pl->pl_PathLock,dup_lock)==LOCK_SAME) {
  1231.                             UnLock(dup_lock);
  1232.                             dup_lock=NULL;
  1233.                         }
  1234.                     }
  1235.                     pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1236.                 }
  1237.                 if (dup_lock) {
  1238.                     if (new_pl=DosAllocMem( sizeof(struct PathList) )) {
  1239.                         new_pl->pl_NextPath = NULL;
  1240.                         new_pl->pl_PathLock = dup_lock;
  1241.                         if (last)
  1242.                             last->pl_NextPath = MKBADDR(new_pl);
  1243.                         else
  1244.                             CLI(proc)->cli_CommandDir = MKBADDR(new_pl);
  1245.                     }
  1246.                     else
  1247.                         UnLock(dup_lock);
  1248.                 }
  1249.             }
  1250.         }
  1251.         Permit();
  1252.         if (options&2)
  1253.             UnLock(lock);
  1254.     }
  1255.     return 0;
  1256. }
  1257.  
  1258. do_pri( void )
  1259. {
  1260.     int t, pri;
  1261.     struct Process *proc;
  1262.  
  1263.     t=(LONG)MaxCli();
  1264.     t=myatoi(av[1],0,t); if (atoierr) return 20;
  1265.     pri=myatoi(av[2],-128,127); if (atoierr) return 20;
  1266.     Forbid();
  1267.     proc=(t==0 ? Myprocess : FindCliProc((LONG)t));
  1268.     if (proc==NULL) fprintf(stderr, "process not found\n");
  1269.     else SetTaskPri((struct Task *)proc, (long)pri);
  1270.     Permit();
  1271.     return 0;
  1272. }
  1273.  
  1274. do_strleft( void )
  1275. {
  1276.     int n;
  1277.  
  1278.     n=posatoi(av[3]); if (atoierr) return 20;
  1279.     set_var_n(LEVEL_SET, av[1], av[2], n);
  1280.     return 0;
  1281. }
  1282.  
  1283. do_strright( void )
  1284. {
  1285.     int n, len=strlen(av[2]);
  1286.  
  1287.     n=posatoi(av[3]); if (atoierr) return 20;
  1288.     if( n>len ) n=len;
  1289.     set_var(LEVEL_SET, av[1], av[2]+len-n );
  1290.     return 0;
  1291. }
  1292.  
  1293. do_strmid( void )
  1294. {
  1295.     int n1, n2=999999, len=strlen(av[2]);
  1296.  
  1297.     n1=myatoi(av[3],1,999999)-1; if (atoierr) return 20;
  1298.     if (n1>len) n1=len;
  1299.     if (ac>4) {
  1300.         n2=posatoi(av[4]); if (atoierr) return 20;
  1301.     }
  1302.     set_var_n(LEVEL_SET, av[1], av[2]+n1, n2);
  1303.     return 0;
  1304. }
  1305.  
  1306. do_strlen( void )
  1307. {
  1308.     char buf[16];
  1309.  
  1310.     sprintf(buf,"%d",strlen(av[2]));
  1311.     set_var(LEVEL_SET, av[1], buf);
  1312.     return 0;
  1313. }
  1314.  
  1315. int atoierr;
  1316.  
  1317. myatoi(char *s,int mmin,int mmax)
  1318. {
  1319.     int n;
  1320.  
  1321.     atoierr=0;   /* GMD: initialise external flag! */
  1322.     n=atol(s);
  1323.  
  1324.     if (!isnum(s)) {   /* AMK: IoErr() replaced by isnum() */
  1325.         atoierr=1;
  1326.         ierror(s,511);
  1327.     }
  1328.     else if (n<mmin || n>mmax) {
  1329.         atoierr=1; n=mmin;
  1330.         fprintf( stderr, "%s(%d) not in (%d,%d)\n",s,n,mmin,mmax );
  1331.     }
  1332.     return n;
  1333. }
  1334.  
  1335. unlatoi(char *s)
  1336. {
  1337.     int n=atol(s);
  1338.     atoierr=0;
  1339.     if (!isnum(s)) {   /* AMK: IoErr() replaced by isnum() */
  1340.         atoierr=1;
  1341.         ierror(s,511);
  1342.         n=0;
  1343.     }
  1344.     return n;
  1345. }
  1346.  
  1347. posatoi(char *s)
  1348. {
  1349.     int n=atol(s);
  1350.     atoierr=0;
  1351.     if (!isnum(s)) {   /* AMK: IoErr() replaced by isnum() */
  1352.         atoierr=1;
  1353.         ierror(s,511);
  1354.         n=0;
  1355.     }
  1356.     else if (n<0 )
  1357.         atoierr=1, n=0, fprintf( stderr, "%s must be positive\n",s );
  1358.     return n;
  1359. }
  1360.  
  1361.  
  1362. do_fltlower( void )
  1363. {
  1364.     return line_filter( strlwr );
  1365. }
  1366.  
  1367. do_fltupper( void )
  1368. {
  1369.     return line_filter( strupr );
  1370. }
  1371.  
  1372. #if 0
  1373. char *
  1374. stripcr( char *get )
  1375. {
  1376.     char *old=get, *put;
  1377.  
  1378.     for( put=get; *get; get++ )
  1379.         if( *get!=13 )
  1380.             *put++=*get;
  1381.     *put++=0;
  1382.     return old;
  1383. }
  1384.  
  1385. do_fltstripcr( void )
  1386. {
  1387.     return line_filter( stripcr );
  1388. }
  1389. #endif
  1390.  
  1391. static int
  1392. line_filter( char *(*func)( char * ) )
  1393. {
  1394.     char buf[256];
  1395.  
  1396.     while (!CHECKBREAK() && myfgets(buf,stdin))
  1397.         puts((*func)(buf));
  1398.     return 0;
  1399. }
  1400.  
  1401. int
  1402. do_linecnt( void )
  1403. {
  1404.     int count=0;
  1405.     char buf[256];
  1406.  
  1407.     while (!CHECKBREAK() && fgets(buf,255,stdin)) ++count;
  1408.     printf("%d lines\n",count);
  1409.     return 0;
  1410. }
  1411.  
  1412. int
  1413. do_uniq( void )
  1414. {
  1415.     int firstline=1;
  1416.     char buf[256], oldbuf[256];
  1417.  
  1418.     while (!CHECKBREAK() && myfgets(buf,stdin)) {
  1419.         if ( firstline || strcmp(buf, oldbuf)) {
  1420.             strcpy(oldbuf, buf);
  1421.             puts(buf);
  1422.         }
  1423.         firstline=0;
  1424.     }
  1425.     return 0;
  1426. }
  1427.  
  1428.  
  1429. #define RXFB_RESULT  17
  1430. #define RXCOMM    0x01000000
  1431.  
  1432. static struct rexxmsg {
  1433.     struct Message rm_Node;             /* EXEC message structure        */
  1434.     APTR     rm_TaskBlock;              /* global structure (private)    */
  1435.     APTR     rm_LibBase;                /* library base (private)        */
  1436.     LONG     rm_Action;                 /* command (action) code         */
  1437.     LONG     rm_Result1;                /* primary result (return code)  */
  1438.     LONG     rm_Result2;                /* secondary result              */
  1439.     STRPTR   rm_Args[16];               /* argument block (ARG0-ARG15)   */
  1440.  
  1441.     struct MsgPort *rm_PassPort;        /* forwarding port               */
  1442.     STRPTR   rm_CommAddr;               /* host address (port name)      */
  1443.     STRPTR   rm_FileExt;                /* file extension                */
  1444.     LONG     rm_Stdin;                  /* input stream (filehandle)     */
  1445.     LONG     rm_Stdout;                 /* output stream (filehandle)    */
  1446.     LONG     rm_avail;                  /* future expansion              */
  1447. } mymsg;                                /* size: 128 bytes               */
  1448.  
  1449.  
  1450. do_rxsend( char *avline )
  1451. {
  1452.     int i, ret=0;
  1453.     long result;
  1454.     struct MsgPort *port, *reply;
  1455.     long len;
  1456.     char buf[20], *resptr;
  1457.  
  1458.     if (!(port = (struct MsgPort *)FindPort(av[1])))
  1459.         { fprintf(stderr, "No port %s!\n", av[1]); return 20; }
  1460.     mymsg.rm_Node.mn_Node.ln_Type = NT_MESSAGE;
  1461.     mymsg.rm_Node.mn_Length = sizeof(struct rexxmsg);
  1462.     mymsg.rm_Action = RXCOMM | (options&1 ? 1L << RXFB_RESULT : 0);
  1463.     if (!(reply = CreateMsgPort())) {
  1464.         fprintf(stderr, "No reply port\n");
  1465.         return 20;
  1466.     }
  1467.     mymsg.rm_Node.mn_ReplyPort = reply;
  1468.  
  1469.     if( options&2 )
  1470.         av[2]=compile_av( av,2,ac,' ',0), ac=3;
  1471.     for ( i=2; i<ac; i++) {
  1472.         mymsg.rm_Args[0] = av[i];
  1473.         mymsg.rm_Result2 = 0;        /* clear out the last result. */
  1474.         PutMsg(port, &mymsg.rm_Node);
  1475.  
  1476.         Wait( 1<<reply->mp_SigBit | SIGBREAKF_CTRL_C );
  1477.  
  1478.         if( CHECKBREAK() ) {
  1479.             ret=5;
  1480.             break;
  1481.         }
  1482.  
  1483.         if (options&1) {
  1484.             if( (result=mymsg.rm_Result2)<1000000 ) { /* like AREXX */
  1485.                 sprintf(buf,"%d",result);              
  1486.                 set_var(LEVEL_SET,v_result,buf);
  1487.             } else {
  1488.                 resptr=(char *)(result-4);
  1489.                 len=*(long *)resptr;
  1490.                 memmove(resptr,resptr+4,len);  /* Null terminate */
  1491.                 resptr[len]=0;      
  1492.                 set_var(LEVEL_SET,v_result,resptr);
  1493.                 FreeMem(resptr, len+4 );
  1494.             }
  1495.         } else 
  1496.             unset_var( LEVEL_SET, v_result );
  1497.     }
  1498.     if( options&2 )
  1499.         free( av[2] );
  1500.  
  1501.     if (reply) DeleteMsgPort(reply);
  1502.     return ret;
  1503. }
  1504.  
  1505. static char *rxreturn;
  1506.  
  1507. do_rxrec( void )
  1508. {
  1509.     struct MsgPort *port;
  1510.     struct rexxmsg *msg;
  1511.     char *portname, *str;
  1512.  
  1513.     if (ac > 1)
  1514.         portname=av[1];
  1515.     else
  1516.         portname="rexx_csh";
  1517.  
  1518.     if (!(port=CreateMsgPort())) {
  1519.         fprintf(stderr, "Can't have MsgPort %s\n", portname);
  1520.         return 20;
  1521.     }
  1522.     port->mp_Node.ln_Name = portname;
  1523.     port->mp_Node.ln_Pri  = 0;
  1524.     AddPort(port);
  1525.     for (;;) {
  1526.         WaitPort(port);
  1527.         while (msg=(struct rexxmsg *)GetMsg(port)) {
  1528.             if ( ! stricmp(msg->rm_Args[0], "bye")) {
  1529.                 ReplyMsg((struct Message *)msg);
  1530.                 RemPort(port);
  1531.                 DeleteMsgPort(port);
  1532.                 return 0;
  1533.             }
  1534.             rxreturn=NULL;
  1535.             exec_command(msg->rm_Args[0]);
  1536.             if (msg->rm_Action & (1L << RXFB_RESULT)) {
  1537.                 if( rxreturn ) {
  1538.                     str= SAllocMem( strlen( rxreturn )+5 , 0 );
  1539.                     *(long *)str=strlen( rxreturn );
  1540.                     strcpy( str+4, rxreturn );
  1541.                     msg->rm_Result2=(long)str;
  1542.                 } else {
  1543.                     str = get_var(LEVEL_SET, v_lasterr);
  1544.                     msg->rm_Result2=(str) ? atoi(str) : 20;
  1545.                 }
  1546.             }
  1547.             ReplyMsg((struct Message *)msg);
  1548.         }
  1549.     }
  1550. }
  1551.  
  1552. int
  1553. do_waitport( void )
  1554. {
  1555.     int count=4*10;
  1556.     struct MsgPort *port=NULL;
  1557.  
  1558.     if( ac==3 ) 
  1559.         { count=2*myatoi(av[2],0, 32000); if( atoierr ) return 20; }
  1560.  
  1561.     while( --count>=0 && !(port=FindPort(av[1])) && !dobreak() )
  1562.         Delay(12);
  1563.  
  1564.     return port ? 0 : 20;
  1565. }
  1566.  
  1567. int
  1568. do_rxreturn( void )
  1569. {
  1570.     rxreturn=compile_av( av, 1, ac, ' ', 1 );
  1571.     return 0;
  1572. }
  1573.  
  1574. do_ascii( void )
  1575. {
  1576.     int x=1, y, c, c1, t;
  1577.     char *fmt1=" %3d %c%c |", *fmt2=" %4d";
  1578.  
  1579.     if( options&1 ) fmt1=" %3o %c%c |", fmt2="%4o";
  1580.     if( options&2 ) fmt1=" %3x %c%c |", fmt2="%4x";
  1581.     if( ac==x )
  1582.         for( y=0; y<32 && !dobreak(); y++ ) {
  1583.             printf("|");
  1584.             for( x=0; x<8; x++ ) {
  1585.                 c1=c=y+32*x; t=' ';
  1586.                 if( c<32 ) t='^', c1+=64;
  1587.                 printf(fmt1,c, t, c1<128 || c1>=160?c1:'.');
  1588.             }
  1589.             printf("\n");
  1590.         }
  1591.     else 
  1592.         for( ; x<ac && !dobreak(); x++ ) {
  1593.             for( y=0; y<strlen(av[x]); y++ )
  1594.                 printf(fmt2,av[x][y]);
  1595.             printf("\n");
  1596.         }
  1597.     return 0;
  1598. }
  1599.  
  1600. void
  1601. appendslash( char *path )
  1602. {
  1603.     int c;
  1604.  
  1605.     if( (c=path[strlen(path)-1]) !='/' && c!=':' )
  1606.         strcat(path,"/");
  1607. }
  1608.  
  1609. static void
  1610. whereis( char *path, char *file )
  1611. {
  1612.     char **eav, buf[100];
  1613.     int  eac, j;
  1614.  
  1615.     buf[0]=0;
  1616.     if( path ) {
  1617.         strcpy(buf,path);
  1618.         appendslash(buf);
  1619.     }
  1620.     strcat(buf,".../");
  1621.     strcat(buf,file);
  1622.     if( !index( file, '*' ) && !index( file, '?') )
  1623.         strcat(buf,"*");
  1624.     if(eav=expand(buf,&eac)) {
  1625.         for( j=0; j<eac && !dobreak(); j++ )
  1626.             printf("%s\n",eav[j]);
  1627.         free_expand(eav);
  1628.     }
  1629. }
  1630.  
  1631. do_whereis( void )
  1632. {
  1633.     char buf[200], *prev, *devs;
  1634.     int i;
  1635.  
  1636.     if( index( av[1],':') || index( av[1],'/' ) )
  1637.         { fprintf(stderr,"No paths please\n"); return 20; };
  1638.  
  1639.     if( options&1 ) {
  1640.         Myprocess->pr_WindowPtr = (APTR)(-1);
  1641.         get_drives( devs=buf );
  1642.         do {
  1643.             prev=devs; devs=index(devs,0xA0);
  1644.             if( devs ) *devs++=0; 
  1645.             whereis( prev, av[1] );
  1646.         } while( devs );
  1647.         Myprocess->pr_WindowPtr = (APTR) o_noreq;
  1648.     } else if( ac==2 ) {
  1649.         whereis( NULL, av[1] );
  1650.     } else {
  1651.         for( i=2; i<ac; i++ ) {
  1652.             strcpy(buf,av[i]);
  1653.             appendslash( buf );
  1654.             whereis( buf, av[1] );
  1655.         }
  1656.     }
  1657.     return 0;
  1658. }
  1659.  
  1660. do_usage( void )
  1661. {
  1662.     int i;
  1663.  
  1664.     if( ac==1 ) {
  1665.         printf("Usage: usage [command...command]\n");
  1666.         printf("[ ]=option   [ | ]=choice   { }=repetition   name...name=1 or more names\n");
  1667.     } else
  1668.         for( i=1; i<ac; i++ )
  1669.             show_usage( av[i] );
  1670.     return 0;
  1671. }
  1672.  
  1673.  
  1674.  
  1675. /* these defines are new in OS 3.x */
  1676. #ifndef WA_NewLookMenus
  1677. #define WA_NewLookMenus (WA_Dummy + 0x30)
  1678. #endif
  1679. #ifndef GTMN_NewLookMenus
  1680. #define GTMN_NewLookMenus GT_TagBase+67
  1681. #endif
  1682. #ifndef WFLG_NEWLOOKMENUS
  1683. #define WFLG_NEWLOOKMENUS 0x00200000
  1684. #endif
  1685.  
  1686.  
  1687.  
  1688. static struct NewMenu *NewMenus = NULL;
  1689. static int AnzMenus = 0, AnzItems = 1;
  1690. static APTR *visualInfo = NULL;
  1691. static struct Menu *menuStrip = NULL;
  1692. static char *fontName = NULL;
  1693. static struct TextAttr textAttr;
  1694. static struct TextFont *textFont = NULL;
  1695.  
  1696. char *MenuCommand[MAXMENUS][MAXMENUITEMS];
  1697.  
  1698. do_menu( void )
  1699. {
  1700.     if( o_nowindow )
  1701.         return 5;
  1702.  
  1703.     if( options&1 )
  1704.         remove_menu();
  1705.  
  1706.     if( ac==2 )
  1707.         show_usage( NULL );
  1708.     else if( AnzMenus<MAXMENUS && ac!=1)
  1709.         install_menu( av+1, ac-1 );
  1710.  
  1711.     set_menu();
  1712.     return 0;
  1713. }
  1714.  
  1715. static void
  1716. install_menu( char *mav[], int mac )
  1717. {
  1718.     char *p, *com;
  1719.     long msize;
  1720.     struct NewMenu *new_NewMenus;
  1721.     int i;
  1722.  
  1723.     if (o_nowindow || !Win)
  1724.         return;
  1725.  
  1726.     /* mac holds number of items, including title which counts as item */
  1727.  
  1728.     if (mac>MAXMENUITEMS)
  1729.         mac=MAXMENUITEMS;
  1730.  
  1731.     ClearMenuStrip( Win );
  1732.     if (menuStrip) FreeMenus(menuStrip);
  1733.     if (visualInfo) FreeVisualInfo(visualInfo);
  1734.     Delay(3);
  1735.  
  1736.     msize = sizeof(struct NewMenu) * (mac+1 + AnzItems-1);    /* one extra 'end' item */
  1737.     new_NewMenus = salloc(msize);
  1738.     memset(new_NewMenus,0,msize);
  1739.     if (NewMenus) {
  1740.         memcpy(new_NewMenus,NewMenus,sizeof(struct NewMenu)*(AnzItems-1));
  1741.         free(NewMenus);
  1742.     }
  1743.     else {
  1744.         int i,j;
  1745.         for (i=0; i<MAXMENUS; i++)
  1746.             for (j=0; j<MAXMENUITEMS; j++)
  1747.                 MenuCommand[i][j] = NULL;
  1748.     }
  1749.     NewMenus = new_NewMenus;
  1750.  
  1751.     NewMenus[AnzItems-1].nm_Type  = NM_TITLE;
  1752.     NewMenus[AnzItems-1].nm_Label = strcpy(salloc(strlen(mav[0])+1),mav[0]);
  1753.  
  1754.     for( i=1; i<mac; i++) {
  1755.         com=NULL;
  1756.         if( p=index(mav[i],',')) {
  1757.             *p=0; com=++p;
  1758.             if( p=index(com,',')) {
  1759.                 *p=0;
  1760.                 NewMenus[AnzItems].nm_CommKey = strdup(++p);
  1761.             }
  1762.         }
  1763.  
  1764.         if( !com || !*com) {
  1765.             com=strcpy(salloc(strlen(mav[i])+2),mav[i]);
  1766.             MenuCommand[AnzMenus][i-1]=com;
  1767.             com+=strlen(com);
  1768.             *com++=13;
  1769.             *com=0;
  1770.         } else {
  1771.             MenuCommand[AnzMenus][i-1]=strcpy(salloc(strlen(com)+1),com);
  1772.         }
  1773.  
  1774.         NewMenus[AnzItems].nm_Type  = NM_ITEM;
  1775.         NewMenus[AnzItems].nm_Label = strcpy(salloc(strlen(mav[i])+2),mav[i]);
  1776.  
  1777.         AnzItems++;
  1778.     }
  1779.  
  1780.     AnzMenus++;
  1781.     NewMenus[AnzItems++].nm_Type = NM_END;
  1782.  
  1783.     if (!(visualInfo=GetVisualInfo(Win->WScreen,TAG_END))) {
  1784.         printf("no visual info\n");
  1785.         free(NewMenus);
  1786.     }
  1787.  
  1788.     if (!(menuStrip=CreateMenus(NewMenus,TAG_END))) {
  1789.         printf("no create menus\n");
  1790.         FreeVisualInfo(visualInfo);
  1791.         free(NewMenus);
  1792.     }
  1793.  
  1794.     /* do we want a monospaced (non-proportional) font? */
  1795.     if (options&2 && !textFont && AnzMenus<=1) {
  1796.         Forbid();
  1797.         if (GfxBase->DefaultFont) {
  1798.             textAttr.ta_Name = fontName = strdup(GfxBase->DefaultFont->tf_Message.mn_Node.ln_Name);
  1799.             textAttr.ta_YSize = GfxBase->DefaultFont->tf_YSize;
  1800.         }
  1801.         else {
  1802.             textAttr.ta_Name  = "topaz.font";
  1803.             textAttr.ta_YSize = 8;
  1804.         }
  1805.         Permit();
  1806.         textAttr.ta_Style = FS_NORMAL;
  1807.         textAttr.ta_Flags = 0;
  1808.         if (textAttr.ta_Name)
  1809.             textFont = OpenDiskFont(&textAttr);
  1810.     }
  1811.  
  1812. /*
  1813.     if (!LayoutMenus(menuStrip,visualInfo,
  1814.                 textFont==NULL ? TAG_IGNORE : GTMN_TextAttr, &textAttr,
  1815.                 TAG_END))
  1816.     {
  1817. */
  1818.     if (!LayoutMenus(menuStrip,visualInfo,
  1819.                 Win->Flags&WFLG_NEWLOOKMENUS ? GTMN_NewLookMenus : TAG_IGNORE, TRUE,
  1820.                 textFont==NULL ? TAG_IGNORE : GTMN_TextAttr, &textAttr,
  1821.                 TAG_END))
  1822.     {
  1823.  
  1824.         printf("no layout menus\n");
  1825.         FreeMenus(menuStrip);
  1826.         FreeVisualInfo(visualInfo);
  1827.         free(NewMenus);
  1828.     }
  1829.  
  1830.     return;
  1831. }
  1832.  
  1833. void remove_menu()
  1834. {
  1835.     if (AnzMenus>0) {
  1836.         struct NewMenu *nm;
  1837.         int i,j;
  1838.  
  1839.         for (i=0; i<MAXMENUS; i++) {
  1840.             for (j=0 ;j<MAXMENUITEMS; j++)
  1841.                 if (MenuCommand[i][j]) {
  1842.                     free(MenuCommand[i][j]);
  1843.                     MenuCommand[i][j] = NULL;
  1844.                 }
  1845.         }
  1846.  
  1847.         for (nm=NewMenus; nm->nm_Type!=NM_END; nm++) {
  1848.             if (nm->nm_Label) {
  1849.                 free(nm->nm_Label);
  1850.                 nm->nm_Label = NULL;
  1851.             }
  1852.             if (nm->nm_CommKey) {
  1853.                 free(nm->nm_CommKey);
  1854.                 nm->nm_CommKey = NULL;
  1855.             }
  1856.         }
  1857.  
  1858.         AnzMenus=0;
  1859.         set_menu();
  1860.     }
  1861. }
  1862.  
  1863. void set_menu()
  1864. {
  1865.     if (o_nowindow || !Win)
  1866.         return;
  1867.  
  1868.     if (AnzMenus>0)
  1869.         SetMenuStrip(Win,menuStrip);
  1870.     else {
  1871.         ClearMenuStrip(Win);
  1872.         FreeMenus(menuStrip);
  1873.         FreeVisualInfo(visualInfo);
  1874.         free(NewMenus);
  1875.         menuStrip  = NULL;
  1876.         visualInfo = NULL;
  1877.         NewMenus   = NULL;
  1878.         AnzMenus = 0;
  1879.         AnzItems = 1;
  1880.         if (textFont) {
  1881.             CloseFont(textFont);
  1882.             textFont = NULL;
  1883.         }
  1884.         if (fontName) {
  1885.             free(fontName);
  1886.             fontName = NULL;
  1887.         }
  1888.     }
  1889.  
  1890.     Delay(3);
  1891. }
  1892.  
  1893.  
  1894. #if 0
  1895. int NumMenus;
  1896.  
  1897. static struct Menu DefaultMenu= {0, 0,0,TITWID,10, MENUENABLED,0,0};
  1898. static struct IntuiText DefaultIntuiText= {0,1,JAM2, 1,1,NULL,0,0};
  1899. static struct MenuItem DefaultMenuItem=
  1900.   {0, 0,0,ITEWID,0, HIGHCOMP|ITEMTEXT|ITEMENABLED,0,0,0,0,0,0};
  1901.  
  1902. struct Menu Menus[10];
  1903. char *MenuCommand[MAXMENUS][MAXMENUITEMS];
  1904.  
  1905. static void
  1906. install_menu( char *mav[], int mac )
  1907. {
  1908.     struct TextAttr *ta;
  1909.     struct Menu *m;
  1910.     struct MenuItem *mi, **pmi;
  1911.     struct IntuiText *it;
  1912.     int y, i, fonthei;
  1913.     char *p, *com;
  1914.  
  1915.     if( o_nowindow || !Win )
  1916.         return;
  1917.  
  1918.     if( mac>=MAXMENUITEMS )
  1919.         mac=MAXMENUITEMS-1;
  1920.  
  1921.     ClearMenuStrip( Win );
  1922.     Delay(3);
  1923.  
  1924.     if( NumMenus )
  1925.         Menus[NumMenus-1].NextMenu=Menus+NumMenus;
  1926.     m  =&Menus[NumMenus];
  1927.     *m =DefaultMenu;
  1928.     m->LeftEdge  = NumMenus*TITWID;
  1929.     m->MenuName  = strcpy(salloc(strlen(mav[0])+1),mav[0]);
  1930.     if( strlen(m->MenuName)>TITWID/8 )
  1931.         m->MenuName[TITWID/8+1]=0;
  1932.     DefaultIntuiText.ITextFont=ta=Win->WScreen->Font;
  1933.     DefaultMenuItem.Height=2+(fonthei=ta->ta_YSize);
  1934.  
  1935.     y=0;
  1936.     pmi=&m->FirstItem;
  1937.     for( i=1; i<mac; i++) {
  1938.         it =(void *)salloc(sizeof(struct IntuiText));
  1939.         *it=DefaultIntuiText;
  1940.         mi =(void *)salloc(sizeof(struct MenuItem ));
  1941.         *mi=DefaultMenuItem;
  1942.  
  1943.         com=NULL;
  1944.         if( p=index(mav[i],',')) {
  1945.             *p=0; com=++p;
  1946.             if( p=index(com,',')) {
  1947.                 *p=0;
  1948.                 mi->Command=p[1];
  1949.                 mi->Flags |=COMMSEQ;
  1950.             }
  1951.         }
  1952.  
  1953.         if( !com || !*com) {
  1954.             com=strcpy(salloc(strlen(mav[i])+2),mav[i]);
  1955.             MenuCommand[NumMenus][i-1]=com;
  1956.             com+=strlen(com);
  1957.             *com++=13;
  1958.             *com=0;
  1959.         } else {
  1960.             MenuCommand[NumMenus][i-1]=strcpy(salloc(strlen(com)+1),com);
  1961.         }
  1962.  
  1963.         it->IText=(UBYTE *)strcpy(salloc(strlen(mav[i])+2),mav[i]);
  1964.  
  1965.         *pmi= mi;
  1966.         pmi = &mi->NextItem;
  1967.         mi->TopEdge = y;
  1968.         mi->ItemFill= (APTR)it;
  1969.  
  1970.         y+=DefaultMenuItem.Height;
  1971.     }
  1972.  
  1973.     NumMenus++;
  1974. MError:
  1975.     return;
  1976. }
  1977.  
  1978. void remove_menu()
  1979. {
  1980.     if (NumMenus>0) {
  1981.         struct MenuItem *mi, *nextmi;
  1982.         int i,j;
  1983.  
  1984.         for( i=0; i<NumMenus; i++ ) {
  1985.             for( mi=Menus[i].FirstItem,j=0 ; mi; mi=nextmi,j++ ) {
  1986.                 free( ((struct IntuiText *)mi->ItemFill)->IText );
  1987.                 free( ((struct IntuiText *)mi->ItemFill) );
  1988.                 nextmi=mi->NextItem;
  1989.                 free(mi);
  1990.                 free(MenuCommand[i][j]);
  1991.             }
  1992.         }
  1993.  
  1994.         NumMenus=0;
  1995.         set_menu();
  1996.     }
  1997. }
  1998.  
  1999. void set_menu()
  2000. {
  2001.     if (o_nowindow || !Win)
  2002.         return;
  2003.  
  2004.     if (NumMenus>0)
  2005.         SetMenuStrip(Win,Menus);
  2006.     else
  2007.         ClearMenuStrip(Win);
  2008.  
  2009.     Delay(3);
  2010. }
  2011. #endif
  2012.  
  2013. int
  2014. do_getenv( void )
  2015. {
  2016.     char buf[256], *val=buf;
  2017.  
  2018.     if( ac!=3 && ac!=2 ) {
  2019.         show_usage( NULL );
  2020.         return 20;
  2021.     }
  2022.     /* AMK: OS20-GetVar replaces ARP-Getenv */
  2023.     if( GetVar(av[ac-1],buf,256,GVF_GLOBAL_ONLY|GVF_BINARY_VAR) < 0L )
  2024.         val="";
  2025.  
  2026.     if( ac==2 )
  2027.         printf( "%s\n", val );
  2028.     else
  2029.         set_var( LEVEL_SET, av[1], val );
  2030.     return 0;
  2031. }
  2032.  
  2033. int
  2034. do_setenv( void )
  2035. {
  2036.     if( ac!=3 ) {
  2037.         show_usage( NULL );
  2038.         return 20;
  2039.     } else
  2040.         setenv( av[1], av[2] );
  2041.     return 0;
  2042. }
  2043.  
  2044. char **
  2045. read_name( char *name, int *ac )
  2046. {
  2047.     FILE *file;
  2048.     char **av=NULL;
  2049.  
  2050.     *ac=0;
  2051.     if( file=name ? fopen( name, "r") : stdin ) {
  2052.         av=read_file( file, ac );
  2053.         if( name ) fclose( file );
  2054.     } else 
  2055.         pError( name );
  2056.     return av;
  2057. }
  2058.  
  2059.  
  2060. char **
  2061. read_file( FILE *file, int *ac )
  2062. {
  2063.     int buflen=4096, lines=0, i, offs, got=0;
  2064.     char *buf, *tmp, *ptr, **lineptr;
  2065.  
  2066.     if( !(buf=ptr=DosAllocMem( buflen )))
  2067.         goto error;
  2068.     do {
  2069.         while( ptr+400 < buf+buflen && (got=myfgets(ptr, file)) && !dobreak())
  2070.             ptr+=strlen(ptr)+1, lines++;
  2071.         if( ptr+256 < buf+buflen ) {
  2072.             offs=ptr-buf;
  2073.             if( !(tmp=DosAllocMem( buflen*2 )))
  2074.                 goto error;
  2075.             memcpy( tmp, buf, buflen );
  2076.             DosFreeMem( buf );
  2077.             buflen*=2, buf=tmp;
  2078.             ptr=buf+offs;
  2079.         }
  2080.     } while( got && !dobreak());
  2081.     if( !(lineptr=(char **)DosAllocMem( (lines+1)*sizeof( char * ))))
  2082.         goto error;
  2083.     *lineptr++=buf;
  2084.     for( ptr=buf, i=0; i<lines; i++ ) {
  2085.         lineptr[i]=ptr;
  2086.         ptr+=strlen(ptr)+1;
  2087.     }
  2088.     *ac=lines;
  2089.     return lineptr;
  2090.  
  2091. error:
  2092.     if( buf ) DosFreeMem( buf );
  2093.     fprintf( stderr, "Out of memory\n" );
  2094.     *ac=0;
  2095.     return NULL;
  2096. }
  2097.  
  2098. void
  2099. free_file( ptr )
  2100.     char **ptr;
  2101. {
  2102.     if( ptr-- ) {
  2103.         if( *ptr )
  2104.             DosFreeMem( *ptr );
  2105.         DosFreeMem(ptr);
  2106.     }
  2107. }
  2108.  
  2109.  
  2110. do_qsort( void )
  2111. {
  2112.     char **lineptr;
  2113.     int  lines, i;
  2114.  
  2115.     if( ac==1 ) {
  2116.         lineptr=read_file( stdin, &lines);
  2117.         DirQuickSort( lineptr, lines, cmp, options&1, 0 );
  2118.         prepscroll(0);
  2119.         for( i=0; i<lines && !dobreak(); i++ ) {
  2120.             quickscroll();
  2121.             puts( lineptr[i] );
  2122.         }
  2123.         free_file( lineptr );
  2124.     } else
  2125.         ierror( NULL,506 );
  2126.     return 0;
  2127. }
  2128.  
  2129. extern int w_width;
  2130.  
  2131. do_truncate( void )
  2132. {
  2133.     char buf[256];
  2134.     int  w=newwidth(), c;
  2135.     char *ptr;
  2136.  
  2137.     if( ac==2 )
  2138.         w=atoi( av[1] );
  2139.  
  2140.     prepscroll(0);
  2141.     while( myfgets(buf,stdin) && !dobreak() ) {
  2142.         for( c=0, ptr=buf; *ptr && c<w; ptr++ )
  2143.             if( *ptr=='\t' )
  2144.                 c+=8-(c&7);
  2145.             else if( *ptr==27 ) {
  2146.                 while( *ptr<'@' )
  2147.                     ptr++;
  2148.             } else 
  2149.                 c++;
  2150.         *ptr=0;
  2151.         quickscroll();
  2152.         puts(buf);
  2153.     }
  2154.     return 0;
  2155. }
  2156.  
  2157. int
  2158. do_readfile( void )
  2159. {
  2160.     char **rav, *str=NULL, *file=NULL;
  2161.     int rac;
  2162.  
  2163.     if( ac>2 ) file=av[2];
  2164.     if( rav=read_name( file, &rac ) ) { 
  2165.         if( str= compile_av( rav, 0, rac, 0xA0, 0 ) )
  2166.             set_var( LEVEL_SET, av[1], str );
  2167.         free_file( rav );
  2168.     }
  2169.     return str ? 0 : 20;
  2170. }
  2171.  
  2172. void
  2173. foreach( char **s, int (*func)(char *s) )
  2174. {
  2175.     char *str;
  2176.  
  2177.     for( ;; ) {
  2178.         str=*s;
  2179.         if( !(*s=index(*s,0xA0)))
  2180.             break;
  2181.         **s=0;
  2182.         (*func)(str);
  2183.         *(*s)++=0xA0;
  2184.         if( breakcheck())
  2185.             return;
  2186.     }
  2187.     (*func)(str);
  2188. }
  2189.  
  2190. int
  2191. do_writefile( void )
  2192. {
  2193.     char *ptr;
  2194.  
  2195.     if( !(ptr=get_var(LEVEL_SET,av[1])))
  2196.         { fprintf(stderr,"Undefined variable %s\n",av[1]); return 20; }
  2197.  
  2198.     foreach( &ptr, puts );
  2199.  
  2200.     return 0;
  2201. }
  2202.  
  2203. int
  2204. do_split( void )
  2205. {
  2206.     int i;
  2207.     char *val, *gap, *oldval;
  2208.  
  2209.     if( !(val=get_var( LEVEL_SET, av[1] )))
  2210.         { fprintf( stderr, "undefined variable %s\n", av[1] ); return 20; }
  2211.     oldval=val=strcpy(salloc(strlen(val)+1),val);
  2212.     for( i=2; i<ac-1; i++ ) {
  2213.         if( gap=index(val,0xA0 )) *gap=0;
  2214.         set_var( LEVEL_SET, av[i], val );
  2215.         val="";
  2216.         if( gap ) *gap=0xA0, val=gap+1;
  2217.     }
  2218.     set_var( LEVEL_SET, av[ac-1], val );
  2219.     free(oldval);
  2220.     return 0;
  2221. }
  2222.  
  2223. char *
  2224. copyof( char *str )
  2225. {
  2226.     return strcpy(salloc(strlen(str)+1),str);
  2227. }
  2228.  
  2229. int
  2230. do_class( char *avline )
  2231. {
  2232.     CLASS *new;
  2233.  
  2234.     if( options&1 ) {
  2235.         avline=next_word(avline);
  2236.         for( new=CRoot,CRoot=NULL; new; new=new->next )
  2237.             Free(new);
  2238.     }
  2239.  
  2240.     if( ac==1 ) {
  2241.         for( new=CRoot; new; new=new->next )
  2242.             printf("%s\n",new->name);
  2243.         return 0;
  2244.     }
  2245.  
  2246.     avline=next_word(avline);
  2247.     if(!(new=malloc( strlen(avline)+5)))
  2248.         ierror( NULL, 512 );
  2249.     else {
  2250.         new->next=NULL;
  2251.         strcpy( new->name,avline );
  2252.         if( CRoot )
  2253.             LastCRoot->next=new;
  2254.         else 
  2255.             CRoot=new;
  2256.         LastCRoot=new;
  2257.     }
  2258.     return 0;
  2259. }
  2260.  
  2261. do_getcl( void )
  2262. {
  2263.     char *s=getclass(av[1]);
  2264.     if( s ) printf("%s\n",s);
  2265.     return 0;
  2266. }
  2267.  
  2268. do_action( char *argline )
  2269. {
  2270.     char *args, err;
  2271.     int abort=options&1;
  2272.  
  2273.     args=compile_av( av,3,ac,' ',0 );
  2274.     err=doaction(av[2],av[1],args);
  2275.     if( !abort )
  2276.         if( err==9 )     ierror(av[2], 205 );
  2277.         else if(err==10) fprintf(stderr,"Can't identify %s\n", av[2] );
  2278.         else if(err==11) fprintf(stderr,"Can't '%s' this file\n",av[1] );
  2279.         else if(err==12) fprintf(stderr,"Error executing the program to '%s' this file\n",av[1] );
  2280.     free(args);
  2281.     return abort ? !err : err;
  2282. }
  2283.  
  2284.  
  2285. #if 0
  2286. static void
  2287. viewfile( FILE *fi )
  2288. {
  2289.     char buf[256];
  2290.     long pages[64];
  2291.  
  2292.     /*xxxyyy*/
  2293.  
  2294. }
  2295.  
  2296. do_more( void )
  2297. {
  2298.     FILE *fi;
  2299.     int i;
  2300.  
  2301.     if( ac==1 && !IsInteractive(Input()))
  2302.         viewfile(stdin);
  2303.     else
  2304.         for( i=1; i<ac && !breackcheck(); i++ ) {
  2305.             if( fi=fopen( av[i], "r" ))
  2306.                 viewfile( fi ), fclose( fi );
  2307.             else 
  2308.                 fprintf( stderr, "Can't open %s\n" );
  2309. }
  2310. #endif
  2311.