home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / tools / make / make_pd / msdos.c < prev    next >
C/C++ Source or Header  |  1987-02-01  |  5KB  |  164 lines

  1. /* msdos.c */
  2. /*
  3. Microsoft C-dependent functions for Make.  Originally written by Rahul
  4. Dhesi for Atoz in 1986.  Modified for use with the P.D. make utility
  5. in February 1987.  Released to the public domain.
  6. */
  7.  
  8. #include <signal.h>
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>        /* function definitions: getenv() and others            */
  12. #include "intdos.h"        /* registers for MS-DOS interrupts                    */
  13. #include <process.h>        /* function definitions: spawn()/exec()/system()    */
  14.  
  15. int break_hit;                /* flag set on user interrupt */
  16. int handle_break();        /* routine to set flag on user interrupt */
  17. int (*oldsignal)();        /* to save old signal() handler */
  18.  
  19. /*******************/
  20. /*
  21. dosswitch() accepts a character specifying a switch character.  If
  22. the character is null, dosswitch() simply returns the current DOS
  23. switch character.  If it is not null, the DOS switch character is set
  24. to the received character and the newly-set character returned by DOS
  25. is returned as the function value.
  26. */
  27.  
  28. unsigned int dosswitch (switchar)
  29. int switchar;
  30. {
  31.     union REGS regs;
  32.     if (switchar == '\0')
  33.         regs.h.al = 0;                    /* get switch character code            */
  34.     else {
  35.         regs.h.al = 1;                    /* set switch character code            */
  36.         regs.h.dl = switchar;        /* char to set switch to                */
  37.       }
  38.     regs.h.ah = 0x37;                    /* get or set switch DOS call            */
  39.     intdos (®s, ®s);
  40.     return ((unsigned int) regs.h.dl); /* return current switch char    */
  41. }
  42.  
  43. /*******************/
  44. /*
  45. subp() executes a subprocess then returns.  It breaks up the received
  46. command line into a command name (first word) and a parameter list
  47. (rest of string) before executing the subprocess.  The environment
  48. of the subprocess is a copy of the parent's environment.  Return
  49. value is -1 if the subprocess could not be created, otherwise it is
  50. the exit status of the subprocess.  The command interpreter is NOT
  51. executed, so DOS commands such as DIR canot be directly used here.
  52. */
  53.  
  54. int subp (command)
  55. char *command;
  56. {
  57.     int status;
  58.     char progname[80];
  59.     char args[128];
  60.     int i, j;
  61.  
  62.     progname[0] = '\0';
  63.     args[0] = '\0';
  64.  
  65.     /* skip leading white space */
  66.     i = 0;
  67.     while (command[i] == ' ' || command[i] == '\t')
  68.         i++;
  69.  
  70.     /* progname gets program name, args gets rest of command string */
  71.     while (command[i] != ' '&& command[i] != '\t' && command[i] != '\0') {
  72.         progname[i] = command[i];
  73.         i++;
  74.     }
  75.  
  76.     progname[i] = '\0';
  77.  
  78.     while (command[i] == ' ' || command[i] == '\t')
  79.         i++;
  80.     for (j = 0; command[i] != '\0'; )
  81.         args[j++] = command[i++];
  82.     args[j] = '\0';
  83.  
  84. #ifdef DEBUG
  85.     printf ("subp:  progname=[%s], args=[%s].\n", progname, args);
  86. #endif
  87.  
  88.     if (args[0] == '\0')
  89.         status = spawnlp (P_WAIT, progname, progname, NULL);
  90.     else
  91.         status = spawnlp (P_WAIT, progname, progname, args, NULL);
  92.     return (status);
  93. }
  94.  
  95. /*******************/
  96. /* system() executes a system command but, unlike the system() function
  97. in the Microsoft C library, it doesn't choke if the DOS switch character
  98. is not "/".  Return value is -1 on error, 0 otherwise.  
  99.  
  100. Due to serious bugs in MS-DOS, commands executed by COMMAND.COM never
  101. return an error status.  To overcome this problem, this implementation
  102. of system() attempts to execute the supplied command string directly
  103. on the assumption that it holds the name of an executable program
  104. with parameters.  If this attempted execution fails, system() then
  105. invokes the command interpreter.  This way we manage to make executable
  106. programs return an error status anyway.
  107.  
  108. To help allow the user to interrupt command execution, we trap the
  109. user interrupt vector and monitor it.  If a user interrupt occurred
  110. during command execution, we return an error status even if the
  111. command was correctly executed.  This doesn't always work.
  112. */
  113.  
  114. int system(cmd)
  115. char *cmd;
  116. {
  117.     int status;
  118.     char *comspec;
  119.     static char comswitch[] = "/C ";
  120.  
  121.     break_hit = 0;
  122.  
  123.     /* trap user interrupts */
  124.     oldsignal = signal (SIGINT, handle_break);
  125.  
  126.     (void) kbhit();
  127.  
  128.     /* Try direct execution.  If succeded, return its status */
  129.     status = subp (cmd);
  130.     if (status != -1)    {                             /* not -1 means executed */
  131.         goto finish;
  132.     }
  133.  
  134.     /* Reach here if direct execution not possible.  Call shell */
  135.     comspec = getenv ("COMSPEC");
  136.     if (comspec == NULL) {
  137.         signal (SIGINT, oldsignal);            /* restore old signal handler */
  138.         return (-1);
  139.     }
  140.  
  141.     if (cmd == NULL || *cmd == '\0') {
  142.         status = spawnlp (P_WAIT, comspec, comspec, NULL);
  143.         goto finish;
  144.     } else {
  145.         comswitch[0] = dosswitch ('\0');
  146.         status = spawnlp (P_WAIT, comspec, comspec, comswitch, cmd, NULL);
  147.         goto finish;
  148.     }
  149.  
  150. finish:
  151.     (void) kbhit();
  152.     signal (SIGINT, oldsignal);            /* restore old signal handler */
  153.     if (break_hit)
  154.         return (256);
  155.     else
  156.         return (status);
  157. }
  158.  
  159. int handle_break()
  160. {
  161.     oldsignal = signal (SIGINT, handle_break);
  162.     break_hit++;
  163. }
  164.