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.