home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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.
- */
-
- #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 *ans, buf[1024], *strpbrk(), *strdup();
- void free_ptr();
-
- /* same rules as strdup() */
- if (input == NULL)
- return(NULL);
- if (*input == NULL)
- return(null_ptr);
- /* any thing to expand? */
- ans = strdup(input);
- if (!strpbrk(input, "$*{}[]\\?~"))
- return(ans);
- /* popen an echo */
- sprintf(buf, "echo %s", input);
-
- pfp = n_popen(buf, "r");
- fgets(buf, 1024, pfp);
- n_pclose(pfp);
-
- if (!strlen(buf))
- 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(buf) -1;
- if (buf[last] != '\n')
- return(ans);
- else
- buf[last] = NULL;
-
- free_ptr(ans);
- ans = strdup(buf);
- 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 == NULL)
- shellpath = "/bin/sh";
-
- shell = strrchr(shellpath, '/') + 1;
- /* 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;
- {
- int f, r, (*hstat)(), (*istat)(), (*qstat)(), status;
-
- f = fileno(ptr);
- fclose(ptr);
- istat = signal(SIGINT, SIG_IGN);
- qstat = signal(SIGQUIT, SIG_IGN);
- hstat = signal(SIGHUP, SIG_IGN);
-
- while ((r = wait(&status)) != popen_pid[f] && r != -1)
- ;
-
- if (r == -1)
- status = -1;
-
- signal(SIGINT, istat);
- signal(SIGQUIT, qstat);
- signal(SIGHUP, hstat);
- return(status);
- }
-