File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / exec.c
Revision 1.1.2.11: download - view: text, annotated - select for diffs - revision graph
Fri Dec 6 01:03:05 2013 UTC (10 years, 7 months ago) by misho
Branches: io6_7
get new way of popen

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>