Annotation of libaitio/src/exec.c, revision 1.1.2.13
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);
1.1.2.13! misho 74: signal(SIGPIPE, SIG_DFL);
1.1.2.1 misho 75:
76: e_free(*pprg);
77: *pprg = NULL;
78: }
79:
80: /*
81: * io_progClose() - Close all programs in pool
82: *
83: * @prg = program pool
84: * @closeNum = close program(s) (0 all)
85: * return: 0 error, >0 closed programs
86: */
87: int
88: io_progClose(prog_t * __restrict prg, u_int closeNum)
89: {
90: register int i;
91: int ret = 0;
92:
93: if (!prg)
94: return 0;
95: if (closeNum > prg->prog_maxn) {
96: io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
97: return 0;
98: }
99:
100: pthread_mutex_lock(&prg->prog_mtx);
101: for (i = array_Size(prg->prog_fds) - 1;
102: (closeNum ? ret < closeNum : 42) && i > -1; i--)
103: if (array_Get(prg->prog_fds, i)) {
1.1.2.11 misho 104: #ifdef POPEN_STREAM
1.1.2.6 misho 105: e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11 misho 106: #else
107: e_pclose((int) array(prg->prog_fds, i, intptr_t));
108: #endif
1.1.2.1 misho 109: array_Del(prg->prog_fds, i, 0);
1.1.2.9 misho 110: clrbit(prg->prog_used, i);
1.1.2.1 misho 111: prg->prog_cnum--;
112: ret++;
113: }
114: pthread_mutex_unlock(&prg->prog_mtx);
115:
116: return ret;
117: }
118:
119: /*
120: * io_progOpen() - Execute number of program(s)
121: *
122: * @prg = program pool
123: * @execNum = execute program(s) (0 max)
124: * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
125: */
126: int
127: io_progOpen(prog_t * __restrict prg, u_int execNum)
128: {
1.1.2.11 misho 129: #ifdef POPEN_STREAM
1.1.2.1 misho 130: FILE *f;
1.1.2.11 misho 131: #else
132: int f;
133: #endif
1.1.2.4 misho 134: int stat, ret = 0;
1.1.2.1 misho 135: register int i;
1.1.2.4 misho 136: pid_t pid;
1.1.2.1 misho 137:
138: if (!prg)
139: return 0;
1.1.2.8 misho 140: if (prg->prog_cnum + execNum > prg->prog_maxn) {
1.1.2.1 misho 141: io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
142: return 0;
143: }
144:
145: pthread_mutex_lock(&prg->prog_mtx);
146: for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)
147: if (!array_Get(prg->prog_fds, i)) {
1.1.2.6 misho 148: f = e_popen(prg->prog_name, "r+", &pid);
1.1.2.11 misho 149: #ifdef POPEN_STREAM
1.1.2.1 misho 150: if (!f) {
1.1.2.11 misho 151: #else
152: if (f == -1) {
153: #endif
1.1.2.1 misho 154: LOGERR;
1.1.2.5 misho 155: ret = -1;
1.1.2.1 misho 156: break;
1.1.2.6 misho 157: } else if (waitpid(pid, &stat, WNOHANG)) {
158: io_SetErr(ECHILD, "Program with pid=%d exit with status %d",
159: pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
1.1.2.5 misho 160: ret = -1;
1.1.2.4 misho 161: break;
1.1.2.1 misho 162: } else
163: array_Set(prg->prog_fds, i, f);
164: prg->prog_cnum++;
165: ret++;
166: }
167: pthread_mutex_unlock(&prg->prog_mtx);
168:
169: return ret;
170: }
171:
172: /*
1.1.2.8 misho 173: * io_progGrow() - Execute to number of programs in pool
174: *
175: * @prg = program pool
176: * @toNum = execute to number of programs (0 max)
177: * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
178: */
179: int
180: io_progGrow(prog_t * __restrict prg, u_int toNum)
181: {
182: if (!prg)
183: return 0;
184: if (toNum > prg->prog_maxn) {
185: io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
186: return 0;
187: }
188: if (!toNum)
189: toNum = prg->prog_maxn;
190:
191: return io_progOpen(prg, toNum - prg->prog_cnum);
192: }
193:
194: /*
1.1.2.1 misho 195: * io_progVacuum() - Vacuum pool to running number of programs
196: *
197: * @prg = program pool
198: * @toNum = vacuum to number of programs (0 to init number)
199: * return: 0 error or >0 closed programs
200: */
201: int
202: io_progVacuum(prog_t * __restrict prg, u_int toNum)
203: {
204: register int i;
205: int ret = 0;
206:
207: if (!prg)
208: return 0;
209: if (toNum > prg->prog_maxn) {
210: io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
211: return 0;
212: }
213: if (!toNum)
214: toNum = prg->prog_inin;
215:
216: pthread_mutex_lock(&prg->prog_mtx);
217: for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)
1.1.2.10 misho 218: if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
1.1.2.11 misho 219: #ifdef POPEN_STREAM
1.1.2.6 misho 220: e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11 misho 221: #else
222: e_pclose((int) array(prg->prog_fds, i, intptr_t));
223: #endif
1.1.2.1 misho 224: array_Del(prg->prog_fds, i, 0);
225: prg->prog_cnum--;
226: ret++;
227: }
228: pthread_mutex_unlock(&prg->prog_mtx);
229:
230: return ret;
231: }
1.1.2.7 misho 232:
233: /*
234: * io_progCheck() - Check exit status of program pool
235: *
236: * @prg = program pool
237: * return: -1 error or >-1 exited programs
238: */
239: int
240: io_progCheck(prog_t * __restrict prg)
241: {
242: int ret = 0;
243: struct tagPIOPID *p;
244: register int i;
245:
246: if (!prg)
247: return -1;
248:
1.1.2.9 misho 249: pthread_mutex_lock(&prg->prog_mtx);
1.1.2.7 misho 250: for (i = 0; i < array_Size(prg->prog_fds); i++)
251: if (array_Get(prg->prog_fds, i) &&
1.1.2.11 misho 252: #ifdef POPEN_STREAM
1.1.2.7 misho 253: (p = pio_pgetpid(array(prg->prog_fds, i, FILE*))))
1.1.2.11 misho 254: #else
255: (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t))))
256: #endif
1.1.2.9 misho 257: if (waitpid(p->pid, &p->stat, WNOHANG) > 0) {
258: clrbit(prg->prog_used, i);
1.1.2.7 misho 259: ret++;
1.1.2.9 misho 260: }
261: pthread_mutex_unlock(&prg->prog_mtx);
1.1.2.7 misho 262:
263: return ret;
264: }
1.1.2.9 misho 265:
266: /*
267: * io_progAttach() - Attach to open program
268: *
269: * @prg = program pool
270: * return: NULL error or !=NULL attached program handle
271: */
1.1.2.11 misho 272: #ifdef POPEN_STREAM
1.1.2.9 misho 273: FILE *
1.1.2.11 misho 274: #else
275: int
276: #endif
1.1.2.9 misho 277: io_progAttach(prog_t * __restrict prg)
278: {
1.1.2.11 misho 279: #ifdef POPEN_STREAM
1.1.2.9 misho 280: FILE *f = NULL;
1.1.2.11 misho 281: #else
282: int f = -1;
283: #endif
1.1.2.9 misho 284: register int i;
285:
286: if (!prg)
1.1.2.11 misho 287: #ifdef POPEN_STREAM
1.1.2.9 misho 288: return NULL;
1.1.2.11 misho 289: #else
290: return -1;
291: #endif
1.1.2.9 misho 292:
293: pthread_mutex_lock(&prg->prog_mtx);
294: for (i = 0; i < array_Size(prg->prog_fds); i++)
295: if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
296: setbit(prg->prog_used, i);
1.1.2.11 misho 297: #ifdef POPEN_STREAM
1.1.2.9 misho 298: f = array(prg->prog_fds, i, FILE*);
1.1.2.11 misho 299: #else
300: f = array(prg->prog_fds, i, intptr_t);
301: #endif
1.1.2.9 misho 302: break;
303: }
304: pthread_mutex_unlock(&prg->prog_mtx);
305:
306: return f;
307: }
308:
309: /*
310: * io_progDetach() - Detch from open program
311: *
312: * @prg= program pool
313: * @pfd = attached program handle
314: * return: none
315: */
316: void
1.1.2.11 misho 317: #ifdef POPEN_STREAM
1.1.2.9 misho 318: io_progDetach(prog_t * __restrict prg, FILE *pfd)
1.1.2.11 misho 319: #else
320: io_progDetach(prog_t * __restrict prg, int pfd)
321: #endif
1.1.2.9 misho 322: {
323: register int i;
324:
325: if (!prg || !pfd)
326: return;
327:
328: pthread_mutex_lock(&prg->prog_mtx);
329: for (i = 0; i < array_Size(prg->prog_fds); i++)
1.1.2.11 misho 330: #ifdef POPEN_STREAM
1.1.2.9 misho 331: if (array(prg->prog_fds, i, FILE*) == pfd) {
1.1.2.11 misho 332: #else
333: if (array(prg->prog_fds, i, intptr_t) == pfd) {
334: #endif
1.1.2.9 misho 335: clrbit(prg->prog_used, i);
336: break;
337: }
338: pthread_mutex_unlock(&prg->prog_mtx);
339: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>