File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / exec.c
Revision 1.1.2.10: download - view: text, annotated - select for diffs - revision graph
Thu Dec 5 23:43:46 2013 UTC (10 years, 7 months ago) by misho
Branches: io6_7
fix

    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: 			e_pclose(array(prg->prog_fds, i, FILE*));
  103: 			array_Del(prg->prog_fds, i, 0);
  104: 			clrbit(prg->prog_used, i);
  105: 			prg->prog_cnum--;
  106: 			ret++;
  107: 		}
  108: 	pthread_mutex_unlock(&prg->prog_mtx);
  109: 
  110: 	return ret;
  111: }
  112: 
  113: /*
  114:  * io_progOpen() - Execute number of program(s)
  115:  *
  116:  * @prg = program pool
  117:  * @execNum = execute program(s) (0 max)
  118:  * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
  119:  */
  120: int
  121: io_progOpen(prog_t * __restrict prg, u_int execNum)
  122: {
  123: 	FILE *f;
  124: 	int stat, ret = 0;
  125: 	register int i;
  126: 	pid_t pid;
  127: 
  128: 	if (!prg)
  129: 		return 0;
  130: 	if (prg->prog_cnum + execNum > prg->prog_maxn) {
  131: 		io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
  132: 		return 0;
  133: 	}
  134: 
  135: 	pthread_mutex_lock(&prg->prog_mtx);
  136: 	for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)
  137: 		if (!array_Get(prg->prog_fds, i)) {
  138: 			f = e_popen(prg->prog_name, "r+", &pid);
  139: 			if (!f) {
  140: 				LOGERR;
  141: 				ret = -1;
  142: 				break;
  143: 			} else if (waitpid(pid, &stat, WNOHANG)) {
  144: 				io_SetErr(ECHILD, "Program with pid=%d exit with status %d", 
  145: 						pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
  146: 				ret = -1;
  147: 				break;
  148: 			} else
  149: 				array_Set(prg->prog_fds, i, f);
  150: 			prg->prog_cnum++;
  151: 			ret++;
  152: 		}
  153: 	pthread_mutex_unlock(&prg->prog_mtx);
  154: 
  155: 	return ret;
  156: }
  157: 
  158: /*
  159:  * io_progGrow() - Execute to number of programs in pool
  160:  *
  161:  * @prg = program pool
  162:  * @toNum = execute to number of programs (0 max)
  163:  * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
  164:  */
  165: int
  166: io_progGrow(prog_t * __restrict prg, u_int toNum)
  167: {
  168: 	if (!prg)
  169: 		return 0;
  170: 	if (toNum > prg->prog_maxn) {
  171: 		io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
  172: 		return 0;
  173: 	}
  174: 	if (!toNum)
  175: 		toNum = prg->prog_maxn;
  176: 
  177: 	return io_progOpen(prg, toNum - prg->prog_cnum);
  178: }
  179: 
  180: /*
  181:  * io_progVacuum() - Vacuum pool to running number of programs
  182:  *
  183:  * @prg = program pool
  184:  * @toNum = vacuum to number of programs (0 to init number)
  185:  * return: 0 error or >0 closed programs
  186:  */
  187: int
  188: io_progVacuum(prog_t * __restrict prg, u_int toNum)
  189: {
  190: 	register int i;
  191: 	int ret = 0;
  192: 
  193: 	if (!prg)
  194: 		return 0;
  195: 	if (toNum > prg->prog_maxn) {
  196: 		io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
  197: 		return 0;
  198: 	}
  199: 	if (!toNum)
  200: 		toNum = prg->prog_inin;
  201: 
  202: 	pthread_mutex_lock(&prg->prog_mtx);
  203: 	for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)
  204: 		if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
  205: 			e_pclose(array(prg->prog_fds, i, FILE*));
  206: 			array_Del(prg->prog_fds, i, 0);
  207: 			prg->prog_cnum--;
  208: 			ret++;
  209: 		}
  210: 	pthread_mutex_unlock(&prg->prog_mtx);
  211: 
  212: 	return ret;
  213: }
  214: 
  215: /*
  216:  * io_progCheck() - Check exit status of program pool
  217:  *
  218:  * @prg = program pool
  219:  * return: -1 error or >-1 exited programs
  220:  */
  221: int
  222: io_progCheck(prog_t * __restrict prg)
  223: {
  224: 	int ret = 0;
  225: 	struct tagPIOPID *p;
  226: 	register int i;
  227: 
  228: 	if (!prg)
  229: 		return -1;
  230: 
  231: 	pthread_mutex_lock(&prg->prog_mtx);
  232: 	for (i = 0; i < array_Size(prg->prog_fds); i++)
  233: 		if (array_Get(prg->prog_fds, i) && 
  234: 				(p = pio_pgetpid(array(prg->prog_fds, i, FILE*))))
  235: 			if (waitpid(p->pid, &p->stat, WNOHANG) > 0) {
  236: 				clrbit(prg->prog_used, i);
  237: 				ret++;
  238: 			}
  239: 	pthread_mutex_unlock(&prg->prog_mtx);
  240: 
  241: 	return ret;
  242: }
  243: 
  244: /*
  245:  * io_progAttach() - Attach to open program
  246:  *
  247:  * @prg = program pool
  248:  * return: NULL error or !=NULL attached program handle
  249:  */
  250: FILE *
  251: io_progAttach(prog_t * __restrict prg)
  252: {
  253: 	FILE *f = NULL;
  254: 	register int i;
  255: 
  256: 	if (!prg)
  257: 		return NULL;
  258: 
  259: 	pthread_mutex_lock(&prg->prog_mtx);
  260: 	for (i = 0; i < array_Size(prg->prog_fds); i++)
  261: 		if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
  262: 			setbit(prg->prog_used, i);
  263: 			f = array(prg->prog_fds, i, FILE*);
  264: 			break;
  265: 		}
  266: 	pthread_mutex_unlock(&prg->prog_mtx);
  267: 
  268: 	return f;
  269: }
  270: 
  271: /*
  272:  * io_progDetach() - Detch from open program
  273:  *
  274:  * @prg= program pool
  275:  * @pfd = attached program handle
  276:  * return: none
  277:  */
  278: void
  279: io_progDetach(prog_t * __restrict prg, FILE *pfd)
  280: {
  281: 	register int i;
  282: 
  283: 	if (!prg || !pfd)
  284: 		return;
  285: 
  286: 	pthread_mutex_lock(&prg->prog_mtx);
  287: 	for (i = 0; i < array_Size(prg->prog_fds); i++)
  288: 		if (array(prg->prog_fds, i, FILE*) == pfd) {
  289: 			clrbit(prg->prog_used, i);
  290: 			break;
  291: 		}
  292: 	pthread_mutex_unlock(&prg->prog_mtx);
  293: }

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