Annotation of libaitio/src/exec.c, revision 1.1.2.12
1.1.2.1 misho 1: #include "global.h"
2:
3:
4: /*
5: * io_progInit() - Init program pool
6: *
7: * @progName = program name for execution
8: * @initNum = initial started programs
9: * @maxNum = maximum started programs
10: * return: NULL error or !=NULL allocated pool (must destroied with io_progDestroy())
11: */
12: prog_t *
13: io_progInit(const char *progName, u_int initNum, u_int maxNum)
14: {
15: prog_t *prg = NULL;
16:
17: if (initNum > maxNum)
18: return NULL;
19:
20: prg = e_malloc(sizeof(prog_t));
21: if (!prg) {
22: io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
23: return NULL;
24: } else
25: memset(prg, 0, sizeof(prog_t));
26:
27: prg->prog_inin = initNum;
28: prg->prog_maxn = maxNum;
29: strlcpy(prg->prog_name, progName, sizeof prg->prog_name);
30:
1.1.2.9 misho 31: prg->prog_used = e_malloc(E_ALIGN(prg->prog_maxn, sizeof *prg->prog_used) /
32: sizeof *prg->prog_used);
33: if (!prg->prog_used) {
34: io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
35: e_free(prg);
36: return NULL;
37: }
38:
1.1.2.1 misho 39: prg->prog_fds = array_Init(prg->prog_maxn);
40: if (!prg->prog_fds) {
41: io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
1.1.2.9 misho 42: e_free(prg->prog_used);
1.1.2.1 misho 43: e_free(prg);
44: return NULL;
45: }
46:
47: pthread_mutex_init(&prg->prog_mtx, NULL);
1.1.2.12! misho 48: signal(SIGPIPE, SIG_IGN);
1.1.2.2 misho 49:
1.1.2.6 misho 50: if (io_progOpen(prg, prg->prog_inin) < 0) {
1.1.2.2 misho 51: io_progDestroy(&prg);
1.1.2.6 misho 52: prg = NULL;
53: }
1.1.2.1 misho 54: return prg;
55: }
56:
57: /*
58: * io_progDestroy() - Destroy entire program pool
59: *
60: * @pprg = program pool
61: * return: none
62: */
63: void
64: io_progDestroy(prog_t ** __restrict pprg)
65: {
66: if (!pprg || !*pprg)
67: return;
68:
69: io_progClose(*pprg, 0);
70:
1.1.2.9 misho 71: e_free((*pprg)->prog_used);
1.1.2.1 misho 72: array_Destroy(&(*pprg)->prog_fds);
73: pthread_mutex_destroy(&(*pprg)->prog_mtx);
74:
75: e_free(*pprg);
76: *pprg = NULL;
77: }
78:
79: /*
80: * io_progClose() - Close all programs in pool
81: *
82: * @prg = program pool
83: * @closeNum = close program(s) (0 all)
84: * return: 0 error, >0 closed programs
85: */
86: int
87: io_progClose(prog_t * __restrict prg, u_int closeNum)
88: {
89: register int i;
90: int ret = 0;
91:
92: if (!prg)
93: return 0;
94: if (closeNum > prg->prog_maxn) {
95: io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
96: return 0;
97: }
98:
99: pthread_mutex_lock(&prg->prog_mtx);
100: for (i = array_Size(prg->prog_fds) - 1;
101: (closeNum ? ret < closeNum : 42) && i > -1; i--)
102: if (array_Get(prg->prog_fds, i)) {
1.1.2.11 misho 103: #ifdef POPEN_STREAM
1.1.2.6 misho 104: e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11 misho 105: #else
106: e_pclose((int) array(prg->prog_fds, i, intptr_t));
107: #endif
1.1.2.1 misho 108: array_Del(prg->prog_fds, i, 0);
1.1.2.9 misho 109: clrbit(prg->prog_used, i);
1.1.2.1 misho 110: prg->prog_cnum--;
111: ret++;
112: }
113: pthread_mutex_unlock(&prg->prog_mtx);
114:
115: return ret;
116: }
117:
118: /*
119: * io_progOpen() - Execute number of program(s)
120: *
121: * @prg = program pool
122: * @execNum = execute program(s) (0 max)
123: * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
124: */
125: int
126: io_progOpen(prog_t * __restrict prg, u_int execNum)
127: {
1.1.2.11 misho 128: #ifdef POPEN_STREAM
1.1.2.1 misho 129: FILE *f;
1.1.2.11 misho 130: #else
131: int f;
132: #endif
1.1.2.4 misho 133: int stat, ret = 0;
1.1.2.1 misho 134: register int i;
1.1.2.4 misho 135: pid_t pid;
1.1.2.1 misho 136:
137: if (!prg)
138: return 0;
1.1.2.8 misho 139: if (prg->prog_cnum + execNum > prg->prog_maxn) {
1.1.2.1 misho 140: io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
141: return 0;
142: }
143:
144: pthread_mutex_lock(&prg->prog_mtx);
145: for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)
146: if (!array_Get(prg->prog_fds, i)) {
1.1.2.6 misho 147: f = e_popen(prg->prog_name, "r+", &pid);
1.1.2.11 misho 148: #ifdef POPEN_STREAM
1.1.2.1 misho 149: if (!f) {
1.1.2.11 misho 150: #else
151: if (f == -1) {
152: #endif
1.1.2.1 misho 153: LOGERR;
1.1.2.5 misho 154: ret = -1;
1.1.2.1 misho 155: break;
1.1.2.6 misho 156: } else if (waitpid(pid, &stat, WNOHANG)) {
157: io_SetErr(ECHILD, "Program with pid=%d exit with status %d",
158: pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
1.1.2.5 misho 159: ret = -1;
1.1.2.4 misho 160: break;
1.1.2.1 misho 161: } else
162: array_Set(prg->prog_fds, i, f);
163: prg->prog_cnum++;
164: ret++;
165: }
166: pthread_mutex_unlock(&prg->prog_mtx);
167:
168: return ret;
169: }
170:
171: /*
1.1.2.8 misho 172: * io_progGrow() - Execute to number of programs in pool
173: *
174: * @prg = program pool
175: * @toNum = execute to number of programs (0 max)
176: * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
177: */
178: int
179: io_progGrow(prog_t * __restrict prg, u_int toNum)
180: {
181: if (!prg)
182: return 0;
183: if (toNum > prg->prog_maxn) {
184: io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
185: return 0;
186: }
187: if (!toNum)
188: toNum = prg->prog_maxn;
189:
190: return io_progOpen(prg, toNum - prg->prog_cnum);
191: }
192:
193: /*
1.1.2.1 misho 194: * io_progVacuum() - Vacuum pool to running number of programs
195: *
196: * @prg = program pool
197: * @toNum = vacuum to number of programs (0 to init number)
198: * return: 0 error or >0 closed programs
199: */
200: int
201: io_progVacuum(prog_t * __restrict prg, u_int toNum)
202: {
203: register int i;
204: int ret = 0;
205:
206: if (!prg)
207: return 0;
208: if (toNum > prg->prog_maxn) {
209: io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
210: return 0;
211: }
212: if (!toNum)
213: toNum = prg->prog_inin;
214:
215: pthread_mutex_lock(&prg->prog_mtx);
216: for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)
1.1.2.10 misho 217: if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
1.1.2.11 misho 218: #ifdef POPEN_STREAM
1.1.2.6 misho 219: e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11 misho 220: #else
221: e_pclose((int) array(prg->prog_fds, i, intptr_t));
222: #endif
1.1.2.1 misho 223: array_Del(prg->prog_fds, i, 0);
224: prg->prog_cnum--;
225: ret++;
226: }
227: pthread_mutex_unlock(&prg->prog_mtx);
228:
229: return ret;
230: }
1.1.2.7 misho 231:
232: /*
233: * io_progCheck() - Check exit status of program pool
234: *
235: * @prg = program pool
236: * return: -1 error or >-1 exited programs
237: */
238: int
239: io_progCheck(prog_t * __restrict prg)
240: {
241: int ret = 0;
242: struct tagPIOPID *p;
243: register int i;
244:
245: if (!prg)
246: return -1;
247:
1.1.2.9 misho 248: pthread_mutex_lock(&prg->prog_mtx);
1.1.2.7 misho 249: for (i = 0; i < array_Size(prg->prog_fds); i++)
250: if (array_Get(prg->prog_fds, i) &&
1.1.2.11 misho 251: #ifdef POPEN_STREAM
1.1.2.7 misho 252: (p = pio_pgetpid(array(prg->prog_fds, i, FILE*))))
1.1.2.11 misho 253: #else
254: (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t))))
255: #endif
1.1.2.9 misho 256: if (waitpid(p->pid, &p->stat, WNOHANG) > 0) {
257: clrbit(prg->prog_used, i);
1.1.2.7 misho 258: ret++;
1.1.2.9 misho 259: }
260: pthread_mutex_unlock(&prg->prog_mtx);
1.1.2.7 misho 261:
262: return ret;
263: }
1.1.2.9 misho 264:
265: /*
266: * io_progAttach() - Attach to open program
267: *
268: * @prg = program pool
269: * return: NULL error or !=NULL attached program handle
270: */
1.1.2.11 misho 271: #ifdef POPEN_STREAM
1.1.2.9 misho 272: FILE *
1.1.2.11 misho 273: #else
274: int
275: #endif
1.1.2.9 misho 276: io_progAttach(prog_t * __restrict prg)
277: {
1.1.2.11 misho 278: #ifdef POPEN_STREAM
1.1.2.9 misho 279: FILE *f = NULL;
1.1.2.11 misho 280: #else
281: int f = -1;
282: #endif
1.1.2.9 misho 283: register int i;
284:
285: if (!prg)
1.1.2.11 misho 286: #ifdef POPEN_STREAM
1.1.2.9 misho 287: return NULL;
1.1.2.11 misho 288: #else
289: return -1;
290: #endif
1.1.2.9 misho 291:
292: pthread_mutex_lock(&prg->prog_mtx);
293: for (i = 0; i < array_Size(prg->prog_fds); i++)
294: if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
295: setbit(prg->prog_used, i);
1.1.2.11 misho 296: #ifdef POPEN_STREAM
1.1.2.9 misho 297: f = array(prg->prog_fds, i, FILE*);
1.1.2.11 misho 298: #else
299: f = array(prg->prog_fds, i, intptr_t);
300: #endif
1.1.2.9 misho 301: break;
302: }
303: pthread_mutex_unlock(&prg->prog_mtx);
304:
305: return f;
306: }
307:
308: /*
309: * io_progDetach() - Detch from open program
310: *
311: * @prg= program pool
312: * @pfd = attached program handle
313: * return: none
314: */
315: void
1.1.2.11 misho 316: #ifdef POPEN_STREAM
1.1.2.9 misho 317: io_progDetach(prog_t * __restrict prg, FILE *pfd)
1.1.2.11 misho 318: #else
319: io_progDetach(prog_t * __restrict prg, int pfd)
320: #endif
1.1.2.9 misho 321: {
322: register int i;
323:
324: if (!prg || !pfd)
325: return;
326:
327: pthread_mutex_lock(&prg->prog_mtx);
328: for (i = 0; i < array_Size(prg->prog_fds); i++)
1.1.2.11 misho 329: #ifdef POPEN_STREAM
1.1.2.9 misho 330: if (array(prg->prog_fds, i, FILE*) == pfd) {
1.1.2.11 misho 331: #else
332: if (array(prg->prog_fds, i, intptr_t) == pfd) {
333: #endif
1.1.2.9 misho 334: clrbit(prg->prog_used, i);
335: break;
336: }
337: pthread_mutex_unlock(&prg->prog_mtx);
338: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>