xref: /openbsd-src/gnu/usr.bin/cvs/os2/run.c (revision 2286d8ed900f26153a3cd5227a124b1c0adce72f)
113571821Stholo /* run.c --- routines for executing subprocesses under OS/2.
213571821Stholo 
313571821Stholo    This file is part of GNU CVS.
413571821Stholo 
513571821Stholo    GNU CVS is free software; you can redistribute it and/or modify it
613571821Stholo    under the terms of the GNU General Public License as published by the
713571821Stholo    Free Software Foundation; either version 2, or (at your option) any
813571821Stholo    later version.
913571821Stholo 
1013571821Stholo    This program is distributed in the hope that it will be useful,
1113571821Stholo    but WITHOUT ANY WARRANTY; without even the implied warranty of
1213571821Stholo    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13461cc63eStholo    GNU General Public License for more details.  */
1413571821Stholo 
1513571821Stholo #include "cvs.h"
1613571821Stholo 
17461cc63eStholo #include "os2inc.h"
18461cc63eStholo 
1913571821Stholo #include <process.h>
2013571821Stholo 
2113571821Stholo #include <stdio.h>
2213571821Stholo #include <stdlib.h>
2313571821Stholo #include <sys/types.h>
2413571821Stholo #include <sys/stat.h>
2513571821Stholo #include <string.h>
2613571821Stholo #include <fcntl.h>
2713571821Stholo #include <errno.h>
2813571821Stholo #include <io.h>
2913571821Stholo 
3013571821Stholo #define STDIN       0
3113571821Stholo #define STDOUT      1
3213571821Stholo #define STDERR      2
3313571821Stholo 
3413571821Stholo static void run_add_arg PROTO((const char *s));
3513571821Stholo static void run_init_prog PROTO((void));
3613571821Stholo 
3713571821Stholo extern char *strtok ();
3813571821Stholo 
3913571821Stholo /*
4013571821Stholo  * To exec a program under CVS, first call run_setup() to setup any initial
4113571821Stholo  * arguments.  The options to run_setup are essentially like printf(). The
4213571821Stholo  * arguments will be parsed into whitespace separated words and added to the
4313571821Stholo  * global run_argv list.
4413571821Stholo  *
4513571821Stholo  * Then, optionally call run_arg() for each additional argument that you'd like
4613571821Stholo  * to pass to the executed program.
4713571821Stholo  *
4813571821Stholo  * Finally, call run_exec() to execute the program with the specified
4913571821Stholo  * arguments.
5013571821Stholo  * The execvp() syscall will be used, so that the PATH is searched correctly.
5113571821Stholo  * File redirections can be performed in the call to run_exec().
5213571821Stholo  */
5313571821Stholo static char **run_argv;
5413571821Stholo static int run_argc;
5513571821Stholo static int run_argc_allocated;
5613571821Stholo 
5713571821Stholo void
run_setup(const char * prog)58*2286d8edStholo run_setup (const char *prog)
5913571821Stholo {
6013571821Stholo     char *cp;
6113571821Stholo     int i;
6213571821Stholo 
63*2286d8edStholo     char *run_prog;
6413571821Stholo 
6513571821Stholo     /* clean out any malloc'ed values from run_argv */
6613571821Stholo     for (i = 0; i < run_argc; i++)
6713571821Stholo     {
6813571821Stholo 	if (run_argv[i])
6913571821Stholo 	{
7013571821Stholo 	    free (run_argv[i]);
7113571821Stholo 	    run_argv[i] = (char *) 0;
7213571821Stholo 	}
7313571821Stholo     }
7413571821Stholo     run_argc = 0;
7513571821Stholo 
76*2286d8edStholo     run_prog = xstrdup (prog);
7713571821Stholo 
7813571821Stholo     /* put each word into run_argv, allocating it as we go */
7913571821Stholo     for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t"))
8013571821Stholo 	run_add_arg (cp);
81*2286d8edStholo 
82*2286d8edStholo     free (run_prog)
8313571821Stholo }
8413571821Stholo 
8513571821Stholo void
run_arg(s)8613571821Stholo run_arg (s)
8713571821Stholo     const char *s;
8813571821Stholo {
8913571821Stholo     run_add_arg (s);
9013571821Stholo }
9113571821Stholo 
9213571821Stholo /* Return a malloc'd copy of s, with double quotes around it.  */
9313571821Stholo static char *
quote(const char * s)9413571821Stholo quote (const char *s)
9513571821Stholo {
9613571821Stholo     size_t s_len = strlen (s);
9713571821Stholo     char *copy = xmalloc (s_len + 3);
9813571821Stholo     char *scan = copy;
9913571821Stholo 
10013571821Stholo     *scan++ = '"';
10113571821Stholo     strcpy (scan, s);
10213571821Stholo     scan += s_len;
10313571821Stholo     *scan++ = '"';
10413571821Stholo     *scan++ = '\0';
10513571821Stholo 
10613571821Stholo     return copy;
10713571821Stholo }
10813571821Stholo 
10913571821Stholo static void
run_add_arg(s)11013571821Stholo run_add_arg (s)
11113571821Stholo     const char *s;
11213571821Stholo {
11313571821Stholo     /* allocate more argv entries if we've run out */
11413571821Stholo     if (run_argc >= run_argc_allocated)
11513571821Stholo     {
11613571821Stholo 	run_argc_allocated += 50;
11713571821Stholo 	run_argv = (char **) xrealloc ((char *) run_argv,
11813571821Stholo 				     run_argc_allocated * sizeof (char **));
11913571821Stholo     }
12013571821Stholo 
12113571821Stholo     if (s)
12213571821Stholo     {
12313571821Stholo 	run_argv[run_argc] = (run_argc ? quote (s) : xstrdup (s));
12413571821Stholo 	run_argc++;
12513571821Stholo     }
12613571821Stholo     else
12713571821Stholo         /* not post-incremented on purpose! */
12813571821Stholo 	run_argv[run_argc] = (char *) 0;
12913571821Stholo }
13013571821Stholo 
13113571821Stholo int
run_exec(stin,stout,sterr,flags)13213571821Stholo run_exec (stin, stout, sterr, flags)
13313571821Stholo     char *stin;
13413571821Stholo     char *stout;
13513571821Stholo     char *sterr;
13613571821Stholo     int flags;
13713571821Stholo {
13813571821Stholo     int shin, shout, sherr;
13913571821Stholo     int sain, saout, saerr;	/* saved handles */
14013571821Stholo     int mode_out, mode_err;
14113571821Stholo     int status = -1;
14213571821Stholo     int rerrno = 0;
14313571821Stholo     int rval   = -1;
14413571821Stholo     void (*old_sigint) (int);
14513571821Stholo 
14613571821Stholo     if (trace)			/* if in trace mode */
14713571821Stholo     {
14813571821Stholo 	(void) fprintf (stderr, "-> system(");
14913571821Stholo 	run_print (stderr);
15013571821Stholo 	(void) fprintf (stderr, ")\n");
15113571821Stholo     }
15213571821Stholo     if (noexec && (flags & RUN_REALLY) == 0) /* if in noexec mode */
15313571821Stholo 	return (0);
15413571821Stholo 
15513571821Stholo     /*
15613571821Stholo      * start the engine and take off
15713571821Stholo      */
15813571821Stholo 
15913571821Stholo     /* make sure that we are null terminated, since we didn't calloc */
16013571821Stholo     run_add_arg ((char *) 0);
16113571821Stholo 
16213571821Stholo     /* setup default file descriptor numbers */
16313571821Stholo     shin = 0;
16413571821Stholo     shout = 1;
16513571821Stholo     sherr = 2;
16613571821Stholo 
16713571821Stholo     /* set the file modes for stdout and stderr */
16813571821Stholo     mode_out = mode_err = O_WRONLY | O_CREAT;
16913571821Stholo     mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC);
17013571821Stholo     mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC);
17113571821Stholo 
17213571821Stholo     /* open the files as required, shXX are shadows of stdin... */
17313571821Stholo     if (stin && (shin = open (stin, O_RDONLY)) == -1)
17413571821Stholo     {
17513571821Stholo 	rerrno = errno;
17613571821Stholo 	error (0, errno, "cannot open %s for reading (prog %s)",
17713571821Stholo 	       stin, run_argv[0]);
17813571821Stholo 	goto out0;
17913571821Stholo     }
18013571821Stholo     if (stout && (shout = open (stout, mode_out, 0666)) == -1)
18113571821Stholo     {
18213571821Stholo 	rerrno = errno;
18313571821Stholo 	error (0, errno, "cannot open %s for writing (prog %s)",
18413571821Stholo 	       stout, run_argv[0]);
18513571821Stholo 	goto out1;
18613571821Stholo     }
18713571821Stholo     if (sterr && (flags & RUN_COMBINED) == 0)
18813571821Stholo     {
18913571821Stholo 	if ((sherr = open (sterr, mode_err, 0666)) == -1)
19013571821Stholo 	{
19113571821Stholo 	    rerrno = errno;
19213571821Stholo 	    error (0, errno, "cannot open %s for writing (prog %s)",
19313571821Stholo 		   sterr, run_argv[0]);
19413571821Stholo 	    goto out2;
19513571821Stholo 	}
19613571821Stholo     }
19713571821Stholo     /* now save the standard handles */
19813571821Stholo     sain = saout = saerr = -1;
19913571821Stholo     sain  = dup( 0); /* dup stdin  */
20013571821Stholo     saout = dup( 1); /* dup stdout */
20113571821Stholo     saerr = dup( 2); /* dup stderr */
20213571821Stholo 
20313571821Stholo     /* the new handles will be dup'd to the standard handles
20413571821Stholo      * for the spawn.
20513571821Stholo      */
20613571821Stholo 
20713571821Stholo     if (shin != 0)
20813571821Stholo       {
20913571821Stholo 	(void) dup2 (shin, 0);
21013571821Stholo 	(void) close (shin);
21113571821Stholo       }
21213571821Stholo     if (shout != 1)
21313571821Stholo       {
21413571821Stholo 	(void) dup2 (shout, 1);
21513571821Stholo 	(void) close (shout);
21613571821Stholo       }
21713571821Stholo     if (flags & RUN_COMBINED)
21813571821Stholo       (void) dup2 (1, 2);
21913571821Stholo     else if (sherr != 2)
22013571821Stholo       {
22113571821Stholo 	(void) dup2 (sherr, 2);
22213571821Stholo 	(void) close (sherr);
22313571821Stholo       }
22413571821Stholo 
22513571821Stholo     /* Ignore signals while we're running this.  */
22613571821Stholo     old_sigint = signal (SIGINT, SIG_IGN);
22713571821Stholo 
22813571821Stholo     /* dup'ing is done.  try to run it now */
22913571821Stholo     rval = spawnvp ( P_WAIT, run_argv[0], run_argv);
23013571821Stholo 
23113571821Stholo     /* Restore signal handling.  */
23213571821Stholo     signal (SIGINT, old_sigint);
23313571821Stholo 
23413571821Stholo     /* restore the original file handles   */
23513571821Stholo     if (sain  != -1) {
23613571821Stholo       (void) dup2( sain, 0);	/* re-connect stdin  */
23713571821Stholo       (void) close( sain);
23813571821Stholo     }
23913571821Stholo     if (saout != -1) {
24013571821Stholo       (void) dup2( saout, 1);	/* re-connect stdout */
24113571821Stholo       (void) close( saout);
24213571821Stholo     }
24313571821Stholo     if (saerr != -1) {
24413571821Stholo       (void) dup2( saerr, 2);	/* re-connect stderr */
24513571821Stholo       (void) close( saerr);
24613571821Stholo     }
24713571821Stholo 
24813571821Stholo     /* Recognize the return code for a failed subprocess.  */
24913571821Stholo     if (rval == -1)
25013571821Stholo         return 2;
25113571821Stholo     else
25213571821Stholo         return rval;		/* return child's exit status */
25313571821Stholo 
25413571821Stholo     /* error cases */
25513571821Stholo     /* cleanup the open file descriptors */
25613571821Stholo   out2:
25713571821Stholo     if (stout)
25813571821Stholo 	(void) close (shout);
25913571821Stholo   out1:
26013571821Stholo     if (stin)
26113571821Stholo 	(void) close (shin);
26213571821Stholo 
26313571821Stholo   out0:
26413571821Stholo     if (rerrno)
26513571821Stholo 	errno = rerrno;
26613571821Stholo     return (status);
26713571821Stholo }
26813571821Stholo 
26913571821Stholo 
27013571821Stholo void
run_print(fp)27113571821Stholo run_print (fp)
27213571821Stholo     FILE *fp;
27313571821Stholo {
27413571821Stholo     int i;
27513571821Stholo 
27613571821Stholo     for (i = 0; i < run_argc; i++)
27713571821Stholo     {
27813571821Stholo 	(void) fprintf (fp, "'%s'", run_argv[i]);
27913571821Stholo 	if (i != run_argc - 1)
28013571821Stholo 	    (void) fprintf (fp, " ");
28113571821Stholo     }
28213571821Stholo }
28313571821Stholo 
28413571821Stholo static char *
requote(const char * cmd)28513571821Stholo requote (const char *cmd)
28613571821Stholo {
28713571821Stholo     char *requoted = xmalloc (strlen (cmd) + 1);
28813571821Stholo     char *p = requoted;
28913571821Stholo 
29013571821Stholo     strcpy (requoted, cmd);
29113571821Stholo     while ((p = strchr (p, '\'')) != NULL)
29213571821Stholo     {
29313571821Stholo         *p++ = '"';
29413571821Stholo     }
29513571821Stholo 
29613571821Stholo     return requoted;
29713571821Stholo }
29813571821Stholo 
29913571821Stholo FILE *
run_popen(cmd,mode)300c26070a5Stholo run_popen (cmd, mode)
30113571821Stholo     const char *cmd;
30213571821Stholo     const char *mode;
30313571821Stholo {
30413571821Stholo     if (trace)
30513571821Stholo #ifdef SERVER_SUPPORT
306c26070a5Stholo 	(void) fprintf (stderr, "%c-> run_popen(%s,%s)\n",
30713571821Stholo 			(server_active) ? 'S' : ' ', cmd, mode);
30813571821Stholo #else
309c26070a5Stholo 	(void) fprintf (stderr, "-> run_popen(%s,%s)\n", cmd, mode);
31013571821Stholo #endif
31113571821Stholo 
31213571821Stholo     if (noexec)
31313571821Stholo 	return (NULL);
31413571821Stholo 
31513571821Stholo     /* If the command string uses single quotes, turn them into
31613571821Stholo        double quotes.  */
31713571821Stholo     {
31813571821Stholo         char *requoted = requote (cmd);
31913571821Stholo 	FILE *result = popen (requoted, mode);
32013571821Stholo 	free (requoted);
32113571821Stholo 	return result;
32213571821Stholo     }
32313571821Stholo }
32413571821Stholo 
32513571821Stholo 
32613571821Stholo /* Running children with pipes connected to them.  */
32713571821Stholo 
32813571821Stholo /* Create a pipe.  Set READWRITE[0] to its reading end, and
32913571821Stholo    READWRITE[1] to its writing end.  */
33013571821Stholo 
33113571821Stholo static int
my_pipe(int * readwrite)33213571821Stholo my_pipe (int *readwrite)
33313571821Stholo {
33413571821Stholo     fprintf (stderr,
33513571821Stholo              "Error: my_pipe() is unimplemented.\n");
33613571821Stholo     exit (1);
33713571821Stholo }
33813571821Stholo 
33913571821Stholo 
34013571821Stholo /* Create a child process running COMMAND with IN as its standard input,
34113571821Stholo    and OUT as its standard output.  Return a handle to the child, or
34213571821Stholo    INVALID_HANDLE_VALUE.  */
34313571821Stholo static int
start_child(char * command,int in,int out)34413571821Stholo start_child (char *command, int in, int out)
34513571821Stholo {
34613571821Stholo     fprintf (stderr,
34713571821Stholo              "Error: start_child() is unimplemented.\n");
34813571821Stholo     exit (1);
34913571821Stholo }
35013571821Stholo 
35113571821Stholo 
35213571821Stholo /* Given an array of arguments that one might pass to spawnv,
35313571821Stholo    construct a command line that one might pass to CreateProcess.
35413571821Stholo    Try to quote things appropriately.  */
35513571821Stholo static char *
build_command(char ** argv)35613571821Stholo build_command (char **argv)
35713571821Stholo {
35813571821Stholo     int len;
35913571821Stholo 
36013571821Stholo     /* Compute the total length the command will have.  */
36113571821Stholo     {
36213571821Stholo         int i;
36313571821Stholo 
36413571821Stholo 	len = 0;
36513571821Stholo         for (i = 0; argv[i]; i++)
36613571821Stholo 	{
36713571821Stholo 	    char *p;
36813571821Stholo 
36913571821Stholo 	    len += 2;  /* for the double quotes */
37013571821Stholo 
37113571821Stholo 	    for (p = argv[i]; *p; p++)
37213571821Stholo 	    {
37313571821Stholo 	        if (*p == '"')
37413571821Stholo 		    len += 2;
37513571821Stholo 		else
37613571821Stholo 		    len++;
37713571821Stholo 	    }
37813571821Stholo 	}
37913571821Stholo         len++;  /* for the space or the '\0'  */
38013571821Stholo     }
38113571821Stholo 
38213571821Stholo     {
38313571821Stholo         char *command = (char *) malloc (len);
38413571821Stholo 	int i;
38513571821Stholo 	char *p;
38613571821Stholo 
38713571821Stholo 	if (! command)
38813571821Stholo 	{
38913571821Stholo 	    errno = ENOMEM;
39013571821Stholo 	    return command;
39113571821Stholo 	}
39213571821Stholo 
39313571821Stholo 	p = command;
39413571821Stholo 	/* copy each element of argv to command, putting each command
39513571821Stholo 	   in double quotes, and backslashing any quotes that appear
39613571821Stholo 	   within an argument.  */
39713571821Stholo 	for (i = 0; argv[i]; i++)
39813571821Stholo 	{
39913571821Stholo 	    char *a;
40013571821Stholo 	    *p++ = '"';
40113571821Stholo 	    for (a = argv[i]; *a; a++)
40213571821Stholo 	    {
40313571821Stholo 	        if (*a == '"')
40413571821Stholo 		    *p++ = '\\', *p++ = '"';
40513571821Stholo 		else
40613571821Stholo 		    *p++ = *a;
40713571821Stholo 	    }
40813571821Stholo 	    *p++ = '"';
40913571821Stholo 	    *p++ = ' ';
41013571821Stholo 	}
41113571821Stholo 	p[-1] = '\0';
41213571821Stholo 
41313571821Stholo         return command;
41413571821Stholo     }
41513571821Stholo }
41613571821Stholo 
41713571821Stholo 
41813571821Stholo /* Create an asynchronous child process executing ARGV,
41913571821Stholo    with its standard input and output connected to the
42013571821Stholo    parent with pipes.  Set *TO to the file descriptor on
42113571821Stholo    which one writes data for the child; set *FROM to
42213571821Stholo    the file descriptor from which one reads data from the child.
42313571821Stholo    Return the handle of the child process (this is what
42413571821Stholo    _cwait and waitpid expect).  */
42513571821Stholo int
piped_child(char ** argv,int * to,int * from)42613571821Stholo piped_child (char **argv, int *to, int *from)
42713571821Stholo {
42813571821Stholo     fprintf (stderr,
42913571821Stholo              "Error: piped_child() is unimplemented.\n");
43013571821Stholo     exit (1);
43113571821Stholo }
43213571821Stholo 
43313571821Stholo /*
43413571821Stholo  * dir = 0 : main proc writes to new proc, which writes to oldfd
43513571821Stholo  * dir = 1 : main proc reads from new proc, which reads from oldfd
43613571821Stholo  *
43713571821Stholo  * If this returns at all, then it was successful and the return value
43813571821Stholo  * is a file descriptor; else it errors and exits.
43913571821Stholo  */
44013571821Stholo int
filter_stream_through_program(int oldfd,int dir,char ** prog,int * pidp)44113571821Stholo filter_stream_through_program (int oldfd, int dir,
44213571821Stholo 			   char **prog, int *pidp)
44313571821Stholo {
44413571821Stholo 	int newfd;  /* Gets set to one end of the pipe and returned. */
44513571821Stholo     HFILE from, to;
44613571821Stholo 	HFILE Old0 = -1, Old1 = -1, Old2 = -1, Tmp;
44713571821Stholo 
44813571821Stholo     if (DosCreatePipe (&from, &to, 4096))
44913571821Stholo         return FALSE;
45013571821Stholo 
45113571821Stholo     /* Save std{in,out,err} */
45213571821Stholo     DosDupHandle (STDIN, &Old0);
45313571821Stholo     DosSetFHState (Old1, OPEN_FLAGS_NOINHERIT);
45413571821Stholo     DosDupHandle (STDOUT, &Old1);
45513571821Stholo     DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
45613571821Stholo     DosDupHandle (STDERR, &Old2);
45713571821Stholo     DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
45813571821Stholo 
45913571821Stholo     /* Redirect std{in,out,err} */
46013571821Stholo 	if (dir)    /* Who goes where? */
46113571821Stholo 	{
46213571821Stholo 		Tmp = STDIN;
46313571821Stholo 		DosDupHandle (oldfd, &Tmp);
46413571821Stholo 		Tmp = STDOUT;
46513571821Stholo 		DosDupHandle (to, &Tmp);
46613571821Stholo 		Tmp = STDERR;
46713571821Stholo 		DosDupHandle (to, &Tmp);
46813571821Stholo 
46913571821Stholo 		newfd = from;
47013571821Stholo 		_setmode (newfd, O_BINARY);
47113571821Stholo 
47213571821Stholo 		DosClose (oldfd);
47313571821Stholo 		DosClose (to);
47413571821Stholo 		DosSetFHState (from, OPEN_FLAGS_NOINHERIT);
47513571821Stholo 	}
47613571821Stholo 	else
47713571821Stholo 	{
47813571821Stholo 		Tmp = STDIN;
47913571821Stholo 		DosDupHandle (from, &Tmp);
48013571821Stholo 		Tmp = STDOUT;
48113571821Stholo 		DosDupHandle (oldfd, &Tmp);
48213571821Stholo 		Tmp = STDERR;
48313571821Stholo 		DosDupHandle (oldfd, &Tmp);
48413571821Stholo 
48513571821Stholo 		newfd = to;
48613571821Stholo 		_setmode (newfd, O_BINARY);
48713571821Stholo 
48813571821Stholo 		DosClose (oldfd);
48913571821Stholo 		DosClose (from);
49013571821Stholo 		DosSetFHState (to, OPEN_FLAGS_NOINHERIT);
49113571821Stholo 	}
49213571821Stholo 
49313571821Stholo     /* Spawn we now our hoary brood. */
49413571821Stholo 	*pidp = spawnvp (P_NOWAIT, prog[0], prog);
49513571821Stholo 
49613571821Stholo     /* Restore std{in,out,err} */
49713571821Stholo     Tmp = STDIN;
49813571821Stholo     DosDupHandle (Old0, &Tmp);
49913571821Stholo     DosClose (Old0);
50013571821Stholo     Tmp = STDOUT;
50113571821Stholo     DosDupHandle (Old1, &Tmp);
50213571821Stholo     DosClose (Old1);
50313571821Stholo     Tmp = STDERR;
50413571821Stholo     DosDupHandle (Old2, &Tmp);
50513571821Stholo     DosClose (Old2);
50613571821Stholo 
50713571821Stholo     if(*pidp < 0)
50813571821Stholo     {
50913571821Stholo         DosClose (from);
51013571821Stholo         DosClose (to);
51113571821Stholo         error (1, 0, "error spawning %s", prog[0]);
51213571821Stholo     }
51313571821Stholo 
51413571821Stholo     return newfd;
51513571821Stholo }
51613571821Stholo 
51713571821Stholo 
51813571821Stholo int
pipe(int * filedesc)51913571821Stholo pipe (int *filedesc)
52013571821Stholo {
52113571821Stholo   /* todo: actually, we can use DosCreatePipe().  Fix this. */
52213571821Stholo   fprintf (stderr,
52313571821Stholo            "Error: pipe() should not have been called in client.\n");
52413571821Stholo   exit (1);
52513571821Stholo }
52613571821Stholo 
52713571821Stholo 
52813571821Stholo void
close_on_exec(int fd)52913571821Stholo close_on_exec (int fd)
53013571821Stholo {
53113571821Stholo   /* Just does nothing for now... */
53213571821Stholo 
53313571821Stholo   /* Actually, we probably *can* implement this one.  Let's see... */
53413571821Stholo   /* Nope.  OS/2 has <fcntl.h>, but no fcntl() !  Wow. */
53513571821Stholo   /* Well, I'll leave this stuff in for future reference. */
53613571821Stholo }
53713571821Stholo 
53813571821Stholo 
53913571821Stholo /* Actually, we #define sleep() in config.h now. */
54013571821Stholo #ifndef sleep
54113571821Stholo unsigned int
sleep(unsigned int seconds)54213571821Stholo sleep (unsigned int seconds)
54313571821Stholo {
54413571821Stholo   /* I don't want to interfere with alarm signals, so I'm going to do
54513571821Stholo      this the nasty way. */
54613571821Stholo 
54713571821Stholo   time_t base;
54813571821Stholo   time_t tick;
54913571821Stholo   int i;
55013571821Stholo 
55113571821Stholo   /* Init. */
55213571821Stholo   time (&base);
55313571821Stholo   time (&tick);
55413571821Stholo 
55513571821Stholo   /* Loop until time has passed. */
55613571821Stholo   while (difftime (tick, base) < seconds)
55713571821Stholo     {
55813571821Stholo       /* This might be more civilized than calling time over and over
55913571821Stholo          again. */
56013571821Stholo       for (i = 0; i < 10000; i++)
56113571821Stholo         ;
56213571821Stholo       time (&tick);
56313571821Stholo     }
56413571821Stholo 
56513571821Stholo   return 0;
56613571821Stholo }
56713571821Stholo #endif /* sleep */
568