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.