/* * simple test program for libexec * * (c) 2024 Dario Rodriguez * This file is in the public domain. */ #include #include #include #include #include #include #include #include "libexec.h" volatile int flag_sigint; volatile int flag_sigchld; void sigchld(int sig); void sigint(int sig); int main(int argc, char *argv[], char *envp[]) { struct timeval tv; exec_t *dateexec,*echoexec,*catexec; exec_t *exec; fd_set readset,writeset; flag_sigchld=flag_sigint=0; int maxfd; int i; int queued,nread; int fd; char *fdname; time_t curtimet,lasttimet; executil_installsignal(SIGINT,sigint); executil_installsignal(SIGCHLD,sigchld); dateexec=exec_init("date","/bin/sh -c \"while true ; do sleep 1 ; date ; echo . >&2 ; done\"",envp); echoexec=exec_init("echo","/bin/echo \"%s\"",envp); catexec=exec_init("cat","/bin/cat",envp); exec_open(dateexec,NULL); exec_open(catexec,NULL); lasttimet=0; while(flag_sigint==0) { int *readfds[]={ &(dateexec->fdout), &(dateexec->fderr), &(echoexec->fdout), &(echoexec->fderr), &(catexec->fdout), &(catexec->fderr), }; if(flag_sigchld) { exec_t *execs[]={dateexec,echoexec,catexec}; flag_sigchld=0; exec_reap(dateexec,echoexec,catexec,NULL); for(i=0;i<(sizeof(execs)/sizeof(execs[0]));i++) { exec=execs[i]; if(exec->laststatus!=-1) fprintf(stderr,"%s: exited with status %i\n",exec->name,exec->laststatus),exec->laststatus=-1; } } tv.tv_sec=1,tv.tv_usec=0; maxfd=0; FD_ZERO(&readset); for(i=0;i<(sizeof(readfds)/sizeof(readfds[0]));i++) { if(*(readfds[i])==-1) continue; FD_SET(*(readfds[i]),&readset); maxfd=(maxfd<*(readfds[i]))?*(readfds[i]):maxfd; } FD_ZERO(&writeset); curtimet=time(NULL); if(catexec->fdin!=-1 && curtimet!=lasttimet) { FD_SET(catexec->fdin,&writeset); maxfd=(maxfdfdin)?catexec->fdin:maxfd; } select(maxfd+1,&readset,&writeset,NULL,&tv); #if 1 fprintf(stderr,"ITERATION\n"); #endif for(i=0;i<(sizeof(readfds)/sizeof(readfds[0]));i++) { if(*(readfds[i])==-1 || !FD_ISSET(*(readfds[i]),&readset) || (exec=executil_fd2exec(*(readfds[i]),dateexec,echoexec,catexec,NULL))==NULL) continue; fd=*(readfds[i]); fdname=(fd==exec->fdout)?"stdout":"stderr"; queued=executil_queued(fd); if(queued<=0) { /* remote closed connection */ fprintf(stderr,"%s:%s: remote closed connection (queued:%i)\n",exec->name,fdname,queued); exec_close(exec); continue; } else { char buf[1024]; queued=(queued>(sizeof(buf)-1))?(sizeof(buf)-1):queued; if((nread=read(fd,buf,queued))name,fdname,nread,queued); exec_close(exec); } buf[nread]='\0'; fprintf(stderr,"%s:%s: read \"",exec->name,fdname); fwrite(buf,1,nread,stderr); fprintf(stderr,"\"\n"); } } if(catexec->fdin!=-1 && FD_ISSET(catexec->fdin,&writeset)) { char msg[32]; snprintf(msg,sizeof(msg),"%li\n",(long)curtimet); msg[sizeof(msg)-1]='\0'; write(catexec->fdin,msg,strlen(msg)); lasttimet=curtimet; } if((time(NULL)%5)==0) { exec_open(echoexec,"multi 5s"); } } return(0); } void sigint(int sig) { flag_sigint++; } void sigchld(int sig) { flag_sigchld++; }