Annotation of libaitio/src/exec.c, revision 1.3.2.1

1.3       misho       1: /*************************************************************************
                      2: * (C) 2013 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
                      3: *  by Michael Pounov <misho@elwix.org>
                      4: *
                      5: * $Author: misho $
1.3.2.1 ! misho       6: * $Id: exec.c,v 1.3 2013/12/18 12:40:21 misho Exp $
1.3       misho       7: *
                      8: **************************************************************************
                      9: The ELWIX and AITNET software is distributed under the following
                     10: terms:
                     11: 
                     12: All of the documentation and software included in the ELWIX and AITNET
                     13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
                     14: 
1.3.2.1 ! misho      15: Copyright 2004 - 2014
1.3       misho      16:        by Michael Pounov <misho@elwix.org>.  All rights reserved.
                     17: 
                     18: Redistribution and use in source and binary forms, with or without
                     19: modification, are permitted provided that the following conditions
                     20: are met:
                     21: 1. Redistributions of source code must retain the above copyright
                     22:    notice, this list of conditions and the following disclaimer.
                     23: 2. Redistributions in binary form must reproduce the above copyright
                     24:    notice, this list of conditions and the following disclaimer in the
                     25:    documentation and/or other materials provided with the distribution.
                     26: 3. All advertising materials mentioning features or use of this software
                     27:    must display the following acknowledgement:
                     28: This product includes software developed by Michael Pounov <misho@elwix.org>
                     29: ELWIX - Embedded LightWeight unIX and its contributors.
                     30: 4. Neither the name of AITNET nor the names of its contributors
                     31:    may be used to endorse or promote products derived from this software
                     32:    without specific prior written permission.
                     33: 
                     34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
                     35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     44: SUCH DAMAGE.
                     45: */
1.2       misho      46: #include "global.h"
                     47: 
                     48: 
                     49: /*
                     50:  * io_progInit() - Init program pool
                     51:  *
                     52:  * @progName = program name for execution
                     53:  * @initNum = initial started programs
                     54:  * @maxNum = maximum started programs
                     55:  * return: NULL error or !=NULL allocated pool (must destroied with io_progDestroy())
                     56:  */
                     57: prog_t *
                     58: io_progInit(const char *progName, u_int initNum, u_int maxNum)
                     59: {
                     60:        prog_t *prg = NULL;
                     61: 
                     62:        if (initNum > maxNum)
                     63:                return NULL;
                     64: 
                     65:        prg = e_malloc(sizeof(prog_t));
                     66:        if (!prg) {
                     67:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                     68:                return NULL;
                     69:        } else
                     70:                memset(prg, 0, sizeof(prog_t));
                     71: 
                     72:        prg->prog_inin = initNum;
                     73:        prg->prog_maxn = maxNum;
                     74:        strlcpy(prg->prog_name, progName, sizeof prg->prog_name);
                     75: 
                     76:        prg->prog_used = e_malloc(E_ALIGN(prg->prog_maxn, sizeof *prg->prog_used) / 
                     77:                        sizeof *prg->prog_used);
                     78:        if (!prg->prog_used) {
                     79:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                     80:                e_free(prg);
                     81:                return NULL;
                     82:        }
                     83: 
                     84:        prg->prog_fds = array_Init(prg->prog_maxn);
                     85:        if (!prg->prog_fds) {
                     86:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                     87:                e_free(prg->prog_used);
                     88:                e_free(prg);
                     89:                return NULL;
                     90:        }
                     91: 
                     92:        pthread_mutex_init(&prg->prog_mtx, NULL);
                     93:        signal(SIGPIPE, SIG_IGN);
                     94: 
                     95:        if (io_progOpen(prg, prg->prog_inin) < 0) {
                     96:                io_progDestroy(&prg);
                     97:                prg = NULL;
                     98:        }
                     99:        return prg;
                    100: }
                    101: 
                    102: /*
                    103:  * io_progDestroy() - Destroy entire program pool
                    104:  *
                    105:  * @pprg = program pool
                    106:  * return: none
                    107:  */
                    108: void
                    109: io_progDestroy(prog_t ** __restrict pprg)
                    110: {
                    111:        if (!pprg || !*pprg)
                    112:                return;
                    113: 
                    114:        io_progClose(*pprg, 0);
                    115: 
                    116:        e_free((*pprg)->prog_used);
                    117:        array_Destroy(&(*pprg)->prog_fds);
                    118:        pthread_mutex_destroy(&(*pprg)->prog_mtx);
                    119:        signal(SIGPIPE, SIG_DFL);
                    120: 
                    121:        e_free(*pprg);
                    122:        *pprg = NULL;
                    123: }
                    124: 
                    125: /*
                    126:  * io_progClose() - Close all programs in pool
                    127:  *
                    128:  * @prg = program pool
                    129:  * @closeNum = close program(s) (0 all)
                    130:  * return: 0 error, >0 closed programs
                    131:  */
                    132: int
                    133: io_progClose(prog_t * __restrict prg, u_int closeNum)
                    134: {
                    135:        register int i;
                    136:        int ret = 0;
                    137:        struct tagPIOPID *p;
                    138: 
                    139:        if (!prg)
                    140:                return 0;
                    141:        if (closeNum > prg->prog_maxn) {
                    142:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
                    143:                return 0;
                    144:        }
                    145: 
                    146:        pthread_mutex_lock(&prg->prog_mtx);
                    147:        for (i = array_Size(prg->prog_fds) - 1; 
                    148:                        (closeNum ? ret < closeNum : 42) && i > -1; i--)
                    149:                if (array_Get(prg->prog_fds, i) && 
                    150: #ifdef POPEN_STREAM
                    151:                                (p = pio_pgetpid(array(prg->prog_fds, i, FILE*)))) {
                    152: #else
                    153:                                (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t)))) {
                    154: #endif
                    155:                        kill(p->pid, SIGTERM);
                    156:                        usleep(1000);
                    157:                        if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
                    158:                                kill(p->pid, SIGKILL);
                    159: #ifdef POPEN_STREAM
                    160:                        e_pclose(array(prg->prog_fds, i, FILE*));
                    161: #else
                    162:                        e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    163: #endif
                    164:                        array_Del(prg->prog_fds, i, 0);
                    165:                        clrbit(prg->prog_used, i);
                    166:                        prg->prog_cnum--;
                    167:                        ret++;
                    168:                }
                    169:        pthread_mutex_unlock(&prg->prog_mtx);
                    170: 
                    171:        return ret;
                    172: }
                    173: 
                    174: /*
                    175:  * io_progCloseAt() - Close program at pool of certain position
                    176:  *
                    177:  * @prg = program pool
                    178:  * @idx = index at pool
                    179:  * return: 0 error or !=0 closed program
                    180:  */
                    181: int
                    182: io_progCloseAt(prog_t * __restrict prg, u_int idx)
                    183: {
                    184:        int ret = 0;
                    185:        struct tagPIOPID *p;
                    186: 
                    187:        if (!prg)
                    188:                return 0;
                    189:        if (idx > prg->prog_maxn) {
                    190:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
                    191:                return 0;
                    192:        }
                    193: 
                    194:        pthread_mutex_lock(&prg->prog_mtx);
                    195:        if (array_Get(prg->prog_fds, idx) && 
                    196: #ifdef POPEN_STREAM
                    197:                        (p = pio_pgetpid(array(prg->prog_fds, idx, FILE*)))) {
                    198: #else
                    199:                        (p = pio_pgetpid((int) array(prg->prog_fds, idx, intptr_t)))) {
                    200: #endif
                    201:                kill(p->pid, SIGTERM);
                    202:                usleep(1000);
                    203:                if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
                    204:                        kill(p->pid, SIGKILL);
                    205: #ifdef POPEN_STREAM
                    206:                e_pclose(array(prg->prog_fds, idx, FILE*));
                    207: #else
                    208:                e_pclose((int) array(prg->prog_fds, idx, intptr_t));
                    209: #endif
                    210:                array_Del(prg->prog_fds, idx, 0);
                    211:                clrbit(prg->prog_used, idx);
                    212:                prg->prog_cnum--;
                    213:                ret++;
                    214:        }
                    215:        pthread_mutex_unlock(&prg->prog_mtx);
                    216: 
                    217:        return ret;
                    218: }
                    219: 
                    220: /*
                    221:  * io_progCloseOf() - Close program at pool with certain handle
                    222:  *
                    223:  * @prg = program pool
                    224:  * @h = handle of program
                    225:  * return: 0 error, >0 closed programs
                    226:  */
                    227: int
                    228: #ifdef POPEN_STREAM
                    229: io_progCloseOf(prog_t * __restrict prg, FILE *h)
                    230: #else
                    231: io_progCloseOf(prog_t * __restrict prg, int h)
                    232: #endif
                    233: {
                    234:        register int i;
                    235:        int ret = 0;
                    236:        struct tagPIOPID *p;
                    237: #ifdef POPEN_STREAM
                    238:        FILE *f;
                    239: #else
                    240:        int f;
                    241: #endif
                    242: 
                    243:        if (!prg)
                    244:                return 0;
                    245: 
                    246:        pthread_mutex_lock(&prg->prog_mtx);
                    247:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    248:                if (array_Get(prg->prog_fds, i)) {
                    249: #ifdef POPEN_STREAM
                    250:                        f = array(prg->prog_fds, i, FILE*);
                    251:                        if (f == h && (p = pio_pgetpid(array(prg->prog_fds, i, FILE*)))) {
                    252: #else
                    253:                        f = (int) array(prg->prog_fds, i, intptr_t);
                    254:                        if (f == h && (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t)))) {
                    255: #endif
                    256:                                kill(p->pid, SIGTERM);
                    257:                                usleep(1000);
                    258:                                if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
                    259:                                        kill(p->pid, SIGKILL);
                    260: #ifdef POPEN_STREAM
                    261:                                e_pclose(array(prg->prog_fds, i, FILE*));
                    262: #else
                    263:                                e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    264: #endif
                    265:                                array_Del(prg->prog_fds, i, 0);
                    266:                                clrbit(prg->prog_used, i);
                    267:                                prg->prog_cnum--;
                    268:                                ret++;
                    269:                                break;
                    270:                        }
                    271:                }
                    272:        pthread_mutex_unlock(&prg->prog_mtx);
                    273: 
                    274:        return ret;
                    275: }
                    276: 
                    277: /*
                    278:  * io_progOpen2() - Start program from pool on first unused slot
                    279:  *
                    280:  * @prg = program pool
                    281:  * return: -1 error, >-1 reside at slot
                    282:  */
                    283: int
                    284: io_progOpen2(prog_t * __restrict prg)
                    285: {
                    286: #ifdef POPEN_STREAM
                    287:        FILE *f = NULL;
                    288: #else
                    289:        int f = -1;
                    290: #endif
                    291:        int stat, ret = -1;
                    292:        register int i;
                    293:        pid_t pid;
                    294: 
                    295:        if (!prg)
                    296:                return -1;
                    297:        if (prg->prog_cnum + 1 > prg->prog_maxn) {
                    298:                io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
                    299:                return -1;
                    300:        }
                    301: 
                    302:        pthread_mutex_lock(&prg->prog_mtx);
                    303:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    304:                if (!array_Get(prg->prog_fds, i)) {
                    305:                        f = e_popen(prg->prog_name, "r+", &pid);
                    306: #ifdef POPEN_STREAM
                    307:                        if (!f) {
                    308: #else
                    309:                        if (f == -1) {
                    310: #endif
                    311:                                LOGERR;
                    312:                                break;
                    313:                        } else if (waitpid(pid, &stat, WNOHANG)) {
                    314:                                io_SetErr(ECHILD, "Program with pid=%d exit with status %d", 
                    315:                                                pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
                    316:                                e_pclose(f);
                    317:                                break;
                    318:                        } else
1.3       misho     319:                                array_Set(prg->prog_fds, i, (intptr_t) f);
1.2       misho     320:                        clrbit(prg->prog_used, i);
                    321:                        prg->prog_cnum++;
                    322:                        ret = i;
                    323:                        break;
                    324:                }
                    325:        pthread_mutex_unlock(&prg->prog_mtx);
                    326: 
                    327:        return ret;
                    328: }
                    329: 
                    330: /*
                    331:  * io_progOpen() - Execute number of program(s)
                    332:  *
                    333:  * @prg = program pool
                    334:  * @execNum = execute program(s) (0 max)
                    335:  * return: -1 error, >0 executed programs
                    336:  */
                    337: int
                    338: io_progOpen(prog_t * __restrict prg, u_int execNum)
                    339: {
                    340: #ifdef POPEN_STREAM
                    341:        FILE *f;
                    342: #else
                    343:        int f;
                    344: #endif
                    345:        int stat, ret = 0;
                    346:        register int i;
                    347:        pid_t pid;
                    348: 
                    349:        if (!prg)
                    350:                return -1;
                    351:        if (prg->prog_cnum + execNum > prg->prog_maxn) {
                    352:                io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
                    353:                return -1;
                    354:        }
                    355: 
                    356:        pthread_mutex_lock(&prg->prog_mtx);
                    357:        for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)
                    358:                if (!array_Get(prg->prog_fds, i)) {
                    359:                        f = e_popen(prg->prog_name, "r+", &pid);
                    360: #ifdef POPEN_STREAM
                    361:                        if (!f) {
                    362: #else
                    363:                        if (f == -1) {
                    364: #endif
                    365:                                LOGERR;
                    366:                                ret = -1;
                    367:                                break;
                    368:                        } else if (waitpid(pid, &stat, WNOHANG)) {
                    369:                                io_SetErr(ECHILD, "Program with pid=%d exit with status %d", 
                    370:                                                pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
                    371:                                e_pclose(f);
                    372:                                ret = -1;
                    373:                                break;
                    374:                        } else
1.3       misho     375:                                array_Set(prg->prog_fds, i, (intptr_t) f);
1.2       misho     376:                        clrbit(prg->prog_used, i);
                    377:                        prg->prog_cnum++;
                    378:                        ret++;
                    379:                }
                    380:        pthread_mutex_unlock(&prg->prog_mtx);
                    381: 
                    382:        return ret;
                    383: }
                    384: 
                    385: /*
                    386:  * io_progGrow() - Execute to number of programs in pool
                    387:  *
                    388:  * @prg = program pool
                    389:  * @toNum = execute to number of programs (0 max)
                    390:  * return: 0 error or nothing to do, 
                    391:  *     >0 executed programs and abs(<0) executed programs with logged error
                    392:  */
                    393: int
                    394: io_progGrow(prog_t * __restrict prg, u_int toNum)
                    395: {
                    396:        if (!prg)
                    397:                return 0;
                    398:        if (toNum > prg->prog_maxn) {
                    399:                io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
                    400:                return 0;
                    401:        }
                    402:        if (!toNum)
                    403:                toNum = prg->prog_maxn;
                    404:        if (toNum < prg->prog_inin)
                    405:                toNum = prg->prog_inin;
                    406: 
                    407:        if ((int) (toNum - prg->prog_cnum) < 1)
                    408:                return 0;
                    409: 
                    410:        return io_progOpen(prg, toNum - prg->prog_cnum);
                    411: }
                    412: 
                    413: /*
                    414:  * io_progVacuum() - Vacuum pool to running number of programs
                    415:  *
                    416:  * @prg = program pool
                    417:  * @toNum = vacuum to number of programs (0 to init number)
                    418:  * return: 0 error or >0 closed programs
                    419:  */
                    420: int
                    421: io_progVacuum(prog_t * __restrict prg, u_int toNum)
                    422: {
                    423:        register int i;
                    424:        int ret = 0;
                    425:        struct tagPIOPID *p;
                    426: 
                    427:        if (!prg)
                    428:                return 0;
                    429:        if (toNum > prg->prog_maxn) {
                    430:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
                    431:                return 0;
                    432:        }
                    433:        if (!toNum)
                    434:                toNum = prg->prog_inin;
                    435: 
                    436:        pthread_mutex_lock(&prg->prog_mtx);
                    437:        for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)
                    438:                if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i) && 
                    439: #ifdef POPEN_STREAM
                    440:                                (p = pio_pgetpid(array(prg->prog_fds, i, FILE*)))) {
                    441:                        kill(p->pid, SIGTERM);
                    442:                        usleep(1000);
                    443:                        if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
                    444:                                kill(p->pid, SIGKILL);
                    445:                        e_pclose(array(prg->prog_fds, i, FILE*));
                    446: #else
                    447:                                (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t)))) {
                    448:                        kill(p->pid, SIGTERM);
                    449:                        usleep(1000);
                    450:                        if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
                    451:                                kill(p->pid, SIGKILL);
                    452:                        e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    453: #endif
                    454:                        array_Del(prg->prog_fds, i, 0);
                    455:                        prg->prog_cnum--;
                    456:                        ret++;
                    457:                }
                    458:        pthread_mutex_unlock(&prg->prog_mtx);
                    459: 
                    460:        return ret;
                    461: }
                    462: 
                    463: /*
                    464:  * io_progCheck() - Check exit status of program pool
                    465:  *
                    466:  * @prg = program pool
                    467:  * @re = resurrect program to init number
                    468:  * return: -1 error or >-1 exited programs
                    469:  */
                    470: int
                    471: io_progCheck(prog_t * __restrict prg, int re)
                    472: {
                    473:        int ret = 0;
                    474:        struct tagPIOPID *p;
                    475:        register int i;
                    476: 
                    477:        if (!prg)
                    478:                return -1;
                    479: 
                    480:        pthread_mutex_lock(&prg->prog_mtx);
                    481:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    482:                if (array_Get(prg->prog_fds, i) && 
                    483: #ifdef POPEN_STREAM
                    484:                                (p = pio_pgetpid(array(prg->prog_fds, i, FILE*)))) {
                    485: #else
                    486:                                (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t)))) {
                    487: #endif
                    488:                        if (waitpid(p->pid, &p->stat, WNOHANG)) {
                    489:                                clrbit(prg->prog_used, i);
                    490: #ifdef POPEN_STREAM
                    491:                                e_pclose(array(prg->prog_fds, i, FILE*));
                    492: #else
                    493:                                e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    494: #endif
                    495:                                array_Del(prg->prog_fds, i, 0);
                    496:                                prg->prog_cnum--;
                    497:                                ret++;
                    498:                        }
                    499:                }
                    500:        pthread_mutex_unlock(&prg->prog_mtx);
                    501: 
                    502:        /* resurrect to init number */
                    503:        if (re && ((int) (prg->prog_inin - prg->prog_cnum) > 0))
                    504:                io_progOpen(prg, prg->prog_inin - prg->prog_cnum);
                    505: 
                    506:        return ret;
                    507: }
                    508: 
                    509: /*
                    510:  * io_progAttach() - Attach to open program
                    511:  *
                    512:  * @prg = program pool
                    513:  * @newOne = Execute new one program after attach
                    514:  * return: NULL error or !=NULL attached program handle
                    515:  */
                    516: #ifdef POPEN_STREAM
                    517: FILE *
                    518: #else
                    519: int
                    520: #endif
                    521: io_progAttach(prog_t * __restrict prg, int newOne)
                    522: {
                    523: #ifdef POPEN_STREAM
                    524:        FILE *f = NULL;
                    525: #else
                    526:        int f = -1;
                    527: #endif
                    528:        register int i;
                    529: 
                    530:        if (!prg)
                    531: #ifdef POPEN_STREAM
                    532:                return NULL;
                    533: #else
                    534:                return -1;
                    535: #endif
                    536: 
                    537:        pthread_mutex_lock(&prg->prog_mtx);
                    538:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    539:                if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
                    540:                        setbit(prg->prog_used, i);
                    541: #ifdef POPEN_STREAM
                    542:                        f = array(prg->prog_fds, i, FILE*);
                    543: #else
                    544:                        f = array(prg->prog_fds, i, intptr_t);
                    545: #endif
                    546:                        break;
                    547:                }
                    548:        pthread_mutex_unlock(&prg->prog_mtx);
                    549: 
                    550:        /* execute new one program */
                    551:        if (newOne) {
                    552:                if (f)
                    553:                        io_progOpen(prg, 1);
                    554:                else if ((i = io_progOpen2(prg)) > -1)
                    555:                        /* not found free program */
                    556: #ifdef POPEN_STREAM
                    557:                        f = array(prg->prog_fds, i, FILE*);
                    558: #else
                    559:                        f = array(prg->prog_fds, i, intptr_t);
                    560: #endif
                    561:        }
                    562: 
                    563:        return f;
                    564: }
                    565: 
                    566: /*
                    567:  * io_progDetach() - Detch from open program
                    568:  *
                    569:  * @prg= program pool
                    570:  * @pfd = attached program handle
                    571:  * return: none
                    572:  */
                    573: void
                    574: #ifdef POPEN_STREAM
                    575: io_progDetach(prog_t * __restrict prg, FILE *pfd)
                    576: #else
                    577: io_progDetach(prog_t * __restrict prg, int pfd)
                    578: #endif
                    579: {
                    580:        register int i;
                    581: 
                    582:        if (!prg || !pfd)
                    583:                return;
                    584: 
                    585:        pthread_mutex_lock(&prg->prog_mtx);
                    586:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    587: #ifdef POPEN_STREAM
                    588:                if (array(prg->prog_fds, i, FILE*) == pfd) {
                    589: #else
                    590:                if (array(prg->prog_fds, i, intptr_t) == pfd) {
                    591: #endif
                    592:                        clrbit(prg->prog_used, i);
                    593:                        break;
                    594:                }
                    595:        pthread_mutex_unlock(&prg->prog_mtx);
                    596: }

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