#include "tcb.h" #include #include #include #include #include #include "alloc.h" static struct { PP *pp0, *pp1; int n_attr; ATTR attr[N_attr]; u_char line[N_line]; } Alloc; typedef struct LS { char len[N_ls]; char *s[N_ls]; struct LS *next; } LS; static u_char *save_attr(u_char *cp, int attr, int *n_attrp, int *np) { int n = *np, n_attr = *n_attrp; switch(attr) { case A_md: cp += 2; Alloc.attr[n_attr].n = n+1; Alloc.attr[n_attr++].attr = A_md; Alloc.attr[n_attr].n = n+2; Alloc.attr[n_attr++].attr = -A_me; n += 2; break; case A_us: cp += 2; Alloc.attr[n_attr].n = n+2; Alloc.attr[n_attr++].attr = A_us; Alloc.attr[n_attr].n = n+3; Alloc.attr[n_attr++].attr = -A_ue; n += 2; break; case '<': case -'<': Alloc.attr[n_attr].n = n; Alloc.attr[n_attr++].attr = attr; Alloc.attr[n_attr++].attr = *cp; break; case '^': case -'^': Alloc.attr[n_attr].n = n; Alloc.attr[n_attr++].attr = attr; Alloc.attr[n_attr++].attr = *cp + '@'; break; } *np = n; *n_attrp = n_attr; return cp; } int set_attr(ATTR attr[], u_char str[], int f_stand, int f_grep, int f_file)/*tcb*/ { int i, n, n_attr, f_attr; u_char c, *cp, *end; end = strchr(str, '\0'); for (cp = str, i = n = n_attr = f_attr = 0; cp < end && i < vt_col(0) - 1 ; i++, n++, cp++) if ((c = *cp) == K_dl || (c == K_at && f_grep) || (c < ' ' && (f_grep || (!f_grep && c != '\n' && c != K_i && c != K_h)))) { if (c == K_dl) c -= 0x80; else if (c == K_at) c = 0; attr[n_attr].n = n; attr[n_attr++].attr = (f_stand > 0) ? -'^' : '^'; attr[n_attr++].attr = c + '@'; f_attr = 1; } else if (!f_file && c >= 0x80 && vt_charset(0) == C_ascii) { attr[n_attr].n = n; attr[n_attr++].attr = (f_stand > 0) ? -'<' : '<'; attr[n_attr++].attr = c; f_attr = 1; } else if (f_attr) { f_attr = 0; attr[n_attr].n = n; attr[n_attr++].attr = (f_stand > 0) ? A_cs : A_ce; i++; } return n_attr; } static void esc_pipe(FILE **pinp, PP *pp, int ppid) { if (pp) free(pp); if (*pinp && *pinp != stdin) fclose(*pinp); if (ppid < 0) kill(-ppid, SIGPIPE); *pinp = NULL; print_line(NULL, EOB, 0, NULL); save_intr(S_errl); save_error("%s: %s.\n", s_S(S_tcb), s_S(S_errl)); } static int linein(FILE *fp, u_char buff[], int *lenp, int *f_binp, int pid) { int i, c, len; len = *lenp; for (c = 0; len < N_line-2 && c != EOF && c != '\n'; len++) { if (!(i = fread(&c, 1, 1, fp))) { if (ferror(fp) && pid && !kill((pid > 0) ? pid : -pid, 0)) { /* received signal while reading (Linux) */ c = 0; } else c = EOF; len--; } else { if (!*f_binp && c < ' ' && !strchr(s_S(S_code), c)) *f_binp = 1; buff[len] = c; } } buff[len] = '\0'; *lenp = len; return c; } PP *alloc_pipe(int init0, FILE **pinp, int *nrowp, BASE *bp0, int nlen0, int ppid0)/*tcb*/ { static PP *pp, *pp0, *pp1; static int init, nlen, bsize, ppid, i_b, f_bin, len, s_len, p_len; static BASE *bp; u_char c, *end, *ce, *cs; int uc, h, i, j, n, n_attr, f_eof; switch(init0) { case -2: bsize = ppid0; set_ppp(&pp1, &pp0, 1); return NULL; break; case -1: if (*pinp == EOP) return NULL; free_bp(bp); if (*pinp && *pinp != stdin) fclose(*pinp); if (ppid < 0) kill(-ppid, SIGPIPE); *pinp = EOP; print_line(NULL, EOB, 0, NULL); return NULL; break; case 0: if (!*pinp || *pinp == EOP) return NULL; break; default: pp0 = pp1 = NULL; bp = bp0; s_len = p_len = *nrowp = 0; ppid = ppid0; nlen = ((init = init0) == T_man) ? -1 : nlen0; vt_move(0, 0); print_line(pinp, EOB, 0, NULL); f_bin = len = i_b = 0; break; } do { if (i_b) { memcpy(Alloc.line, &Alloc.line[len - i_b], i_b); len = i_b; i_b = 0; } else len = 0; f_eof = linein(*pinp, Alloc.line, &len, &f_bin, ppid); end = Alloc.line + len; uc = 0; for (ce = cs = Alloc.line, i = n = j = n_attr = 0; ce < end; ) { c = *ce; if (f_bin <= 0 && c == '\t') for (h = 7 - (i & 7); h && i < vt_col(0); h--, i++) ; else if (i <= vt_col(0) - 1 && c != '\n' && (c == K_dl || (c < ' ' && f_bin <= 0 && c != K_h) || (c < ' ' && f_bin > 0) || (vt_charset(0) == C_ascii && c == K_h && (ce[-1] >= 0x80 || (ce[-1] == K_h && ce[-2] >= 0x80))))) { if (++i >= vt_col(0)) continue; if (c == K_dl) c -= 0x80; save_attr(&c, '^', &n_attr, &n); } else if (ce < end-1) { if (c >= 0x80 && vt_charset(0) == C_ascii) { save_attr(&c, '<', &n_attr, &n); i += 3; } if (f_bin > 0) ; else if (c == '_') { if (ce[1] == K_h) { uc = 1; /* underline continuation */ ce = save_attr(ce, A_us, &n_attr, &n); continue; } } else if (c == K_h) { ce = save_attr(ce, A_md, &n_attr, &n); continue; } else if (uc) { if (uc < 2) uc++; else uc = 0; } } if ((j = *ce == '\n') || i >= vt_col(0)) { if (!(pp = calloc(sizeof(PP), 1))) { esc_pipe(pinp, pp, ppid); return pp0; } if (n_attr) { Alloc.attr[n_attr++].n = -1; if (!(pp->attr = malloc(sizeof(ATTR) * n_attr))) { free(pp); esc_pipe(pinp, pp, ppid); return pp0; } memcpy(pp->attr, Alloc.attr, sizeof(ATTR) * n_attr); } if (j) { if ((h = ce - cs) < 0) h = 0; if (!(pp->cs = malloc(h + 1))) { if (pp->attr) free(pp->attr); esc_pipe(pinp, pp, ppid); return pp0; } pp->f.str = 1; memcpy(pp->cs, cs, h); pp->f.len = h; } else { /* length more than vt_col(0) */ if ((h = ce - cs - uc) < 0) h = 0; if (!(pp->cs = malloc(h + 1))) { if (pp->attr) free(pp->attr); esc_pipe(pinp, pp, ppid); return pp0; } pp->f.str = 1; memcpy(pp->cs, cs, h); ce = cs + h - 1; pp->f.len = h; } pp->cs[h] = '\0'; pp->prev = pp1; if (!pp0) pp0 = pp; else pp1->next = pp; pp1 = pp; if (pp->prev) pp->f.line = pp->prev->f.line + pp->prev->f.nl; else pp->f.line = 1; pp->f.nl = j; s_len += h; p_len += sizeof(PP) + ((n_attr) ? sizeof(ATTR) * n_attr : 0); if (s_len > bsize || p_len > bsize) { /* not enouth buffer */ if (*pinp && *pinp != stdin) fclose(*pinp); if (ppid < 0) kill(-ppid, SIGPIPE); *pinp = NULL; print_line(NULL, EOB, 0, NULL); save_intr(S_err4); return pp0; } cs = ce + 1; i = n = -1; n_attr = 0; if (++*nrowp <= vt_row(0) - 1 && nlen >= 0) { /* display up to LINES-1 */ vt_move(*nrowp-1, 0); vt_eeol(); put_str(pp, 0); print_line(pp0, pp0, -nlen, NULL); } else if (*nrowp == vt_row(0)) { if (f_bin > 0) pp0->f.bin = 1; else f_bin = -1; } if (j) break; } i++; ce++; n++; } if ((i = f_eof == EOF) || !pp0) { if (!i || (!j && ce == end && len)) { /* end of line is not '\n' */ if ((pp = calloc(sizeof(PP), 1))) { if (n_attr) { Alloc.attr[n_attr++].n = -1; if ((pp->attr = malloc(sizeof(ATTR) * n_attr))) memcpy(pp->attr, Alloc.attr, sizeof(ATTR) * n_attr); else { esc_pipe(pinp, pp, ppid); return pp0; } } if ((h = ce - cs) < 0) h = 0; if ((pp->cs = malloc(h + 1))) { pp->f.str = 1; memcpy(pp->cs, cs, h); pp->f.len = h; pp->prev = pp1; if (!pp0) pp0 = pp; else pp1->next = pp; pp1 = pp; if (pp->prev) pp->f.line = pp->prev->f.line + pp->prev->f.nl; else pp->f.line = 1; pp->f.nl = 0; if (++*nrowp <= vt_row(0) - 1 && nlen >= 0) { vt_move(*nrowp-1, 0); vt_eeol(); put_str(pp, 0); print_line(pp0, pp0, -nlen, NULL); } } else { if (pp->attr) free(pp->attr); esc_pipe(pinp, pp, ppid); return pp0; } } } if (*pinp && *pinp != stdin) fclose(*pinp); if (ppid < 0) kill(-ppid, SIGPIPE); *pinp = NULL; print_line(NULL, EOB, 0, NULL); } else if (!j && ce == end) i_b = n; } while (0); return pp0; } static void alloc_l(LIST *list, int *rowp, int f_grep, int f_file) { if (list) { alloc_l(list->left, rowp, f_grep, f_file); { PP *pp; if ((pp = calloc(sizeof(PP), 1))) { if ((pp->cs = strdup(list->name))) { u_char *p = alloca(strlen(pp->cs) + 1); if ((Alloc.n_attr = set_attr(Alloc.attr, list->name , 0, f_grep, f_file))) { Alloc.attr[Alloc.n_attr++].n = -1; if ((pp->attr = malloc(sizeof(ATTR)*Alloc.n_attr))) memcpy(pp->attr, Alloc.attr, sizeof(ATTR)*Alloc.n_attr); else { save_intr(S_errl); save_error("%s: %s.\n", s_S(S_tcb), s_S(S_errl)); free(pp->cs); free(pp); return; } } pp->prev = Alloc.pp1; if (!Alloc.pp0) Alloc.pp0 = pp; else if (Alloc.pp1) Alloc.pp1->next = pp; Alloc.pp1 = pp; pp->f.str = 1; strcpy(p, pp->cs); if (strlen(p) > vt_col(0)) p[vt_col(0)] = '\0'; pp->f.len = strlen(p); pp->f.line = (pp->prev) ? pp->prev->f.line + 1 : 1; pp->f.nl = 1; (*rowp)++; } else { free(pp); save_intr(S_errl); save_error("%s: %s.\n", s_S(S_tcb), s_S(S_errl)); return; } } } alloc_l(list->right, rowp, f_grep, f_file); } } PP *alloc_list(LIST *list, int *rowp, int f_grep, int f_file)/*tcb*/ { int n_row = 0; Alloc.pp0 = Alloc.pp1 = NULL; alloc_l(list, &n_row, f_grep, f_file); *rowp = n_row; return Alloc.pp0; } PP *alloc_str(STR s0[], int *rowp, int f_grep, int f_file)/*tcb*/ { int n_attr; STR *sp; PP *pp, *pp1; static PP *pp0; pp = pp0 = pp1 = NULL; *rowp = 0; for (sp = s0; sp; sp = sp->next) { if ((pp = calloc(sizeof(PP), 1))) { if ((pp->cs = strdup(sp->name))) { u_char *p = alloca(strlen(pp->cs) + 1); n_attr = set_attr(Alloc.attr, sp->name, 0, f_grep, f_file); Alloc.attr[n_attr++].n = -1; if ((pp->attr = malloc(sizeof(ATTR)*n_attr))) memcpy(pp->attr, Alloc.attr, sizeof(ATTR)*n_attr); else { free(pp->cs); free(pp); save_intr(S_errl); break; } pp->prev = pp1; if (!pp0) pp0 = pp; else pp1->next = pp; pp1 = pp; pp->f.str = 1; strcpy(p, pp->cs); if (strlen(p) > vt_col(0)) p[vt_col(0)] = '\0'; pp->f.len = strlen(p); pp->f.line = (pp->prev) ? pp->prev->f.line + 1 : 1; pp->f.nl = 1; (*rowp)++; } else { free(pp); save_intr(S_errl); break; } } else { save_intr(S_errl); break; } } if (load_intr() == S_errl) save_error("%s: %s.\n", s_S(S_tcb), s_S(S_errl)); return pp0; } PP *alloc_pp(u_char buff[], int f_M0, int size, int *rowp, char name[])/*tcb*/ { /* edit output from `f(e)grep -b(n)` or `ls -l` */ int c, i, h, len, n_row, n_attr, n, nb, f_M, f_ascii, f_file; u_int tell, st_size; u_char *cs, *cp, *ce, *end; PP *pp, *pp0, *pp1; static struct { int f_M, split; char *name; } tab[6]; if (!tab[0].name) { tab[0].name = s_P(P_mode)[M_key]; tab[1].name = s_P(P_mode)[M_du]; tab[2].name = s_P(P_mode)[M_locate]; tab[3].name = s_S(S_help); } if (f_M0 < 0) { /* <== menu.c (6) */ for (i = 0; i < 4; i++) if (!strcmp(tab[i].name, name)) break; if (i == 4 && *name == '/') i++; f_M = tab[i].f_M; st_size = tab[i].split; } else { f_M = f_M0; for (i = 0, buff; i < size; i++) if (!buff[i]) buff[i] = ' '; /* * when `egrep -n (-b)' by ^J^C (^J^B) outputted following: * 123:... * 456:... * 789:... * CUT will split buffer (file) at line-number (bytes): * 1 - 122 * 123 - 455 * 456 - 788 * 789 - st_size */ st_size = (f_M == M_cut) ? *rowp : 0; /* *rowp: total-lines (bytes) */ } end = buff + size; pp = pp0 = pp1 = NULL; tell = 0; len = n_row = 0; f_file = is_file(f_M); f_ascii = vt_charset(0) == C_ascii; cs = (f_M == T_dir && size) /* delete the line "total ..." */ ? (u_char*)&strchr(buff, '\n')[1] : buff; if (f_M == M_cut && strncmp(cs, "0:", 2) && strncmp(cs, "1:", 2)) if ((pp = calloc(sizeof(PP), 1))) { if ((pp->cs = strdup("--"))) { pp->f.str = 1; pp->f.len = strlen(pp->cs); pp->prev = NULL; pp0 = pp1 = pp; pp->f.line = 1; pp->f.nl = 1; n_row++; } else { free(pp); return NULL; } } else return NULL; for (c = i = n = nb = n_attr = 0, ce = Alloc.line; cs < end; ) { /* skip string `NNNN:' (<== f(e)grep -n ...) */ if (f_M == T_cut || f_M == M_cut || f_M == M_key) { if (i > 10 && !len) { for (len = 0; Alloc.line[len] != ':' && len < 10; len++) ; if (len == 10) len = 0; } else if (!n && (cp = strchr(cs, ':'))) nb = cp - cs + 1; } else if (!n) nb = 0; if ((c = *cs++) != '\n') { if (c == '\t') /* convert '\t' to ' ' */ if (f_M == M_du) for (h = 7 - (i & 7); h && i < vt_col(0) + len; h--, i++) *ce++ = ' '; else c = ' '; else if (i <= vt_col(0) - 1 && (c == K_dl || (c < ' ' && c != K_h) || (f_ascii && c == K_h && (cs[-2] >= 0x80 || (cs[-2] == K_h && cs[-3] >= 0x80))))) if (++i >= vt_col(0)) continue; if (c == '_') { if (*cs == '_' && cs[1] == K_h && cs[2] == K_h) { cs += 3; continue; } else if (*cs == K_h) { cs++; continue; } } else if (c == K_h) { cs++; continue; } h = 0; if (f_file || !f_ascii) *ce++ = c; if (i < vt_col(0) + len - 1) { if ((h = c >= 0x80 && f_ascii && !f_file)) h = (i += 3) > vt_col(0) + len; if (!h) { if (!f_file && f_ascii) *ce++ = c; i++; n++; continue; } } if (f_file) while (cs < end && (c = *cs) != '\n') /* save complete filename */ *ce++ = *cs++; else while (cs < end && (c = *cs) != '\n') /* cut at the length of CULUMNS */ cs++; cs++; n = 0; } *ce = 0; if ((pp = calloc(sizeof(PP), 1))) { if (f_M == T_cut || f_M == M_cut || f_M == M_key) { strcpy(Alloc.line, tome(Alloc.line, 0)); if (!(cp = strchr(Alloc.line, ':'))) { pp->tell = tell; cp = Alloc.line; } else { *cp = 0; tell = pp->tell = atoi(Alloc.line); cp++; } } else cp = Alloc.line; if ((pp->cs = strdup(cp))) { u_char *p = alloca(strlen(pp->cs) + 1); pp->f.str = 1; if ((n_attr = set_attr(Alloc.attr, pp->cs, 0, 0, f_file))) { Alloc.attr[n_attr++].n = -1; if ((pp->attr = malloc(sizeof(ATTR)*n_attr))) memcpy(pp->attr, Alloc.attr, sizeof(ATTR)*n_attr); else { free(pp->cs); free(pp); save_intr(S_errl); break; } } if (!f_file) pp->f.len = ((i = strlen(pp->cs)) > vt_col(0)) ? vt_col(0) : i; else { strcpy(p, pp->cs); if (strlen(p) > vt_col(0)) p[vt_col(0)] = '\0'; pp->f.len = strlen(p); } pp->prev = pp1; if (!pp0) pp0 = pp; else pp1->next = pp; pp1 = pp; if (pp->prev) pp->f.line = pp->prev->f.line + pp->prev->f.nl; else pp->f.line = 1; pp->f.nl = c == '\n'; n = i = len = n_attr = 0; ce = Alloc.line; n_row++; } else { free(pp); save_intr(S_errl); break; } } else { save_intr(S_errl); break; } } if (load_intr() == S_errl) save_error("%s: %s.\n", s_S(S_tcb), s_S(S_errl)); if (f_M == M_cut) pp->split = st_size; if (rowp) *rowp = n_row; if (f_M0 >= 0 && f_M != T_dir) { for (i = 0; i < 4; i++) if (tab[i].name && !strcmp(tab[i].name, name)) break; if (i == 4 && *name == '/') i++; tab[i].f_M = f_M; tab[i].split = st_size; } return pp0; } PP *alloc_head(u_char buff0[], int f_M0, int size0, int *rowp)/*tcb*/ { int c, i, j, k, n_row, split; u_char *end, *cs, *ce, *cp; char *p; PP *pp, *pp1, *pp2 = NULL; static u_char *buff; static PP *pp0; static int f_M, size; if (f_M0 < 0) pp2 = pp0; else { f_M = f_M0; size = size0; buff = buff0; } pp0 = pp1 = NULL; cp = buff; end = cp + size; i = j = k = split = 0; n_row = 0; switch(f_M) { case T_lha: /* skip two lines: "PERMSSN UID GID SIZE RATIO STAMP NAME" "----------------- ------- ------ ------------ --------------------" */ while (*cp++ != '\n') ; while (*cp++ != '\n') ; break; case T_unzip: /* skip three lines: "Archive: *.zip" " Length Date Time Name" " ------ ---- ---- ----" */ while (1) { for (i = 0; (Alloc.line[i] = *cp++) != '\n' && i < 256; i++) ; if (i == 256) Alloc.line[i-1] = '\0'; if (!strncmp(Alloc.line, " --", 3)) break; } break; } for (ce = Alloc.line; cp < end; ) { if ((c = *cp++) != '\n') { *ce = c; if (j < 255) { ce++; j++; continue; } *ce = 0; while (*cp++ != '\n') ; } else *ce = 0; switch(f_M) { case T_tar: if ((cs = strstr(Alloc.line, " -> "))) *cs = '\0'; for (i = 0, ce = strchr(Alloc.line, '\0') - 1; ; i++) { for (; ce > Alloc.line; ce--) if (*ce == ' ' || (i && *ce == '/')) break; if (!i) { if (cs) *cs = ' '; cs = &ce[1]; } if (i && *ce == '/') { while (1) { while (*ce != ' ') ce++; while (*ce == ' ') ce++; for (p = ce; *p >= '0' && *p <= '9'; p++) ; if (*p == ' ' || *p == ',') break; else ce = p; } break; } else while (*ce == ' ') ce--; } if (ce > Alloc.line) { /* get file size */ for (k = split = 0; *ce != ' '; ce++) { if (*ce == ',') split = -1; /* special device */ else if (!split) k = k * 10 + *ce - '0'; } ce++; } else k = 0; ce = cs; break; case T_lha: /* search for string "NNN%" or "******" */ for (ce = Alloc.line, i = 0; *ce != '%' && *ce != '*' && i < 40; i++) ce++; if (strchr(Alloc.line, '\0')[-1] == '/') split = -1; /* directory */ if (i == 40) { /* within the line: "----------------- ------- ------ ------------ --------------------" */ cp = end; continue; } cs = ce; for (i = 0; i < 4; i++) { while (*ce != ' ') ce++; while (*ce == ' ') ce++; } cs++; for (i = 0; i < 2; i++) { while (*cs == ' ') cs--; while (*cs != ' ') cs--; } cs++; /* get file size */ for (k = 0; *cs != ' '; cs++) k = k * 10 + *cs - '0'; break; case T_unzip: for (cs = Alloc.line; *cs == ' ' && *cs != '-'; cs++) ; if (*cs == '-') { /* within the line: "------ -------" */ cp = end; continue; } /* get file size */ for (k = 0; *cs != ' '; cs++) k = k * 10 + *cs - '0'; for (ce = cs, i = 0; i < 2; i++) { while (*ce == ' ') ce++; if (!i) memcpy(Alloc.line, ce, 9); while (*ce != ' ') ce++; } while (*ce == ' ') ce++; break; } if ((pp = calloc(sizeof(PP), 1))) { if ((pp->split = split) < 0) k = 0; /* no size */ else pp->split = k; sprintf(&Alloc.line[9], "%10d ", k); cs = &Alloc.line[20]; while ((*cs = *ce++) != '\n' && *cs) cs++; if (*cs == '\n') *cs = '\0'; if (*Alloc.line == 'd' || *Alloc.line == 'l') /* directory or symlink */ pp->split = -1; if ((pp->cs = strdup(Alloc.line))) { pp->f.len = ((i = strlen(pp->cs)) > vt_col(0)) ? vt_col(0) : i; pp->f.str = 1; pp->prev = pp1; if (!pp0) pp0 = pp; else pp1->next = pp; pp1 = pp; if (pp->prev) pp->f.line = pp->prev->f.line + pp->prev->f.nl; else pp->f.line = 1; pp->f.nl = c == '\n'; j = split = 0; ce = Alloc.line; n_row++; } else { free(pp); save_intr(S_errl); break; } } else { save_intr(S_errl); break; } } if (load_intr() == S_errl) save_error("%s: %s.\n", s_S(S_tcb), s_S(S_errl)); if (f_M0 < 0) { /* <== SIGWINCH (menu.c:(5)) */ for (pp = pp0, pp1 = pp2; pp; pp = pp->next, pp1 = pp1->next) { pp->tell = pp1->tell; pp->split = pp1->split; } free_pp(pp2); } else if (rowp) *rowp = n_row; return pp0; } void alloc_tar(u_char cp0[], PP pp0[], int size)/*tcb*/ { int i; u_char *cp, *end, *sp; PP *pp; end = cp0 + size; for (cp = cp0, pp = pp0, end--; ;) { if ((cp += 512) > end) { /* skip header */ cp = end; pp->split = -1; } pp->tell = (u_int)cp; if (pp->split < 0) pp->split = 0; for (i = 0; i < pp->split && cp < end; i++) cp++; if (cp == end) pp->split = i; if (!(pp = pp->next)) break; strcpy(Alloc.line, &pp->cs[20]); if ((sp = strchr(Alloc.line, ' '))) *sp = '\0'; if (cp < end) { i = strlen(Alloc.line); while (strncmp(cp, Alloc.line, i)) /* search for next header */ if (cp >= end) break; else cp++; } } } void alloc_lha(u_char cp0[], PP pp0[], int size)/*tcb*/ { int i; u_char *cp, *end; PP *pp; for (cp = cp0, end = cp + size, pp = pp0; ; ) { if (cp < end) { if (pp->split >= 0) for (i = 0; i < 3; i++) /* skip three lines: "::::::::" "filename" "::::::::" */ while (cp < end && *cp++ != '\n') ; else pp->split = 0; pp->tell = (u_int)cp; if (cp == end) pp->split = 0; else { for (i = 0; i < pp->split && cp < end; i++) cp++; if (cp == end) pp->split = i; } } else { pp->tell = (u_int)end; pp->split = 0; } if (!(pp = pp->next)) break; } } void alloc_unzip(u_char cp0[], PP pp0[], int size)/*tcb*/ { int i; u_char *cp, *end; PP *pp; for (cp = cp0, end = cp + size, pp = pp0; ; ) { if (cp < end) { if (pp->split < 0) pp->split = 0; pp->tell = (u_int)cp; for (i = 0; i < pp->split && cp < end; i++) cp++; if (cp == end) pp->split = i; } else { pp->tell = (u_int)end; pp->split = 0; } if (!(pp = pp->next)) break; } } char **alloc_arg(char *arg, int *argcp)/*tcb*/ { int i, j, k; char **argv, *cp; while (*arg == ' ') arg++; for (cp = arg; *cp; cp++) if (*cp == '\t') *cp = ' '; for (cp = arg, k = 2; *cp; ) { /* get number of argument */ while (*cp && *cp != ' ') cp++; for (; *cp && *cp == ' '; cp++) ; if (*cp) k++; } if (argcp) *argcp = k; if ((argv = calloc(sizeof(char*), k))) { i = j = 0; cp = arg; do { /* set arguments for execvp() */ while (*cp == ' ') cp++; if ((i = ichrstr(cp, ' ', NULL))) cp[i-1] = 0; if (!j) { if ((*argv = strdup(cp))) { if (!argcp && !is_inst(s_S(S_path), *argv)) { /* argv[0] isn't installed */ strcpy(arg, *argv); free(*argv); free(argv); save_intr(S_errl); break; } } else { free(argv); save_intr(S_errl); break; } } else if (!(argv[j] = strdup(cp))) { free_arg(argv); save_intr(S_errl); break; } if (k == ++j + 1) break; cp[i-1] = ' '; cp = &cp[i]; } while (i); if (load_intr() == S_errl) { save_error("%s: %s.\n", s_S(S_tcb), s_S(S_errl)); return NULL; } argv[j] = NULL; } else { save_intr(S_errl); save_error("%s: %s.\n", s_S(S_tcb), s_S(S_errl)); } return argv; } void free_arg(char **argv)/*tcb*/ { int i; for (i = 0; argv[i]; i++) free(argv[i]); free(argv); } u_char *alloc_split(char name[], int tell, int size)/*tcb*/ { FILE *fp; u_char *cp; while (!(cp = malloc(size)) && (size /= 2)) ; if (cp) { fp = fopen(name, "r"); fseek(fp, tell, 0); fread(cp, 1, size, fp); fclose(fp); } return cp; } u_char *alloc_buff(int *sizep, int fd, int pid, int f_cr)/*tcb*/ { FILE *fp; int f_checkbin, size, temp, fsize, code; u_char *cp, *buff; static int bsize; struct tmp { int len; u_char *buff; struct tmp *next; } *tp, *old, *tp0 = NULL; if (*sizep < 0) { bsize = f_cr; return NULL; } if (pid < 0) { if (!*sizep) return NULL; else fsize = *sizep; } else fsize = 0; f_checkbin = f_cr; size = code = 0; old = NULL; fp = fdopen(fd, "r"); errno = 0; tp = NULL; do { /* read every N_pipe bytes */ if (!(tp = calloc(1, sizeof(struct tmp)))) { if (pid > 0 && !kill(pid, 0)) kill(pid, SIGPIPE); save_intr(S_errl); break; } if (old) old->next = tp; else tp0 = tp; if (!(tp->buff = malloc(N_pipe+2))) { if (pid > 0 && !kill(pid, 0)) kill(pid, SIGPIPE); free(tp); if (old) old->next = NULL; else tp0 = NULL; save_intr(S_errl); break; } if (pid < 0) { if (fsize >= N_pipe) { tp->len = fread(tp->buff, 1, N_pipe, fp); old = tp; } else { tp->len = fread(tp->buff, 1, fsize, fp); old = NULL; } fsize -= N_pipe; } else if ((tp->len = fread(tp->buff, 1, N_pipe, fp)) < N_pipe) if (ferror(fp) && pid > 0 && !kill(pid, 0)) /* received signal while reading (Linux) */ old = tp; else old = NULL; else old = tp; if ((size += tp->len) >= bsize) { /* not enough buffer */ if (pid > 0 && !kill(pid, 0)) kill(pid, SIGPIPE); save_intr(S_err4); } if (f_checkbin) { temp = size; /* check file-type with first N_pipe bytes */ if ((code = init_code(size, tp->buff, f_cr)) < 0) old = NULL; else f_checkbin = 0; size = temp; } if (fd && f_cr >= 0 && load_intr() == S_err0) break; } while (old && size < bsize); if (!size) buff = NULL; else { if (!(buff = calloc(1, size+2))) { save_intr(S_errl); /* `fp' (:fd) will be closed at end of fork_scan() */ fp = fopen(s_S(S_tmp), "w"); for (tp = tp0, cp = buff; tp; cp += tp->len, tp = tp->next) fwrite(tp->buff, 1, tp->len, fp); fclose(fp); fp = NULL; } else for (tp = tp0, cp = buff; tp; cp += tp->len, tp = tp->next) memcpy(cp, tp->buff, tp->len); } for (tp = tp0; tp; tp = old) { free(tp->buff); old = tp->next; free(tp); } if (!fp) { while (!(buff = calloc(1, size+2)) && (size /= 2)) ; if (size) { fp = fopen(s_S(S_tmp), "r"); fread(buff, 1, size, fp); fclose(fp); } else if (buff) { free(buff); buff = NULL; } unlink(s_S(S_tmp)); } if (load_intr() == S_errl) save_error("%s: %s.\n", s_S(S_tcb), s_S(S_errl)); *sizep = size; return buff; } PP *alloc_sh(u_char *str, int pid0, int c)/*tcb*/ { PP *pp; static PP *pp0, *pp1; static int pid, s_len, bsize; if (!str) { bsize = c; return NULL; } if (pid0 < 0) { pp0 = pp1 = NULL; set_ppp(&pp1, &pp0, 1); pid = -pid0; s_len = 0; } else if (!pid) return NULL; if ((pp = calloc(sizeof(PP), 1))) { pp->prev = pp1; if (!pp0) pp0 = pp; else pp1->next = pp; pp1 = pp; if (pp->prev) { pp->f.line = pp->prev->f.line + pp->prev->f.nl; s_len += pp->prev->f.len; } else pp->f.line = 1; pp->f.nl = c == '\n' || c == '\\'; if (str == EO9) { pp->cs = EO9; /* SHELL prompt (virtual line) */ if (c == '\\') /* line continuation */ pp->prev->split = 1; /* (2) */ } else { c = strlen(str); if (str[c-1] == '\n') str[c-1] = '\0'; if ((pp->cs = strdup(str))) { pp->f.str = 1; pp->f.len = strlen(pp->cs); s_len = pp->f.len; } else { free(pp); save_intr(S_errl); kill(pid, SIGHUP); pid = 0; } } } else { save_intr(S_errl); kill(pid, SIGHUP); pid = 0; } if (load_intr() == S_errl) save_error("%s: %s: %s.\n" , s_S(S_tcb), &s_P(P_mode)[M_shell][1], s_S(S_errl)); return (s_len > bsize) ? EO9 : pp0; } void make_bp(BASE *bp, char mess[], char *name, char *cp)/*tcb*/ { /* alloc string for error-message */ free_bp(bp); strcpy(Alloc.line, mess); if (name) if (cp) save_error("%s: %s: %s (%s).\n", s_S(S_tcb), name, Alloc.line, cp); else save_error("%s: %s: %s.\n", s_S(S_tcb), name, Alloc.line); if (cp) { strcat(Alloc.line, " ("); strcat(Alloc.line, cp); strcat(Alloc.line, ")"); } if ((bp->buff = strdup(toul(Alloc.line, 1)))) { if ((bp->pp = set_pp(bp->buff, strlen(bp->buff), &bp->nrow, 0, 0))) { bp->pp->tell = (u_int)EOE; /* mark of error */ bp->size = -1; } else { free(bp->buff); bp->buff = NULL; } } } PP *set_pp(u_char *cs, int size, int *rowp, int f_code, int f_bin)/*tcb*/ { int p_len; int uc, h, i, j, n, n_row, n_attr; u_char c, *ce, *end; PP *pp, *pp0 = NULL, *pp1 = NULL; static int bsize; if (!cs) { if (size) bsize = size; return NULL; } end = cs + size; ce = cs; p_len = 0; uc = 0; for (n = j = n_attr = 0, i = f_code, n_row = 0; ce < end; ) { c = *ce; if (f_code) ; /* ^[^M (display as is) */ else if (!f_bin && c == '\t') for (h = 7 - (i & 7); h && i < vt_col(0); h--, i++) ; else if (!f_bin && c == '\r' && ce[1] != '\n') c = '\n'; else if (i <= vt_col(0) - 1 && c != '\n' && (c == K_dl || (c < ' ' && !f_bin && c != K_h) || (c < ' ' && f_bin) || (vt_charset(0) == C_ascii && c == K_h && (ce[-1] >= 0x80 || (ce[-1] == K_h && ce[-2] >= 0x80))))) if (i >= vt_col(0) - 1) { i++; continue; } else { if (c == K_dl) c -= 0x80; save_attr(&c, '^', &n_attr, &n); i++; } else { if (c >= 0x80 && vt_charset(0) == C_ascii) { save_attr(&c, '<', &n_attr, &n); i += 3; } if (f_bin) ; else if (c == '_') { /* underline */ if (ce[1] == K_h) { uc = 1; ce = save_attr(ce, A_us, &n_attr, &n); continue; } } else if (c == K_h) { /* bold */ ce = save_attr(ce, A_md, &n_attr, &n); continue; } else if (uc) { if (uc < 2) uc++; else uc = 0; } } if ((!f_code && (j = c == '\n')) || i >= vt_col(0)) { if ((pp = calloc(sizeof(PP), 1))) { pp->cs = cs; if (f_code) pp->f.code = 1; else if (n_attr) { Alloc.attr[n_attr++].n = -1; /* mark end of attribute */ if ((pp->attr = malloc(sizeof(ATTR) * n_attr))) memcpy(pp->attr, Alloc.attr, sizeof(ATTR) * n_attr); else { free(pp); save_intr(S_errl); ce = end; continue; } } pp->prev = pp1; if (!pp0) pp0 = pp; else pp1->next = pp; pp1 = pp; if (pp->prev) pp->f.line = pp->prev->f.line + ((f_code) ? 1 : pp->prev->f.nl); else pp->f.line = 1; pp->f.nl = j; p_len += sizeof(PP) + ((n_attr) ? sizeof(ATTR) * n_attr : 0); if (p_len > bsize) { ce = end; save_intr(S_err4); continue; } if (!f_code && j) { cs = ce + 1; pp->f.len = ((h = ce - pp->cs) < 0) ? 0 : h; ce--; } else { pp->f.len = ((h = ce - cs - uc) < 0) ? 0 : h; cs = pp->cs + pp->f.len; } uc = 0; ce = cs - !f_code; i = -!f_code; n = -1; n_attr = 0; n_row++; } else { ce = end; save_intr(S_errl); continue; } } i++; ce++; n++; } if (ce > cs && !j && ce == end) { /* end of buffer is not '\n' */ if ((pp = calloc(sizeof(PP), 1))) { do { pp->cs = cs; pp->f.len = ce - cs; if (f_code) pp->f.code = 1; else if (n_attr) { Alloc.attr[n_attr++].n = -1; if ((pp->attr = malloc(sizeof(ATTR) * n_attr))) memcpy(pp->attr, Alloc.attr, sizeof(ATTR) * n_attr); else { free(pp); save_intr(S_errl); continue; } } pp->prev = pp1; if (!pp0) pp0 = pp; else pp1->next = pp; pp1 = pp; if (pp->prev) pp->f.line = pp->prev->f.line + pp->f.nl; else pp->f.line = 1; n_row++; } while (0); } else save_intr(S_errl); } if (load_intr() == S_errl) save_error("%s: %s.\n", s_S(S_tcb), s_S(S_errl)); *rowp = n_row; return pp0; } PP **set_ppp(void *p, void *p0, int f_set)/*tcb*/ { /* replace old line-pointer with new one */ static PP **ppp, **ppp0; if (f_set) { ppp = p; ppp0 = p0; } else if (!f_set) { *ppp = p; *ppp0 = p0; } return ppp; } int alloc_winch(BASE *bp, int f_ppp)/*tcb*/ { /* adjust line-pointer after changing window size */ u_char *cp, *buff; PP *pp; int size, row, f_bin, f_code; FILE *fp; f_code = bp->pp->f.code; f_bin = bp->pp->f.bin; for (row = size = 0, pp = bp->pp; pp; pp = pp->next) { size += pp->f.len; if (!f_code && pp->f.nl) { size++; row++; } } if (!(buff = malloc(size))) { save_intr(S_errl); save_error("%s: %s.\n", s_S(S_tcb), s_S(S_errl)); fp = fopen(s_S(S_tmp), "w"); for (row = 0, pp = bp->pp; pp; pp = pp->next) { fwrite(pp->cs, 1, pp->f.len, fp); if (!f_code && pp->f.nl) { fputc('\n', fp); row++; } } fclose(fp); } else for (row = 0, cp = buff, pp = bp->pp; pp; pp = pp->next) { memcpy(cp, pp->cs, pp->f.len); cp += pp->f.len; if (!f_code && pp->f.nl) { *cp++ = '\n'; row++; } } free_bp(bp); if (!buff) { while (!(buff = malloc(size)) && (size /= 2)) ; if (size) { fp = fopen(s_S(S_tmp), "r"); fread(buff, 1, size, fp); fclose(fp); } } bp->buff = buff; if ((bp->size = size)) { bp->pp = set_pp(bp->buff, bp->size, &bp->nrow, f_code, f_bin); bp->pp->f.bin = f_bin; for (pp = bp->pp; pp && pp->next; pp = pp->next); } if (f_ppp) set_ppp(pp, bp->pp, 0); return bp->nrow; } LS *save_ls(LS *lp, LS *ls) { if (!lp) { lp = malloc(sizeof(LS)); memcpy(lp, ls, sizeof(LS)); lp->next = NULL; } else lp->next = save_ls(lp->next, ls); return lp; } void free_ls(LS *lp) { if (lp->next) free_ls(lp->next); free(lp); } int alloc_ls(u_char buff[], int size)/*tcb*/ { /* truncate extra space characters from `ls' output */ int c, ls_b, ls_i, ls_len, f_dev, f_sym; char *cp0, *cp, *end, *ls_p; LS *p, *lp, ls; char *tab, *tp, tmp[10]; tab = tp = malloc(size); end = buff + size; cp0 = cp = (u_char*)((int)strchr(buff, '\n') + 1); ls_b = ls_i = ls_len = f_dev = f_sym = 0; ls_p = cp; lp = NULL; while (cp < end && !f_dev) if (((c = *cp++) != ' ' && c != '\n') || (f_sym && c != '\n') || (c == ' ' && (!strncmp(cp, "-> ", 3) || cp[-2] == '\\'))) { ls_len++; if (ls_b < ls_i) { ls_b = ls_i; ls_p = &cp[-1]; } if (c == ' ' && cp[-2] != '\\') f_sym = 1; } else if (ls_b == ls_i || c == '\n') { if (c == '\n') ls_len++; ls.len[ls_i] = ls_len; ls.s[ls_i] = tp; memcpy(tp, ls_p, ls_len); tp[ls_len] = '\0'; if (!f_dev && (strchr(tp, '\0'))[-1] == ',') f_dev = 1; tp += ls_len + 1; ls_i++; if (c == '\n') { lp = save_ls(lp, &ls); ls_b = ls_i = f_sym = 0; ls_p = cp; } ls_len = 0; } if (f_dev) ls_len = size; else { for (p = lp; p; p = p->next) { ls_i = 0; do { if (ls.len[ls_i] < p->len[ls_i]) ls.len[ls_i] = p->len[ls_i]; } while (!strchr(p->s[ls_i++], '\n')); } ls_len = 0; *cp0 = '\0'; ls_len = strlen(buff); for (p = lp; p; p = p->next) { ls_i = 0; do { if (!(cp = strchr(p->s[ls_i], '\n'))) { sprintf(tmp, "%%%ds ", ls.len[ls_i]); sprintf(Alloc.line, tmp, p->s[ls_i]); } else sprintf(Alloc.line, "%s", p->s[ls_i]); strcat(buff, Alloc.line); ls_len += strlen(Alloc.line); ls_i++; } while (!cp); } } free_ls(lp); free(tab); return ls_len; } void free_bp(BASE *bp)/*tcb*/ { if (!bp) return; if (bp->buff) { free(bp->buff); bp->buff = NULL; } if (bp->pp) bp->pp = free_pp(bp->pp); bp->size = bp->nrow = 0; }