void sig_handler(int sig) { t_sh *shell; shell = get_sh_info(NULL); SETFLAG(shell->signal, FLAGPOS(sig)); if (sig == SIGINT) { my_putstr("\n", 1, -1); my_putstr(shell->param.str_prompt, 1, -1); if (shell->param.fallback == 1) { if (shell->param.cmd != NULL) shell->param.cmd[0] = '\0'; shell->param.pos = 0; refresh_view(&(shell->param)); view(shell->param.cmd, &(shell->param)); } } if (sig == SIGWINCH && shell->param.fallback == 1) clear_cmd(shell->param.cmd, &(shell->param)); if ((sig == SIGHUP) || (sig == SIGTERM) || (sig == SIGQUIT)) { SETFLAG(shell->beepbeepexit, FLAGPOS(EXIT_F_POS)); close(0); } init_sig(&sig_handler); }
void builtin_fg(t_cmd *cmd, UNSEDP t_fds *fd, t_sh *shell) { int pgid; int i; int nb; i = 0; nb = 0; if (shell->process_group == NULL || !shell->jobcontrol) return ; if (cmd->argv[1] != NULL) nb = my_getnbr(cmd->argv[1]) - 1; while ((shell->process_group[i] != NULL) && (i < nb)) i++; if (shell->process_group[i] != NULL) { pgid = shell->process_group[i]->pid.pgid; if (pgid != -1) { SETFLAG(shell->process_group[i]->flags, FLAGPOS(FGRP_FORGROUND)); SETFLAG(shell->process_group[i]->flags, FLAGPOS(FGRP_RUNNING)); if (set_forground_pgrp(pgid) == -1) set_forground_pgrp(shell->pid.pgid); kill(-pgid, SIGCONT); } } }
void builtin_exit(t_cmd *cmd, UNSEDP t_fds *fd, t_sh *shell) { if (cmd->argv[1] != NULL) shell->beepbeepexit = my_getnbr(cmd->argv[1]); else shell->beepbeepexit = 0; SETFLAG(shell->beepbeepexit, FLAGPOS(EXIT_F_POS)); UNSETFLAG(shell->beepbeepexit, FLAGPOS(EXIT_FORK)); }
void no_fg_jobs_status(t_sh *shell) { t_grp *fg_grp; if ((fg_grp = get_forground_grp(shell)) != NULL) { UNSETFLAG(fg_grp->flags, FLAGPOS(FGRP_RUNNING)); UNSETFLAG(fg_grp->flags, FLAGPOS(FGRP_FORGROUND)); set_forground_pgrp(shell->pid.pgid); } }
int exec_process(t_cmd *cmd, t_fds *fd, t_sh *shell, int (*f)(char *cmd, char **argv, t_sh *shell)) { int ret_exec; if ((cmd->pid.pid = check_perror("Fork", fork())) == 0) { if (cmd->pid.pgid != -1) { if (check_perror("Setpgid", setpgid(0, cmd->pid.pgid)) == -1) check_perror("Setpgid", setpgid(0, 0)); } else check_perror("Setpgid", setpgid(0, 0)); check_perror("Dup2", dup2(fd->stdin, 0)); check_perror("Dup2", dup2(fd->stdout, 1)); check_perror("Dup2", dup2(fd->stderr, 2)); if ((ret_exec = f(cmd->cmd_fpath, cmd->argv, shell)) == -1) my_perror(cmd->cmd_fpath); my_exit(ret_exec); SETFLAG(shell->beepbeepexit, FLAGPOS(EXIT_FORK)); } else if (cmd->pid.pid != -1) check_grp_set(cmd->pid.pid, (cmd->pid.pgid == -1) ? cmd->pid.pid : cmd->pid.pgid); return (cmd->pid.pid); }
t_grp *get_forground_grp(t_sh *shell) { int i; t_grp **pr_grp; t_grp *tmp_grp; i = 0; pr_grp = shell->process_group; if (pr_grp == NULL) return (NULL); while ((tmp_grp = pr_grp[i]) != NULL) { if (GETFLAG(tmp_grp->flags, FLAGPOS(FGRP_FORGROUND)) && !GETFLAG(tmp_grp->flags, FLAGPOS(FGRP_TERMINATED))) return (tmp_grp); i++; } return (NULL); }
void set_forground_process_g(t_sh *shell, t_grp *grp) { int i; t_grp *tmp_grp; i = 0; if (shell->process_group == NULL) return ; while ((tmp_grp = shell->process_group[i]) != NULL) { if (tmp_grp == grp) { SETFLAG(tmp_grp->flags, FLAGPOS(FGRP_FORGROUND)); if (set_forground_pgrp(grp->pid.pgid) == -1) set_forground_pgrp(shell->pid.pgid); } else UNSETFLAG(tmp_grp->flags, FLAGPOS(FGRP_FORGROUND)); i++; } }
int exec_process_group(t_sh *shell, t_grp *grp) { int tmp; if (grp == NULL) return (-1); if ((tmp = (is_grp_exec(shell, grp) - 1)) != -1) tmp = open_redirection(grp, shell); if (MEXIT) return (0); if (tmp != -1) if ((exec_a_pipe(shell, grp) == -1) || (MEXIT)) return (-1); shell->process_group = (t_grp**)add_ptr_t_tab((void**)shell->process_group, (void*)grp); if (GETFLAG(grp->flags, FLAGPOS(FGRP_FORGROUND)) && (grp->pid.pgid != -1)) set_forground_process_g(shell, grp); else UNSETFLAG(grp->flags, FLAGPOS(FGRP_FORGROUND)); return (0); }
void rm_all_terminated_grp(t_sh *shell) { int i; t_grp *grp; i = 0; if (shell != NULL) while ((shell->process_group != NULL) && (grp = shell->process_group[i]) != NULL) { if (GETFLAG(grp->flags, FLAGPOS(FGRP_TERMINATED))) { i = 0; free_process_group(grp); rm_ptr_f_tab((void**)shell->process_group, (void*)grp); } i++; } }
void builtin_bg(t_cmd *cmd, UNSEDP t_fds *fd, t_sh *shell) { int pgid; int i; int nb; i = 0; nb = 0; if (shell->process_group == NULL) return ; if (cmd->argv[1] != NULL) nb = my_getnbr(cmd->argv[1]) - 1; while ((shell->process_group[i] != NULL) && (i < nb)) i++; if (shell->process_group[i] != NULL) { pgid = shell->process_group[i]->pid.pgid; SETFLAG(shell->process_group[i]->flags, FLAGPOS(FGRP_RUNNING)); kill(-pgid, SIGCONT); } }
void FastDup::Compare(FileReference *first, off_t filesize, DupeSetCallback callback) { int blockcount = (int)ceil(filesize / BLOCKSIZE); int fcount = 0; for (FileReference *p = first; p; p = p->next) ++fcount; bool progress = (Interactive && (filesize*fcount >= 3*1048576)); int ipint = 0; if (progress) { ipint = (int)ceil(double(blockcount*fcount)/100); printf("Comparing %d files... \E[s0%%", fcount); fflush(stdout); } /* FDs */ int ffd[fcount]; /* File reference map, used afterwards to map back to the real file */ FileReference *frmap[fcount]; /* Data buffers */ char *rrdbuf = new char[fcount * BLOCKSIZE]; char *rdbuf[fcount]; ssize_t rdbp = 0; /* Matchflag is 1 for each file pair that may still match, 0 * for pairs that cannot match, or 2 indicating that the current * block of both files is known to match (which will be reset * to 1 before the next block). * * To save space, a somewhat complex equation is used to calculate * the positions of the flag for a given pair of files (i and j). * The result of this equation is to map them so that, if there are * 3 files total, [0] is 0 & 1, [1] is 0 & 2, [2] is 1 & 2, and * no space is wasted. * * To calculate the position for files i and j with a maximum of f * files, assuming that j > i, use: * int(((f-1)*i)-(i*(i/2.0-0.5))+(j-i)-1); */ char matchflag[(fcount*(fcount-1))/2]; #define FLAGPOS(i,j) int(((fcount-1)*(i))-((i)*((i)/2.0-0.5))+((j)-(i))-1) /* Holds the result for the matching of the current file (i) against * all other TESTED files, by the index of the second file (j). Note * that many parts of this may be left untouched due to other * optimizations preventing a comparison. Use only when that * information is known. Values are identical to the return of * memcmp; -1 for i < j, 0 for i == j, 1 for i > j. * * Used to avoid comparisons by finding when two other files cannot * match this block, or must match this block (i.e. i > j and i < k, * or i == j and i == k). */ int mresult[fcount]; /* Omit is true for files that have no possible matches left. These * are not read or processed at all. */ bool omit[fcount]; /* Number of files omitted; used to end early if we run out of possible * matches */ int omitted = 0; /* Used to calculate omit, by keeping track of the number of comparisons * with other files that have been skipped against this file. When this * reaches fcount for a given file index, that file may be omitted. */ int skipcount[fcount]; memset(matchflag, 1, sizeof(matchflag)); memset(omit, false, sizeof(omit)); memset(skipcount, 0, sizeof(skipcount)); int i = 0, j = 0; for (FileReference *p = first; p; p = p->next, ++i) { frmap[i] = p; const char *fn = p->FullPath(); rdbuf[i] = rrdbuf + (BLOCKSIZE * i); if ((ffd[i] = open(fn, O_RDONLY)) < 0) { printf("Unable to open file '%s': %s\n", fn, strerror(errno)); // Note: if handled in any other way, clean up open FDs and rrdbuf exit(EXIT_FAILURE); } } // Loop over blocks of the files, which will be compared int ti = 0; for (int block = 0;; ++block) { for (i = 0; i < fcount; i++) { if (omit[i]) continue; rdbp = read(ffd[i], rdbuf[i], BLOCKSIZE); if (progress && (++ti == ipint)) { ti = 0; fprintf(stdout, "\E[u%d%%", int((double((block+1)*(i+1))/(blockcount*fcount))*100)); fflush(stdout); } if (rdbp < 0) { printf("%d: Read error: %s\n", i, strerror(errno)); // Note: if handled in any other way, cleanup exit(EXIT_FAILURE); } else if (!rdbp) { // All files are assumed to be equal in size break; } } if (!rdbp) break; for (i = 0; i < fcount; i++) { if (omit[i]) continue; for (j = i + 1; j < fcount; j++) { if (omit[j]) continue; int flagpos = FLAGPOS(i, j); if (!matchflag[flagpos]) continue; else if (matchflag[flagpos] == 2) { matchflag[flagpos] = 1; mresult[j] = 0; } else mresult[j] = memcmp(rdbuf[i], rdbuf[j], rdbp); for (int k = j - 1; k > i; --k) { if (omit[k]) continue; int kflagpos = FLAGPOS(k, j); if (!matchflag[kflagpos]) continue; if (mresult[k] != mresult[j]) { matchflag[kflagpos] = 0; ++skipcount[j]; if (++skipcount[k] == fcount - 1) { omit[k] = true; close(ffd[k]); ffd[k] = -1; omitted++; } } else if (mresult[k] == 0 && mresult[j] == 0) { /* These will be equal, so we can avoid comparing them; signal this by setting * matchflag to 2 for this block (it is one-shot, and will be reset before the * next block). This is a huge saver when there is more than one duplicate of * the same file. */ matchflag[kflagpos] = 2; } } if (mresult[j] != 0) { matchflag[flagpos] = 0; skipcount[i]++; if (++skipcount[j] == fcount - 1) { omit[j] = true; close(ffd[j]); ffd[j] = -1; omitted++; } } } if (skipcount[i] == fcount - 1) { omit[i] = true; close(ffd[i]); ffd[i] = -1; if (++omitted == fcount) goto endscan; } } }