📄 execunix.c
字号:
if (cmdtab[slot].stream[ERR] == NULL) { perror( "fdopen" ); exit( EXITBAD ); } } /* ensure enough room for rule and target name */ if (action && target) { len = strlen(action) + 1; if (cmdtab[slot].action_length < len) { BJAM_FREE(cmdtab[ slot ].action); cmdtab[ slot ].action = BJAM_MALLOC_ATOMIC(len); cmdtab[ slot ].action_length = len; } strcpy(cmdtab[ slot ].action, action); len = strlen(target) + 1; if (cmdtab[slot].target_length < len) { BJAM_FREE(cmdtab[ slot ].target); cmdtab[ slot ].target = BJAM_MALLOC_ATOMIC(len); cmdtab[ slot ].target_length = len; } strcpy(cmdtab[ slot ].target, target); } else { BJAM_FREE(cmdtab[ slot ].action); BJAM_FREE(cmdtab[ slot ].target); cmdtab[ slot ].action = 0; cmdtab[ slot ].target = 0; cmdtab[ slot ].action_length = 0; cmdtab[ slot ].target_length = 0; } /* Save the operation for execwait() to find. */ cmdtab[ slot ].func = func; cmdtab[ slot ].closure = closure; /* Wait until we're under the limit of concurrent commands. */ /* Don't trust globs.jobs alone. */ while( cmdsrunning >= MAXJOBS || cmdsrunning >= globs.jobs ) if( !execwait() ) break;}/* returns 1 if file is closed, 0 if descriptor is still live * * i is index into cmdtab * * s (stream) indexes * * cmdtab[i].stream[s] * cmdtab[i].buffer[s] and * cmdtab[i].fd[s] */int read_descriptor(int i, int s){ int ret, len; char buffer[BUFSIZ]; while (0 < (ret = fread(buffer, sizeof(char), BUFSIZ-1, cmdtab[i].stream[s]))) { buffer[ret] = 0; if (!cmdtab[i].buffer[s]) { /* never been allocated */ cmdtab[i].buffer[s] = (char*)BJAM_MALLOC_ATOMIC(ret+1); memcpy(cmdtab[i].buffer[s], buffer, ret+1); } else { /* previously allocated */ char *tmp = cmdtab[i].buffer[s]; len = strlen(tmp); cmdtab[i].buffer[s] = (char*)BJAM_MALLOC_ATOMIC(len+ret+1); memcpy(cmdtab[i].buffer[s], tmp, len); memcpy(cmdtab[i].buffer[s]+len, buffer, ret+1); BJAM_FREE(tmp); } } return feof(cmdtab[i].stream[s]);}void close_streams(int i, int s){ /* close the stream and pipe descriptor */ fclose(cmdtab[i].stream[s]); cmdtab[i].stream[s] = 0; close(cmdtab[i].fd[s]); cmdtab[i].fd[s] = 0;}void populate_file_descriptors(int *fmax, fd_set *fds){ int i, fd_max = 0; struct tms buf; clock_t current = times(&buf); select_timeout = globs.timeout; /* compute max read file descriptor for use in select */ FD_ZERO(fds); for (i=0; i<globs.jobs; ++i) { if (0 < cmdtab[i].fd[OUT]) { fd_max = fd_max < cmdtab[i].fd[OUT] ? cmdtab[i].fd[OUT] : fd_max; FD_SET(cmdtab[i].fd[OUT], fds); } if (globs.pipe_action != 0) { if (0 < cmdtab[i].fd[ERR]) { fd_max = fd_max < cmdtab[i].fd[ERR] ? cmdtab[i].fd[ERR] : fd_max; FD_SET(cmdtab[i].fd[ERR], fds); } } if (globs.timeout && cmdtab[i].pid) { clock_t consumed = (current - cmdtab[i].start_time) / tps; clock_t process_timesout = globs.timeout - consumed; if (0 < process_timesout && process_timesout < select_timeout) { select_timeout = process_timesout; } if (globs.timeout <= consumed) { killpg(cmdtab[i].pid, SIGKILL); cmdtab[i].exit_reason = EXIT_TIMEOUT; } } } *fmax = fd_max;}/* * execwait() - wait and drive at most one execution completion */intexecwait(){ int i, ret, fd_max; int pid, status, finished; int rstat; timing_info time_info; fd_set fds; struct tms new_time; /* Handle naive make1() which doesn't know if cmds are running. */ if( !cmdsrunning ) return 0; /* process children that signaled */ finished = 0; while (!finished && cmdsrunning) { /* compute max read file descriptor for use in select */ populate_file_descriptors(&fd_max, &fds); if (0 < globs.timeout) { /* force select to timeout so we can terminate expired processes */ tv.tv_sec = select_timeout; tv.tv_usec = 0; /* select will wait until: io on a descriptor, a signal, or we time out */ ret = select(fd_max+1, &fds, 0, 0, &tv); } else { /* select will wait until io on a descriptor or a signal */ ret = select(fd_max+1, &fds, 0, 0, 0); } if (0 < ret) { for (i=0; i<globs.jobs; ++i) { int out = 0, err = 0; if (FD_ISSET(cmdtab[i].fd[OUT], &fds)) out = read_descriptor(i, OUT); if (FD_ISSET(cmdtab[i].fd[ERR], &fds)) err = read_descriptor(i, ERR); /* if feof on either descriptor, then we're done */ if (out || err) { /* close the stream and pipe descriptors */ close_streams(i, OUT); if (globs.pipe_action != 0) close_streams(i, ERR); /* reap the child and release resources */ pid = waitpid(cmdtab[i].pid, &status, 0); if (pid == cmdtab[i].pid) { finished = 1; pid = 0; cmdtab[i].pid = 0; /* set reason for exit if not timed out */ if (WIFEXITED(status)) { if (0 == WEXITSTATUS(status)) cmdtab[i].exit_reason = EXIT_OK; else cmdtab[i].exit_reason = EXIT_FAIL; } /* print out the rule and target name */ out_action(cmdtab[i].action, cmdtab[i].target, cmdtab[i].command, cmdtab[i].buffer[OUT], cmdtab[i].buffer[ERR], cmdtab[i].exit_reason); times(&new_time); time_info.system = (double)(new_time.tms_cstime - old_time.tms_cstime) / CLOCKS_PER_SEC; time_info.user = (double)(new_time.tms_cutime - old_time.tms_cutime) / CLOCKS_PER_SEC; time_info.start = cmdtab[i].start_dt; time_info.end = time(0); old_time = new_time; /* Drive the completion */ --cmdsrunning; if( intr ) rstat = EXEC_CMD_INTR; else if( status != 0 ) rstat = EXEC_CMD_FAIL; else rstat = EXEC_CMD_OK; /* assume -p0 in effect so only pass buffer[0] containing merged output */ (*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat, &time_info, cmdtab[i].command, cmdtab[i].buffer[0] ); BJAM_FREE(cmdtab[i].buffer[OUT]); cmdtab[i].buffer[OUT] = 0; BJAM_FREE(cmdtab[i].buffer[ERR]); cmdtab[i].buffer[ERR] = 0; BJAM_FREE(cmdtab[i].command); cmdtab[i].command = 0; cmdtab[i].func = 0; cmdtab[i].closure = 0; cmdtab[i].start_time = 0; } else { printf("unknown pid %d with errno = %d\n", pid, errno); exit(EXITBAD); } } } } } return 1;}# endif /* USE_EXECUNIX */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -