ftp.nice.ch/pub/next/unix/communication/pcomm.NIHS.bs.tar.gz#/pcomm/Source/expand.c

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

/*
 * Do file name expansion with "native" shell.  Using the native shell
 * (as described in the SHELL environmental variable) allows for csh or
 * ksh abbreviations that sh doesn't recognize.  Returns a pointer to
 * a static area.
 */

#define EXPAND_BUF	2048

#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include "config.h"

char *
expand(input)
char *input;
{
	extern char *null_ptr;
	FILE *pfp, *n_popen();
	int last;
	char buf[1024], *strpbrk(), *strcpy();
	static char ans[EXPAND_BUF];

					/* same rules as str_dup() */
	if (input == NULL)
		return(NULL);
	if (*input == '\0')
		return(null_ptr);
					/* any thing to expand? */
	if (!strpbrk(input, "$*{}[]\\?~")) {
		strcpy(ans, input);
		return(ans);
	}
					/* popen an echo */
	sprintf(buf, "echo %s", input);

	pfp = n_popen(buf, "r");
	fgets(ans, EXPAND_BUF, pfp);
	n_pclose(pfp);

	if (!strlen(ans)) {
		strcpy(ans, input);
		return(ans);
	}
	/*
	 * A horrible kludge...  if the last character is not a line
	 * feed, then the csh has returned an error message.  Otherwise
	 * zap the line feed.
	 */
	last = strlen(ans) -1;
	if (ans[last] != '\n') {
		strcpy(ans, input);
		return(ans);
	}
	else
		ans[last] = '\0';

	return(ans);
}

#define	tst(a,b) (*mode == 'r'? (b) : (a))
#define	RDR	0
#define	WTR	1
static int popen_pid[20];

FILE *
n_popen(cmd, mode)
char *cmd, *mode;
{
	int myside, hisside, ppid, p[2];
	char *shellpath, *shell, *flags, *getenv(), *strrchr();
	void _exit();

	if (pipe(p) < 0)
		return NULL;

	myside = tst(p[WTR], p[RDR]);
	hisside = tst(p[RDR], p[WTR]);
					/* get the environmental variable */
	shellpath = getenv("SHELL");
	if (shellpath == NULL || *shellpath == '\0')
		shellpath = "/bin/sh";

	if (shell = strrchr(shellpath, '/'))
		shell++;
	else {
		shellpath = "/bin/sh";
		shell = "sh";
	}
					/* fix up the flags */
	if (!strcmp(shell, "csh"))
		flags = "-fc";
	else
		flags = "-c";		/* Korn shell too */

	if (!(ppid = fork())) {
		int stdio;
					/* no error messages please */
		close(2);
		open("/dev/null", O_WRONLY);
#ifdef SETUGID
		setgid(getgid());
		setuid(getuid());
#endif /* SETUGID */
		stdio = tst(0, 1);
		close(myside);
		close(stdio);
		fcntl(hisside, F_DUPFD, stdio);
		close(hisside);
		execl(shellpath, shell, flags, cmd, (char *) 0);
		_exit(1);
	}
	if (ppid == -1) {
		close(myside);
		close(hisside);
		return NULL;
	}

	popen_pid[myside] = ppid;

	close(hisside);
	return(fdopen(myside, mode));
}

n_pclose(ptr)
FILE *ptr;
{
	SIG_TYPE (*hstat)(), (*istat)(), (*qstat)();
	int f, r, sig_status;

	f = fileno(ptr);
	fclose(ptr);
	istat = signal(SIGINT, SIG_IGN);
	qstat = signal(SIGQUIT, SIG_IGN);
	hstat = signal(SIGHUP, SIG_IGN);

	while ((r = wait(&sig_status)) != popen_pid[f] && r != -1)
		;

	if (r == -1)
		sig_status = -1;

	signal(SIGINT, istat);
	signal(SIGQUIT, qstat);
	signal(SIGHUP, hstat);
	return(sig_status);
}

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