|
|
1.1 root 1: #include <stdio.h>
2: #include <pwd.h>
3: #include <signal.h>
4: #include "mail.h"
5: #include "string.h"
6: #include "process.h"
7:
8: /*
9: * the following is pretty safe because upas is very stingy
10: * in its file descriptor use. system V fanatics should
11: * use the approriate system V system call to get the number
12: * of file descriptors
13: */
14: #ifndef NOFILE
15: #define NOFILE 20
16: #endif
17: #ifndef NSYSFILE
18: #define NSYSFILE 3
19: #endif
20:
21: extern char *malloc();
22: extern void exit();
23: extern char *getenv();
24:
25: /* make a stream to a child process */
26: extern stream *
27: instream()
28: {
29: stream *rv;
30: int pfd[2];
31:
32: if ((rv = (stream *)malloc(sizeof(stream))) == NULL)
33: return NULL;
34: if (pipe(pfd) < 0)
35: return NULL;
36: if ((rv->fp = fdopen(pfd[1], "w")) == NULL){
37: close(pfd[0]);
38: close(pfd[1]);
39: return NULL;
40: }
41: rv->fd = pfd[0];
42: return rv;
43: }
44:
45: /* make a stream from a child process */
46: extern stream *
47: outstream()
48: {
49: stream *rv;
50: int pfd[2];
51:
52: if ((rv = (stream *)malloc(sizeof(stream))) == NULL)
53: return NULL;
54: if (pipe(pfd) < 0)
55: return NULL;
56: if ((rv->fp = fdopen(pfd[0], "r")) == NULL){
57: close(pfd[0]);
58: close(pfd[1]);
59: return NULL;
60: }
61: rv->fd = pfd[1];
62: return rv;
63: }
64:
65: extern void
66: stream_free(sp)
67: stream *sp;
68: {
69: close(sp->fd);
70: fclose(sp->fp);
71: free((char *)sp);
72: }
73:
74: static char *env[] = { "IFS= \t\n", 0, 0, 0, 0 };
75: static string *spath;
76: static string *home;
77: static string *tz;
78:
79: /* start a new process */
80: extern process *
81: proc_start(cmd, inp, outp, errp, uid)
82: char *cmd; /* command to run */
83: stream *inp, *outp, *errp; /* streams to be used */
84: {
85: struct passwd *pw;
86: process *pp;
87: int i;
88: char *tzp;
89:
90: if ((pp = (process *)malloc(sizeof(process))) == NULL) {
91: if (inp != NULL)
92: stream_free(inp);
93: if (outp != NULL)
94: stream_free(outp);
95: if (errp != NULL)
96: stream_free(errp);
97: return NULL;
98: }
99: pp->std[0] = inp;
100: pp->std[1] = outp;
101: pp->std[2] = errp;
102: switch (pp->pid = fork()) {
103: case -1:
104: proc_free(pp);
105: return NULL;
106: case 0:
107: fflush(stdout);
108: if (spath==NULL) {
109: spath = s_new();
110: s_append(spath, "PATH=");
111: s_append(spath, UPASROOT);
112: s_append(spath, ":/bin:/usr/bin");
113: home = s_new();
114: env[1] = s_to_c(spath);
115: }
116: uid=(uid<0)?getuid():uid;
117: pw = getpwuid(uid);
118: if (pw != NULL){
119: setlogname(pw->pw_name);
120: s_append(s_restart(home), "HOME=");
121: s_append(home, pw->pw_dir);
122: env[2] = s_to_c(home);
123: } else
124: env[2] = "HOME=/";
125: if (tz==NULL) {
126: if(tzp = getenv("TZ")){
127: tz = s_new();
128: s_append(tz, "TZ=");
129: s_append(tz, tzp);
130: env[3] = s_to_c(tz);
131: }
132: }
133: setgid(-1);
134: setuid(uid);
135: for (i=0; i<3; i++)
136: if (pp->std[i] != NULL)
137: fclose(pp->std[i]->fp);
138: for (i=0; i<NSYSFILE; i++)
139: if (pp->std[i] != NULL)
140: dup2(pp->std[i]->fd, i);
141: for (i = NSYSFILE; i < NOFILE; i++)
142: close(i);
143: execle("/bin/sh", "sh", "-c", cmd, 0, env);
144: perror("proc_start");
145: exit(1);
146: default:
147: for (i=0; i<3; i++)
148: if (pp->std[i] != NULL) {
149: close(pp->std[i]->fd);
150: pp->std[i]->fd = -1;
151: }
152: return pp;
153: }
154: }
155:
156: /* wait for a process to stop */
157: extern int
158: proc_wait(pp)
159: process *pp; /* description of process */
160: {
161: int status=0;
162: int pid;
163:
164: while((pid = wait(&status))>=0) {
165: if (pid==pp->pid)
166: break;
167: }
168: pp->pid = -1;
169: pp->status = status;
170: return status;
171: }
172:
173: /* free a process */
174: extern int
175: proc_free(pp)
176: process *pp;
177: {
178: int i;
179:
180: for (i = 0; i < 3; i++)
181: if (pp->std[i])
182: stream_free(pp->std[i]);
183: if (pp->pid >= 0){
184: kill(pp->pid, SIGKILL);
185: (void)proc_wait(pp);
186: }
187: free((char *)pp);
188: return 0;
189: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.