home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / elvis184.zip / src / sysdos.c < prev    next >
C/C++ Source or Header  |  1994-03-26  |  5KB  |  212 lines

  1. /* sysdos.c  -- DOS version of system.c */
  2.  
  3. /* Author:
  4.  *    Guntram Blohm
  5.  *    Buchenstrasse 19
  6.  *    7904 Erbach, West Germany
  7.  *    Tel. ++49-7305-6997
  8.  *    sorry - no regular network connection
  9.  */
  10.  
  11.  
  12. /* This file is derived from Steve Kirkendall's system.c.
  13.  *
  14.  * Entry points are:
  15.  *    system(cmd)    - run a single shell command
  16.  *    rpipe(cmd, in)    - run a shell command with stdin/stdout piped
  17.  *    rpclose(fd)    - close a pipe that was created via rpipe()
  18.  *    gethome(argv0)    - return name of home directory
  19.  *
  20.  * This file is for use with DOS and TOS. For OS/2, slight modifications
  21.  * might be sufficient. For UNIX, use system.c. For Amiga, completely
  22.  * rewrite this stuff.
  23.  *
  24.  * Another system function, filter, is the same on DOS and UNIX and thus
  25.  * can be found in the original system.c.
  26.  */
  27.  
  28. #include "config.h"
  29. #include "vi.h"
  30. #ifndef XDOS
  31. extern char **environ;
  32. #endif
  33.  
  34. #if TURBOC
  35. #define switchar() '/'
  36. #endif
  37.  
  38. #if MSDOS
  39. #include <process.h>
  40. #ifndef XDOS
  41. extern unsigned char _osmajor;
  42. #endif
  43. #endif
  44. #if TOS
  45. #include <osbind.h>
  46. #endif
  47.  
  48.  
  49. #if MSDOS || TOS
  50. #include <string.h>
  51.  
  52. /*
  53.  * Calling command is a bit nasty because of the undocumented yet sometimes
  54.  * used feature to change the option char to something else than /.
  55.  * Versions 2.x and 3.x support this, 4.x doesn't.
  56.  *
  57.  * For Atari, some shells define a shortcut entry which is faster than
  58.  * shell -c. Also, Mark Williams uses a special ARGV environment variable
  59.  * to pass more than 128 chars to a called command.
  60.  * We try to support all of these features here.
  61.  */
  62.  
  63. int system(cmd)
  64.     const char    *cmd;
  65. {
  66. #if MSDOS
  67.     char *cmdswitch="/c";
  68.     if (_osmajor<4)
  69.         cmdswitch[0]=switchar();
  70.     return spawnle(P_WAIT, o_shell, o_shell, cmdswitch, cmd, (char *)0, environ);
  71. #else
  72.     long    ssp;
  73.     int    (*shell)();
  74.     char    line[130];
  75.     char    env[4096], *ep=env;
  76.     int    i;
  77.  
  78. /* does our shell have a shortcut, that we can use? */
  79.  
  80.     ssp = Super(0L);
  81.     shell = *((int (**)())0x4F6);
  82.     Super(ssp);
  83.     if (shell)
  84.         return (*shell)(cmd);
  85.  
  86. /* else we'll have to call a shell ... */
  87.  
  88.     for (i=0; environ[i] && strncmp(environ[i], "ARGV=", 5); i++)
  89.     {    strcpy(ep, environ[i]);
  90.         ep+=strlen(ep)+1;
  91.     }
  92.     if (environ[i])
  93.     {
  94.         strcpy(ep, environ[i]); ep+=strlen(ep)+1;
  95.         strcpy(ep, o_shell); ep+=strlen(ep)+1;
  96.         strcpy(ep, "-c"); ep+=3;
  97.         strcpy(ep, cmd); ep+=strlen(ep)+1;
  98.     }
  99.     *ep='\0';
  100.     strcpy(line+1, "-c ");
  101.     strncat(line+1, cmd, 126);
  102.     line[0]=strlen(line+1);
  103.     return Pexec(0, o_shell, line, env);
  104. #endif
  105. }
  106.  
  107. /* This private function opens a pipe from a filter.  It is similar to the
  108.  * system() function above, and to popen(cmd, "r").
  109.  * sorry - i cant use cmdstate until rpclose, but get it from spawnle.
  110.  */
  111.  
  112. static int cmdstate;
  113. static char output[80];
  114.  
  115. int rpipe(cmd, in)
  116.     char    *cmd;    /* the filter command to use */
  117.     int    in;    /* the fd to use for stdin */
  118. {
  119.     int    fd, old0, old1, old2;
  120.  
  121.     /* create the file that will collect the filter's output */
  122.     strcpy(output, o_directory);
  123.     if ((fd=strlen(output)) && !strchr("/\\:", output[fd-1]))
  124.         output[fd++]=SLASH;
  125.     strcpy(output+fd, SCRATCHIN+3);
  126.     mktemp(output);
  127.     close(creat(output, 0666));
  128.     if ((fd=open(output, O_RDWR))==-1)
  129.     {
  130.         unlink(output);
  131.         return -1;
  132.     }
  133.  
  134.     /* save and redirect stdin, stdout, and stderr */
  135.     old0=dup(0);
  136.     old1=dup(1);
  137.     if (in)
  138.     {
  139.         dup2(in, 0);
  140.         close(in);
  141.     }
  142.     dup2(fd, 1);
  143.  
  144.     /* call command */
  145.     cmdstate=system(cmd);
  146.  
  147.     /* restore old std... */
  148.     dup2(old0, 0); close(old0);
  149.     dup2(old1, 1); close(old1);
  150.  
  151.     /* rewind command output */
  152.     lseek(fd, 0L, 0);
  153.     return fd;
  154. }
  155.  
  156. /* This function closes the pipe opened by rpipe(), and returns 0 for success */
  157. int rpclose(fd)
  158.     int    fd;
  159. {
  160.     int    status;
  161.  
  162.     close(fd);
  163.     unlink(output);
  164.     return cmdstate;
  165. }
  166.  
  167. /* This function returns the name of the home directory.  If there is an
  168.  * environment variable named "HOME", then its value is used; otherwise,
  169.  * argv[0] is expected to contain the full pathname of the ELVIS.EXE, and
  170.  * its directory will be used as the home directory.  The first time this
  171.  * function is called, you must pass it the value of argv[0] but after that
  172.  * you can pass it a NULL pointer.
  173.  *
  174.  * NOTE: This may alter the argv[0] string.
  175.  */
  176. char *gethome(exe)
  177.     char    *exe;    /* full pathname of the ELVIS.EXE file */
  178. {
  179.     static char    *home;
  180.  
  181.     /* if this is the first time this func has been called, find home */
  182.     if (!home)
  183.     {
  184.         home = getenv("HOME");
  185.         if (!home)
  186.         {
  187.             home = exe;
  188.             exe = strrchr(exe, SLASH);
  189.             if (exe)
  190.             {
  191.                 /* Yes, it was a full pathname.  Strip off the
  192.                  * "ELVIS.EXE" part of the name, and use the
  193.                  * rest as the name of the home directory.
  194.                  */
  195.                 *exe = '\0';
  196.             }
  197.             else
  198.             {
  199.                 /* Not a full pathname.  Use the current
  200.                  * directory as the home directory.
  201.                  */
  202.                 home = ".";
  203.             }
  204.         }
  205.     }
  206.  
  207.     /* return home */
  208.     return home;
  209. }
  210.  
  211. #endif
  212.