home *** CD-ROM | disk | FTP | other *** search
- /* msdos.c */
- /*
- Microsoft C-dependent functions for Make. Originally written by Rahul
- Dhesi for Atoz in 1986. Modified for use with the P.D. make utility
- in February 1987. Released to the public domain.
- */
-
- #include <signal.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h> /* function definitions: getenv() and others */
- #include "intdos.h" /* registers for MS-DOS interrupts */
- #include <process.h> /* function definitions: spawn()/exec()/system() */
-
- int break_hit; /* flag set on user interrupt */
- int handle_break(); /* routine to set flag on user interrupt */
- int (*oldsignal)(); /* to save old signal() handler */
-
- /*******************/
- /*
- dosswitch() accepts a character specifying a switch character. If
- the character is null, dosswitch() simply returns the current DOS
- switch character. If it is not null, the DOS switch character is set
- to the received character and the newly-set character returned by DOS
- is returned as the function value.
- */
-
- unsigned int dosswitch (switchar)
- int switchar;
- {
- union REGS regs;
- if (switchar == '\0')
- regs.h.al = 0; /* get switch character code */
- else {
- regs.h.al = 1; /* set switch character code */
- regs.h.dl = switchar; /* char to set switch to */
- }
- regs.h.ah = 0x37; /* get or set switch DOS call */
- intdos (®s, ®s);
- return ((unsigned int) regs.h.dl); /* return current switch char */
- }
-
- /*******************/
- /*
- subp() executes a subprocess then returns. It breaks up the received
- command line into a command name (first word) and a parameter list
- (rest of string) before executing the subprocess. The environment
- of the subprocess is a copy of the parent's environment. Return
- value is -1 if the subprocess could not be created, otherwise it is
- the exit status of the subprocess. The command interpreter is NOT
- executed, so DOS commands such as DIR canot be directly used here.
- */
-
- int subp (command)
- char *command;
- {
- int status;
- char progname[80];
- char args[128];
- int i, j;
-
- progname[0] = '\0';
- args[0] = '\0';
-
- /* skip leading white space */
- i = 0;
- while (command[i] == ' ' || command[i] == '\t')
- i++;
-
- /* progname gets program name, args gets rest of command string */
- while (command[i] != ' '&& command[i] != '\t' && command[i] != '\0') {
- progname[i] = command[i];
- i++;
- }
-
- progname[i] = '\0';
-
- while (command[i] == ' ' || command[i] == '\t')
- i++;
- for (j = 0; command[i] != '\0'; )
- args[j++] = command[i++];
- args[j] = '\0';
-
- #ifdef DEBUG
- printf ("subp: progname=[%s], args=[%s].\n", progname, args);
- #endif
-
- if (args[0] == '\0')
- status = spawnlp (P_WAIT, progname, progname, NULL);
- else
- status = spawnlp (P_WAIT, progname, progname, args, NULL);
- return (status);
- }
-
- /*******************/
- /* system() executes a system command but, unlike the system() function
- in the Microsoft C library, it doesn't choke if the DOS switch character
- is not "/". Return value is -1 on error, 0 otherwise.
-
- Due to serious bugs in MS-DOS, commands executed by COMMAND.COM never
- return an error status. To overcome this problem, this implementation
- of system() attempts to execute the supplied command string directly
- on the assumption that it holds the name of an executable program
- with parameters. If this attempted execution fails, system() then
- invokes the command interpreter. This way we manage to make executable
- programs return an error status anyway.
-
- To help allow the user to interrupt command execution, we trap the
- user interrupt vector and monitor it. If a user interrupt occurred
- during command execution, we return an error status even if the
- command was correctly executed. This doesn't always work.
- */
-
- int system(cmd)
- char *cmd;
- {
- int status;
- char *comspec;
- static char comswitch[] = "/C ";
-
- break_hit = 0;
-
- /* trap user interrupts */
- oldsignal = signal (SIGINT, handle_break);
-
- (void) kbhit();
-
- /* Try direct execution. If succeded, return its status */
- status = subp (cmd);
- if (status != -1) { /* not -1 means executed */
- goto finish;
- }
-
- /* Reach here if direct execution not possible. Call shell */
- comspec = getenv ("COMSPEC");
- if (comspec == NULL) {
- signal (SIGINT, oldsignal); /* restore old signal handler */
- return (-1);
- }
-
- if (cmd == NULL || *cmd == '\0') {
- status = spawnlp (P_WAIT, comspec, comspec, NULL);
- goto finish;
- } else {
- comswitch[0] = dosswitch ('\0');
- status = spawnlp (P_WAIT, comspec, comspec, comswitch, cmd, NULL);
- goto finish;
- }
-
- finish:
- (void) kbhit();
- signal (SIGINT, oldsignal); /* restore old signal handler */
- if (break_hit)
- return (256);
- else
- return (status);
- }
-
- int handle_break()
- {
- oldsignal = signal (SIGINT, handle_break);
- break_hit++;
- }
-