ftp.nice.ch/pub/next/unix/editor/elvis-2.0.N.bs.tar.gz#/elvis-2.0.N.bs/osmsdos/osprg.c

This is osprg.c in view mode; [Download] [Up]

/* osmsdos/osprg.c */

#include "elvis.h"
#include <sys/types.h>
#include <dos.h>
#include <fcntl.h>
#include <io.h>

/* Microsoft has an annoying habit of adding underscores to the front of
 * conventional names.
 */
#ifndef O_WRONLY
# define O_WRONLY	_O_WRONLY
# define O_RDONLY	_O_RDONLY
# define O_RDWR		_O_RDWR
# define O_CREAT	_O_CREAT
# define O_EXCL		_O_EXCL
# define O_TRUNC	_O_TRUNC
#endif

static char	*cmd;		/* the command to run */
static char	tempread[100];	/* name of temp file for prog's stdout */
static char	tempwrite[100];	/* name of temp file for prog's stdout */
static int	fd;		/* file descriptor for reading or writing */
static int	status;		/* exit status of the program */

/* Declares which program we'll run, and what we'll be doing with it.
 * This function should return True if successful.  If there is an error,
 * it should issue an error message via msg(), and return False.
 */
BOOLEAN prgopen(char *command, BOOLEAN willwrite, BOOLEAN willread)
{
	/* remember the command we're supposed to run */
	cmd = command;

	/* if we're going to be reading, then choose a tempread name now */
	if (willread)
	{
		strcpy(tempread, o_directory ? dirpath(tochar8(o_directory), "rdXXXXXX") : "rdXXXXXX");
		mktemp(tempread);

		/* open it and close it, just to make sure it exists */
		fd = open(tempread, O_WRONLY|O_CREAT|O_EXCL, 0600);
		if (fd < 0)
		{
			msg(MSG_ERROR, "[s]can't create temp file $1", tempread);
			return False;
		}
		close(fd);
	}
	else
		tempread[0] = '\0';

	/* if we'll be writing, then choose a tempwrite name and open it */
	if (willwrite)
	{
		strcpy(tempwrite, o_directory ? dirpath(tochar8(o_directory), "wrXXXXXX") : "wrXXXXXX");
		mktemp(tempwrite);
		fd = open(tempwrite, O_WRONLY|O_CREAT|O_EXCL, 0600);
		if (fd < 0)
		{
			msg(MSG_ERROR, "[s]can't create temp file $1", tempwrite);
			if (tempread[0])
				remove(tempread);
			return False;
		}
	}
	else
		tempwrite[0] = '\0';

	return True;
}

/* Write the contents of buf to the program's stdin, and return nbytes
 * if successful, or -1 for error.  Note that this text should
 * be subjected to the same kind of transformations as textwrite().
 * In fact, it may use textwrite() internally.
 *
 * For DOS, this is simply a write() to the temp file.
 */
int prgwrite(CHAR *buf, int nbytes)
{
	return write(fd, buf, nbytes);
}

/* Marks the end of writing.  Returns True if all is okay, or False if
 * error.
 */
BOOLEAN prggo(void)
{
	int	old0;	/* elvis' stdin */
	int	old1;	/* elvis' stdout */
	int	old2;	/* elvis' stderr */
	CHAR	*arg[3];/* arguments when evaluating command string */

	/* are we supposed to redirect stdin? */
	if (tempwrite[0])
	{
		/* close the file we've been writing to */
		close(fd);

		/* save the old stdin as another fd so we can switch back later */
		old0 = dup(0);
		assert(old0 > 2);

		/* open the temp file as stdin */
		close(0);
#ifdef NDEBUG
		(void)open(tempwrite, O_RDONLY);
#else
		assert(open(tempwrite, O_RDONLY) == 0);
#endif
	}

	/* are we supposed to redirect stdout/stderr ? */
	if (tempread[0])
	{
		/* save the old stdout and stderr as other fds */
		old1 = dup(1);
		old2 = dup(2);
		assert(old1 > 2 && old2 > 2);

		/* open the temp file as stdout/stderr */
		close(1);
		close(2);
#ifdef NDEBUG
		(void)open(tempread, O_WRONLY);
		dup(1);
#else
		assert(open(tempread, O_WRONLY) == 1);
		assert(dup(1) == 2);
#endif
	}

#if 0
	/* if redirecting anything, then evaluate the command string like a
	 * message, substituting the input and/or output files for $1 and $2
	 */
	if ((tempwrite[0] || tempread[0]) && CHARchr(cmd, '$'))
	{
		arg[0] = toCHAR(tempwrite);
		arg[1] = toCHAR(tempread);
		arg[2] = NULL;
		cmd = tochar8(calculate(toCHAR(cmd), arg, True));
		if (!cmd)
		{
			if (tempwrite[0])
				remove(tempwrite);
			if (tempread[0])
				remove(tempread);
			return False;
		}
	}
#endif

	/* run the program */
	status = system(cmd);

	/* if we redirected stdin, undo it now */
	if (tempwrite[0])
	{
		/* undo the redirection */
		close(0);
#ifdef NDEBUG
		(void)dup(old0);
#else
		assert(dup(old0) == 0);
#endif
		close(old0);

		/* delete the temp file */
		remove(tempwrite);
	}

	/* if we redirected stdout/stderr, undo it now and open the temp file */
	if (tempread[0])
	{
		/* undo the redirection */
		close(1);
		close(2);
#ifdef NDEBUG
		(void)dup(old1);
		(void)dup(old2);
#else
		assert(dup(old1) == 1);
		assert(dup(old2) == 2);
#endif
		close(old1);
		close(old2);

		/* open the temp file */
		fd = open(tempread, O_RDONLY);
		assert(fd > 0);
	}

	return True;
}


/* Reads text from the program's stdout, and returns the number of
 * characters read.  At EOF, it returns 0.  Note that this text
 * should be subjected to the same kinds of transformations as
 * textread().
 */
int prgread(CHAR *buf, int nbytes)
{
	return read(fd, buf, nbytes);
}

/* Clean up, and return the program's exit status.  The exit status
 * should be 0 normally.
 */
int prgclose(void)
{
	/* if we were reading stdout, then close & delete that temp file */
	if (tempread[0])
	{
		close(fd);
		remove(tempread);
	}

	/* return the program's exit status */
	return status;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.