home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / shell / csh539src.lha / comm3.c < prev    next >
C/C++ Source or Header  |  1994-09-06  |  59KB  |  2,857 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.  
  242.  
  243. do_assign( void )
  244. {
  245.     int i;
  246.  
  247.     if     (  ac==1  ) assignlist();
  248.     else if(  ac==2  ) doassign(av[1], NULL);
  249.     else if( !(ac&1) ) ierror(NULL, 500);
  250.     else
  251.         for( i=1; i<ac; i+=2 )
  252.             doassign( av[i],av[i+1] );
  253.     return 0;
  254. }
  255.  
  256.  
  257. /* AMK: rewritten code, removed bug when strlen(log) was 0 */
  258. static void
  259. doassign(char *log, char *phy)
  260. {
  261.     int last=strlen(log);
  262.  
  263.     if (last<2 || log[last-1] != ':') fprintf(stderr, "Bad name %s\n", log);
  264.     else {
  265.         int succ=0;
  266.  
  267.         log[last-1] = 0;
  268.  
  269.         if (!phy)
  270.             succ=AssignLock(log,NULL);
  271.         else if (options&1) {   /* add assign, CLI: assign ADD */
  272.             BPTR lock;
  273.             if( lock=Lock(phy,ACCESS_READ) )
  274.                 if( !(succ=AssignAdd(log,lock)))
  275.                     UnLock(lock);
  276.         }
  277.  
  278.         /* late-binding assign, CLI: assign DEFER */
  279.         else if (options&2 || options&8)
  280.             succ=AssignLate(log,phy);
  281.  
  282.         /* non-binding assign, CLI: assign PATH */
  283.         else if (options&4 || options&16)
  284.             succ=AssignPath(log,phy);
  285.         else if (!options) {
  286.             BPTR lock;
  287.             if( lock=Lock(phy,ACCESS_READ) )
  288.                 if( !(succ=AssignLock(log,lock)))
  289.                     UnLock(lock);
  290.         }
  291.  
  292.         if( !succ )
  293.             pError( log );
  294.     }
  295. }
  296.  
  297.  
  298. static void
  299. assignlist()
  300. {
  301.     char *ptr;
  302.     struct DosList *dl;
  303.     struct AssignList *path;
  304.     ULONG flags;
  305.     char fmt[256],devname[256];
  306.     char **dev_list;
  307.     long dev_num,i,cnt;
  308.  
  309.     dev_list = NULL;
  310.     dev_num  = 0;
  311.     flags    = LDF_VOLUMES|LDF_READ;
  312.  
  313.     Myprocess->pr_WindowPtr = (APTR)(-1);
  314.  
  315.     if (dl=LockDosList(flags)) {
  316.         while (dl=NextDosEntry(dl,flags)) {
  317.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  318.             sprintf(fmt,"%s%s",devname,
  319.                     dl->dol_misc.dol_volume.dol_LockList?"":" [Mounted]");
  320.             add_array_list(&dev_list,&dev_num,fmt);
  321.         }
  322.         UnLockDosList(flags);
  323.     }
  324.  
  325.     Myprocess->pr_WindowPtr = o_noreq ? (APTR) -1L : 0L/*Mywindow*/;
  326.  
  327.     QuickSort(dev_list,dev_num);
  328.     printf("Volumes:\n");
  329.     for(i=0; i<dev_num; i++)
  330.         printf("%s\n",dev_list[i]);
  331.     free_array_list(dev_list,dev_num);
  332.  
  333.     if (dobreak())
  334.         return;
  335.  
  336.     dev_list = NULL;
  337.     dev_num  = 0;
  338.     flags    = LDF_ASSIGNS|LDF_READ;
  339.  
  340.     Myprocess->pr_WindowPtr = (APTR)(-1);
  341.  
  342.     if (dl=LockDosList(flags)) {
  343.         while (dl=NextDosEntry(dl,flags)) {
  344.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  345.  
  346.             sprintf(fmt,"%-14s ",devname);
  347.             ptr = fmt+strlen(fmt);
  348.  
  349.             switch (dl->dol_Type) {
  350.                 case DLT_DIRECTORY :
  351.                     if(dl->dol_Lock) {
  352.                         if (!NameFromLock(dl->dol_Lock,ptr,200L)) {
  353.                             struct FileLock *fl_tmp = BADDR(dl->dol_Lock);
  354.                             /* get volume name of assign to an unmounted volume */
  355.                             if (fl_tmp->fl_Volume) {
  356.                                 struct DosList *dl_tmp = BADDR(fl_tmp->fl_Volume);
  357.                                 if (dl_tmp->dol_Name) {
  358.                                     BtoCStr(devname,dl_tmp->dol_Name,254L);  /* 256 - '\0' + ':' */
  359.                                     sprintf(ptr,"Volume: %s",devname);
  360.                                 }
  361.                                 else
  362.                                     strcpy(ptr,"n/a");
  363.                             }
  364.                             else
  365.                                 strcpy(ptr,"n/a");
  366.                             /*fprintf(stderr,"csh.assignlist.1: NameFromLock() failed\n");*/
  367.                             /*strcpy(ptr,"Lock's name too long");*/
  368.                         }
  369.                     }
  370.                     else
  371.                         strcpy(ptr,"Nonexisting lock");
  372. /* --- */
  373.                     if (path=dl->dol_misc.dol_assign.dol_List) {
  374.                         char **ass_list=NULL;
  375.                         long ass_num=0,str_len=0;
  376.                         char *ass_str;
  377.  
  378.                         add_array_list(&ass_list,&ass_num,fmt);
  379.                         str_len += strlen(fmt);
  380.  
  381.                         for (; path; path=path->al_Next) {
  382.                             sprintf(fmt,"%-13s+ ","");
  383.                             ptr = fmt+strlen(fmt);
  384.                             if (path->al_Lock) {
  385.                                 if (!NameFromLock(path->al_Lock,ptr,200L)) {
  386.                                     struct FileLock *fl_tmp = BADDR(path->al_Lock);
  387.                                     /* get volume name of assign to an unmounted volume */
  388.                                     if (fl_tmp->fl_Volume) {
  389.                                         struct DosList *dl_tmp = BADDR(fl_tmp->fl_Volume);
  390.                                         if (dl_tmp->dol_Name) {
  391.                                             BtoCStr(devname,dl_tmp->dol_Name,254L);  /* 256 - '\0' + ':' */
  392.                                             sprintf(ptr,"Volume: %s",devname);
  393.                                         }
  394.                                         else
  395.                                             strcpy(ptr,"n/a");
  396.                                     }
  397.                                     else
  398.                                         strcpy(ptr,"n/a");
  399.                                     /*fprintf(stderr,"csh.assignlist.2: NameFromLock() failed\n");*/
  400.                                     /*strcpy(ptr,"Lock's name too long");*/
  401.                                 }
  402.                             }
  403.                             else
  404.                                 strcpy(ptr,"Nonexisting lock");
  405.                             add_array_list(&ass_list,&ass_num,fmt);
  406.                             str_len += strlen(fmt)+1;
  407.                         }
  408.  
  409.                         if (ass_str=malloc(str_len+1)) {
  410.                             char *p=ass_str;
  411.                             for(i=0; i<ass_num; i++) {
  412.                                 strcpy(p,ass_list[i]);
  413.                                 p += strlen(p);
  414.                                 if ((i+1)<ass_num) {
  415.                                     *p++ = '\n';
  416.                                     *p   = '\0';
  417.                                 }
  418.                             }
  419.                             add_array_list(&dev_list,&dev_num,ass_str);
  420.                             free(ass_str);
  421.                         }
  422.  
  423.                         free_array_list(ass_list,ass_num);
  424.                     }
  425.                     else
  426.                         add_array_list(&dev_list,&dev_num,fmt);
  427. /* --- */
  428. #if 0
  429.                     add_array_list(&dev_list,&dev_num,fmt);
  430.  
  431.                     for(path=dl->dol_misc.dol_assign.dol_List; path; path=path->al_Next) {
  432.                         sprintf(fmt,"%-13s+ ","");
  433.                         ptr = fmt+strlen(fmt);
  434.                         if (path->al_Lock) {
  435.                             if (!NameFromLock(path->al_Lock,ptr,200L)) {
  436.                                 struct FileLock *fl_tmp = BADDR(path->al_Lock);
  437.                                 /* get volume name of assign to an unmounted volume */
  438.                                 if (fl_tmp->fl_Volume) {
  439.                                     struct DosList *dl_tmp = BADDR(fl_tmp->fl_Volume);
  440.                                     if (dl_tmp->dol_Name) {
  441.                                         BtoCStr(devname,dl_tmp->dol_Name,254L);  /* 256 - '\0' + ':' */
  442.                                         sprintf(ptr,"Volume: %s",devname);
  443.                                     }
  444.                                     else
  445.                                         strcpy(ptr,"n/a");
  446.                                 }
  447.                                 else
  448.                                     strcpy(ptr,"n/a");
  449.                                 /*fprintf(stderr,"csh.assignlist.3: NameFromLock() failed\n");*/
  450.                                 /*strcpy(ptr,"Lock's name too long");*/
  451.                             }
  452.                         }
  453.                         else
  454.                             strcpy(ptr,"Nonexisting lock");
  455.                         add_array_list(&dev_list,&dev_num,fmt);
  456.                     }
  457. #endif
  458.                     break;
  459.                 case DLT_LATE      :
  460.                     sprintf(ptr,"<%s>",dl->dol_misc.dol_assign.dol_AssignName);
  461.                     add_array_list(&dev_list,&dev_num,fmt);
  462.                     break;
  463.                 case DLT_NONBINDING:
  464.                     sprintf(ptr,"[%s]",dl->dol_misc.dol_assign.dol_AssignName);
  465.                     add_array_list(&dev_list,&dev_num,fmt);
  466.                     break;
  467.                 default:
  468.                     strcpy(ptr,"Unknown assign");
  469.                     add_array_list(&dev_list,&dev_num,fmt);
  470.                     break;
  471.             }
  472.         }
  473.         UnLockDosList(flags);
  474.     }
  475.  
  476.     Myprocess->pr_WindowPtr = o_noreq ? (APTR) -1L : 0L/*Mywindow*/;
  477.  
  478.     QuickSort(dev_list,dev_num);
  479.     printf("\nDirectories:\n");
  480.     for(i=0; !dobreak() && i<dev_num; i++)
  481.         printf("%s\n",dev_list[i]);
  482.     free_array_list(dev_list,dev_num);
  483.  
  484.     if (dobreak())
  485.         return;
  486.  
  487.     dev_list = NULL;
  488.     dev_num  = 0;
  489.     flags    = LDF_DEVICES|LDF_READ;
  490.  
  491.     Myprocess->pr_WindowPtr = (APTR)(-1);
  492.  
  493.     if (dl=LockDosList(flags)) {
  494.         while (dl=NextDosEntry(dl,flags)) {
  495.             if (dl->dol_Task) {
  496.                 BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  497.                 add_array_list(&dev_list,&dev_num,devname);
  498.             }
  499.         }
  500.         UnLockDosList(flags);
  501.     }
  502.  
  503.     Myprocess->pr_WindowPtr = o_noreq ? (APTR) -1L : 0L/*Mywindow*/;
  504.  
  505.     QuickSort(dev_list,dev_num);
  506.     printf("\nDevices (with FileSystem):\n");
  507.     for(i=0,cnt=0; i<dev_num; i++) {
  508.         if (IsFileSystem(dev_list[i])) {
  509.             if (cnt>0 && cnt%5==0)
  510.                 printf("\n");
  511.             printf("%s ",dev_list[i]);
  512.             ++cnt;
  513.         }
  514.     }
  515.     printf("\n");
  516.     free_array_list(dev_list,dev_num);
  517.  
  518.     if (dobreak())
  519.         return;
  520.  
  521.     dev_list = NULL;
  522.     dev_num  = 0;
  523.     flags    = LDF_DEVICES|LDF_READ;
  524.  
  525.     Myprocess->pr_WindowPtr = (APTR)(-1);
  526.  
  527.     if (dl=LockDosList(flags)) {
  528.         while (dl=NextDosEntry(dl,flags)) {
  529.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  530.             add_array_list(&dev_list,&dev_num,devname);
  531.         }
  532.         UnLockDosList(flags);
  533.     }
  534.  
  535.     Myprocess->pr_WindowPtr = o_noreq ? (APTR) -1L : 0L/*Mywindow*/;
  536.  
  537.     QuickSort(dev_list,dev_num);
  538.     printf("\nDevices:\n");
  539.     for(i=0; i<dev_num; i++) {
  540.         if (i>0 && i%5==0)
  541.             printf("\n");
  542.         printf("%s ",dev_list[i]);
  543.     }
  544.     printf("\n");
  545.     free_array_list(dev_list,dev_num);
  546.  
  547. return;
  548. #if 0
  549.     printf("\nDirectories:\n");
  550.     for( ; arr[i] && !dobreak(); i++ ) {
  551.         log=arr[i]+1; ptr=log+strlen(log)+1;
  552.         switch( *(log-1)) {
  553.         case 3:
  554.             printf("%-20s%s\n", log, ptr);
  555.             for(;;) {
  556.                 ptr+=strlen(ptr)+1;
  557.                 if( !*ptr ) break;
  558.                     printf("%-19s+%s\n", "", ptr);
  559.             }
  560.             break;
  561.         case 4: printf("%-20s<%s>\n", log, ptr); break;
  562.         case 5: printf("%-20s[%s]\n", log, ptr); break;
  563.         }
  564.     }
  565. #endif
  566. }
  567.  
  568.  
  569.  
  570. do_join( void )
  571. {
  572.     BPTR sou, dest;
  573.     char *buffer;
  574.     int i;
  575.     long n;
  576.     char *namedest=av[--ac];
  577.  
  578.     if (options==0 && exists(namedest)) { ierror(namedest,203); return 20; }
  579.     if ( (buffer=malloc(8192)) == NULL ) { ierror(NULL,103); return 20; }
  580.     if ( (dest=Open(namedest, MODE_NEWFILE)) == NULL )
  581.         { pError(namedest); goto fail1; }
  582.     for (i=1; i<ac; i++) {
  583.         if ( (sou=Open(av[i], MODE_OLDFILE)) == NULL ) pError(av[i]);
  584.         else
  585.             while( (n=Read(sou, buffer, 8192L)) > 0 )
  586.                 if (Write(dest, buffer, n) != n)
  587.                     { pError(namedest); Close(sou); goto fail2; }
  588.         Close(sou);
  589.     }
  590. fail2:
  591.     Close(dest);
  592. fail1:
  593.     free(buffer);
  594.     return 0;
  595. }
  596.  
  597. #define BUFDIM 512L
  598. #define MAXSTR 256
  599.  
  600. int minstr;
  601.  
  602. static int
  603. strings_in_file(long mask, char *s, char *path)
  604. {
  605.     long n,i;
  606.     char c;
  607.     char readbuf[BUFDIM+1], strbuf[MAXSTR+1];
  608.     BPTR fh;
  609.     int strctr=0;
  610.     BOOL out, hdout = TRUE;  /* hdout = header output */
  611.     BOOL usestdin = (s==NULL);
  612.     BOOL inter = IsInteractive(Output());
  613.  
  614.     prepscroll(0);
  615.  
  616.     if (usestdin)
  617.         fh = Input();
  618.     else
  619.         fh = Open(s,MODE_OLDFILE);
  620.  
  621.     if (fh) {
  622.         while ( (n=Read(fh, readbuf, BUFDIM))>0 && !CHECKBREAK() )
  623.             for (i=0; i<n && !CHECKBREAK(); i++) {   /* GMD: speed up ^C reaction */
  624.                 c=readbuf[i];
  625.                 if (c<0x20 || c>0x7f) {
  626.                     out=(strctr>=minstr);
  627.                     if (!out) strctr=0;
  628.                 } else {
  629.                     strbuf[strctr++]=c;
  630.                     out=(strctr>=BUFDIM);
  631.                 }
  632.                 if (out) {
  633.                     strbuf[strctr]='\0';
  634.                     if (options&8 && hdout) {
  635.                             printf("Strings in %s (len>=%d):\n",path?path:"STDIN",minstr);
  636.                             hdout=FALSE;
  637.                     }
  638.                     printf("%s%s%s%s%s\n",
  639.                         (options&4) ? (path?path:"STDIN") : "",
  640.                         (options&4) ? ": " : "",
  641.                         (options&2) ? "|" : "",
  642.                         strbuf,
  643.                         (options&2) ? "|" : "");
  644. #if 0
  645.                     if (options&2) {
  646.                         printf("%s: |%s|\n",path?path:"STDIN",strbuf);
  647.                     }
  648.                     else {
  649.                         if (hdout) {
  650.                             printf("Strings in %s (len>=%d):\n",path?path:"STDIN",minstr);
  651.                             hdout=FALSE;
  652.                         }
  653.                         puts(strbuf);
  654.                     }
  655. #endif
  656.                     if (inter) fflush(stdout);
  657.                     quickscroll();
  658.                     strctr=0;
  659.                 }
  660.             }
  661.         /* only close file if not standard input */
  662.         if (!usestdin)
  663.             Close(fh);
  664.     } else
  665.         pError(s);
  666.  
  667.     return 0;
  668. }
  669.  
  670. do_strings( void )
  671. {
  672.     if (isnum(av[ac-1])) {
  673.         minstr = myatoi(av[--ac],1,255);
  674.         if (atoierr) {
  675.             fprintf(stderr,"Need a valid string length parameter (1-255)!\n");
  676.             return 0;
  677.         }
  678.     }
  679.     else
  680.         minstr = 4;
  681.  
  682.     if (ac<2)
  683.         strings_in_file(0, NULL, NULL);
  684.     else
  685.         all_args( strings_in_file, 0);
  686.  
  687.     return 0;
  688. }
  689.  
  690. BPTR myfile[MAXMYFILES];
  691.  
  692. do_open( void )
  693. {
  694.     long mode;
  695.     int n;
  696.  
  697.     switch (toupper(av[2][0])) {
  698.         case 'R': mode=MODE_OLDFILE; break;
  699.         case 'W': mode=MODE_NEWFILE; break;
  700.         default : ierror(NULL,500); return 1;
  701.     }
  702.     n=myatoi(av[3],0,MAXMYFILES-1); if (atoierr) return 20;
  703.     if (myfile[n]) myclose(n);
  704.     myfile[n]=Open(av[1],mode);
  705.     return myfile[n]==NULL;
  706. }
  707.  
  708. do_close( void )
  709. {
  710.     int i, n;
  711.  
  712.     if (ac==1)
  713.         for (i=1; i<MAXMYFILES; i++)
  714.             myclose(i);
  715.     for (i=1; i<ac; i++) {
  716.         n=myatoi(av[i],0,MAXMYFILES-1); if (atoierr) return 20;
  717.         myclose(n);
  718.     }
  719.     return 0;
  720. }
  721.  
  722. void
  723. myclose(int n)
  724. {
  725.     if (myfile[n]) { Close(myfile[n]); myfile[n]=NULL; }
  726. }
  727.  
  728. do_fileslist( void )
  729. {
  730.     int i, flag=0;
  731.  
  732.     printf("Open files:");
  733.     for (i=0; i<MAXMYFILES; i++)
  734.         if (myfile[i]) { printf(" %d",i); flag=1; }
  735.     if (!flag) printf(" None!");
  736.     printf("\n");
  737.     return 0;
  738. }
  739.  
  740. BPTR
  741. extOpen( char *name, long mode )
  742. {
  743.     if (name[0]=='.' && name[1]>='0' && name[1]<='9')
  744.         return myfile[atoi(name+1)];
  745.     return Open(name,mode);
  746. }
  747.  
  748.  
  749. void
  750. extClose(BPTR fh)
  751. {
  752.     int i;
  753.  
  754.     for (i=0; i<MAXMYFILES; i++)
  755.         if (myfile[i]==fh) return;
  756.     Close(fh);
  757. }
  758.  
  759. do_basename( void )
  760. {
  761.     char *res;
  762.     int  i;
  763.  
  764.     for( i=2; i<ac; i++ )
  765.         av[i]=FilePart(av[i]);
  766.     set_var(LEVEL_SET, av[1], res=compile_av(av,2,ac,0xA0,0));
  767.     free(res);
  768.     return 0;
  769. }
  770.  
  771. do_tackon( void )
  772. {
  773.     char buf[256];
  774.  
  775.     strcpy(buf, av[2]);
  776.     AddPart(buf, av[3], 256L);
  777.     set_var(LEVEL_SET, av[1], buf);
  778.     return 0;
  779. }
  780.  
  781. extern char shellres[];
  782.  
  783. do_resident( void )
  784. {
  785.     struct Segment *seg;
  786.     char buf[256],devname[256];
  787.     char **dev_list1=NULL,**dev_list2=NULL;
  788.     long dev_num1=0,dev_num2=0,i;
  789.  
  790.     if (options==0 && ac>1) options=1;
  791.     switch (options) {
  792.     case 0:
  793.         Forbid();
  794.         seg = (struct Segment *)BADDR(((struct DosInfo *)BADDR(DOSBase->dl_Root->rn_Info))->di_NetHand);
  795.         while (seg) {
  796.             BtoCStr(devname,MKBADDR(seg->seg_Name),254L);  /* 256 - '\0' + ':' */
  797.             if (seg->seg_UC >= 0) {
  798.                 sprintf(buf,"%-18s%4.1ld",devname,seg->seg_UC-1);
  799.                 add_array_list(&dev_list1,&dev_num1,buf);
  800.             }
  801.             else {
  802.                 switch (seg->seg_UC) {
  803.                 case CMD_INTERNAL:
  804.                     sprintf(buf,"%-18s%s",devname,"INTERNAL");
  805.                     add_array_list(&dev_list2,&dev_num2,buf);
  806.                     break;
  807.                 case CMD_SYSTEM:
  808. /* don't print this */ /*
  809.                     sprintf(buf,"%-18s%s",devname,"SYSTEM");
  810.                     add_array_list(&dev_list2,&dev_num2,buf);
  811. */
  812.                     break;
  813.                 case CMD_DISABLED:
  814.                     sprintf(buf,"%-18s%s",devname,"DISABLED");
  815.                     add_array_list(&dev_list2,&dev_num2,buf);
  816.                     break;
  817.                 default:
  818.                     sprintf(buf,"%-18s%s",devname,"UNKNOWN");
  819.                     add_array_list(&dev_list2,&dev_num2,buf);
  820.                     break;
  821.                 }
  822.             }
  823.             seg = (struct Segment *)BADDR(seg->seg_Next);
  824.         }
  825.         Permit();
  826.         printf("NAME              USE COUNT\n\n");
  827.  
  828.         QuickSort(dev_list1,dev_num1);
  829.         for(i=0; !dobreak() && i<dev_num1; i++)
  830.             printf("%s\n",dev_list1[i]);
  831.         free_array_list(dev_list1,dev_num1);
  832.  
  833.         for(i=0; !dobreak() && i<dev_num2; i++)
  834.             printf("%s\n",dev_list2[i]);
  835.         free_array_list(dev_list2,dev_num2);
  836.  
  837.         break;
  838.     case 1:
  839.         for (i=1; i<ac; i++)
  840.             if (loadres(av[i]))
  841.                 printf("OK! %s is now resident\n", FilePart(av[i]));
  842.             else
  843.                 pError(av[i]);
  844.         break;
  845.     case 2:
  846.         for (i=1; i<ac; i++) {
  847.             Forbid();
  848.             if (seg=FindSegment(av[i],NULL,0L)) {
  849.                 if (RemSegment(seg)) {
  850.                     Permit();
  851.                     printf("Removed %s\n",av[i]);
  852.                 }
  853.                 else {
  854.                     Permit();
  855.                     ierror(av[i],ERROR_OBJECT_IN_USE);
  856.                 }
  857.             }
  858.             else {
  859.                 Permit();
  860.                 ierror(av[i],ERROR_OBJECT_NOT_FOUND);
  861.             }
  862.         }
  863.         break;
  864.     case 4:
  865.         for (i=1; i<ac; i++) {
  866.             if( !o_resident ) {
  867.                 /* AMK: OS20-SetVar replaces ARP-Setenv */
  868.                 SetVar(shellres,"1",-1L,GVF_GLOBAL_ONLY|GVF_BINARY_VAR);
  869.                 o_resident=1;
  870.             }
  871.             sprintf(buf,"res_%s",FilePart(av[i]));
  872.             /* AMK: OS20-SetVar replaces ARP-Setenv */
  873.             SetVar(buf,av[i],-1L,GVF_GLOBAL_ONLY|GVF_BINARY_VAR);
  874.         }
  875.         break;
  876.     default:
  877.         ierror(NULL,500);
  878.         break;
  879.     }
  880.     return 0;
  881. }
  882.  
  883. int
  884. loadres(char *s)
  885. {
  886.     BPTR seg;
  887.     BOOL okay = FALSE;
  888.  
  889.     if (seg=NewLoadSeg(s,NULL))
  890.         okay=AddSegment(FilePart(s),seg,1L);
  891.  
  892.     return (okay);
  893. }
  894.  
  895. #define FIRSTCOMMAND 4
  896. extern BPTR redir_out, redir_in;
  897. extern int find_command2( char * );
  898.  
  899. struct TagItem tags[]={
  900.     {SYS_Input,  0},
  901.     {SYS_Output, 0},
  902.     {SYS_Asynch, 1},
  903.     {TAG_DONE,   0} };
  904.  
  905. do_truerun(char *avline, int backflag)
  906. {
  907.     BPTR input, output;
  908.     char *args;
  909.     char *new_args;
  910.     char *aliastxt;
  911.     int err;
  912.  
  913.     int cmdnum;
  914.     BOOL execcsh = FALSE;
  915.  
  916.     if (backflag) {
  917.         input  = Open("NIL:",MODE_NEWFILE);
  918.         output = Open("NIL:",MODE_NEWFILE);
  919.     } else {
  920.         input = redir_in ? redir_in : Open("NIL:",MODE_NEWFILE);
  921.         if (redir_out)
  922.             output = redir_out;
  923. #if 0
  924.         else if (Output() && IsInteractive(Output())) {
  925.             if (((struct FileHandle *)BADDR(Output()))->fh_Port!=DOSFALSE) {
  926.                 struct MsgPort *old;
  927.                 old = SetConsoleTask(((struct FileHandle *)BADDR(Output()))->fh_Type);
  928.                 output = Open("CONSOLE:",MODE_OLDFILE);
  929.                 (void)SetConsoleTask(old);
  930.             }
  931.         }
  932. #else
  933.         else if (output = Open("CONSOLE:",MODE_OLDFILE)) {
  934.         }
  935. #endif
  936.         else
  937.             output = Open("NIL:",MODE_NEWFILE);
  938.     }
  939.  
  940.     cmdnum = find_command2(av[1]);
  941.     /* kprintf("find_command2(av[1]) : %d\n",cmdnum); */
  942.  
  943.     if (cmdnum >= FIRSTCOMMAND)
  944.         execcsh = TRUE;
  945.  
  946.     if (aliastxt=get_var(LEVEL_ALIAS,av[1])) {
  947.         execcsh = TRUE;
  948.         /*kprintf("do_truerun: %s is alias = %s\n",av[1],aliastxt);*/
  949.     }
  950.  
  951.     /* kprintf("run (avline,unparsed): %s\n",avline); */
  952.     args=compile_av(av,1,ac,' ',1);
  953.  
  954.     tags[0].ti_Data= input;
  955.     tags[1].ti_Data= output;
  956.  
  957.     /* kprintf("run (args,parsed)    : %s\n",args); */
  958.  
  959.     /* execcsh ist bei "alias sl search; run sl" ja noch korrekt,
  960.        aber bei "alias clc calculator; run clc" kommt nur Mist raus */
  961.  
  962.     if (execcsh) {
  963.         if (new_args = malloc(strlen(args)+strlen("csh -c ")+1)) {
  964.             sprintf(new_args,"csh -c %s",args);
  965.             /* kprintf("run (new_args)       : %s\n",new_args); */
  966.             err=System( new_args, tags );
  967.             free(new_args);
  968.         }
  969.         else
  970.             err = -1;
  971.     }
  972.     else {
  973.         /* kprintf("run (args)           : %s\n",args); */
  974.         err = System( args, tags );
  975.     }
  976.  
  977.     if( err!=0 ) {
  978.         Close( tags[0].ti_Data );
  979.         Close( tags[1].ti_Data );
  980.         pError(av[1]);
  981.     }
  982.     free(args);
  983.  
  984.     return 0;
  985. }
  986.  
  987. #if 0
  988. extern BPTR redir_out, redir_in;
  989.  
  990. static struct ProcessControlBlock pcb={
  991.     4000,        /* pcb_StackSize    */
  992.     0,        /* pcb_Pri        */
  993.     };
  994. /* remaining fields are NULL */
  995.  
  996. do_truerun(char *avline, int backflag)
  997. {
  998.     char name[100], *args, buf[10];
  999.     int cli;
  1000.  
  1001.     args=next_word(next_word(avline));
  1002.     if (backflag) {
  1003.         pcb.pcb_Control= 0;
  1004.         pcb.pcb_Input  = Open("NIL:",MODE_OLDFILE);
  1005.         pcb.pcb_Output = Open("NIL:",MODE_OLDFILE);
  1006.     } else {
  1007.         pcb.pcb_Control= 0;
  1008.         pcb.pcb_Input  = redir_in;
  1009.         pcb.pcb_Output = redir_out;
  1010.  
  1011.     }
  1012.  
  1013.     if((cli=ASyncRun(av[1],args,&pcb))<0)
  1014.         if (dofind(av[1], "", name,v_path))
  1015.             cli=ASyncRun(name,args,&pcb);
  1016.  
  1017.     if( cli<0 && cli >= -11 ) {
  1018.         if( redir_out ) extClose( redir_out );
  1019.         if( redir_in  ) extClose( redir_in  );
  1020.     }
  1021.  
  1022.     sprintf(buf,"%d",cli);
  1023.     set_var(LEVEL_SET,"_newproc",buf);
  1024.  
  1025.     if( cli<0 ) {
  1026.         ierror(av[1],205);
  1027.         return 20;
  1028.     }
  1029.     return 0;
  1030. }
  1031. #endif
  1032.  
  1033. int
  1034. exists( char *name )
  1035. {
  1036.     BPTR lock;
  1037.     char *nam=FilePart(name);
  1038.     int ret=0;
  1039.  
  1040.     Myprocess->pr_WindowPtr = (APTR)(-1);
  1041.     if ( strlen(nam)<=MAXFILENAME && (lock=Lock(name,ACCESS_READ))) {
  1042.         UnLock(lock);
  1043.         ret=1;
  1044.     }
  1045.     Myprocess->pr_WindowPtr = o_noreq ? (APTR) -1L : 0L/*Mywindow*/;
  1046.     return ret;
  1047. }
  1048.  
  1049. int
  1050. mounted( char *dev )
  1051. {
  1052.     struct DosList *dl;
  1053.     ULONG flags = LDF_ALL|LDF_READ;
  1054.     int gotcha = FALSE;
  1055.     char devname[256];
  1056.  
  1057.     if (dl=LockDosList(flags)) {
  1058.         while ((!gotcha) && (dl=NextDosEntry(dl,flags))) {
  1059.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  1060.             if (stricmp(devname,dev)==0)
  1061.                 gotcha = TRUE;
  1062.         }
  1063.         UnLockDosList(flags);
  1064.     }
  1065.  
  1066.     return (gotcha);
  1067. }
  1068.  
  1069. #define HTYPELINE 16L
  1070.  
  1071. static int
  1072. htype_a_file(long mask, char *s, char *path)
  1073. {
  1074.     BPTR fh;
  1075.     long n, filesize=0;
  1076.     UBYTE buf[HTYPELINE+1];
  1077.     char out[80], *put;
  1078.     int i, inter=IsInteractive(Output());
  1079.     BOOL usestdin = (s==NULL);
  1080.  
  1081.     if (usestdin)
  1082.         fh = Input();
  1083.     else
  1084.         fh = Open(s,MODE_OLDFILE);
  1085.  
  1086.     if (fh==NULL) { pError(s); return 20; }
  1087.     prepscroll(0);
  1088.     while ( (n=Read(fh,(char *)buf,HTYPELINE))>0 && !dobreak()) {
  1089.         put=out;
  1090.         put+=sprintf(put,"%06lx: ",filesize);
  1091.         filesize+=n;
  1092.         for (i=0; i<n; i++) {
  1093.             put+=sprintf( put,(i&3) ? "%02x" : " %02x",buf[i]);
  1094.             if ((buf[i]&127)<0x20) buf[i]='.';
  1095.         }
  1096.         for ( ; i<HTYPELINE; i++) {
  1097.             put+=sprintf( put, (i&3) ? "  " : "   ");
  1098.             buf[i]=' ';
  1099.         }
  1100.         buf[i]=0;
  1101.         sprintf(put,"    %s",buf);
  1102.         puts(out);
  1103.         if( inter ) fflush(stdout);
  1104.         quickscroll();
  1105.     }
  1106.     /* only close file if not standard input */
  1107.     if (!usestdin)
  1108.         Close(fh);
  1109.     return 0;
  1110. }
  1111.  
  1112. do_htype( void )
  1113. {
  1114.     if (ac<2)
  1115.         htype_a_file(0, NULL, NULL);
  1116.     else
  1117.         all_args( htype_a_file, 0);
  1118.     return 0;
  1119. }
  1120.  
  1121. #define STACK_MIN_FREE 10000
  1122. do_stack( void )
  1123. {
  1124.     long n;
  1125.  
  1126.     if (ac>1) {
  1127.         if (isnum(av[1])) {   /* AMK: IoErr() replaced by isnum() */
  1128.             n=atol(av[1]);
  1129.             if ( n < 1600 )
  1130.                 printf("Requested size too small\n");
  1131.             else if ( n > (AvailMem(MEMF_LARGEST)-STACK_MIN_FREE) )
  1132.                 printf("Requested size too large\n");
  1133.             else
  1134.             Mycli->cli_DefaultStack=(long)(n >> 2L);
  1135.         }
  1136.         else {
  1137.             ierror(av[1],511);   /* AMK: message if error */
  1138.             return 20;
  1139.         }
  1140.     }
  1141.     else {
  1142.         if (options&1)
  1143.             printf("%ld\n",(long)Mycli->cli_DefaultStack << 2L);
  1144.         else
  1145.             printf("current stack size is %ld bytes\n",
  1146.                     (long)Mycli->cli_DefaultStack << 2L);
  1147.     }
  1148.     return 0;
  1149. }
  1150.  
  1151. do_fault( void )
  1152. {
  1153.     PERROR *p;
  1154.     int i, n;
  1155.  
  1156.     for (i=1; i<ac; i++) {
  1157.         n=myatoi(av[i],0,32767);
  1158.         if (!atoierr) {
  1159.             for (p=Perror; p->errnum && p->errnum!=n; p++);
  1160.             if (p->errnum)
  1161.                 printf("Fault %d: %s\n",n,p->errstr);
  1162.             else
  1163.                 printf("Fault %d not recognized\n",n);
  1164.         }
  1165.     }
  1166.     return 0;
  1167. }
  1168.  
  1169. struct rpncommand {
  1170.     char *str;
  1171.     int parsin, parsout;
  1172.     };
  1173.  
  1174. static struct rpncommand rpn[]={
  1175.     "+",    2,    1,
  1176.     "-",    2,    1,
  1177.     "*",    2,    1,
  1178.     "/",    2,    1,
  1179.     "%",    2,    1,
  1180.     "&",    2,    1,
  1181.     "|",    2,    1,
  1182.     "~",    1,    1,
  1183.     ">",    2,    1,
  1184.     "<",    2,    1,
  1185.     "==",    2,    1,
  1186.     "!",    1,    1,
  1187.     "MAX",    2,    1,
  1188.     "MIN",    2,    1,
  1189.     "DUP",    1,    2,
  1190.     "DROP",    1,    0,
  1191.     "SWAP",    2,    2,
  1192.     "HELP",    0,    0,
  1193.     NULL,    0,    1,    /* this looks for a number */
  1194. };
  1195.  
  1196. static long stack[50];
  1197. static int sp;
  1198.  
  1199.  
  1200. eval_rpn( char **av, int ac, int flag )
  1201. {
  1202.     char *zero="Division by zero\n";
  1203.     struct rpncommand *temp;
  1204.     long n0, n1, t;
  1205.     int j, i=0, oldsp=sp;
  1206.  
  1207.     for (; i<ac; i++) {
  1208.         for (j=0; rpn[j].str && stricmp(rpn[j].str,av[i]); j++) ;
  1209.         n0=stack[sp-1];
  1210.         n1=stack[sp-2];
  1211.         sp -= (rpn[j].parsin);
  1212.         if (sp<0) { fprintf(stderr, "RPN: Empty stack\n"); goto error; }
  1213.         switch (j) {
  1214.           case 0:    n0 += n1;            break;
  1215.           case 1:    n0 = n1-n0;            break;
  1216.           case 2:    n0 *= n1;            break;
  1217.           case 3:    if(n0) n0=n1/n0; else fprintf(stderr,zero); break;
  1218.           case 4:    if(n0) n0=n1%n0; else fprintf(stderr,zero); break;
  1219.           case 5:    n0 &= n1;            break;
  1220.           case 6:    n0 |= n1;            break;
  1221.           case 7:    n0 =  ~n0    ;        break;
  1222.           case 8:    n0 = (n1 > n0);        break;
  1223.           case 9:    n0 = (n1 < n0);        break;
  1224.           case 10:    n0 = (n0 == n1);    break;
  1225.           case 11:    n0 = !n0;            break;
  1226.           case 12:    n0=n1>n0 ? n1 : n0;    break;
  1227.           case 13:    n0=n1<n0 ? n1 : n0;    break;
  1228.           case 14:    n1=n0;                break;
  1229.           case 15:    t=n0; n0=n1; n1=t;    break;
  1230.           case 16:                        break;
  1231.           case 17:    printf("In Commands Out\n");
  1232.             for (temp=rpn; temp->str; temp++)
  1233.                 printf(" %d %-10s%d\n",
  1234.                 temp->parsin,temp->str,temp->parsout);
  1235.             break;
  1236.           default:    n0=atol(av[i]);
  1237.                 if (!isnum(av[i])) {   /* AMK: IoErr() replaced by isnum() */
  1238.                     fprintf(stderr, "Bad RPN cmd: %s\n",av[i]);
  1239.                     goto error;
  1240.                 }
  1241.                 break;
  1242.           }
  1243.         stack[sp]=n0;
  1244.         stack[sp+1]=n1;
  1245.         sp += rpn[j].parsout;
  1246.     }
  1247.     if( flag && sp-1)
  1248.         fprintf( 
  1249.           stderr,
  1250.           "RPN: Stack not empty\n"
  1251.         );
  1252.  
  1253.     t=sp; sp=oldsp;
  1254.     if( flag )
  1255.         return stack[t-1]; /* return top value */
  1256.     else
  1257.         return t-sp;
  1258.  
  1259. error:
  1260.     sp=oldsp;
  1261.     return 0;
  1262. }
  1263.  
  1264.  
  1265. do_rpn(char *garbage,int ifflag) /* ifflag!=0 if called from if */
  1266. {
  1267.     int i=1;
  1268.     long t;
  1269.  
  1270.     t=eval_rpn( av+i, ac-i, ifflag );
  1271.     if (ifflag) return t;              /* called from if: return top value */
  1272.     for (i=sp+t-1;i>=sp;i--) printf("%ld\n", stack[i]);/* else print stack */
  1273.  
  1274.     return t ? 0 : 20;
  1275. }
  1276.  
  1277.  
  1278.  
  1279. void *DosAllocMem(long size)
  1280. {
  1281.     return( AllocVec(size,MEMF_CLEAR|MEMF_PUBLIC) );
  1282. }
  1283.  
  1284.  
  1285.  
  1286. void DosFreeMem(void *block)
  1287. {
  1288.     FreeVec(block);
  1289. }
  1290.  
  1291.  
  1292.  
  1293. /* do_rehash related stuff ... */
  1294.  
  1295. #define PATHHASH_RSRC "CSH-PathHash"
  1296. #define PATHHASH_SEMA "CSH-PathHash"
  1297.  
  1298. struct PathHashRsrc {
  1299.     struct Library phr_Lib;
  1300.     struct SignalSemaphore phr_Sema;
  1301.     long phr_entries;
  1302.     char *phr_data;
  1303. };
  1304.  
  1305.  
  1306.  
  1307. char *get_rehash_prog(char *last,char *progname)
  1308. {
  1309.     long i;
  1310.     char *filepart;
  1311.  
  1312.     if (last) {
  1313.         for(i=0; i<prghash_num && prghash_list[i]!=last; i++)
  1314.             ;
  1315.  
  1316.         for(++i; i<prghash_num; i++) {
  1317.             if (filepart=FilePart(prghash_list[i])) {
  1318.                 if (strnicmp(progname,filepart,strlen(progname))==0)
  1319.                     return( prghash_list[i] );
  1320.             }
  1321.         }
  1322.     }
  1323.  
  1324.     for(i=0; i<prghash_num; i++) {
  1325.         if (filepart=FilePart(prghash_list[i])) {
  1326.             if (strnicmp(progname,filepart,strlen(progname))==0)
  1327.                 return( prghash_list[i] );
  1328.         }
  1329.     }
  1330.  
  1331.     return( NULL );
  1332. }
  1333.  
  1334.  
  1335.  
  1336. void resolve_multiassign(char *ma,char ***dev_list,long *dev_num)
  1337. {
  1338.     struct DosList *dl;
  1339.     struct AssignList *path;
  1340.     ULONG flags;
  1341.     char *colon;
  1342.     char fmt[256],devname[256];
  1343.  
  1344.     flags = LDF_ASSIGNS|LDF_READ;
  1345.     colon = strchr(ma,':');
  1346.  
  1347.     if (colon && (dl=LockDosList(flags))) {
  1348.         *colon = '\0';
  1349.         while (dl=NextDosEntry(dl,flags)) {
  1350.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  1351.  
  1352.             if (stricmp(devname,ma)==0) {
  1353.  
  1354.                 if (dl->dol_Type == DLT_DIRECTORY) {
  1355.                     if(dl->dol_Lock) {
  1356.                         if (NameFromLock(dl->dol_Lock,fmt,255L)) {
  1357.                             if (*(colon+1))
  1358.                                 AddPart(fmt,colon+1,255);
  1359.                             add_array_list(dev_list,dev_num,fmt);
  1360.                         }
  1361.                         else {
  1362.                             fprintf(stderr,"csh.resolve_multiassign.1: NameFromLock() failed\n");
  1363.                         }
  1364.                     }
  1365.                     else
  1366.                         printf("Nonexisting lock (1) %s\n",devname);
  1367.  
  1368.                     if (path=dl->dol_misc.dol_assign.dol_List) {
  1369.                         for (; path; path=path->al_Next) {
  1370.                             if (dl->dol_Lock) {
  1371.                                 if (NameFromLock(path->al_Lock,fmt,255L)) {
  1372.                                     if (*(colon+1))
  1373.                                         AddPart(fmt,colon+1,255);
  1374.                                     add_array_list(dev_list,dev_num,fmt);
  1375.                                 }
  1376.                                 else {
  1377.                                     fprintf(stderr,"csh.resolve_multiassign.2: NameFromLock() failed\n");
  1378.                                 }
  1379.                             }
  1380.                             else
  1381.                                 printf("Nonexisting lock (2) %s\n",devname);
  1382.                         }
  1383.                     }
  1384.                 }
  1385.             }
  1386.         }
  1387.         UnLockDosList(flags);
  1388.         *colon = ':';
  1389.     }
  1390. }
  1391.  
  1392.  
  1393.  
  1394. void remove_local_pathhash(void)
  1395. {
  1396.     free_array_list(prghash_list,prghash_num);
  1397.     prghash_list = NULL;
  1398.     prghash_num  = 0;
  1399. }
  1400.  
  1401.  
  1402.  
  1403. BOOL remove_global_pathhash(void)
  1404. {
  1405.     struct PathHashRsrc *rsrc;
  1406.     BOOL success = FALSE;
  1407.  
  1408.     Forbid();
  1409.     if (rsrc = OpenResource(PATHHASH_RSRC)) {
  1410.         if (rsrc->phr_Lib.lib_OpenCnt == 0) {
  1411.             RemResource(rsrc);
  1412.             RemSemaphore(&rsrc->phr_Sema);
  1413.             FreeVec(rsrc->phr_Sema.ss_Link.ln_Name);
  1414.             FreeVec(rsrc->phr_Lib.lib_Node.ln_Name);
  1415.             if (rsrc->phr_data) FreeVec(rsrc->phr_data);
  1416.             FreeVec(rsrc);
  1417.             success = TRUE;
  1418.         }
  1419.     }
  1420.     Permit();
  1421.  
  1422.     return(success);
  1423. }
  1424.  
  1425.  
  1426.  
  1427. void load_pathhash_from_mem(struct PathHashRsrc *rsrc)
  1428. {
  1429.     char *cp;
  1430.     long i;
  1431.  
  1432.     remove_local_pathhash();
  1433.  
  1434.     cp = rsrc->phr_data;
  1435.  
  1436.     for (i=rsrc->phr_entries; i>0; i--) {
  1437.         add_array_list(&prghash_list,&prghash_num,cp);
  1438.         cp += strlen(cp)+1;
  1439.     }
  1440. }
  1441.  
  1442.  
  1443.  
  1444. void save_pathhash_to_mem(struct PathHashRsrc *rsrc,long hashlen)
  1445. {
  1446.     char *new_data;
  1447.  
  1448.     if (new_data = AllocVec(hashlen,MEMF_PUBLIC|MEMF_CLEAR)) {
  1449.         long slen,i;
  1450.  
  1451.         /* free old path hash data */
  1452.         if (rsrc->phr_data) FreeVec(rsrc->phr_data);
  1453.  
  1454.         /* set new memory pointer */
  1455.         rsrc->phr_data = new_data;
  1456.  
  1457.         /* copy path hash data to memory */
  1458.         for(i=0; i<prghash_num; i++) {
  1459.             slen = strlen(prghash_list[i])+1;
  1460.             CopyMem(prghash_list[i],new_data,slen);
  1461.             new_data += slen;
  1462.         }
  1463.  
  1464.         /* set new number of entries */
  1465.         rsrc->phr_entries = prghash_num;
  1466.     }
  1467. }
  1468.  
  1469.  
  1470.  
  1471. do_rehash( void )
  1472. {
  1473.     /*
  1474.             (re-)build internal hash-list        (no option)
  1475.        -c : clear hash-list from memory          (options&1)
  1476.        -l : load hash-list from disk to memory   (options&2)
  1477.        -o : output hash-list from memory         (options&4)
  1478.        -s : save hash-list from memory to disk   (options&8)
  1479.        -g : free global hash-list                (options&16)
  1480.     */
  1481.     struct PathHashRsrc *rsrc;
  1482.     long i;
  1483.     char buf[256];
  1484.  
  1485.     if (options&1) {    /* clear hash-list */
  1486.  
  1487.         remove_local_pathhash();
  1488.     }
  1489.     else if (options&2) {    /* load hash-list */
  1490.         FILE *fp;
  1491.         char *lf,*fname;
  1492.         BOOL readin = FALSE;
  1493.  
  1494.         if (!(fname=get_var(LEVEL_SET,v_prghash))) {
  1495.             fprintf(stderr,"$_prghash unset\n");
  1496.             return 20;
  1497.         }
  1498.  
  1499.         Forbid();
  1500.         if (!(rsrc = OpenResource(PATHHASH_RSRC))) {
  1501.             if (rsrc=AllocVec(sizeof(struct PathHashRsrc),MEMF_PUBLIC|MEMF_CLEAR)) {
  1502.                 rsrc->phr_Lib.lib_Node.ln_Type = NT_RESOURCE;
  1503.                 rsrc->phr_Lib.lib_Node.ln_Pri  = 0;
  1504.                 if (rsrc->phr_Lib.lib_Node.ln_Name=AllocVec(strlen(PATHHASH_RSRC)+1,MEMF_PUBLIC|MEMF_CLEAR)) {
  1505.                     strcpy(rsrc->phr_Lib.lib_Node.ln_Name,PATHHASH_RSRC);
  1506.                     if (rsrc->phr_Sema.ss_Link.ln_Name=AllocVec(strlen(PATHHASH_SEMA)+1,MEMF_PUBLIC|MEMF_CLEAR)) {
  1507.                         strcpy(rsrc->phr_Sema.ss_Link.ln_Name,PATHHASH_SEMA);
  1508.                         rsrc->phr_Sema.ss_Link.ln_Pri = 0;
  1509.                         AddSemaphore(&rsrc->phr_Sema);
  1510.                         AddResource(rsrc);
  1511.                         readin = TRUE;
  1512.                     }
  1513.                     else {
  1514.                         FreeVec(rsrc->phr_Lib.lib_Node.ln_Name);
  1515.                         FreeVec(rsrc);
  1516.                     }
  1517.                 }
  1518.                 else {
  1519.                     FreeVec(rsrc);
  1520.                 }
  1521.             }
  1522.         }
  1523.         if (rsrc) {
  1524.             rsrc->phr_Lib.lib_OpenCnt++;
  1525.             if (readin)
  1526.                 ObtainSemaphore(&rsrc->phr_Sema);
  1527.             else
  1528.                 ObtainSemaphoreShared(&rsrc->phr_Sema);
  1529.         }
  1530.         Permit();
  1531.  
  1532.         if (!rsrc) {
  1533.             printf("csh: cannot create resource\n");
  1534.             return 10;
  1535.         }
  1536.  
  1537.         /* clear old list -- if any */
  1538.         remove_local_pathhash();
  1539.  
  1540.         if (readin) {
  1541.             long hashlen = 0;
  1542.             if (fp=fopen(fname,"r")) {
  1543.                 while (fgets(buf,255,fp)) {
  1544.                     if (lf=strchr(buf,'\n')) {
  1545.                         *lf = '\0';
  1546.                     }
  1547.                     add_array_list(&prghash_list,&prghash_num,buf);
  1548.                     hashlen += strlen(buf)+1;
  1549.                 }
  1550.                 fclose(fp);
  1551.             }
  1552.             else
  1553.                 pError(fname);
  1554.             save_pathhash_to_mem(rsrc,hashlen);
  1555.         }
  1556.         else {
  1557.             load_pathhash_from_mem(rsrc);
  1558.         }
  1559.  
  1560.         Forbid();
  1561.         ReleaseSemaphore(&rsrc->phr_Sema);
  1562.         rsrc->phr_Lib.lib_OpenCnt--;
  1563.         Permit();
  1564.     }
  1565.     else if (options&4) {    /* output hash-list */
  1566.  
  1567.         for(i=0; !dobreak() && i<prghash_num; i++)
  1568.             printf("%s\n",prghash_list[i]);
  1569.     }
  1570.     else if (options&8) {    /* save hash-list */
  1571.         FILE *fp;
  1572.         char *fname;
  1573.  
  1574.         if (!(fname=get_var(LEVEL_SET,v_prghash))) {
  1575.             fprintf(stderr,"$_prghash unset\n");
  1576.             return 20;
  1577.         }
  1578.  
  1579.         if (fp=fopen(fname,"w")) {
  1580.             for(i=0; i<prghash_num; i++)
  1581.                 fprintf(fp,"%s\n",prghash_list[i]);
  1582.             fclose(fp);
  1583.         }
  1584.         else
  1585.             pError(fname);
  1586.  
  1587.     }
  1588.     else if (options&16) {    /* free global hash-list */
  1589.  
  1590.         if (!remove_global_pathhash())
  1591.             printf("csh: cannot clear, currently in use or does not exist\n");
  1592.     }
  1593.     else {
  1594.         BPTR lock;
  1595.         struct PathList *pl;
  1596.         struct FileInfoBlock *fib;
  1597.         char **path_list = NULL;
  1598.         long path_num = 0;
  1599.         long hashlen = 0;
  1600.         long slen;
  1601.  
  1602.         /* clear old list -- if any */
  1603.         remove_local_pathhash();
  1604.  
  1605.         Forbid();
  1606.         pl = (struct PathList *)BADDR(Mycli->cli_CommandDir);
  1607.         while (pl) {
  1608.             if (pl->pl_PathLock) {
  1609.                 if (NameFromLock(pl->pl_PathLock,buf,255L))
  1610.                     add_array_list(&path_list,&path_num,buf);
  1611.                 else
  1612.                     fprintf(stderr,"csh.do_rehash: NameFromLock() failed\n");
  1613.             }
  1614.             pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1615.         }
  1616.         Permit();
  1617.  
  1618.         resolve_multiassign("C:",&path_list,&path_num);
  1619.  
  1620.         if (fib=AllocVec(sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) {
  1621.             for(i=0; !dobreak() && i<path_num; i++) {
  1622.                 if (lock=Lock(path_list[i],SHARED_LOCK)) {
  1623.                     if (Examine(lock,fib)) {
  1624.                         while (!dobreak() && ExNext(lock,fib)) {
  1625.                             if (fib->fib_DirEntryType<0 && (!(fib->fib_Protection&FIBF_EXECUTE) || fib->fib_Protection&FIBF_SCRIPT)) {
  1626.                                 slen = strlen(fib->fib_FileName);
  1627.                                 if (slen<5 || stricmp(fib->fib_FileName+slen-5,".info")!=0) {
  1628.                                     strcpy(buf,path_list[i]);
  1629.                                     if (AddPart(buf,fib->fib_FileName,255)) {
  1630.                                         add_array_list(&prghash_list,&prghash_num,buf);
  1631.                                         hashlen += strlen(buf)+1;
  1632.                                     }
  1633.                                     else {
  1634.                                         printf("path too long: %s -> %s\n",path_list[i],fib->fib_FileName);
  1635.                                     }
  1636.                                 }
  1637.                             }
  1638.                         }
  1639.                     }
  1640.                     UnLock(lock);
  1641.                 }
  1642.             }
  1643.             FreeVec(fib);
  1644.         }
  1645.  
  1646.         free_array_list(path_list,path_num);
  1647.  
  1648.         Forbid();
  1649.         if (!(rsrc = OpenResource(PATHHASH_RSRC))) {
  1650.             if (rsrc=AllocVec(sizeof(struct PathHashRsrc),MEMF_PUBLIC|MEMF_CLEAR)) {
  1651.                 rsrc->phr_Lib.lib_Node.ln_Type = NT_RESOURCE;
  1652.                 rsrc->phr_Lib.lib_Node.ln_Pri  = 0;
  1653.                 if (rsrc->phr_Lib.lib_Node.ln_Name=AllocVec(strlen(PATHHASH_RSRC)+1,MEMF_PUBLIC|MEMF_CLEAR)) {
  1654.                     strcpy(rsrc->phr_Lib.lib_Node.ln_Name,PATHHASH_RSRC);
  1655.                     if (rsrc->phr_Sema.ss_Link.ln_Name=AllocVec(strlen(PATHHASH_SEMA)+1,MEMF_PUBLIC|MEMF_CLEAR)) {
  1656.                         strcpy(rsrc->phr_Sema.ss_Link.ln_Name,PATHHASH_SEMA);
  1657.                         rsrc->phr_Sema.ss_Link.ln_Pri = 0;
  1658.                         AddSemaphore(&rsrc->phr_Sema);
  1659.                         AddResource(rsrc);
  1660.                     }
  1661.                     else {
  1662.                         FreeVec(rsrc->phr_Lib.lib_Node.ln_Name);
  1663.                         FreeVec(rsrc);
  1664.                     }
  1665.                 }
  1666.                 else {
  1667.                     FreeVec(rsrc);
  1668.                 }
  1669.             }
  1670.         }
  1671.         if (rsrc) {
  1672.             rsrc->phr_Lib.lib_OpenCnt++;
  1673.             ObtainSemaphore(&rsrc->phr_Sema);
  1674.         }
  1675.         Permit();
  1676.  
  1677.         if (!rsrc) {
  1678.             printf("csh: cannot create resource\n");
  1679.             return 10;
  1680.         }
  1681.  
  1682.         save_pathhash_to_mem(rsrc,hashlen);
  1683.  
  1684.         Forbid();
  1685.         ReleaseSemaphore(&rsrc->phr_Sema);
  1686.         rsrc->phr_Lib.lib_OpenCnt--;
  1687.         Permit();
  1688.     }
  1689.  
  1690.     return 0;
  1691. }
  1692.  
  1693.  
  1694.  
  1695. do_path( void )
  1696. {
  1697.     struct Process *proc;
  1698.     BPTR lock,dup_lock;
  1699.     long mycli,clinum,mincli,maxcli;
  1700.     struct PathList *pl,*new_pl,*old,*last;
  1701.     char buf[256];
  1702.     int i;
  1703.  
  1704.     if ( options&1 ) {
  1705.         long noram = 0;
  1706.         Forbid();
  1707.         mincli = 1;
  1708.         maxcli = MaxCli();
  1709.         mycli  = Myprocess->pr_TaskNum;
  1710.         if (!(options&2))
  1711.             mincli = maxcli = mycli;
  1712.         for (clinum = mincli; clinum<=maxcli; clinum++) {
  1713.             if (proc=FindCliProc(clinum)) {
  1714.                 pl = (struct PathList *)BADDR(CLI(proc)->cli_CommandDir);
  1715.                 while (pl) {
  1716.                     if (pl->pl_PathLock) {
  1717.                         UnLock(pl->pl_PathLock);
  1718.                     }
  1719.                     old = pl;
  1720.                     pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1721.                     if (TypeOfMem(old) && ((ULONG)old & 4L))
  1722.                         DosFreeMem( old );
  1723.                     else
  1724.                         ++noram;
  1725.                 }
  1726.                 CLI(proc)->cli_CommandDir=NULL;
  1727.             }
  1728.         }
  1729.         Permit();
  1730.         if (noram>0) {
  1731.             fprintf(stderr,"%ld structure%s (%ld bytes) not freed, memory isn't in known RAM\n",
  1732.                     noram,
  1733.                     (noram>1) ? "s":"",
  1734.                     noram*sizeof(struct PathList));
  1735.         }
  1736.     } else if( ac==1 ) {
  1737.         char **dev_list=NULL;
  1738.         long dev_num=0,i;
  1739.         puts("Current dir");
  1740.         Forbid();
  1741.         pl = (struct PathList *)BADDR(Mycli->cli_CommandDir);
  1742.         while (pl) {
  1743.             if (pl->pl_PathLock) {
  1744.                 if (NameFromLock(pl->pl_PathLock,buf,255L))
  1745.                     add_array_list(&dev_list,&dev_num,buf);
  1746.                 else
  1747.                     fprintf(stderr,"csh.do_path: NameFromLock() failed\n");
  1748.             }
  1749.             pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1750.         }
  1751.         Permit();
  1752.  
  1753.         for(i=0; !dobreak() && i<dev_num; i++)
  1754.             printf("%s\n",dev_list[i]);
  1755.         free_array_list(dev_list,dev_num);
  1756.  
  1757.         if (!dobreak())
  1758.             puts("C:");
  1759.         return 0;
  1760.     }
  1761.     for( i=1; i<ac; i++ ) {
  1762.         if( !(lock=Lock(av[i],ACCESS_READ)) ) {
  1763.             ierror(av[i],205);
  1764.             continue;
  1765.         }
  1766.         if( !isdir(av[i])) {
  1767.             ierror(av[i],212);
  1768.             UnLock(lock);
  1769.             continue;
  1770.         }
  1771.         Forbid();
  1772.         mincli = 1;
  1773.         maxcli = MaxCli();
  1774.         mycli  = Myprocess->pr_TaskNum;
  1775.         if (!(options&2))
  1776.             mincli = maxcli = mycli;
  1777.         for (clinum = mincli; clinum<=maxcli; clinum++) {
  1778.             if (proc=FindCliProc(clinum)) {
  1779.                 if (options&2)
  1780.                     dup_lock = DupLock(lock);
  1781.                 else
  1782.                     dup_lock = lock;
  1783.                 last = pl = (struct PathList *)BADDR(CLI(proc)->cli_CommandDir);
  1784.                 while (pl && dup_lock) {
  1785.                     last = pl;
  1786.                     if (pl->pl_PathLock) {
  1787.                         if (SameLock(pl->pl_PathLock,dup_lock)==LOCK_SAME) {
  1788.                             UnLock(dup_lock);
  1789.                             dup_lock=NULL;
  1790.                         }
  1791.                     }
  1792.                     pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1793.                 }
  1794.                 if (dup_lock) {
  1795.                     if (new_pl=DosAllocMem( sizeof(struct PathList) )) {
  1796.                         new_pl->pl_NextPath = NULL;
  1797.                         new_pl->pl_PathLock = dup_lock;
  1798.                         if (last)
  1799.                             last->pl_NextPath = MKBADDR(new_pl);
  1800.                         else
  1801.                             CLI(proc)->cli_CommandDir = MKBADDR(new_pl);
  1802.                     }
  1803.                     else
  1804.                         UnLock(dup_lock);
  1805.                 }
  1806.             }
  1807.         }
  1808.         Permit();
  1809.         if (options&2)
  1810.             UnLock(lock);
  1811.     }
  1812.     return 0;
  1813. }
  1814.  
  1815. do_pri( void )
  1816. {
  1817.     int t, pri;
  1818.     struct Process *proc;
  1819.  
  1820.     t=(LONG)MaxCli();
  1821.     t=myatoi(av[1],0,t); if (atoierr) return 20;
  1822.     pri=myatoi(av[2],-128,127); if (atoierr) return 20;
  1823.     Forbid();
  1824.     proc=(t==0 ? Myprocess : FindCliProc((LONG)t));
  1825.     if (proc==NULL) fprintf(stderr, "process not found\n");
  1826.     else SetTaskPri((struct Task *)proc, (long)pri);
  1827.     Permit();
  1828.     return 0;
  1829. }
  1830.  
  1831. do_strleft( void )
  1832. {
  1833.     int n;
  1834.  
  1835.     n=posatoi(av[3]); if (atoierr) return 20;
  1836.     set_var_n(LEVEL_SET, av[1], av[2], n);
  1837.     return 0;
  1838. }
  1839.  
  1840. do_strright( void )
  1841. {
  1842.     int n, len=strlen(av[2]);
  1843.  
  1844.     n=posatoi(av[3]); if (atoierr) return 20;
  1845.     if( n>len ) n=len;
  1846.     set_var(LEVEL_SET, av[1], av[2]+len-n );
  1847.     return 0;
  1848. }
  1849.  
  1850. do_strmid( void )
  1851. {
  1852.     int n1, n2=999999, len=strlen(av[2]);
  1853.  
  1854.     n1=myatoi(av[3],1,999999)-1; if (atoierr) return 20;
  1855.     if (n1>len) n1=len;
  1856.     if (ac>4) {
  1857.         n2=posatoi(av[4]); if (atoierr) return 20;
  1858.     }
  1859.     set_var_n(LEVEL_SET, av[1], av[2]+n1, n2);
  1860.     return 0;
  1861. }
  1862.  
  1863. do_strlen( void )
  1864. {
  1865.     char buf[16];
  1866.  
  1867.     sprintf(buf,"%d",strlen(av[2]));
  1868.     set_var(LEVEL_SET, av[1], buf);
  1869.     return 0;
  1870. }
  1871.  
  1872. int atoierr;
  1873.  
  1874. myatoi(char *s,int mmin,int mmax)
  1875. {
  1876.     int n;
  1877.  
  1878.     atoierr=0;   /* GMD: initialise external flag! */
  1879.     n=atol(s);
  1880.  
  1881.     if (!isnum(s)) {   /* AMK: IoErr() replaced by isnum() */
  1882.         atoierr=1;
  1883.         ierror(s,511);
  1884.     }
  1885.     else if (n<mmin || n>mmax) {
  1886.         /*fprintf( stderr, "%s(%d) not in (%d,%d)\n",s,n,mmin,mmax );*/
  1887.         fprintf( stderr, "%s not in (%d,%d)\n",s,mmin,mmax );
  1888.         atoierr=1; n=mmin;
  1889.     }
  1890.     return n;
  1891. }
  1892.  
  1893. unlatoi(char *s)
  1894. {
  1895.     int n=atol(s);
  1896.     atoierr=0;
  1897.     if (!isnum(s)) {   /* AMK: IoErr() replaced by isnum() */
  1898.         atoierr=1;
  1899.         ierror(s,511);
  1900.         n=0;
  1901.     }
  1902.     return n;
  1903. }
  1904.  
  1905. posatoi(char *s)
  1906. {
  1907.     int n=atol(s);
  1908.     atoierr=0;
  1909.     if (!isnum(s)) {   /* AMK: IoErr() replaced by isnum() */
  1910.         atoierr=1;
  1911.         ierror(s,511);
  1912.         n=0;
  1913.     }
  1914.     else if (n<0 )
  1915.         atoierr=1, n=0, fprintf( stderr, "%s must be positive\n",s );
  1916.     return n;
  1917. }
  1918.  
  1919.  
  1920. do_fltlower( void )
  1921. {
  1922.     return line_filter( strlwr );
  1923. }
  1924.  
  1925. do_fltupper( void )
  1926. {
  1927.     return line_filter( strupr );
  1928. }
  1929.  
  1930. #if 0
  1931. char *
  1932. stripcr( char *get )
  1933. {
  1934.     char *old=get, *put;
  1935.  
  1936.     for( put=get; *get; get++ )
  1937.         if( *get!=13 )
  1938.             *put++ = *get;
  1939.     *put++=0;
  1940.     return old;
  1941. }
  1942.  
  1943. do_fltstripcr( void )
  1944. {
  1945.     return line_filter( stripcr );
  1946. }
  1947. #endif
  1948.  
  1949. static int
  1950. line_filter( char *(*func)( char * ) )
  1951. {
  1952.     char buf[256];
  1953.  
  1954.     while (!CHECKBREAK() && myfgets(buf,stdin))
  1955.         puts((*func)(buf));
  1956.     return 0;
  1957. }
  1958.  
  1959. int
  1960. do_linecnt( void )
  1961. {
  1962.     int count=0;
  1963.     char buf[256];
  1964.  
  1965.     while (!CHECKBREAK() && fgets(buf,255,stdin)) ++count;
  1966.     printf("%d lines\n",count);
  1967.     return 0;
  1968. }
  1969.  
  1970. int
  1971. do_uniq( void )
  1972. {
  1973.     int firstline=1;
  1974.     char buf[256], oldbuf[256];
  1975.  
  1976.     while (!CHECKBREAK() && myfgets(buf,stdin)) {
  1977.         if ( firstline || strcmp(buf, oldbuf)) {
  1978.             strcpy(oldbuf, buf);
  1979.             puts(buf);
  1980.         }
  1981.         firstline=0;
  1982.     }
  1983.     return 0;
  1984. }
  1985.  
  1986.  
  1987. #define RXFB_RESULT  17
  1988. #define RXCOMM    0x01000000
  1989.  
  1990. static struct rexxmsg {
  1991.     struct Message rm_Node;             /* EXEC message structure        */
  1992.     APTR     rm_TaskBlock;              /* global structure (private)    */
  1993.     APTR     rm_LibBase;                /* library base (private)        */
  1994.     LONG     rm_Action;                 /* command (action) code         */
  1995.     LONG     rm_Result1;                /* primary result (return code)  */
  1996.     LONG     rm_Result2;                /* secondary result              */
  1997.     STRPTR   rm_Args[16];               /* argument block (ARG0-ARG15)   */
  1998.  
  1999.     struct MsgPort *rm_PassPort;        /* forwarding port               */
  2000.     STRPTR   rm_CommAddr;               /* host address (port name)      */
  2001.     STRPTR   rm_FileExt;                /* file extension                */
  2002.     LONG     rm_Stdin;                  /* input stream (filehandle)     */
  2003.     LONG     rm_Stdout;                 /* output stream (filehandle)    */
  2004.     LONG     rm_avail;                  /* future expansion              */
  2005. } mymsg;                                /* size: 128 bytes               */
  2006.  
  2007.  
  2008. do_rxsend( char *avline )
  2009. {
  2010.     int i, ret=0;
  2011.     long result;
  2012.     struct MsgPort *port, *reply;
  2013.     long len;
  2014.     char buf[20], *resptr;
  2015.  
  2016.     if (!(port = (struct MsgPort *)FindPort(av[1])))
  2017.         { fprintf(stderr, "No port %s!\n", av[1]); return 20; }
  2018.     mymsg.rm_Node.mn_Node.ln_Type = NT_MESSAGE;
  2019.     mymsg.rm_Node.mn_Length = sizeof(struct rexxmsg);
  2020.     mymsg.rm_Action = RXCOMM | (options&1 ? 1L << RXFB_RESULT : 0);
  2021.     if (!(reply = CreateMsgPort())) {
  2022.         fprintf(stderr, "No reply port\n");
  2023.         return 20;
  2024.     }
  2025.     mymsg.rm_Node.mn_ReplyPort = reply;
  2026.  
  2027.     if( options&2 )
  2028.         av[2]=compile_av( av,2,ac,' ',0), ac=3;
  2029.     for ( i=2; i<ac; i++) {
  2030.         mymsg.rm_Args[0] = av[i];
  2031.         mymsg.rm_Result2 = 0;        /* clear out the last result. */
  2032.         PutMsg(port, &mymsg.rm_Node);
  2033.  
  2034.         Wait( 1<<reply->mp_SigBit | SIGBREAKF_CTRL_C );
  2035.  
  2036.         if( CHECKBREAK() ) {
  2037.             ret=5;
  2038.             break;
  2039.         }
  2040.  
  2041.         if (options&1) {
  2042.             if( (result=mymsg.rm_Result2)<1000000 ) { /* like AREXX */
  2043.                 sprintf(buf,"%d",result);              
  2044.                 set_var(LEVEL_SET,v_result,buf);
  2045.             } else {
  2046.                 resptr=(char *)(result-4);
  2047.                 len = *(long *)resptr;
  2048.                 memmove(resptr,resptr+4,len);  /* Null terminate */
  2049.                 resptr[len]=0;      
  2050.                 set_var(LEVEL_SET,v_result,resptr);
  2051.                 FreeMem(resptr, len+4 );
  2052.             }
  2053.         } else 
  2054.             unset_var( LEVEL_SET, v_result );
  2055.     }
  2056.     if( options&2 )
  2057.         free( av[2] );
  2058.  
  2059.     if (reply) DeleteMsgPort(reply);
  2060.     return ret;
  2061. }
  2062.  
  2063. static char *rxreturn;
  2064.  
  2065. do_rxrec( void )
  2066. {
  2067.     struct MsgPort *port;
  2068.     struct rexxmsg *msg;
  2069.     char *portname, *str;
  2070.  
  2071.     if (ac > 1)
  2072.         portname=av[1];
  2073.     else
  2074.         portname="rexx_csh";
  2075.  
  2076.     if (!(port=CreateMsgPort())) {
  2077.         fprintf(stderr, "Can't have MsgPort %s\n", portname);
  2078.         return 20;
  2079.     }
  2080.     port->mp_Node.ln_Name = portname;
  2081.     port->mp_Node.ln_Pri  = 0;
  2082.     AddPort(port);
  2083.     for (;;) {
  2084.         WaitPort(port);
  2085.         while (msg=(struct rexxmsg *)GetMsg(port)) {
  2086.             if ( ! stricmp(msg->rm_Args[0], "bye")) {
  2087.                 ReplyMsg((struct Message *)msg);
  2088.                 RemPort(port);
  2089.                 DeleteMsgPort(port);
  2090.                 return 0;
  2091.             }
  2092.             rxreturn=NULL;
  2093.             exec_command(msg->rm_Args[0]);
  2094.             if (msg->rm_Action & (1L << RXFB_RESULT)) {
  2095.                 if( rxreturn ) {
  2096.                     str= SAllocMem( strlen( rxreturn )+5 , 0 );
  2097.                     *(long *)str=strlen( rxreturn );
  2098.                     strcpy( str+4, rxreturn );
  2099.                     msg->rm_Result2=(long)str;
  2100.                 } else {
  2101.                     str = get_var(LEVEL_SET, v_lasterr);
  2102.                     msg->rm_Result2=(str) ? atoi(str) : 20;
  2103.                 }
  2104.             }
  2105.             ReplyMsg((struct Message *)msg);
  2106.         }
  2107.     }
  2108. }
  2109.  
  2110. int
  2111. do_waitport( void )
  2112. {
  2113.     int count=4*10;
  2114.     struct MsgPort *port=NULL;
  2115.  
  2116.     if( ac==3 ) 
  2117.         { count=2*myatoi(av[2],0, 32000); if( atoierr ) return 20; }
  2118.  
  2119.     while( --count>=0 && !(port=FindPort(av[1])) && !dobreak() )
  2120.         Delay(12);
  2121.  
  2122.     return port ? 0 : 20;
  2123. }
  2124.  
  2125. int
  2126. do_rxreturn( void )
  2127. {
  2128.     rxreturn=compile_av( av, 1, ac, ' ', 1 );
  2129.     return 0;
  2130. }
  2131.  
  2132. do_ascii( void )
  2133. {
  2134.     int x=1, y, c, c1, t;
  2135.     char *fmt1=" %3d %c%c |", *fmt2=" %4d";
  2136.  
  2137.     if( options&1 ) fmt1=" %3o %c%c |", fmt2="%4o";
  2138.     if( options&2 ) fmt1=" %3x %c%c |", fmt2="%4x";
  2139.     if( ac==x )
  2140.         for( y=0; y<32 && !dobreak(); y++ ) {
  2141.             printf("|");
  2142.             for( x=0; x<8; x++ ) {
  2143.                 c1=c=y+32*x; t=' ';
  2144.                 if( c<32 ) t='^', c1+=64;
  2145.                 printf(fmt1,c, t, c1<128 || c1>=160?c1:'.');
  2146.             }
  2147.             printf("\n");
  2148.         }
  2149.     else 
  2150.         for( ; x<ac && !dobreak(); x++ ) {
  2151.             for( y=0; y<strlen(av[x]); y++ )
  2152.                 printf(fmt2,av[x][y]);
  2153.             printf("\n");
  2154.         }
  2155.     return 0;
  2156. }
  2157.  
  2158. void
  2159. appendslash( char *path )
  2160. {
  2161.     int c;
  2162.  
  2163.     if( (c=path[strlen(path)-1]) !='/' && c!=':' )
  2164.         strcat(path,"/");
  2165. }
  2166.  
  2167. static void
  2168. whereis( char *path, char *file )
  2169. {
  2170.     char **eav, buf[100];
  2171.     int  eac, j;
  2172.  
  2173.     buf[0]=0;
  2174.     if( path ) {
  2175.         strcpy(buf,path);
  2176.         appendslash(buf);
  2177.     }
  2178.     strcat(buf,".../");
  2179.     strcat(buf,file);
  2180.     if( !index( file, '*' ) && !index( file, '?') )
  2181.         strcat(buf,"*");
  2182.     if(eav=expand(buf,&eac)) {
  2183.         for( j=0; j<eac && !dobreak(); j++ )
  2184.             printf("%s\n",eav[j]);
  2185.         free_expand(eav);
  2186.     }
  2187. }
  2188.  
  2189. do_whereis( void )
  2190. {
  2191.     char buf[200], *prev, *devs;
  2192.     int i;
  2193.  
  2194.     if( index( av[1],':') || index( av[1],'/' ) )
  2195.         { fprintf(stderr,"No paths please\n"); return 20; };
  2196.  
  2197.     if( options&1 ) {
  2198.         Myprocess->pr_WindowPtr = (APTR)(-1);
  2199.         get_drives( devs=buf );
  2200.         do {
  2201.             prev=devs; devs=index(devs,0xA0);
  2202.             if( devs ) *devs++=0; 
  2203.             whereis( prev, av[1] );
  2204.         } while( devs );
  2205.         Myprocess->pr_WindowPtr = o_noreq ? (APTR) -1L : 0L/*Mywindow*/;
  2206.     } else if( ac==2 ) {
  2207.         whereis( NULL, av[1] );
  2208.     } else {
  2209.         for( i=2; i<ac; i++ ) {
  2210.             strcpy(buf,av[i]);
  2211.             appendslash( buf );
  2212.             whereis( buf, av[1] );
  2213.         }
  2214.     }
  2215.     return 0;
  2216. }
  2217.  
  2218. do_usage( void )
  2219. {
  2220.     int i;
  2221.  
  2222.     if( ac==1 ) {
  2223.         printf("Usage: usage [command...command]\n");
  2224.         printf("[ ]=option   [ | ]=choice   { }=repetition   name...name=1 or more names\n");
  2225.     } else
  2226.         for( i=1; i<ac; i++ )
  2227.             show_usage( av[i] );
  2228.     return 0;
  2229. }
  2230.  
  2231.  
  2232.  
  2233. /* these defines are new in OS 3.x */
  2234. #ifndef WA_NewLookMenus
  2235. #define WA_NewLookMenus (WA_Dummy + 0x30)
  2236. #endif
  2237. #ifndef GTMN_NewLookMenus
  2238. #define GTMN_NewLookMenus GT_TagBase+67
  2239. #endif
  2240. #ifndef WFLG_NEWLOOKMENUS
  2241. #define WFLG_NEWLOOKMENUS 0x00200000
  2242. #endif
  2243.  
  2244.  
  2245.  
  2246. static struct NewMenu *NewMenus = NULL;
  2247. static int AnzMenus = 0, AnzItems = 1;
  2248. static APTR *visualInfo = NULL;
  2249. static struct Menu *menuStrip = NULL;
  2250. static char *fontName = NULL;
  2251. static struct TextAttr textAttr;
  2252. static struct TextFont *textFont = NULL;
  2253.  
  2254. char *MenuCommand[MAXMENUS][MAXMENUITEMS];
  2255.  
  2256. do_menu( void )
  2257. {
  2258.     if( o_nowindow || !Mywindow )
  2259.         return 5;
  2260.  
  2261.     if( options&1 )
  2262.         remove_menu();
  2263.  
  2264.     if( ac==2 )
  2265.         show_usage( NULL );
  2266.     else if( AnzMenus<MAXMENUS && ac!=1)
  2267.         install_menu( av+1, ac-1 );
  2268.  
  2269.     set_menu();
  2270.     return 0;
  2271. }
  2272.  
  2273. static void
  2274. install_menu( char *mav[], int mac )
  2275. {
  2276.     char *p, *com;
  2277.     long msize;
  2278.     struct NewMenu *new_NewMenus;
  2279.     int i;
  2280.  
  2281.     if (o_nowindow || !Mywindow)
  2282.         return;
  2283.  
  2284.     /* mac holds number of items, including title which counts as item */
  2285.  
  2286.     if (mac>MAXMENUITEMS)
  2287.         mac=MAXMENUITEMS;
  2288.  
  2289.     ClearMenuStrip( Mywindow );
  2290.     if (menuStrip) FreeMenus(menuStrip);
  2291.     if (visualInfo) FreeVisualInfo(visualInfo);
  2292.     Delay(3);
  2293.  
  2294.     msize = sizeof(struct NewMenu) * (mac+1 + AnzItems-1);    /* one extra 'end' item */
  2295.     new_NewMenus = salloc(msize);
  2296.     memset(new_NewMenus,0,msize);
  2297.     if (NewMenus) {
  2298.         memcpy(new_NewMenus,NewMenus,sizeof(struct NewMenu)*(AnzItems-1));
  2299.         free(NewMenus);
  2300.     }
  2301.     else {
  2302.         int i,j;
  2303.         for (i=0; i<MAXMENUS; i++)
  2304.             for (j=0; j<MAXMENUITEMS; j++)
  2305.                 MenuCommand[i][j] = NULL;
  2306.     }
  2307.     NewMenus = new_NewMenus;
  2308.  
  2309.     NewMenus[AnzItems-1].nm_Type  = NM_TITLE;
  2310.     NewMenus[AnzItems-1].nm_Label = strcpy(salloc(strlen(mav[0])+1),mav[0]);
  2311.  
  2312.     for( i=1; i<mac; i++) {
  2313.         com=NULL;
  2314.         if( p=index(mav[i],',')) {
  2315.             *p=0; com = ++p;
  2316.             if( p=index(com,',')) {
  2317.                 *p=0;
  2318.                 NewMenus[AnzItems].nm_CommKey = strdup(++p);
  2319.             }
  2320.         }
  2321.  
  2322.         if( !com || !*com) {
  2323.             com=strcpy(salloc(strlen(mav[i])+2),mav[i]);
  2324.             MenuCommand[AnzMenus][i-1]=com;
  2325.             com+=strlen(com);
  2326.             *com++=13;
  2327.             *com=0;
  2328.         } else {
  2329.             MenuCommand[AnzMenus][i-1]=strcpy(salloc(strlen(com)+1),com);
  2330.         }
  2331.  
  2332.         NewMenus[AnzItems].nm_Type  = NM_ITEM;
  2333.         NewMenus[AnzItems].nm_Label = strcpy(salloc(strlen(mav[i])+2),mav[i]);
  2334.  
  2335.         AnzItems++;
  2336.     }
  2337.  
  2338.     AnzMenus++;
  2339.     NewMenus[AnzItems++].nm_Type = NM_END;
  2340.  
  2341.     if (!(visualInfo=GetVisualInfo(Mywindow->WScreen,TAG_END))) {
  2342.         printf("no visual info\n");
  2343.         free(NewMenus);
  2344.     }
  2345.  
  2346.     if (!(menuStrip=CreateMenus(NewMenus,TAG_END))) {
  2347.         printf("no create menus\n");
  2348.         FreeVisualInfo(visualInfo);
  2349.         free(NewMenus);
  2350.     }
  2351.  
  2352.     /* do we want a monospaced (non-proportional) font? */
  2353.     if (options&2 && !textFont && AnzMenus<=1) {
  2354.         Forbid();
  2355.         if (GfxBase->DefaultFont) {
  2356.             textAttr.ta_Name = fontName = strdup(GfxBase->DefaultFont->tf_Message.mn_Node.ln_Name);
  2357.             textAttr.ta_YSize = GfxBase->DefaultFont->tf_YSize;
  2358.         }
  2359.         else {
  2360.             textAttr.ta_Name  = "topaz.font";
  2361.             textAttr.ta_YSize = 8;
  2362.         }
  2363.         Permit();
  2364.         textAttr.ta_Style = FS_NORMAL;
  2365.         textAttr.ta_Flags = 0;
  2366.         if (textAttr.ta_Name)
  2367.             textFont = OpenDiskFont(&textAttr);
  2368.     }
  2369.  
  2370.     /*
  2371.      *  "CON:" windows don't have the WFLG_NEWLOOKMENUS flag set,
  2372.      *  so that NewLook menus doesn't work :-(
  2373.      */
  2374.  
  2375. #if 0
  2376.     if (Mywindow->Flags & WFLG_NEWLOOKMENUS)
  2377.         kprintf("Found WFLG_NEWLOOKMENUS.\n");
  2378.     else
  2379.         kprintf("Cannot find WFLG_NEWLOOKMENUS.\n");
  2380. /*
  2381.     Mywindow->Flags |= WFLG_NEWLOOKMENUS;
  2382.     RefreshWindowFrame(Mywindow);
  2383. */
  2384.     if (!LayoutMenus(menuStrip,visualInfo,
  2385.                 GTMN_NewLookMenus, TRUE,
  2386.                 textFont==NULL ? TAG_IGNORE : GTMN_TextAttr, &textAttr,
  2387.                 TAG_END))
  2388. #else
  2389.     if (!LayoutMenus(menuStrip,visualInfo,
  2390.                 Mywindow->Flags&WFLG_NEWLOOKMENUS ? GTMN_NewLookMenus : TAG_IGNORE, TRUE,
  2391.                 textFont==NULL ? TAG_IGNORE : GTMN_TextAttr, &textAttr,
  2392.                 TAG_END))
  2393. #endif
  2394.     {
  2395.         printf("csh: layout menus failed\n");
  2396.         FreeMenus(menuStrip);
  2397.         FreeVisualInfo(visualInfo);
  2398.         free(NewMenus);
  2399.     }
  2400.  
  2401.     return;
  2402. }
  2403.  
  2404. void remove_menu()
  2405. {
  2406.     if (AnzMenus>0) {
  2407.         struct NewMenu *nm;
  2408.         int i,j;
  2409.  
  2410.         for (i=0; i<MAXMENUS; i++) {
  2411.             for (j=0 ;j<MAXMENUITEMS; j++)
  2412.                 if (MenuCommand[i][j]) {
  2413.                     free(MenuCommand[i][j]);
  2414.                     MenuCommand[i][j] = NULL;
  2415.                 }
  2416.         }
  2417.  
  2418.         for (nm=NewMenus; nm->nm_Type!=NM_END; nm++) {
  2419.             if (nm->nm_Label) {
  2420.                 free(nm->nm_Label);
  2421.                 nm->nm_Label = NULL;
  2422.             }
  2423.             if (nm->nm_CommKey) {
  2424.                 free(nm->nm_CommKey);
  2425.                 nm->nm_CommKey = NULL;
  2426.             }
  2427.         }
  2428.  
  2429.         AnzMenus=0;
  2430.         set_menu();
  2431.     }
  2432. }
  2433.  
  2434. void set_menu()
  2435. {
  2436.     if (o_nowindow || !Mywindow)
  2437.         return;
  2438.  
  2439.     if (AnzMenus>0)
  2440.         SetMenuStrip(Mywindow,menuStrip);
  2441.     else {
  2442.         ClearMenuStrip(Mywindow);
  2443.         FreeMenus(menuStrip);
  2444.         FreeVisualInfo(visualInfo);
  2445.         free(NewMenus);
  2446.         menuStrip  = NULL;
  2447.         visualInfo = NULL;
  2448.         NewMenus   = NULL;
  2449.         AnzMenus = 0;
  2450.         AnzItems = 1;
  2451.         if (textFont) {
  2452.             CloseFont(textFont);
  2453.             textFont = NULL;
  2454.         }
  2455.         if (fontName) {
  2456.             free(fontName);
  2457.             fontName = NULL;
  2458.         }
  2459.     }
  2460.  
  2461.     Delay(3);
  2462. }
  2463.  
  2464.  
  2465. #if 0
  2466. int NumMenus;
  2467.  
  2468. static struct Menu DefaultMenu= {0, 0,0,TITWID,10, MENUENABLED,0,0};
  2469. static struct IntuiText DefaultIntuiText= {0,1,JAM2, 1,1,NULL,0,0};
  2470. static struct MenuItem DefaultMenuItem=
  2471.   {0, 0,0,ITEWID,0, HIGHCOMP|ITEMTEXT|ITEMENABLED,0,0,0,0,0,0};
  2472.  
  2473. struct Menu Menus[10];
  2474. char *MenuCommand[MAXMENUS][MAXMENUITEMS];
  2475.  
  2476. static void
  2477. install_menu( char *mav[], int mac )
  2478. {
  2479.     struct TextAttr *ta;
  2480.     struct Menu *m;
  2481.     struct MenuItem *mi, **pmi;
  2482.     struct IntuiText *it;
  2483.     int y, i, fonthei;
  2484.     char *p, *com;
  2485.  
  2486.     if( o_nowindow || !Mywindow )
  2487.         return;
  2488.  
  2489.     if( mac>=MAXMENUITEMS )
  2490.         mac=MAXMENUITEMS-1;
  2491.  
  2492.     ClearMenuStrip( Mywindow );
  2493.     Delay(3);
  2494.  
  2495.     if( NumMenus )
  2496.         Menus[NumMenus-1].NextMenu=Menus+NumMenus;
  2497.     m  = &Menus[NumMenus];
  2498.     *m = DefaultMenu;
  2499.     m->LeftEdge  = NumMenus*TITWID;
  2500.     m->MenuName  = strcpy(salloc(strlen(mav[0])+1),mav[0]);
  2501.     if( strlen(m->MenuName)>TITWID/8 )
  2502.         m->MenuName[TITWID/8+1]=0;
  2503.     DefaultIntuiText.ITextFont=ta=Mywindow->WScreen->Font;
  2504.     DefaultMenuItem.Height=2+(fonthei=ta->ta_YSize);
  2505.  
  2506.     y=0;
  2507.     pmi = &m->FirstItem;
  2508.     for( i=1; i<mac; i++) {
  2509.         it =(void *)salloc(sizeof(struct IntuiText));
  2510.         *it=DefaultIntuiText;
  2511.         mi =(void *)salloc(sizeof(struct MenuItem ));
  2512.         *mi=DefaultMenuItem;
  2513.  
  2514.         com=NULL;
  2515.         if( p=index(mav[i],',')) {
  2516.             *p=0; com = ++p;
  2517.             if( p=index(com,',')) {
  2518.                 *p=0;
  2519.                 mi->Command=p[1];
  2520.                 mi->Flags |=COMMSEQ;
  2521.             }
  2522.         }
  2523.  
  2524.         if( !com || !*com) {
  2525.             com=strcpy(salloc(strlen(mav[i])+2),mav[i]);
  2526.             MenuCommand[NumMenus][i-1]=com;
  2527.             com+=strlen(com);
  2528.             *com++=13;
  2529.             *com=0;
  2530.         } else {
  2531.             MenuCommand[NumMenus][i-1]=strcpy(salloc(strlen(com)+1),com);
  2532.         }
  2533.  
  2534.         it->IText=(UBYTE *)strcpy(salloc(strlen(mav[i])+2),mav[i]);
  2535.  
  2536.         *pmi= mi;
  2537.         pmi = &mi->NextItem;
  2538.         mi->TopEdge = y;
  2539.         mi->ItemFill= (APTR)it;
  2540.  
  2541.         y+=DefaultMenuItem.Height;
  2542.     }
  2543.  
  2544.     NumMenus++;
  2545. MError:
  2546.     return;
  2547. }
  2548.  
  2549. void remove_menu()
  2550. {
  2551.     if (NumMenus>0) {
  2552.         struct MenuItem *mi, *nextmi;
  2553.         int i,j;
  2554.  
  2555.         for( i=0; i<NumMenus; i++ ) {
  2556.             for( mi=Menus[i].FirstItem,j=0 ; mi; mi=nextmi,j++ ) {
  2557.                 free( ((struct IntuiText *)mi->ItemFill)->IText );
  2558.                 free( ((struct IntuiText *)mi->ItemFill) );
  2559.                 nextmi=mi->NextItem;
  2560.                 free(mi);
  2561.                 free(MenuCommand[i][j]);
  2562.             }
  2563.         }
  2564.  
  2565.         NumMenus=0;
  2566.         set_menu();
  2567.     }
  2568. }
  2569.  
  2570. void set_menu()
  2571. {
  2572.     if (o_nowindow || !Mywindow)
  2573.         return;
  2574.  
  2575.     if (NumMenus>0)
  2576.         SetMenuStrip(Mywindow,Menus);
  2577.     else
  2578.         ClearMenuStrip(Mywindow);
  2579.  
  2580.     Delay(3);
  2581. }
  2582. #endif
  2583.  
  2584. int
  2585. do_getenv( void )
  2586. {
  2587.     char buf[256], *val=buf;
  2588.  
  2589.     if( ac!=3 && ac!=2 ) {
  2590.         show_usage( NULL );
  2591.         return 20;
  2592.     }
  2593.     /* AMK: OS20-GetVar replaces ARP-Getenv */
  2594.     if( GetVar(av[ac-1],buf,256,GVF_GLOBAL_ONLY|GVF_BINARY_VAR) < 0L )
  2595.         val="";
  2596.  
  2597.     if( ac==2 )
  2598.         printf( "%s\n", val );
  2599.     else
  2600.         set_var( LEVEL_SET, av[1], val );
  2601.     return 0;
  2602. }
  2603.  
  2604. int
  2605. do_setenv( void )
  2606. {
  2607.     if( ac!=3 ) {
  2608.         show_usage( NULL );
  2609.         return 20;
  2610.     } else
  2611.         setenv( av[1], av[2] );
  2612.     return 0;
  2613. }
  2614.  
  2615. char **
  2616. read_name( char *name, int *ac )
  2617. {
  2618.     FILE *file;
  2619.     char **av=NULL;
  2620.  
  2621.     *ac=0;
  2622.     if( file=name ? fopen( name, "r") : stdin ) {
  2623.         av=read_file( file, ac );
  2624.         if( name ) fclose( file );
  2625.     } else 
  2626.         pError( name );
  2627.     return av;
  2628. }
  2629.  
  2630.  
  2631. char **
  2632. read_file( FILE *file, int *ac )
  2633. {
  2634.     int buflen=4096, lines=0, i, offs, got=0;
  2635.     char *buf, *tmp, *ptr, **lineptr;
  2636.  
  2637.     if( !(buf=ptr=DosAllocMem( buflen )))
  2638.         goto error;
  2639.     do {
  2640.         while( ptr+400 < buf+buflen && (got=myfgets(ptr, file)) && !dobreak())
  2641.             ptr+=strlen(ptr)+1, lines++;
  2642.         if( ptr+256 < buf+buflen ) {
  2643.             offs=ptr-buf;
  2644.             if( !(tmp=DosAllocMem( buflen*2 )))
  2645.                 goto error;
  2646.             memcpy( tmp, buf, buflen );
  2647.             DosFreeMem( buf );
  2648.             buflen*=2, buf=tmp;
  2649.             ptr=buf+offs;
  2650.         }
  2651.     } while( got && !dobreak());
  2652.     if( !(lineptr=(char **)DosAllocMem( (lines+1)*sizeof( char * ))))
  2653.         goto error;
  2654.     *lineptr++=buf;
  2655.     for( ptr=buf, i=0; i<lines; i++ ) {
  2656.         lineptr[i]=ptr;
  2657.         ptr+=strlen(ptr)+1;
  2658.     }
  2659.     *ac=lines;
  2660.     return lineptr;
  2661.  
  2662. error:
  2663.     if( buf ) DosFreeMem( buf );
  2664.     fprintf( stderr, "Out of memory\n" );
  2665.     *ac=0;
  2666.     return NULL;
  2667. }
  2668.  
  2669. void
  2670. free_file( ptr )
  2671.     char **ptr;
  2672. {
  2673.     if( ptr-- ) {
  2674.         if( *ptr )
  2675.             DosFreeMem( *ptr );
  2676.         DosFreeMem(ptr);
  2677.     }
  2678. }
  2679.  
  2680.  
  2681. do_qsort( void )
  2682. {
  2683.     char **lineptr;
  2684.     int  lines, i;
  2685.  
  2686.     if( ac==1 ) {
  2687.         lineptr=read_file( stdin, &lines);
  2688.         DirQuickSort( lineptr, lines, (options&2) ? cmp_case : cmp, options&1, 0 );
  2689.         prepscroll(0);
  2690.         for( i=0; i<lines && !dobreak(); i++ ) {
  2691.             quickscroll();
  2692.             puts( lineptr[i] );
  2693.         }
  2694.         free_file( lineptr );
  2695.     } else
  2696.         ierror( NULL,506 );
  2697.     return 0;
  2698. }
  2699.  
  2700. extern int w_width;
  2701.  
  2702. do_truncate( void )
  2703. {
  2704.     char buf[256];
  2705.     int  w=newwidth(), c; /**/
  2706.     /*int  w = w_width, c;*/
  2707.     char *ptr;
  2708.  
  2709.     if( ac==2 )
  2710.         w=atoi( av[1] );
  2711.  
  2712.     prepscroll(0);
  2713.     while( myfgets(buf,stdin) && !dobreak() ) {
  2714.         for( c=0, ptr=buf; *ptr && c<w; ptr++ )
  2715.             if( *ptr=='\t' )
  2716.                 c+=8-(c&7);
  2717.             else if( *ptr==27 ) {
  2718.                 while( *ptr<'@' )
  2719.                     ptr++;
  2720.             } else 
  2721.                 c++;
  2722.         *ptr=0;
  2723.         quickscroll();
  2724.         puts(buf);
  2725.     }
  2726.     return 0;
  2727. }
  2728.  
  2729. int
  2730. do_readfile( void )
  2731. {
  2732.     char **rav, *str=NULL, *file=NULL;
  2733.     int rac;
  2734.  
  2735.     if( ac>2 ) file=av[2];
  2736.     if( rav=read_name( file, &rac ) ) { 
  2737.         if( str= compile_av( rav, 0, rac, 0xA0, 0 ) )
  2738.             set_var( LEVEL_SET, av[1], str );
  2739.         free_file( rav );
  2740.     }
  2741.     return str ? 0 : 20;
  2742. }
  2743.  
  2744. void
  2745. foreach( char **s, int (*func)(char *s) )
  2746. {
  2747.     char *str;
  2748.  
  2749.     for( ;; ) {
  2750.         str = *s;
  2751.         if( !(*s=index(*s,0xA0)))
  2752.             break;
  2753.         **s=0;
  2754.         (*func)(str);
  2755.         *(*s)++=0xA0;
  2756.         if( breakcheck())
  2757.             return;
  2758.     }
  2759.     (*func)(str);
  2760. }
  2761.  
  2762. int
  2763. do_writefile( void )
  2764. {
  2765.     char *ptr;
  2766.  
  2767.     if( !(ptr=get_var(LEVEL_SET,av[1])))
  2768.         { fprintf(stderr,"Undefined variable %s\n",av[1]); return 20; }
  2769.  
  2770.     foreach( &ptr, puts );
  2771.  
  2772.     return 0;
  2773. }
  2774.  
  2775. int
  2776. do_split( void )
  2777. {
  2778.     int i;
  2779.     char *val, *gap, *oldval;
  2780.  
  2781.     if( !(val=get_var( LEVEL_SET, av[1] )))
  2782.         { fprintf( stderr, "undefined variable %s\n", av[1] ); return 20; }
  2783.     oldval=val=strcpy(salloc(strlen(val)+1),val);
  2784.     for( i=2; i<ac-1; i++ ) {
  2785.         if( gap=index(val,0xA0 )) *gap=0;
  2786.         set_var( LEVEL_SET, av[i], val );
  2787.         val="";
  2788.         if( gap ) *gap=0xA0, val=gap+1;
  2789.     }
  2790.     set_var( LEVEL_SET, av[ac-1], val );
  2791.     free(oldval);
  2792.     return 0;
  2793. }
  2794.  
  2795. char *
  2796. copyof( char *str )
  2797. {
  2798.     return strcpy(salloc(strlen(str)+1),str);
  2799. }
  2800.  
  2801. int
  2802. do_class( char *avline )
  2803. {
  2804.     CLASS *new;
  2805.  
  2806.     if( options&1 ) {
  2807.         avline=next_word(avline);
  2808.         for( new=CRoot,CRoot=NULL; new; new=new->next )
  2809.             Free(new);
  2810.     }
  2811.  
  2812.     if( ac==1 ) {
  2813.         for( new=CRoot; new; new=new->next )
  2814.             printf("%s\n",new->name);
  2815.         return 0;
  2816.     }
  2817.  
  2818.     avline=next_word(avline);
  2819.     if(!(new=malloc( strlen(avline)+5)))
  2820.         ierror( NULL, 512 );
  2821.     else {
  2822.         new->next=NULL;
  2823.         strcpy( new->name,avline );
  2824.         if( CRoot )
  2825.             LastCRoot->next=new;
  2826.         else 
  2827.             CRoot=new;
  2828.         LastCRoot=new;
  2829.     }
  2830.     return 0;
  2831. }
  2832.  
  2833. do_getcl( void )
  2834. {
  2835.     char *s=getclass(av[1]);
  2836.     if( s ) printf("%s\n",s);
  2837.     return 0;
  2838. }
  2839.  
  2840. do_action( char *argline )
  2841. {
  2842.     char *args, err;
  2843.     int abort=options&1;
  2844.  
  2845.     args=compile_av( av,3,ac,' ',0 );
  2846.     err=doaction(av[2],av[1],args);
  2847.     if( !abort )
  2848.         if( err==9 )     ierror(av[2], 205 );
  2849.         else if(err==10) fprintf(stderr,"Can't identify %s\n", av[2] );
  2850.         else if(err==11) fprintf(stderr,"Can't '%s' this file\n",av[1] );
  2851.         else if(err==12) fprintf(stderr,"Error executing the program to '%s' this file\n",av[1] );
  2852.     free(args);
  2853.     return abort ? !err : err;
  2854. }
  2855.  
  2856.  
  2857.