|
|
1.1 root 1: #ifndef lint
2: static char rcs_id[] = "$Header: command.c,v 1.13 87/09/11 08:18:00 toddb Exp $";
3: #endif lint
4: /*
5: * COPYRIGHT 1987
6: * DIGITAL EQUIPMENT CORPORATION
7: * MAYNARD, MASSACHUSETTS
8: * ALL RIGHTS RESERVED.
9: *
10: * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
11: * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
12: * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
13: * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
14: *
15: * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS,
16: * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT
17: * SET FORTH ABOVE.
18: *
19: *
20: * Permission to use, copy, modify, and distribute this software and its
21: * documentation for any purpose and without fee is hereby granted, provided
22: * that the above copyright notice appear in all copies and that both that
23: * copyright notice and this permission notice appear in supporting documentation,
24: * and that the name of Digital Equipment Corporation not be used in advertising
25: * or publicity pertaining to distribution of the software without specific,
26: * written prior permission.
27: */
28:
29: /* command.c -- interface to exec mh commands. */
30:
31: #include "xmh.h"
32: #include <sys/types.h>
33: #include <sys/stat.h>
34: #include <sys/signal.h>
35: #include <sys/wait.h>
36: #include <sys/time.h>
37: #include <sys/resource.h>
38: #include <sys/file.h>
39:
40: #ifndef FD_SET
41: #define NFDBITS (8*sizeof(fd_set))
42: #define FD_SETSIZE NFDBITS
43: #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
44: #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
45: #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
46: #define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
47: #endif
48:
49:
50:
51: /* Return the full path name of the given mh command. */
52:
53: static char *FullPathOfCommand(str)
54: char *str;
55: {
56: static char result[100];
57: (void) sprintf(result, "%s/%s", defMhPath, str);
58: return result;
59: }
60:
61:
62: static int childdone; /* Gets nonzero when the child process
63: finishes. */
64: ChildDone()
65: {
66: childdone++;
67: }
68:
69: /* Execute the given command, and wait until it has finished. While the
70: command is executing, watch the X socket and cause Xlib to read in any
71: incoming data. This will prevent the socket from overflowing during
72: long commands. */
73:
74: DoCommand(argv, inputfile, outputfile)
75: char **argv; /* The command to execute, and its args. */
76: char *inputfile; /* Input file for command. */
77: char *outputfile; /* Output file for command. */
78: {
79: FILEPTR fid;
80: int pid;
81: fd_set readfds, fds;
82: FD_ZERO(&fds);
83: FD_SET(QConnectionNumber(theDisplay), &fds);
84: if (debug) {(void)fprintf(stderr, "Executing %s ...", argv[0]); (void) fflush(stderr);}
85: childdone = FALSE;
86: (void) signal(SIGCHLD, ChildDone);
87: pid = fork();
88: if (pid == -1) Punt("Couldn't fork!");
89: if (pid) { /* We're the parent process. */
90: while (!childdone) {
91: readfds = fds;
92: (void) select(QConnectionNumber(theDisplay)+1, (int *) &readfds,
93: (int *) NULL, (int *) NULL, (struct timeval *) NULL);
94: if (FD_ISSET(QConnectionNumber(theDisplay), &readfds)) {
95: (void) QXPending(theDisplay);
96: }
97: }
98: (void) wait((union wait *) NULL);
99: if (debug) (void)fprintf(stderr, " done\n");
100: } else { /* We're the child process. */
101: if (inputfile) {
102: fid = FOpenAndCheck(inputfile, "r");
103: (void) dup2(fileno(fid), fileno(stdin));
104: }
105: if (outputfile) {
106: fid = FOpenAndCheck(outputfile, "w");
107: (void) dup2(fileno(fid), fileno(stdout));
108: }
109: if (!debug) { /* Throw away error messages. */
110: fid = FOpenAndCheck("/dev/null", "w");
111: (void) dup2(fileno(fid), fileno(stderr));
112: if (!outputfile)
113: (void) dup2(fileno(fid), fileno(stderr));
114: }
115: (void) execv(FullPathOfCommand(argv[0]), argv);
116: (void) execvp(argv[0], argv);
117: Punt("Execvp failed!");
118: }
119: }
120:
121:
122:
123: /* Execute the given command, waiting until it's finished. Put the output
124: in a newly mallocced string, and return a pointer to that string. */
125:
126: char *DoCommandToString(argv)
127: char ** argv;
128: {
129: char *result;
130: char *file;
131: int fid, length;
132: file = DoCommandToFile(argv);
133: length = GetFileLength(file);
134: result = XtMalloc((unsigned) length + 1);
135: fid = myopen(file, O_RDONLY, 0666);
136: if (length != read(fid, result, length))
137: Punt("Couldn't read result from DoCommandToString");
138: result[length] = 0;
139: if (debug) (void) fprintf(stderr, "('%s')\n", result);
140: (void) myclose(fid);
141: DeleteFileAndCheck(file);
142: return result;
143: }
144:
145:
146: #ifdef NOTDEF /* This implementation doesn't work right on null return. */
147: char *DoCommandToString(argv)
148: char **argv;
149: {
150: static char result[1030];
151: int fildes[2], pid, l;
152: if (debug) {(void)fprintf(stderr, "Executing %s ...", argv[0]); (void) fflush(stderr);}
153: (void) pipe(fildes);
154: pid = vfork();
155: if (pid == -1) Punt("Couldn't fork!");
156: if (pid) {
157: while (wait((union wait *) 0) == -1) ;
158: l = read(fildes[0], result, 1024);
159: if (l <= 0) Punt("Couldn't read result from DoCommandToString");
160: (void) myclose(fildes[0]);
161: result[l] = 0;
162: while (result[--l] == 0) ;
163: while (result[l] == '\n') result[l--] = 0;
164: if (debug) (void)fprintf(stderr, " done: '%s'\n", result);
165: return result;
166: } else {
167: (void) dup2(fildes[1], fileno(stdout));
168: (void) execv(FullPathOfCommand(argv[0]), argv);
169: (void) execvp(argv[0], argv);
170: Punt("Execvp failed!");
171: return NULL;
172: }
173: }
174: #endif
175:
176:
177:
178: /* Execute the command to a temporary file, and return the name of the file. */
179:
180: char *DoCommandToFile(argv)
181: char **argv;
182: {
183: char *name;
184: name = MakeNewTempFileName();
185: DoCommand(argv, (char *) NULL, name);
186: return name;
187: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.