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.