home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / e / elv17src.zip / SYSDOS.C < prev    next >
C/C++ Source or Header  |  1992-12-30  |  5KB  |  209 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.  
  35. #if MSDOS
  36. #include <process.h>
  37. #ifndef XDOS
  38. extern unsigned char _osmajor;
  39. #endif
  40. #endif
  41. #if TOS
  42. #include <osbind.h>
  43. #endif
  44.  
  45.  
  46. #if MSDOS || TOS
  47. #include <string.h>
  48.  
  49. /*
  50.  * Calling command is a bit nasty because of the undocumented yet sometimes
  51.  * used feature to change the option char to something else than /.
  52.  * Versions 2.x and 3.x support this, 4.x doesn't.
  53.  *
  54.  * For Atari, some shells define a shortcut entry which is faster than
  55.  * shell -c. Also, Mark Williams uses a special ARGV environment variable
  56.  * to pass more than 128 chars to a called command.
  57.  * We try to support all of these features here.
  58.  */
  59.  
  60. int system(cmd)
  61.     const char    *cmd;
  62. {
  63. #if MSDOS
  64.     char *cmdswitch="/c";
  65.     if (_osmajor<4)
  66.         cmdswitch[0]=switchar();
  67.     return spawnle(P_WAIT, o_shell, o_shell, cmdswitch, cmd, (char *)0, environ);
  68. #else
  69.     long    ssp;
  70.     int    (*shell)();
  71.     char    line[130];
  72.     char    env[4096], *ep=env;
  73.     int    i;
  74.  
  75. /* does our shell have a shortcut, that we can use? */
  76.  
  77.     ssp = Super(0L);
  78.     shell = *((int (**)())0x4F6);
  79.     Super(ssp);
  80.     if (shell)
  81.         return (*shell)(cmd);
  82.  
  83. /* else we'll have to call a shell ... */
  84.  
  85.     for (i=0; environ[i] && strncmp(environ[i], "ARGV=", 5); i++)
  86.     {    strcpy(ep, environ[i]);
  87.         ep+=strlen(ep)+1;
  88.     }
  89.     if (environ[i])
  90.     {
  91.         strcpy(ep, environ[i]); ep+=strlen(ep)+1;
  92.         strcpy(ep, o_shell); ep+=strlen(ep)+1;
  93.         strcpy(ep, "-c"); ep+=3;
  94.         strcpy(ep, cmd); ep+=strlen(ep)+1;
  95.     }
  96.     *ep='\0';
  97.     strcpy(line+1, "-c ");
  98.     strncat(line+1, cmd, 126);
  99.     line[0]=strlen(line+1);
  100.     return Pexec(0, o_shell, line, env);
  101. #endif
  102. }
  103.  
  104. /* This private function opens a pipe from a filter.  It is similar to the
  105.  * system() function above, and to popen(cmd, "r").
  106.  * sorry - i cant use cmdstate until rpclose, but get it from spawnle.
  107.  */
  108.  
  109. static int cmdstate;
  110. static char output[80];
  111.  
  112. int rpipe(cmd, in)
  113.     char    *cmd;    /* the filter command to use */
  114.     int    in;    /* the fd to use for stdin */
  115. {
  116.     int    fd, old0, old1, old2;
  117.  
  118.     /* create the file that will collect the filter's output */
  119.     strcpy(output, o_directory);
  120.     if ((fd=strlen(output)) && !strchr("/\\:", output[fd-1]))
  121.         output[fd++]=SLASH;
  122.     strcpy(output+fd, SCRATCHIN+3);
  123.     mktemp(output);
  124.     close(creat(output, 0666));
  125.     if ((fd=open(output, O_RDWR))==-1)
  126.     {
  127.         unlink(output);
  128.         return -1;
  129.     }
  130.  
  131.     /* save and redirect stdin, stdout, and stderr */
  132.     old0=dup(0);
  133.     old1=dup(1);
  134.     if (in)
  135.     {
  136.         dup2(in, 0);
  137.         close(in);
  138.     }
  139.     dup2(fd, 1);
  140.  
  141.     /* call command */
  142.     cmdstate=system(cmd);
  143.  
  144.     /* restore old std... */
  145.     dup2(old0, 0); close(old0);
  146.     dup2(old1, 1); close(old1);
  147.  
  148.     /* rewind command output */
  149.     lseek(fd, 0L, 0);
  150.     return fd;
  151. }
  152.  
  153. /* This function closes the pipe opened by rpipe(), and returns 0 for success */
  154. int rpclose(fd)
  155.     int    fd;
  156. {
  157.     int    status;
  158.  
  159.     close(fd);
  160.     unlink(output);
  161.     return cmdstate;
  162. }
  163.  
  164. /* This function returns the name of the home directory.  If there is an
  165.  * environment variable named "HOME", then its value is used; otherwise,
  166.  * argv[0] is expected to contain the full pathname of the ELVIS.EXE, and
  167.  * its directory will be used as the home directory.  The first time this
  168.  * function is called, you must pass it the value of argv[0] but after that
  169.  * you can pass it a NULL pointer.
  170.  *
  171.  * NOTE: This may alter the argv[0] string.
  172.  */
  173. char *gethome(exe)
  174.     char    *exe;    /* full pathname of the ELVIS.EXE file */
  175. {
  176.     static char    *home;
  177.  
  178.     /* if this is the first time this func has been called, find home */
  179.     if (!home)
  180.     {
  181.         home = getenv("HOME");
  182.         if (!home)
  183.         {
  184.             home = exe;
  185.             exe = strrchr(exe, SLASH);
  186.             if (exe)
  187.             {
  188.                 /* Yes, it was a full pathname.  Strip off the
  189.                  * "ELVIS.EXE" part of the name, and use the
  190.                  * rest as the name of the home directory.
  191.                  */
  192.                 *exe = '\0';
  193.             }
  194.             else
  195.             {
  196.                 /* Not a full pathname.  Use the current
  197.                  * directory as the home directory.
  198.                  */
  199.                 home = ".";
  200.             }
  201.         }
  202.     }
  203.  
  204.     /* return home */
  205.     return home;
  206. }
  207.  
  208. #endif
  209.