home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / shell / csh531s.lha / run.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-05  |  15.6 KB  |  709 lines

  1. /*
  2.  * RUN.C
  3.  *
  4.  * (c)1986 Matthew Dillon     9 October 1986
  5.  *
  6.  *    RUN   handles running of external commands.
  7.  *
  8.  * Version 2.07M by Steve Drew 10-Sep-87
  9.  * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  10.  * Version 5.00L by Urban Mueller 17-Feb-91
  11.  * Version 5.20L by Andreas M. Kirchwitz (Fri, 13 Mar 1992)
  12.  *
  13.  */
  14.  
  15. #include "shell.h"
  16.  
  17. int MySyncRun( char *com, char *args, BPTR in, BPTR out, int nosync );
  18. int echofunc(void);
  19.  
  20. int
  21. do_run( char *str, int nosync )
  22. {
  23.     int retcode;
  24.     char buf[200];        /* enough space for 100 char cmd name + path stuff */
  25.     char *path, *path2, *argline, *copy, *ext, *end;
  26.  
  27.     if( !*av[0] )
  28.         return 0;
  29.  
  30.     if( (retcode=echofunc())>=0 )
  31.         return retcode;
  32.  
  33.     a0tospace( av[0] );                                 /* allow "com mand" */
  34.  
  35.     argline=compile_av(av, 1, ac, ' ', 1);
  36.  
  37.     if (strlen(av[0]) > 100) { ierror(NULL,509); return -1; }
  38.  
  39.     if( ac==1 && isdir(av[0])) {
  40.         sprintf(buf,"cd \"%s\"",av[0]);
  41.         return execute( buf );
  42.     }
  43.  
  44.     IoError=IoErr();
  45.     if( (IoError==218 || IoError==225 || IoError==226) && index(av[0],':')) {
  46.         ierror( av[0], IoError );
  47.         return 20;
  48.     }
  49.  
  50.     sprintf(buf,"res_%s",FilePart(av[0]));               /* delayed residents */
  51.     /* AMK: OS20-GetVar replaces ARP-Getenv */
  52.     if (o_resident && GetVar(buf,buf+100,90L,GVF_GLOBAL_ONLY|GVF_BINARY_VAR)>=0L) {
  53.         /* AMK: OS20-SetVar replaces ARP-Setenv */
  54.         SetVar(buf,NULL,NULL,GVF_GLOBAL_ONLY|GVF_BINARY_VAR);
  55.         loadres(buf+100);
  56.     }
  57.  
  58.     if( (retcode=MySyncRun(av[0],argline,0,0,nosync))>=0 )   /* AmigaDOS path */
  59.         goto done2;
  60.  
  61.     if( retcode==-2 /*PR_NOMEM*/ ) {
  62.         ierror( av[0], 103 );
  63.         return 20;
  64.     }
  65.  
  66.     IoError=IoErr();
  67.     if( (IoError==218 || IoError==225 || IoError==226) && index(av[0],':')) {
  68.         ierror( av[0], IoError );
  69.         return 20;
  70.     }
  71.  
  72.     if (path = dofind(av[0],"",buf+80,v_path)) {             /* shell path    */
  73.         DPTR *dp;
  74.         BPTR fh;
  75.         int stat, script;
  76.         if((retcode = MySyncRun(path,argline,0,0,nosync))>=0)
  77.             goto done2;
  78.         if(dp=dopen(path,&stat)) {
  79.             script= dp->fib->fib_Protection&FIBF_SCRIPT;
  80.             dclose(dp);
  81.             if( !stat && script ) {
  82.                 char *t;
  83.                 buf[0]=0;
  84.                 if( fh=Open(path,MODE_OLDFILE )) {
  85.                     Read(fh,buf,79);
  86.                     Close(fh);
  87.                     if(t=index(buf,'\n')) *t=0;
  88.                 }
  89.                 if( buf[0]=='/' && buf[1]=='*' ) {
  90.                     sprintf(buf, "Rx %s", str );
  91.                 } else if( (buf[0]!=';' || buf[0]!='#') && buf[1]=='!' ) {
  92.                     memmove(buf,buf+2,strlen(buf+2)+1);
  93.                     strcat( buf," ");
  94.                     strcat( buf,str);
  95.                 } else {
  96.                     sprintf(buf,"Execute %s", str );
  97.                 }
  98.                 return execute( a0tospace(buf));
  99.             }
  100.         }
  101.     }
  102.  
  103.     if(!(end=rindex(av[0],'.'))) end="";               /* automatic sourcing */
  104.     ext=strcmp(end,".sh") ? ".sh" : "";
  105.     if (path = dofind(av[0],ext,buf,v_path)) {
  106.         av[1] = buf;
  107.         copy = salloc(strlen(str)+3);
  108.         sprintf(copy,"x %s",str);
  109.         retcode = do_source(copy);
  110.         goto done;
  111.     }
  112.  
  113.     copy=salloc(strlen(av[0])+strlen(argline)+5);
  114.     sprintf(copy,"%s %s",av[0],argline);
  115.  
  116.     ext=strcmp(end,".rexx") ? ".rexx" : "";           /* automatic rx-ing   */
  117.     if( path = dofind(av[0], ext, buf, v_rxpath )) {
  118.         strcat (path," ");
  119.         if( strlen(argline)>140 ) argline[140]=0;
  120.         strcat (path,argline);
  121.  
  122. /*        strncpy(path+strlen(path),argline,190); */
  123.         if( (retcode=MySyncRun("rx",path,0,0,0)) >=0 ) goto done;
  124.         if (path2 = dofind("rx","",buf+160,v_path)) {
  125.             retcode = MySyncRun(path2,path,0,0,0);
  126.             goto done;
  127.         }
  128.  
  129.     }
  130.  
  131.     if( !doaction(av[0],"exec",argline)) {
  132.         retcode=0;
  133.         goto done;
  134.     }
  135.  
  136.     retcode=-1;
  137.     fprintf(stderr,"Command not found %s\n",av[0]);
  138.  
  139. done:
  140.     free( copy );
  141. done2:
  142.     setioerror( IoErr() );
  143.     free( argline );
  144.     return retcode;
  145. }
  146.  
  147.  
  148.  
  149. #ifndef END_STREAM_CH
  150. #define END_STREAM_CH -1L
  151. #endif
  152. BPTR
  153.     new_input,    /* for execute'ing a script file */
  154.     old_inp_fh,    /* old input filehandle */
  155.     old_out_fh,    /* old output filehandle */
  156.     seglist_cmd;    /* to be returned from NewLoadSeg */
  157.  
  158.  
  159. void set_returncodes(long returncode,long result2)
  160. {
  161.     Mycli->cli_ReturnCode = returncode;
  162.     Mycli->cli_Result2    = result2;
  163. }
  164.  
  165.  
  166.  
  167. void clean_up_io(void)
  168. {
  169.     long ch;
  170.     Flush(Output());
  171.     ch = UnGetC(Input(),END_STREAM_CH) ? 0 : '\n';
  172.     while ((ch != '\n') && (ch != END_STREAM_CH))
  173.         ch = FGetC(Input());
  174. }
  175.  
  176. long command_examine(char *fname,BPTR *plock)
  177. {
  178.     /*
  179.     Given a filename, attempt to determine if we can process it. Either
  180.     by running it, or by 'executing' it (a script).
  181.  
  182.     Returns:
  183.         0 = can RunCommand the file
  184.         1 = can source/script/execute the file
  185.       < 0 = error
  186.     */
  187.     struct FileInfoBlock *fib;
  188.     long i;
  189.     BPTR lock;
  190.  
  191.     *plock = NULL;
  192.  
  193.     if (!(lock=Lock(fname,ACCESS_READ)))
  194.         return -1;
  195.  
  196.     if (!(fib = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,NULL))) {
  197.         UnLock(lock);
  198.         return -9;
  199.     }
  200.  
  201.     if (!Examine(lock,fib)) {
  202.         UnLock(lock);
  203.         FreeDosObject(DOS_FIB,fib);
  204.         return -2;
  205.     }
  206.  
  207.     i = fib->fib_DirEntryType;
  208.  
  209.     if (i==ST_SOFTLINK) {
  210.         /*
  211.            Let our caller resolve the link, and if it resolves to a file,
  212.            call us again.
  213.         */
  214.         UnLock(lock);
  215.         FreeDosObject(DOS_FIB,fib);
  216.         return -10;
  217.     }
  218.  
  219.     if (!((i==ST_FILE) || (i==ST_LINKFILE))) {
  220.         UnLock(lock);
  221.         FreeDosObject(DOS_FIB,fib);
  222.         return -3;
  223.     }
  224.  
  225.     i = fib->fib_Protection;
  226.     i = (i & 0x70) | (0x0f & ~i);
  227.     if (!((i & FIBF_SCRIPT) || (i & FIBF_EXECUTE))) {
  228.         /* Not an executable or a script file. */
  229.         UnLock(lock);
  230.         FreeDosObject(DOS_FIB,fib);
  231.         return -4;
  232.     }
  233.  
  234.     FreeDosObject(DOS_FIB,fib);
  235.     seglist_cmd = NULL;
  236.     new_input = NULL;
  237.     *plock = ParentDir(lock);
  238.  
  239.     if (i & FIBF_SCRIPT) {
  240.         /*
  241.             Open the file, but let the 'outside world' dick with CurrentInput.
  242.             Not me. Outside of my definition. :)
  243.         */
  244.         if (!(new_input=OpenFromLock(lock))) {
  245.             UnLock(lock);
  246.             UnLock(*plock);
  247.             return -5;
  248.         }
  249.         /* Remember that 'lock' is now INVALID and should not be touched. */
  250.         return 1;
  251.     }
  252.  
  253.     if (i & FIBF_EXECUTE) {
  254.         /* LoadSeg the sucker. */
  255.         if (!(seglist_cmd=NewLoadSeg(fname,NULL))) {
  256.             /* Probably a 'bad' file (i.e., not actually an executable). */
  257.             UnLock(lock);
  258.             UnLock(*plock);
  259.             return -6;
  260.         }
  261.         UnLock(lock);
  262.         return 0;
  263.     }
  264.  
  265.     if (lock) UnLock(lock);
  266.     if (*plock) UnLock(*plock);
  267.     return -7;    /* should NEVER reach this point */
  268. }
  269.  
  270.  
  271.  
  272. long command_device(char *device,char *fname)
  273. {
  274.     /*
  275.     For the Device specified by *device, search each element of the
  276.     assign (since it could be a multi-assign) and try to find a
  277.     command file. A command file can be either an executable file, or
  278.     a script file (one with the script bit set).
  279.  
  280.     Returns:
  281.         0 = can RunCommand this file (seglist_cmd set)
  282.         1 = can source/script/execute this file (new_input set)
  283.       < 0 = error
  284.        -8 = Bad device name
  285.  
  286.     Note that this routine generates only one error of its own. All
  287.     other results are passed straight thru from command_examine ().
  288.     */
  289.  
  290.     long gotlock,            /* we have a directory lock or not */
  291.          result,            /* from command_examine () */
  292.          done = 0;            /* found something we could use */
  293.     struct DevProc *dp = NULL;    /* for searching multi-assigned paths */
  294.     struct MsgPort *fstask;        /* for GetFileSysTask () */
  295.     BPTR plock,            /* parent of fname */
  296.          lock,            /* on source directory */
  297.          dir_lock;            /* save current directory */
  298.  
  299.     /*printf("search: %s -> %s\n",device,fname);*/
  300.  
  301.     fstask = GetFileSysTask ();
  302.  
  303.     do {
  304.         dp = GetDeviceProc(device,dp);
  305.         if (dp) {
  306.             SetFileSysTask(dp->dvp_Port);
  307.  
  308.             lock = NULL;
  309.             gotlock = 0;
  310.             if (dp->dvp_Lock) {
  311.                 dir_lock = CurrentDir(dp->dvp_Lock);
  312.                 gotlock = 1;
  313.             }
  314.             else {
  315.                 if (lock=Lock(device,ACCESS_READ)) {
  316.                     dir_lock = CurrentDir(lock);
  317.                     gotlock = 1;
  318.                 }
  319.             }
  320.             if (gotlock) {
  321.                 result = command_examine(fname,&plock);
  322.                 /*
  323.                     NOTE: Philosophically speaking, if result <= -2, what
  324.                     should we do? This means that command_examine () actually
  325.                     found a file by the correct name, but it was unsuitable for
  326.                     some reason.
  327.                     Currently, we continue to search, in hopes that St. Nicholas
  328.                     will soon be here...(ie, we will find a file that meets our
  329.                     criteria). This is questionable as to its correctness.
  330.                 */
  331.                 if (result<0) {
  332.                     done = 0;
  333.                 }
  334.                 else {
  335.                     BPTR hdir_lock;
  336.                     if (plock)
  337.                         hdir_lock = plock;
  338.                     else if (lock)
  339.                         hdir_lock = lock;
  340.                     else if (dp->dvp_Lock)
  341.                         hdir_lock = dp->dvp_Lock;
  342.                     else
  343.                         hdir_lock = NULL;
  344. /*
  345.                     {char buf[256];
  346.                     if (hdir_lock && NameFromLock(hdir_lock,buf,256))
  347.                         printf("hdir_lock: %s\n",buf);
  348.                     }
  349. */
  350.                     done = 1;
  351.                     /*
  352.                     --- This was from XSHell, but wasn't correct ---
  353.                     Myprocess->pr_HomeDir = DupLock(lock?lock:dp->dvp_Lock);
  354.                     */
  355.                     Myprocess->pr_HomeDir = DupLock(hdir_lock);
  356.                     UnLock(plock);
  357.                 }
  358.                 if (lock) {
  359.                     UnLock(lock);
  360.                     lock = NULL;
  361.                 }
  362.                 CurrentDir(dir_lock);
  363.             }
  364.         }
  365.     } while (!done                               &&
  366.          dp && (dp->dvp_Flags & DVPF_ASSIGN) &&
  367.          IoErr() == ERROR_OBJECT_NOT_FOUND);
  368.  
  369.     SetFileSysTask (fstask);
  370.     if (dp) FreeDeviceProc(dp);
  371.  
  372.     if (!done && result >= 0) {
  373.         /* Can happen when GetDeviceProc returns a NULL dp on the first go. */
  374.         result = -8;
  375.     }
  376.  
  377.     return result;
  378. }
  379.  
  380.  
  381.  
  382. long command_processor(long abs_cmd,char *device,char *fname)
  383. {
  384.     /*
  385.     Results:
  386.         Those returned by command_examine () and command_device ().
  387.  
  388.         0 = can RunCommand (seglist_cmd set)
  389.         1 = can source/script/execute (new_input set)
  390.       < 0 = error
  391.     */
  392.  
  393.     struct PathList *pl;    /* to parse the PATH */
  394.     long result,        /* from command_examine () or command_device () */
  395.          sub_cmd;        /* command is in a sub-directory */
  396.     BPTR plock;        /* points to parent directory of fname */
  397.     char buf [256];        /* where to put elements of the Cli Path */
  398.  
  399.     sub_cmd = abs_cmd & 2;    /* a '/' was found in the input filename */
  400.     abs_cmd &= 1;        /* so it only has one meaning: a ':' was found */
  401.  
  402.     if (*device == '\0')
  403.         abs_cmd = 0;    /* handle special case of empty device */
  404.  
  405.     if (abs_cmd) {        /* absolute path like 'dh0:myprog' */
  406.         result = command_device(device,fname);
  407.         return result;
  408.     }
  409.     if (sub_cmd) {        /* relative path like 'mydir/myprog' */
  410.         result = command_examine (fname, &plock);
  411.         if (result < 0) return result;
  412.         /*
  413.             NOTE: Is the following OK? Or should we DupLock() and then
  414.             UnLock()? I don't see why....
  415.         */
  416.         Myprocess->pr_HomeDir = plock;
  417.         plock = NULL;
  418.         return result;
  419.     }
  420.     /* file in current directory */
  421.     result = command_examine(fname,&plock);
  422.     if (result >= 0) {
  423.         Myprocess->pr_HomeDir = plock;
  424.         plock = NULL;
  425.         return result;
  426.     }
  427.     /* DOS search path */
  428.     /* Forbid(); */
  429.     pl = (struct PathList *)BADDR(Mycli->cli_CommandDir);
  430.     while (pl && !dobreak()) {
  431.         if (pl->pl_PathLock) {
  432.             if (NameFromLock(pl->pl_PathLock,buf,256)) {
  433.                 result = command_device(buf,fname);
  434.                 if (result >= 0) {
  435.                     /* Permit(); */
  436.                     return result;
  437.                 }
  438.             }
  439.         }
  440.         pl = (struct PathList *)BADDR(pl->pl_NextPath);
  441.     }
  442.     /* Permit(); */
  443.  
  444.     /* Last, but CERTAINLY not least, search 'C:' */
  445.     if (!dobreak())
  446.         result = command_device("C:",fname);
  447.  
  448.     return result;
  449. }
  450.  
  451.  
  452.  
  453. int
  454. MySyncRun( char *com, char *args, BPTR in, BPTR out, int nosync )
  455. {
  456.     struct Segment *cmdseg = NULL;
  457.     int len=strlen(args);
  458.     char myname[256];
  459.     BPTR myhdir,mymod;
  460.     long abs_cmd = 0;
  461.     char *p,*pname=strdup(com), *ppath=strdup(com), *pdev=strdup(com);
  462.     long rslt = -1;
  463.  
  464. /*
  465.     old_inp_fh = SelectInput (Mycli->cli_CurrentInput);
  466.     old_out_fh = SelectOutput(Mycli->cli_StandardOutput);
  467.     Flush(Input());
  468.     Flush(Output());
  469. */
  470.     GetProgramName(myname,255);
  471.     myhdir = Myprocess->pr_HomeDir;
  472.     mymod  = Mycli->cli_Module;
  473.  
  474.     /* clear it so that we don't "free" ourself on MySyncRun_done: */
  475.     Myprocess->pr_HomeDir = NULL;
  476.     Mycli->cli_Module = NULL;
  477.  
  478.     args[len]='\n'; args[len+1]=0;        /* trailing '\n' */
  479.  
  480.     if (!pname || !ppath || !pdev)
  481.         goto MySyncRun_done;
  482.  
  483.     if (p=FilePart(com))
  484.         strcpy(pname,p);
  485.  
  486.     if (p=strchr(pdev,':')) {
  487.         abs_cmd |= 1;
  488.         strcpy(ppath,++p);
  489.         *p='\0';
  490.     }
  491.     else strcpy(pdev,"");
  492.  
  493.     if (strchr(ppath,'/'))
  494.         abs_cmd |= 2;
  495.  
  496. /*
  497. printf("prog: %s, arg: %s, async: %s\n",com,args,nosync?"yes":"no");
  498. printf("pdev: %s, ppath: %s, pname: %s [%ld]\n",pdev,ppath,pname,abs_cmd);
  499. */
  500.  
  501.     seglist_cmd = NULL;
  502.     new_input = NULL;
  503.  
  504.     if (!abs_cmd) {
  505.         Forbid();
  506.         if (!(cmdseg = FindSegment(com,NULL,FALSE)))
  507.             cmdseg = FindSegment(com,NULL,TRUE);
  508.         if (cmdseg) {
  509. /*
  510.     Randell says ...
  511.             if ((cmdseg->seg_UC < CMD_DISABLED) ||
  512.     ... but if a command is disabled why we should execute it?
  513. */
  514.             if ((cmdseg->seg_UC <= CMD_DISABLED) ||
  515.                 (cmdseg->seg_UC == CMD_SYSTEM))
  516.                 cmdseg = NULL;
  517.             else if (cmdseg->seg_UC >= 0)
  518.                 cmdseg->seg_UC++;
  519.         }
  520.         Permit();
  521.         if (cmdseg) {
  522.             seglist_cmd = cmdseg->seg_Seg;
  523.             Myprocess->pr_HomeDir = NULL;
  524.         }
  525.     }
  526.  
  527.     if (!cmdseg) {
  528.         rslt = command_processor(abs_cmd,pdev,ppath);
  529.         /*printf("cmd_processor returned %ld\n",rslt);*/
  530.         if (rslt<0) {
  531.             /*printf("Object not found: %s\n",pname);*/
  532.             goto MySyncRun_done;
  533.             /*return -1;*/
  534.         }
  535.     }
  536.  
  537.     if (new_input) {                /* rslt = 1 */
  538.         struct TagItem sys_tags[3];
  539.         char scp_name[256];
  540.         char exec_buf[1000];
  541.  
  542.         /*printf("let's try to start a script ...\n");*/
  543.         NameFromFH(new_input,scp_name,255);
  544.         Close(new_input);
  545.  
  546.         sys_tags[0].ti_Tag  = SYS_Input;
  547.         sys_tags[0].ti_Data = (ULONG)NULL;
  548.         sys_tags[1].ti_Tag  = SYS_Output;
  549.         sys_tags[1].ti_Data = (ULONG)Myprocess->pr_COS;
  550.         sys_tags[2].ti_Tag  = TAG_DONE;
  551.         sys_tags[2].ti_Data = NULL;
  552.  
  553.         sprintf(exec_buf,"%s %s",scp_name,args);
  554.         rslt = SystemTagList(exec_buf,sys_tags);
  555.         /*Close(sys_tags[1].ti_Data);*/
  556. /*
  557.         char buf2[200];
  558.         sprintf(buf2,"%s %s",com,args);
  559.         Execute("",new_input,Myprocess->pr_COS);
  560. */
  561.         /*clean_up_io();*/
  562.     }
  563.  
  564.     if (seglist_cmd) {                /* rslt = 0 */
  565.         SetIoErr(0);
  566.  
  567.         if (!SetProgramName(pname))
  568.             SetProgramName("CSH-program");
  569.  
  570.         if (Mycli->cli_DefaultStack < 1000)
  571.             Mycli->cli_DefaultStack=4000;
  572.  
  573.         Mycli->cli_Module = seglist_cmd;
  574.         rslt = RunCommand(seglist_cmd,Mycli->cli_DefaultStack*4,args,strlen(args));
  575.  
  576.         if ((rslt==-1) && (IoErr()==ERROR_NO_FREE_STORE)) {
  577.             printf("we are out of memory for RunCommand()\n");
  578.             set_returncodes(RETURN_FAIL,ERROR_NO_FREE_STORE);
  579.             rslt = RETURN_FAIL;
  580.             goto MySyncRun_done;
  581.         }
  582.  
  583.         set_returncodes(rslt,IoErr());
  584.  
  585.         SetProgramName(myname);
  586.     }
  587.  
  588. MySyncRun_done:
  589.     if (cmdseg) {
  590.         Forbid();
  591.         if (cmdseg->seg_UC>0)
  592.             cmdseg->seg_UC--;
  593.         Permit();
  594.         Mycli->cli_Module = NULL;
  595.     }
  596.  
  597.     if (!cmdseg && seglist_cmd) {
  598.         if (Mycli->cli_Module)
  599.             UnLoadSeg(Mycli->cli_Module);
  600.         Mycli->cli_Module = NULL;
  601.     }
  602.  
  603.     if (Myprocess->pr_HomeDir) {
  604.         /*
  605.         char hd[256];
  606.         NameFromLock(Myprocess->pr_HomeDir,hd,255);
  607.         printf("homedir set to %s, now unlocking.\n",hd);
  608.         */
  609.         UnLock(Myprocess->pr_HomeDir);
  610.         Myprocess->pr_HomeDir = NULL;
  611.     }
  612.  
  613.     Myprocess->pr_HomeDir = myhdir;
  614.     Mycli->cli_Module     = mymod;
  615.  
  616.     if (pname) free(pname);
  617.     if (ppath) free(ppath);
  618.     if (pdev)  free(pdev);
  619.  
  620.     /*clean_up_io();*/
  621.  
  622. /*
  623.     old_out_fh = SelectOutput (Mycli->cli_StandardOutput);
  624.     old_inp_fh = SelectInput  (Mycli->cli_CurrentInput);
  625. */
  626.  
  627.     return rslt;
  628. #if 0
  629.     if (done) return rslt;
  630.  
  631.     char buf2[200];
  632.     args[len]=0;        /* remove trailing '\n' */
  633.  
  634.     printf("trying old style...\n");
  635.  
  636.     if( nosync ) {
  637.         sprintf(buf2,"%s %s",com,args);
  638.         Execute(buf2,0,Myprocess->pr_COS);
  639.         return 0;
  640.     }
  641.  
  642.     if( (ret= SyncRun( com, args, in, out ))>=0 )
  643.         return ret;
  644.  
  645.     if( ret==PR_NOMEM /* -2L */ ) {
  646.         ierror(NULL,103);
  647.         return 20;
  648.     }
  649.  
  650.     return -1;
  651. #endif
  652. }
  653.  
  654.  
  655. #if 0
  656. int
  657. do_which( char *str )
  658. {
  659.     char *got, *com=av[1];
  660.  
  661.     if( get_var(LEVEL_ALIAS,com) ) {
  662.         printf("Shell Alias '%s'\n",com);
  663.         return 0;
  664.     }
  665.  
  666.     if( *(got=find_internal( com ))>1 ) {
  667.         printf("Shell Internal '%s'\n",got);
  668.         return 0;
  669.     }
  670.  
  671.  
  672.  
  673.     printf( "Not found\n" );
  674.     return 20;
  675. }
  676. #endif
  677.  
  678.  
  679. char *
  680. dofind( char *cmd, char *ext, char *buf, char *path)
  681. {
  682.     char *ptr, *s=path, *ret=NULL;
  683.  
  684.     Myprocess->pr_WindowPtr = (APTR)(-1);
  685.     sprintf(buf,"%s%s",cmd,ext);
  686.     if (exists(buf)) {
  687.         ret=buf;
  688.         goto terminate;
  689.     }
  690.     if ((char*)FilePart(buf)==buf) {
  691.         if( *path=='_' )
  692.             s = get_var(LEVEL_SET, path);
  693.         while (*s) {
  694.             for (ptr=buf; *s && *s!=','; ) *ptr++ = *s++;
  695.             if( ptr[-1]!=':' && ptr[-1]!='/')
  696.                 *ptr++='/';
  697.             sprintf(ptr, "%s%s", cmd, ext);
  698.             if (exists(buf)) {
  699.                 ret=buf;
  700.                 goto terminate;
  701.             }
  702.             if (*s) s++;
  703.         }
  704.     }
  705. terminate:
  706.     Myprocess->pr_WindowPtr = (APTR)o_noreq;
  707.     return ret;
  708. }
  709.