ftp.nice.ch/pub/next/tools/frontends/SystemWorks.1.1.N.bs.tar.gz#/SystemWorks-1.1/support.c

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

#import <objc/Object.h>
#import <string.h>
#import <fcntl.h>
#import <stdio.h>
#import <ctype.h>
#import <signal.h>
#import <errno.h>
#import <sys/wait.h>
#import <appkit/nextstd.h>
#import <appkit/defaults.h>
#import <appkit/Application.h>

static id		target;

void
processTerminated()
{
	id	(*notify)();
	int	pid;
	union wait status;

	notify = [target methodFor: @selector(processTerminated:status:)];
	pid = wait3(&status, (WNOHANG | WUNTRACED), NULL);
	(*notify)(target, @selector(processTerminated:status:), pid, &status);
}

void
backgroundRead()
{
	id	(*notify)();
	int	pid;
	union wait status;

	notify = [target methodFor: @selector(backgroundRead:status:)];
	pid = wait3(&status, (WNOHANG | WUNTRACED), NULL);
	(*notify)(target, @selector(backgroundRead:status:), pid, &status);
}

setNotifyTarget(anObject)
id	anObject;
{
	target = anObject;
	signal(SIGCHLD, processTerminated);
	signal(SIGTTIN, backgroundRead);
}

char *
stringDup(char *dup, char *str)
{
	if (!str)
		return str;
	if (!dup || strcmp(dup, str)) {
		NX_FREE(dup);
		NX_MALLOC(dup, char, strlen(str)+1);
		strcpy(dup, str);
	}
	return dup;
}

char *
strdup(char *str)
{
	char *dup;
	dup = malloc(strlen(str)+1);
	strcpy(dup, str);
	return dup;
}

void
tilde_expand(char *str)
{
	char *home;
	int len;

	if (str[0] == '~' && str[1] == '/') {			// no support for ~somebody currently
		home = NXHomeDirectory();
		len = strlen(NXHomeDirectory());
		bcopy(str+1, str+len, strlen(str));		// actually srlen(str+1)+1
		bcopy(home, str, len);
	}
}

char *
parse_quote(char *str, char **next)
{
	char *p, *q;
	if (p = q = strchr(str, '"')) {
		do {
			q = strchr(q+1, '"');
			if (!q) return NULL;
		} while (*(q-1) == '\\');
		*q = '\0';
		*next = q+1;
		return p+1;
	}
	return NULL;
}

static
alloc_args(char *command, int *argc_p, char ***argv_p)
{
	char *p, **argv;
	int i = 0, j = 0;

	argv = malloc(256);
	argv[0] = malloc(256);
	for (p = command; *p; ++p) {
		if (isspace(*p)) {
			while (isspace(p[1])) ++p;
			argv[i][j] = '\0';
			argv[i] = realloc(argv[i], strlen(argv[i])+1);
			if (*p) {
				++i; j = 0;
				argv[i] = malloc(256);
			}
		} else {
			argv[i][j] = *p;
			++j;
		}
	}
	argv[i][j] = '\0';
	argv[++i] = NULL;
	*argc_p = i;
	*argv_p = argv;
}

static
free_args(int argc, char **argv)
	// programs which live long MUST NOT waste memory, I think.
{
	int i;
	for (i = 0; i < argc; ++i) {
		free(argv[i]);
	}
	free(argv);
}

#define MAXARGS 64
int
exec_vp(file, argv)
char *file;
char **argv;
{
	char *colon, *pathseq, path[256], *newargv[MAXARGS];
	int i, len;

	if (strchr(file, '/') != NULL)
		pathseq = ":";
	else
		pathseq = NXGetDefaultValue("SystemWorks", "PATH");
	for (; (colon = strchr(pathseq, ':')) != NULL; pathseq = colon +1) {
		len = colon - pathseq;
		strncpy(path, pathseq, len);
		path[len] = '\0';
		if (len > 0)
			strcat(path, "/");
		strcat(path, file);
		execv(path, argv);
		if (errno == ENOEXEC) {
			i = 0;
			do {
				if (i >= MAXARGS-1) {
					errno = E2BIG;
					return (-1);
				}
				newargv[i+1] = argv[i];
			} while (argv[i++] != NULL);
			newargv[0] = "sh";
			execv("/bin/sh", newargv);
			perror("execv");
		}
	}
	return (-1);
}


int
invoke(char *command, int infd, char *infile, int outfd, char *outfile)
{
	int argc;
	char **argv;
	int pid, fd;

	alloc_args(command, &argc, &argv);
	switch (pid = fork()) {
	case -1:
		printf("can't fork");
		break;
	case 0:
		if (infd != 0) {
			close(0);
			if (infd > 0)
				dup(infd);
			else if ((fd = open(infile, O_RDONLY, 0)) == -1 || fd != 0) {
				fprintf(stderr, "can't open infile");
			}
		}
		if (outfd != 1) {
			close(1);
			if (outfd > 1)
				dup(outfd);
			else if ((fd = open(outfile, O_WRONLY | O_CREAT, 0666)) == -1 || fd != 1) {
				fprintf(stderr, "can't open outfile");
			}
		}
		for (fd = 3; fd < 20; ++fd)  close(fd);
		exec_vp(argv[0], argv);
		fprintf(stderr, "can't exec '%s'", argv[0]);
		exit(0);
	default:
		if (infd > 0) close(infd);
		if (outfd > 1) close(outfd);
		free_args(argc, argv);
		return pid;
	}
}

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