/* expands the prompt if necessary * ----------------------------------------------------------------------- */ void prompt_expand(void) { /* expand PS1 only */ if(prompt_number != 1) return; /* expand prompt tree if present */ if(prompt_node) { stralloc sa; /* escape prompt */ stralloc_init(&sa); #ifdef DEBUG /* debug_list(prompt_node, 0); */ #endif expand_catsa(prompt_node, &sa, 0); stralloc_nul(&sa); stralloc_zero(&prompt_expansion); prompt_escape(sa.s, &prompt_expansion); stralloc_nul(&prompt_expansion); #ifdef DEBUG /* debug_stralloc("prompt", &sa, 0);*/ #endif } }
/* evaluate case conditional construct (3.9.4.3) * ----------------------------------------------------------------------- */ int eval_case(struct eval *e, struct ncase *ncase) { union node *node; union node *pat; int ret = 0; stralloc word; stralloc pattern; stralloc_init(&word); stralloc_init(&pattern); if(ncase->word) expand_catsa(ncase->word, &word, X_NOSPLIT); stralloc_nul(&word); for(node = ncase->list; node; node = node->list.next) { for(pat = node->ncasenode.pats; pat; pat = pat->list.next) { expand_catsa(pat, &pattern, X_NOSPLIT); stralloc_nul(&pattern); if(shell_fnmatch(pattern.s, pattern.len, word.s, word.len, SH_FNM_PERIOD) == 0) { ret = eval_tree(e, node->ncasenode.cmds, E_LIST); goto end; } stralloc_zero(&pattern); } } end: stralloc_free(&pattern); stralloc_free(&word); return ret; }
size_t stralloc_scan(stralloc* out, const stralloc* in, size_t (*scan_function)(const char*, char*)) { size_t i; stralloc_zero(out); for(i = 0; i < in->len; ++out->len) { if(!stralloc_readyplus(out, 1)) return 0; i += scan_function(&in->s[i], &out->s[out->len]); } return out->len; }
size_t stralloc_fmt(stralloc* out, const char* in, size_t in_len, size_t (*fmt_function)()) { size_t i; stralloc_zero(out); for(i = 0; i < in_len; ++i) { if(!stralloc_readyplus(out, 10)) return 0; out->len += fmt_function(&out->s[out->len], in[i]); } stralloc_trunc(out, out->len); return out->len; }
int path_absolute(const char* path, stralloc* sa) { int ret = 0; stralloc_zero(sa); if(!path_isabs(path)) { path_getcwd(sa); stralloc_catc(sa, PATHSEP_C); stralloc_cats(sa, path); return 1; } stralloc_copys(sa, path); return 0; }
static int mangleurl(stralloc* tag,const char* baseurl) { char* x; const char* y; static stralloc before,arg,after,tmp; int found; struct stat ss; found=0; if (stralloc_istag(tag,"a") || stralloc_istag(tag,"link")) found=1; else if (stralloc_istag(tag,"img") || stralloc_istag(tag,"frame")) found=2; if (!found) return 0; if (extractparam(tag,found==1?"href":"src",&before,&arg,&after)) { if (stralloc_starts(&arg,"/") || stralloc_starts(&arg,"http://") || stralloc_starts(&arg,"https://")) { canonicalize(&arg,baseurl); } else return 0; /* url was already relative */ if (stralloc_0(&arg)==0) return -1; stralloc_chop(&arg); x=arg.s+7; if (*x=='/') ++x; y=baseurl+7; if (*y=='/') ++y; /* now x is something like * "www.spiegel.de/img/0,1020,525770,00.jpg" * and baseurl is something like * "www.spiegel.de/panorama/0,1518,378421,00.html" * and we want to change x into "../img/0,1020,525770,00.jpg" */ if (stat(x,&ss)!=0) return 0; for (;;) { int i=str_chr(x,'/'); int j=str_chr(y,'/'); if (i>0 && i==j && byte_equal(x,i,y)) { x+=i+1; y+=i+1; while (*x=='/') ++x; while (*y=='/') ++y; } else break; } stralloc_zero(&tmp); for (;;) { int i=str_chr(y,'/'); if (y[i]=='/') { y+=i+1; while (*y=='/') ++y; if (stralloc_cats(&tmp,"../")==0) return -1; } else break; } { int i,needquote; for (i=needquote=0; x[i]; ++i) if (!isalnum(x[i]) && x[i]!='/' && x[i]!='_' && x[i]!='.') needquote=1; if (needquote) { if (stralloc_cats(&before,"\"")==0 || stralloc_cat(&before,&tmp)==0 || stralloc_cats(&before,x)==0 || stralloc_cats(&before,"\"")==0) return -1; } else if (stralloc_cat(&before,&tmp)==0 || stralloc_cats(&before,x)==0) return -1; } if (stralloc_cat(&before,&after)==0) return -1; if (stralloc_copy(tag,&before)==0) return -1; } return 0; }
/* main loop, parse lines into trees and execute them * ----------------------------------------------------------------------- */ void sh_loop(void) { struct parser p; union node *list; stralloc cmd; /* if we're in interactive mode some additional stuff is to be initialized */ if(source->mode & SOURCE_IACTIVE) history_load(); stralloc_init(&cmd); parse_init(&p, P_DEFAULT); while(!(parse_gettok(&p, P_DEFAULT) & T_EOF)) { p.pushback++; parse_lineno = source->line; var_setvint("LINENO", parse_lineno, V_DEFAULT); /* launch the parser to get a complete command */ if((list = parse_list(&p))) { struct eval e; if(source->mode & SOURCE_IACTIVE) { tree_printlist(list, &cmd, NULL); stralloc_catc(&cmd, '\n'); stralloc_nul(&cmd); history_set(cmd.s); cmd.s = NULL; history_advance(); } #ifdef DEBUG /* debug_list(list, 0); buffer_putnlflush(fd_err->w);*/ #endif /* DEBUG */ eval_push(&e, E_JCTL); eval_tree(&e, list, E_ROOT|E_LIST); sh->exitcode = eval_pop(&e); stralloc_zero(&cmd); tree_free(list); } else if(!(p.tok & (T_NL | T_SEMI | T_BGND))) { /* we have a parse error */ if(p.tok != T_EOF) parse_error(&p, 0); /* exit if not interactive */ if(!(source->mode & SOURCE_IACTIVE)) sh_exit(1); /* ..otherwise discard the input buffer */ source_flush(); p.pushback = 0; } if(p.tok & (T_NL|T_SEMI|T_BGND)) p.pushback = 0; /* reset prompt */ prompt_number = 0; } }
void xml_read_callback(xmlreader* r, xml_read_callback_fn* fn) { ssize_t n; buffer* b = r->b; stralloc tag, attr, val; stralloc_init(&tag); stralloc_init(&attr); stralloc_init(&val); hmap_init(XML_HMAP_BUCKETS, &r->attrmap); while((n = buffer_skip_until(b, "<", 1)) > 0) { const char* s; stralloc_zero(&tag); r->self_closing = r->closing = 0; s = buffer_peek(b); if(*s == '/') { r->closing = 1; buffer_skipc(b); } else if(*s == '?') { r->self_closing = 1; } else if(*s == '!') { if(buffer_skip_until(b, ">", 1) <= 0) return; continue; } if((n = buffer_gettok_sa(b, &tag, " \n\t\r\v/>", 7)) < 0) return; stralloc_nul(&tag); buffer_skipspace(b); while((s = buffer_peek(b)) && isalpha(*s)) { char ch; int quoted = 0; const char* charset; stralloc_zero(&attr); stralloc_zero(&val); if((n = buffer_gettok_sa(b, &attr, "=", 1)) < 0) break; if(buffer_skipc(b) < 0) return; if(*buffer_peek(b) == '"') { if(buffer_skipc(b) < 0) return; quoted = 1; } charset = quoted ? "\"" : "/> \t\r\n\v"; if((n = buffer_gettok_sa(b, &val, charset, str_len(charset))) < 0) break; if(quoted && buffer_skipc(b) < 0) return; stralloc_nul(&attr); stralloc_nul(&val); hmap_set(&r->attrmap, attr.s, attr.len, val.s, val.len + 1); if(!fn(r, XML_ATTRIBUTE, &attr, &val, NULL)) return; buffer_skipspace(b); } buffer_skipspace(b); if((s = buffer_peek(b)) && str_chr("/?", *s) < 2) { r->self_closing = 1; r->closing = 0; buffer_skipc(b); } buffer_skipspace(b); if((s = buffer_peek(b)) && *s == '>') buffer_skipc(b); if(!fn(r, XML_ELEMENT, &tag, NULL, &r->attrmap)) return; if(r->attrmap) { hmap_destroy(&r->attrmap); r->attrmap = NULL; } hmap_init(XML_HMAP_BUCKETS, &r->attrmap); stralloc_zero(&tag); if((n = buffer_gettok_sa(b, &tag, "<", 1)) < 0) return; s = buffer_peek(b); if(!is_whitespace(tag.s, tag.len)) { if(!fn(r, XML_TEXT, NULL, &tag, NULL)) return; } } }
int buffer_get_new_token_sa_pred(buffer* b,stralloc* sa,sa_predicate p) { stralloc_zero(sa); return buffer_get_token_sa_pred(b,sa,p); }
int buffer_get_new_token_sa(buffer* b,stralloc* sa,const char* charset,size_t setlen) { stralloc_zero(sa); return buffer_get_token_sa(b,sa,charset,setlen); }
/* ----------------------------------------------------------------------- */ int term_read(int fd, char *buf, unsigned int len) { char c; int ret; static unsigned long remain; if(remain) { check_remain: if(len > remain) len = remain; byte_copy(buf, len, &term_cmdline.s[term_cmdline.len - remain]); remain -= len; if(!remain) { tcsetattr(fd, TCSANOW, &term_tcattr); stralloc_zero(&term_cmdline); } return len; } /* tcsetattr(fd, TCSANOW, &term_tcattr);*/ term_attr(term_input.fd, 1); prompt_show(); while((ret = buffer_getc(&term_input, &c)) > 0) { switch(c) { /* control-c discards the current line */ case 3: stralloc_zero(&term_cmdline); /* newline */ case '\n': term_newline(); remain = term_cmdline.len; goto check_remain; /* control-a is HOME */ case 1: term_home(); break; /* control-e is END */ case 5: term_end(); break; /* control-d is EOF */ case 4: if(!term_cmdline.len) { buffer_puts(term_output, "EOF"); buffer_putnlflush(term_output); ret = 0; goto fail; } break; /* do the ANSI codes */ case '\033': term_ansi(); break; /* backspace */ case 127: case '\b': term_backspace(); break; /* printable chars */ case '\t': c = ' '; default: if(term_insert) term_insertc(c); else term_overwritec(c); break; } } fail: return ret; }
/* sets or displays current hostname * ----------------------------------------------------------------------- */ int builtin_hostname(int argc, char **argv) { int c; int force = 0; /* check options */ while((c = shell_getopt(argc, argv, "f")) > 0) { switch(c) { case 'f': force = 1; break; default: builtin_invopt(argv); return 1; } } /* if there is an argument we set it as new hostname */ if(argv[shell_optind]) { unsigned long n; n = str_len(argv[shell_optind]); /* unless force is set and if the new hostname is the same as the current then do not update it */ if(!force && n == sh_hostname.len && !byte_diff(sh_hostname.s, n, argv[shell_optind])) return 0; #ifdef HAVE_SETHOSTNAME /* set the supplied hostname */ #if !defined(__CYGWIN__) && !defined(__MINGW32__) if(sethostname(argv[shell_optind], n)) #else errno = ENOSYS; #endif { /* report any error */ builtin_error(argv, "sethostname"); return 1; } #endif /* on success update internal hostname */ stralloc_copyb(&sh_hostname, argv[shell_optind], n); } /* if there is no argument we display the current hostname */ else { /* force re-get of hostname by clearing it now */ if(force) stralloc_zero(&sh_hostname); /* get hostname if it isn't there */ if(sh_hostname.len == 0) shell_gethostname(&sh_hostname); /* report errors */ if(sh_hostname.len == 0) { builtin_error(argv, "gethostname"); return 1; } /* finally output the hostname */ buffer_putsa(fd_out->w, &sh_hostname); buffer_putnlflush(fd_out->w); } return 0; }