#include "tcb.h" #include #include #include #include #include static struct { void (*segv)(int); int abort; /* mark for segmentation fault */ jmp_buf jb; } Init; static void init_clear(int dummy) { signal(SIGSEGV, Init.segv); Init.abort = 1; longjmp(Init.jb, 0); } void init_man(BASE *bp, FILE **pinp, char name[], u_char prev[], char arg[], int *klenp)/*tcb*/ { int pid; free_bp(bp); sprintf(arg, "%c%c", K_z, 0); *pinp = fork_man(&pid, name); bp->pp = alloc_pipe(T_man, pinp, &bp->nrow, bp, strlen(name), pid); bp->nrow = 1; while (*pinp && bp->nrow < vt_row(0)) alloc_pipe(0, pinp, &bp->nrow, NULL, 0, 0); if (!bp->pp) make_bp(bp, s_S(S_err6), NULL, NULL); } int init_pipe(BASE *bp, FILE **pinp, int f_Mb, char mess[], char prev[], char arg[], int *klenp, CHILD **chpp, int ppid)/*tcb*/ { int f_M, nlen, pid = 0; char *p; free_bp(bp); if (f_Mb == T_pipe) { f_M = f_Mb; f_Mb = 1; *chpp = NULL; } else { f_M = f_Mb; if ((*chpp = check_ext(mess, NULL, 0)) && is_chp(*chpp, NULL)) sprintf(arg, " (%s)", (*chpp)->argv[0]); else *chpp = NULL; } if (!*chpp) sprintf(arg, "%c%c", K_z, 0); p = (f_M == T_pipe2) ? s_P(P_mode)[T_pipe2] : mess; nlen = disp_window(bp->pp, bp->pp, f_M, p, prev, arg, klenp); bp->pp = alloc_pipe(f_Mb, pinp, &bp->nrow, bp, nlen, ppid); if ((f_M == T_pipe || f_M == T_pipe2) && !(pid = fork())) { int c; while (1) { if ((c = vt_getch(1))) if (f_M == T_pipe) { killpg(getpgrp(), SIGINT); break; } else if (ppid) { kill(ppid, SIGHUP); /* ==> from_shell() */ break; } } echo_mess(S_err0); exit(0); } while (*pinp && bp->nrow < vt_row(0)) alloc_pipe(0, pinp, &bp->nrow, NULL, 0, 0); if (pid && !kill(pid, 0)) kill(pid, SIGKILL); print_line(bp->pp, bp->pp, -nlen, NULL); return nlen; } void init_cut(BASE *bp, char name[], u_char str[], BASE *cut_bp)/*tcb*/ { int f_M, code; Init.abort = 0; Init.segv = signal(SIGSEGV, init_clear); setjmp(Init.jb); if (Init.abort) { make_bp(bp, strerror(EINVAL), name, s_S(S_err8)); return; } free_bp(bp); if (!(bp->buff = fork_grep(&bp->size, str, cut_bp->pp, 0))) make_bp(bp, (access(s_S(S_intr), F_OK) < 0) ? s_S(S_err2) : s_S(S_err0), name, NULL); else { bp->buff = check_type(bp->buff, &bp->size, NULL, &f_M, 3, &code); bp->nrow = cut_bp->nrow + 1; bp->pp = alloc_pp(bp->buff, M_cut, bp->size, &bp->nrow, name); } signal(SIGSEGV, Init.segv); } void init_cut2(BASE *bp, u_char *buff, char name[], u_char str[])/*tcb*/ { struct stat st; int f_M, code; Init.abort = 0; Init.segv = signal(SIGSEGV, init_clear); setjmp(Init.jb); if (Init.abort) { make_bp(bp, strerror(EINVAL), name, s_S(S_err8)); return; } free_bp(bp); if (!(bp->buff = (buff) ? fork_grep3(&bp->size, buff, str, name) : fork_grep2(&bp->size, str, name))) make_bp(bp, (access(s_S(S_intr), F_OK) < 0) ? s_S(S_err2) : s_S(S_err0), name, NULL); else { bp->buff = check_type(bp->buff, &bp->size, NULL, &f_M, 3, &code); if (*name == ' ') sscanf(name, "%d", (int*)(&(st.st_size))); else stat(name, &st); bp->nrow = st.st_size; bp->pp = alloc_pp(bp->buff, M_cut, bp->size, &bp->nrow, name); } signal(SIGSEGV, Init.segv); } CHILD *init_arc(BASE *bp, char name[], u_int bsize, u_char prev[], char arg[], PP *pp, int f_cr)/*tcb*/ { int size, f_M, code; u_char *buff, *buff2; CHILD *roff; static CHILD *chp = NULL; Init.abort = 0; Init.segv = signal(SIGSEGV, init_clear); setjmp(Init.jb); if (Init.abort) { make_bp(bp, strerror(EINVAL), name, s_S(S_err8)); return chp; } if (!(bp->size = pp->split)) make_bp(bp, s_S(S_err1), name, NULL); else { strcpy(arg, name); if (bp->size > bsize) bp->size = bsize; while (!(bp->buff = malloc(bp->size + 2)) && (bp->size /= 2)) ; memcpy(bp->buff, (u_char*)pp->tell, bp->size); do { chp = check_ext(arg, bp->buff, bp->size); if (!f_cr || !chp) { if (chp) chp = NULL; *arg = '\0'; } else if (chp->f.exec) { fork_exec(chp, arg, bp->buff, bp->size); signal(SIGSEGV, Init.segv); return (CHILD*)EOE; } else { buff = fork_chp(chp, bp->buff, &bp->size, arg); if (bp->size) { if ((roff = check_ext(NULL, buff, bp->size))) { buff2 = fork_chp(roff, buff, &bp->size, arg); free(buff); buff = buff2; chp = roff; } free(bp->buff); bp->buff = buff; continue; } } *arg = '\0'; } while (0); if (!bp->size) make_bp(bp, strerror(EINVAL), name, NULL); else { size = bp->size; bp->buff = check_type(bp->buff, &bp->size, NULL, &f_M, f_cr, &code); bp->pp = set_pp(bp->buff, bp->size, &bp->nrow, (code == C_bin), 0); if (f_M == T_type) { if (check_chp(S_file)) chp = get_child(NULL, "...", s_S(S_file), NULL); else chp = NULL; bp->size = size; } } } signal(SIGSEGV, Init.segv); return chp; } FILE *init_arc2(BASE *bp, PP *pp, char name[], char arg[], int *ppid)/*tcb*/ { u_char *cp; int i, f_chp, pid, pv[6]; CHILD *chp, *chp2; FILE *fp; if (!pp->split) { make_bp(bp, s_S(S_err1), name, NULL); return EOP; } f_chp = 0; chp2 = NULL; cp = name; if ((chp = check_ext(name, NULL, 0)) && (f_chp = is_chp(chp, NULL))) switch(f_chp) { case 2: /* bzip2 */ chp = get_child(NULL, NULL, s_S(S_bzip2), NULL); /* set -d option */ case 1: /* gzip etc. */ case 4: /* lha */ case 5: /* tar */ strcpy(chp->argv[chp->f.argc], "-"); break; case 3: /* unzip */ strcpy(chp->argv[chp->f.argc], s_S(S_tmp)); break; case 7: /* bzip2+tar */ case 6: /* gzip+tar */ chp2 = (f_chp == 7) ? get_child(NULL, NULL, s_S(S_bzip2), NULL) : (CHILD*)chp->argv[chp->f.argc + 1]; strcpy(chp2->argv[chp2->f.argc], "-"); break; default: break; } else chp = NULL; pipe(pv); if (!(pid = fork())) { signal(SIGPIPE, SIG_DFL); if (chp) { pipe(&pv[2]); if (!fork()) { if (chp2) { pipe(&pv[4]); if (!fork()) { close(pv[4]); fp = fdopen(pv[5], "w"); cp = (u_char*)pp->tell; for (i = pp->split; i > 0; i -= N_pipe, cp += N_pipe) fwrite(cp, 1, (i - N_pipe < 0) ? i : N_pipe, fp); fclose(fp); exit(0); } close(0); dup2(pv[4], 0); close(pv[4]); close(pv[5]); close(1); dup2(pv[3], 1); close(pv[3]); close(pv[2]); execvp(*chp2->argv, chp2->argv); } else { close(pv[2]); fp = fdopen(pv[3], "w"); cp = (u_char*)pp->tell; for (i = pp->split; i > 0; i -= N_pipe, cp += N_pipe) fwrite(cp, 1, (i - N_pipe < 0) ? i : N_pipe, fp); fclose(fp); exit(0); } } dup_error(); close(0); dup2(pv[2], 0); close(pv[2]); close(pv[3]); close(1); dup2(pv[1], 1); close(pv[1]); close(pv[0]); if (f_chp == 3) { fp = fopen(s_S(S_tmp), "w"); while ((i = fgetc(stdin)) != EOF) fputc(i, fp); fclose(fp); } execvp(*chp->argv, chp->argv); } else { close(pv[0]); fp = fdopen(pv[1], "w"); cp = (u_char*)pp->tell; for (i = pp->split; i > 0; i -= N_pipe, cp += N_pipe) fwrite(cp, 1, (i - N_pipe < 0) ? i : N_pipe, fp); fclose(fp); exit(0); } } close(pv[1]); *ppid = -pid; return fdopen(pv[0], "r"); } void init_grep(BASE *bp, char name[], u_char str[], PP *pp, int fgrep)/*tcb*/ { Init.abort = 0; Init.segv = signal(SIGSEGV, init_clear); setjmp(Init.jb); if (Init.abort) { make_bp(bp, strerror(EINVAL), name, s_S(S_err8)); return; } if (*name == ' ' || !is_access(name, bp)) if (!(bp->buff = fork_grep(&bp->size, str, pp, fgrep))) make_bp(bp, (access(s_S(S_intr), F_OK) < 0) ? s_S(S_err2) : s_S(S_err0), name, NULL); else bp->pp = alloc_pp(bp->buff, T_cut, bp->size, &bp->nrow, name); signal(SIGSEGV, Init.segv); } void init_ls(BASE *bp, char name[], int f_M, int f_ls)/*tcb*/ { struct stat st; if (f_M != T_locate && f_M != M_du) if (stat(name, &st) < 0) { getcwd(name, N_line); if (strchr(name, '\0')[-1] != '/') strcat(name, "/"); } free_bp(bp); Init.abort = 0; Init.segv = signal(SIGSEGV, init_clear); setjmp(Init.jb); if (Init.abort) { make_bp(bp, strerror(EINVAL), name, s_S(S_err8)); return; } do { switch(f_M) { case T_dir: if (!S_ISDIR(st.st_mode)) get_dir(name); /* get current directory name */ chdir(name); if (!(bp->buff = fork_bin(get_child(NULL, NULL, s_S(S_ls), name), &bp->size, T_dir, -1))) { make_bp(bp, (access(s_S(S_intr), F_OK) < 0) ? strerror(EACCES) : s_S(S_err0), name, NULL); continue; } if (f_ls) bp->size = alloc_ls(bp->buff, bp->size); break; case T_locate: if (!(bp->buff = fork_bin(get_child(NULL, NULL, s_S(S_locate), name) , &bp->size, M_locate, 0))) { make_bp(bp, (access(s_S(S_intr), F_OK) < 0) ? s_S(S_err3) : s_S(S_err0), name, NULL); continue; } strcpy(name, s_P(P_mode)[M_locate]); break; } bp->size = conv_ls(bp->buff); bp->pp = alloc_pp(bp->buff, f_M, bp->size, &bp->nrow, name); } while (0); signal(SIGSEGV, Init.segv); } void init_split(BASE *bp, char name[], PP *pp, BASE *cut_bp, int f_cr)/*tcb*/ { int code, f_M = T_split; Init.abort = 0; Init.segv = signal(SIGSEGV, init_clear); setjmp(Init.jb); if (Init.abort) { make_bp(bp, strerror(EINVAL), name, s_S(S_err8)); return; } if (!(bp->buff = fork_split(&bp->size, pp, cut_bp->pp))) make_bp(bp, (access(s_S(S_intr), F_OK) < 0) ? s_S(S_err2) : s_S(S_err0), name, NULL); else { bp->buff = check_type(bp->buff, &bp->size, NULL, &f_M , (f_cr != 0), &code); bp->pp = set_pp(bp->buff, bp->size, &bp->nrow, (code == C_bin), 0); } signal(SIGSEGV, Init.segv); } void init_split2(BASE *bp, u_char *buff, u_int bsize, u_char name[], PP *pp, int f_cr)/*tcb*/ { int code, f_M; Init.abort = 0; Init.segv = signal(SIGSEGV, init_clear); setjmp(Init.jb); if (Init.abort) { make_bp(bp, strerror(EINVAL), name, s_S(S_err8)); return; } if ((bp->size = (pp->next) ? pp->next->tell - pp->tell : pp->split - pp->tell) <= 0) make_bp(bp, s_S(S_err1), name, NULL); else { if (bp->size > bsize) bp->size = bsize; if (*name == ' ') { while (!(bp->buff = malloc(bp->size)) && (bp->size /= 2)) ; memcpy(bp->buff, &buff[pp->tell], bp->size); } else bp->buff = alloc_split(name, pp->tell, bp->size); bp->buff = check_type(bp->buff, &bp->size, NULL, &f_M , (f_cr != 0), &code); bp->pp = set_pp(bp->buff, bp->size, &bp->nrow, (code == C_bin), 0); } signal(SIGSEGV, Init.segv); } FILE *init_split3(BASE *bp, char name[], PP *pp, PP *ps)/*tcb*/ { int i, pv[2]; PP *pe; FILE *fp; if (!pp->prev) { for (i = 1, pe = ps; i < pp->tell; pe = pe->next, i++) ; i = 1; } else for (i = 1; i < pp->tell; ps = ps->next, i++) ; i = ((pp->next) ? pp->next->tell : pp->split) - i; for (pe = ps; i; pe = pe->next,i--) ; pipe(pv); if (!fork()) { close(pv[0]); fp = fdopen(pv[1], "w"); signal(SIGPIPE, SIG_DFL); for (; ps != pe; ps = ps->next) { fwrite(ps->cs, 1, ps->f.len, fp); if (ps->f.nl) fputc('\n', fp); } fclose(fp); exit(0); } close(pv[1]); return fdopen(pv[0], "r"); } FILE *init_split4(BASE *bp, u_char *buff, u_char name[], PP *pp)/*tcb*/ { int i, pv[2]; FILE *fp, *fp1; if (!(i = (pp->next) ? pp->next->tell - pp->tell : pp->split - pp->tell)) { make_bp(bp, s_S(S_err1), name, NULL); return EOP; } if (!pp->prev) { i += pp->tell; pp->tell = 0; } pipe(pv); if (!fork()) { signal(SIGPIPE, SIG_DFL); close(pv[0]); fp1 = fdopen(pv[1], "w"); if (*name == ' ') for (; i; i--) fputc(*buff++, fp1); else { fp = fopen(name, "r"); fseek(fp, pp->tell, 0); for (; i; i--) fputc(fgetc(fp), fp1); fclose(fp); } fclose(fp1); exit(0); } close(pv[1]); return fdopen(pv[0], "r"); } int init_bin(BASE *bp, BASE *head, CHILD **chpp, int f_M, char name[], int f_cr)/*tcb*/ { int i, fd, f_Mb, code; u_char *buff; CHILD *roff; static CHILD *chp; struct stat st; if (*name == '/' && is_access(name, bp) < 0) return f_M; if (head->buff) free_bp(head); Init.abort = 0; Init.segv = signal(SIGSEGV, init_clear); setjmp(Init.jb); if (Init.abort) { if (head->buff) free_bp(head); make_bp(bp, strerror(EINVAL), name, s_S(S_err8)); *chpp = chp; return f_M; } errno = 0; chp = *chpp; fd = 0; switch(f_M) { case T_key: case M_key: bp->buff = fork_key(&bp->size, f_M); bp->pp = alloc_pp(bp->buff, M_key, bp->size, &bp->nrow, name); break; case M_du: stat(s_S(S_mess), &st); fd = open(s_S(S_mess), O_RDONLY); case M_error: if (!fd) { stat(s_S(S_error), &st); fd = open(s_S(S_error), O_RDONLY); } case M_log: if (!fd) { stat(s_S(S_log), &st); fd = open(s_S(S_log), O_RDONLY); } free_bp(bp); case T_file: case T_file2: if (!fd) { if (stat(name, &st) < 0) { make_bp(bp, strerror(ENOENT), name, NULL); break; } fd = open(name, O_RDONLY); } else if (fd < 0) { make_bp(bp, s_S(S_err1), name, NULL); break; } bp->size = st.st_size; bp->buff = fork_scan(&bp->size, -1, fd, f_cr); if (f_M == M_du) { i = bp->size * 2; bp->buff[bp->size] = '\0'; } close(fd); case M_tcb: if (f_M == M_tcb) { free_bp(bp); bp->size = strlen(s_S(S_TCB)); bp->buff = strdup(s_S(S_TCB)); } if (!bp->size) make_bp(bp, s_S(S_err1), name, NULL); else { if (f_M == M_du) { bp->pp = alloc_pp(bp->buff, f_M, bp->size, &bp->nrow, name); unlink(s_S(S_mess)); } else { f_Mb = f_M; bp->buff = check_type(bp->buff, &bp->size, name, &f_M, f_cr, &code); i = f_M != M_log && f_M != M_error && f_M != M_tcb && code == C_bin; if (f_M == T_type) { chp = check_chp(S_file); if (f_Mb == T_file2 && code < 0) { free(bp->buff); fd = open(name, O_RDONLY); bp->size = st.st_size; bp->buff = fork_scan(&bp->size, -1, fd, 0); close(fd); code = C_bin; } } bp->pp = set_pp(bp->buff, bp->size, &bp->nrow, i, 0); } } break; case T_tar: case T_lha: case T_unzip: if (!(head->buff = fork_arc(name, f_M, chp, &head->size, &bp->size, bp))) make_bp(bp, (access(s_S(S_intr), F_OK) < 0) ? strerror(EINVAL) : s_S(S_err0), name, NULL); else { bp->pp = alloc_head(head->buff, f_M, head->size, &bp->nrow); if (!bp->pp) make_bp(bp, (access(s_S(S_intr), F_OK) < 0) ? strerror(EINVAL) : s_S(S_err0), name, NULL); else switch(f_M) { case T_tar: alloc_tar(bp->buff, bp->pp, bp->size); break; case T_lha: alloc_lha(bp->buff, bp->pp, bp->size); break; case T_unzip: alloc_unzip(bp->buff, bp->pp, bp->size); break; } } break; case T_bin: case T_gz: case T_roff: if (!(bp->buff = fork_bin(chp, &bp->size, T_bin, f_cr))) make_bp(bp, (access(s_S(S_intr), F_OK) < 0) ? strerror(EINVAL) : s_S(S_err0), name, NULL); else { bp->buff = check_type(bp->buff, &bp->size, NULL, &f_M, f_cr, &code); if ((roff = check_ext(NULL, bp->buff, bp->size))) { buff = fork_chp(roff, bp->buff, &bp->size, name); free(bp->buff); bp->buff = buff; chp = roff; } bp->pp = set_pp(bp->buff, bp->size, &bp->nrow, 0, 0); } break; default: break; } *chpp = chp; signal(SIGSEGV, Init.segv); return f_M; }