int sln(const char* path) { stralloc s, d; char* to; ssize_t i; stralloc_init(&s); stralloc_copys(&s, path); stralloc_init(&d); stralloc_copy(&d, &s); while(reduce(&d)) { buffer_puts(buffer_2, "'"); buffer_putsa(buffer_2, &d); buffer_puts(buffer_2, "' -> '"); buffer_putsa(buffer_2, &s); buffer_puts(buffer_2, "'\n"); buffer_flush(buffer_2); stralloc_nul(&s); stralloc_nul(&d); if(mklink_sa(&s, &d) == -1) { errmsg_warnsys("symlink failed", NULL); exit(2); } stralloc_copy(&s, &d); } return 0; }
/* 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; }
/* process all here-docs * * nredir->data is set to the next here-doc redirection by redir_addhere() * after processing it is set to the content of the here-doc (an narg node) * ----------------------------------------------------------------------- */ void redir_source(void) { struct parser p; stralloc delim; int r; parse_init(&p, P_HERE); stralloc_init(&delim); for(; redir_list; redir_list = &redir_list->data->nredir) { /* expand the delimiter */ stralloc_init(&delim); expand_catsa((union node *)redir_list, &delim, 0); /* when any character of the delimiter has been escaped then treat the whole here-doc as non-expanded word */ r = parse_here(&p, &delim, (redir_list->list->nargstr.flag & S_ESCAPED)); tree_free(redir_list->list); redir_list->list = parse_getarg(&p); /* free expanded delimiters */ stralloc_free(&delim); } }
/* evaluates backquoted command list, while writing stdout to a stralloc */ union node* expand_command(struct nargcmd *cmd, union node **nptr, struct vartab* varstack, int flags) { union node *n = *nptr; stralloc sa; stralloc_init(&sa); /* make the output buffer write to the stralloc */ buffer_tosa(buffer_1, &sa); /* evaluate the command tree in a subshell */ /*sh_push(&sh); sh_subshell(cmd->list, E_EXIT); sh_pop(&sh);*/ /* split trailing newlines */ while(sa.len && sa.s[sa.len - 1] == '\n') sa.len--; /* expand the output of the command FIXME: we could do this much nicer by doing an expand_write() which is set as buffer op on the output fd. so we won't have to alloc all the stuff twice! */ n = expand_cat(sa.s, sa.len, nptr, varstack, flags); stralloc_free(&sa); return n; }
/* 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 } }
void http_init(http* h, const char* host, uint16 port) { byte_zero(h, sizeof(http)); h->sock = -1; stralloc_init(&h->host); stralloc_copys(&h->host, host); h->port = port; h->request = NULL; }
int main() { stralloc sa; buffer b; stralloc line; stralloc_init(&sa); stralloc_init(&line); stralloc_copys(&sa,"this is a test\nline 2\n"); buffer_fromsa(&b,&sa); while (buffer_getline_sa(&b,&line)==0) { buffer_puts(buffer_1,"got line: \""); if (stralloc_chop(&line)!='\n') break; buffer_putsa(buffer_1,&line); buffer_putsflush(buffer_1,"\"\n"); stralloc_copys(&line,""); } return 0; }
static int pls_reader(playlist* pl) { int ret; static playlist_entry entry; buffer* inbuf = pl->ptr; stralloc line; stralloc_init(&line); if(( ret = buffer_getline_sa(inbuf, &line))) { size_t index2, index; index2 = index = 0; while(line.len > 1 && (line.s[line.len - 1] == '\r' || line.s[line.len - 1] == '\n')) line.len--; stralloc_0(&line); if(!str_diffn(&line.s[index], "Number", 6)) { } else if(line.s[index] == '[') { } else if((index2 = str_chr(&line.s[index], '=')) > 0) { unsigned long trackno = 0; index = index2; index2++; do { index--; } while(isdigit(line.s[index]) && index > 0); scan_ulong(&line.s[index], &trackno); if(!str_diffn(&line.s[index], "File", 4)) { stralloc_copys(&entry.path, &line.s[index2]); stralloc_0(&entry.path); } else if(!str_diffn(&line.s[index], "Title", 5)) { stralloc_copys(&entry.title, &line.s[index2]); stralloc_0(&entry.title); } else if(!str_diffn(&line.s[index], "Length", 6)) { unsigned long len; scan_ulong(&line.s[index2], &len); entry.length = len; } /* uint32 index = 8; index += scan_ulong(&line.s[index], &len); entry.length = len; index++; stralloc_copys(&entry.title, &line.s[index]); stralloc_0(&entry.title); */ } else { /* stralloc_copy(&entry.path, &line); stralloc_0(&entry.path); if(pl->callback) { pl->callback(pl, &entry.title, &entry.path, entry.length); }*/ } } return ret; }
int main() { stralloc sa; int res; stralloc_init(&sa); res=buffer_get_token_sa_pred(buffer_0,&sa,ishttp); buffer_puts(buffer_1,"buffer_get_token_sa_pred returned "); buffer_putlong(buffer_1,res); buffer_putsflush(buffer_1,".\n\n"); buffer_putsa(buffer_1,&sa); buffer_flush(buffer_1); return 0; }
/* evaluates backquoted command list, while writing stdout to a stralloc * ----------------------------------------------------------------------- */ union node *expand_command(struct nargcmd *cmd, union node **nptr, int flags) { union node *n = *nptr; struct vartab vars; struct fd fd; struct fdstack fdst; struct env sh; stralloc sa; stralloc_init(&sa); /* do this in a new i/o context so we can redirect stdout */ vartab_push(&vars); /* make the output buffer write to the stralloc */ fdstack_push(&fdst); fd_push(&fd, STDOUT_FILENO, FD_WRITE); fd_subst(&fd, &sa); /* evaluate the command tree in a subshell */ sh_push(&sh); sh_subshell(cmd->list, E_EXIT); sh_pop(&sh); fdstack_pop(&fdst); vartab_pop(&vars); /* split trailing newlines */ while(sa.len && sa.s[sa.len - 1] == '\n') sa.len--; /* expand the output of the command FIXME: we could do this much nicer by doing an expand_write() which is set as buffer op on the output fd. so we won't have to alloc all the stuff twice! */ n = expand_cat(sa.s, sa.len, nptr, flags); stralloc_free(&sa); return n; }
/* set a variable * ----------------------------------------------------------------------- */ struct var *var_set(char *v, int flags) { struct var *var; /* find/create the variable */ if((var = var_create(v, flags)) == NULL) return var; /* free if it was a previously allocated string */ if(var->sa.a) stralloc_free(&var->sa); stralloc_init(&var->sa); var->sa.s = v; var->sa.len = str_len(v); var->offset = var->len; if(var->len < var->sa.len) var->offset++; return var; }
char *whirlpool_digest(const char *str) { whirlpool_t ctx; stralloc_t sa; char *buf; uint8_t digest[DIGESTBYTES]; int i; whirlpool_init(&ctx); whirlpool_add(&ctx, (const unsigned char * const) str, str_len(str)*8); whirlpool_finalize(&ctx, digest); stralloc_init(&sa); for (i = 0; i < DIGESTBYTES; i++) stralloc_catf(&sa, "%02X", digest[i]); buf = stralloc_finalize(&sa); stralloc_free(&sa); return buf; }
int list_dir_internal(stralloc* dir, char type) { size_t l; struct dir_s d; stralloc pre; int dtype; int is_dir, is_symlink; size_t len; #if !WINDOWS_NATIVE struct stat st; static dev_t root_dev; #endif char *name, *s; (void)type; while(dir->len > 1 && IS_DIRSEP(dir->s[dir->len - 1])) dir->len--; stralloc_nul(dir); #if !WINDOWS_NATIVE if(root_dev == 0) { if(stat(dir->s, &st) != -1) { root_dev = st.st_dev; } } #endif if(dir_open(&d, dir->s) != 0) { buffer_puts(buffer_2, "ERROR: Opening directory "); buffer_putsa(buffer_2, dir); buffer_puts(buffer_2, " failed!\n"); buffer_flush(buffer_2); goto end; } if(dir->s[dir->len - 1] != DIRSEP_C) stralloc_cats(dir, DIRSEP_S); l = dir->len; while((name = dir_read(&d))) { unsigned int mode = 0, nlink = 0, uid = 0, gid = 0; uint64 size = 0, mtime = 0; dtype = dir_type(&d); dir->len = l; if(str_equal(name, "") || str_equal(name, ".") || str_equal(name, "..")) { continue; } stralloc_readyplus(dir, str_len(name) + 1); str_copy(dir->s + dir->len, name); dir->len += str_len(name); is_symlink = !!(dtype & D_SYMLINK); #if !WINDOWS_NATIVE if(!opt_deref && lstat(dir->s, &st) != -1) { if(root_dev && st.st_dev) { if(st.st_dev != root_dev) { continue; } } } #endif #if !WINDOWS_NATIVE if(S_ISLNK(st.st_mode)) { stat(dir->s, &st); } mode = st.st_mode; #endif if(dtype) { is_dir = !!(dtype & D_DIRECTORY); } else { #if WINDOWS_NATIVE is_dir = 0; #else is_dir = !!S_ISDIR(mode); #endif } if(dtype & D_SYMLINK) is_symlink = 1; #if !WINDOWS_NATIVE nlink = st.st_nlink; uid = st.st_uid; gid = st.st_gid; size = st.st_size; mtime = st.st_mtime; #else mode = (is_dir ? 0040000 : 0100000) | (is_symlink ? 0120000 : 0); #if USE_READDIR if(!is_dir) { size = dir_size(&d); /* dir_INTERNAL(&d)->dir_entry->d_name); */ mtime = dir_time(&d); } else { mtime = 0; size = 0; } #else size = dir_size(&d); mtime = dir_time(&d, D_TIME_MODIFICATION); #endif #endif if(opt_list && size >= opt_minsize) { stralloc_init(&pre); /* Mode string */ mode_str(&pre, mode); stralloc_catb(&pre, " ", 1); /* num links */ make_num(&pre, nlink, 3); stralloc_catb(&pre, " ", 1); /* uid */ make_num(&pre, uid, 0); stralloc_catb(&pre, " ", 1); /* gid */ make_num(&pre, gid, 0); stralloc_catb(&pre, " ", 1); /* size */ make_num(&pre, size, 6); stralloc_catb(&pre, " ", 1); /* time */ make_num(&pre, mtime, 0); /* make_time(&pre, mtime, 10); */ stralloc_catb(&pre, " ", 1); } /* fprintf(stderr, "%d %08x\n", is_dir, dir_ATTRS(&d)); */ if(is_dir) stralloc_catc(dir, opt_separator); if(dir->len > MAX_PATH) { buffer_puts(buffer_2, "ERROR: Directory "); buffer_putsa(buffer_2, dir); buffer_puts(buffer_2, " longer than MAX_PATH (" STRINGIFY(MAX_PATH) ")!\n"); /*buffer_putulong(buffer_2, MAX_PATH); buffer_puts(buffer_2, ")!\n");*/ buffer_flush(buffer_2); goto end; } s = dir->s; len = dir->len; if(len >= 2 && s[0] == '.' && IS_DIRSEP(s[1])) { len -= 2; s += 2; } if(opt_list && size >= opt_minsize) buffer_putsa(buffer_1, &pre); if(opt_relative_to) { size_t sz = str_len(opt_relative_to); if(str_diffn(s, opt_relative_to, sz) == 0) { s += sz; len -= sz; while(*s == '\\' || *s == '/') { s++; len--; } } } if(size >= opt_minsize) { buffer_put(buffer_1, s, len); buffer_put(buffer_1, "\n", 1); buffer_flush(buffer_1); } if(is_dir && (opt_deref || !is_symlink)) { dir->len--; list_dir_internal(dir, 0); } } end: dir_close(&d); return 0; }
int dir_type(struct dir_s* d) { int r = 0; #if !USE_READDIR && (defined(_WIN32) || defined(_WIN32) || defined(__MSYS__)) if(dir_INTERNAL(d)->dir_finddata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) r |= D_SYMLINK; else if(dir_INTERNAL(d)->dir_finddata.dwFileAttributes & 0x10) r |= D_DIRECTORY; else if(dir_INTERNAL(d)->dir_finddata.dwFileAttributes & 0x20) r |= D_FILE; #else #ifndef DT_DIR #define DT_DIR 4 #endif #ifndef DT_REG #define DT_REG 8 #endif #ifndef DT_LNK #define DT_LNK 10 #endif #if defined(_DIRENT_HAVE_D_TYPE) || (!defined(__MSYS__) && !defined(__CYGWIN__)) switch((dir_TYPE(d))) { case DT_DIR: { r |= D_DIRECTORY; break; } case DT_REG: { r |= D_FILE; break; } case DT_LNK: { r |= D_SYMLINK; break; } case 0: default: { break; } } #else { stralloc sa; struct stat st; DIR* dh = dir_INTERNAL(d)->dir_handle; stralloc_init(&sa); dir_path(d, &sa); stralloc_nul(&sa); if(lstat(sa.s, &st) != -1) { if(S_ISLNK(st.st_mode)) r |= D_SYMLINK; else if(S_ISDIR(st.st_mode)) r |= D_DIRECTORY; else if(S_ISREG(st.st_mode)) r |= D_FILE; } #ifdef DEBUG_OUTPUT buffer_puts(buffer_2, "dir_type path: "); buffer_putsa(buffer_2, &sa); buffer_putnlflush(buffer_2); #endif // printf("dh: %p __d_dirname: %s\n", dh, dh->__d_dirname); stralloc_free(&sa); } //#error No dirent type method #endif #endif return r; }
int main(int argc, char* argv[]) { int index = 0, c; static const struct longopt opts[] = {{"help", 0, NULL, 'h'}, {"verbose", 0, 0, 'v'}, {0}}; errmsg_iam(argv[0]); for(;;) { c = getopt_long(argc, argv, "hv", opts, &index); if(c == -1) break; if(c == '\0') continue; switch(c) { case 'h': usage(argv[0]); return 0; case 'v': verbose = 1; break; default: { usage(argv[0]); return 1; } } } while(optind < argc) { const char* a = argv[optind++]; int i = str_rchr(a, '.'); if(str_equal(&a[i], ".list")) { buffer in; if(!buffer_mmapread(&in, a)) { stralloc target, link; ssize_t ret; stralloc_init(&target); stralloc_init(&link); for(;;) { if((ret = buffer_get_new_token_sa(&in, &target, " \t\v", 2)) < 0) break; if(ret == 0 || target.s[0] == '\0') break; if(target.len > 0) --target.len; if((ret = buffer_get_new_token_sa(&in, &link, "\r\n", 2)) < 0) break; if(ret == 0 || link.s[0] == '\0') break; stralloc_chomp(&link); mklink_sa(&target, &link); if(!stralloc_endb(&link, ".so", 3)) { if(sln(link.s)) return 1; } } buffer_close(&in); } } else { if(sln(argv[i])) return 1; } } }
union node* expand_param(struct nargparam* param, union node** nptr, struct vartab* varstack, char* argv[], int exitcode, int flags) { union node* n = *nptr; stralloc value; char* str = NULL; const char *v = NULL; unsigned long argc, vlen = 0; for(argc = 0; argv[argc]; ++argc) ; stralloc_init(&value); /* treat special arguments */ if(param->flag & S_SPECIAL) { switch(param->flag & S_SPECIAL) { /* $# substitution */ case S_ARGC: { stralloc_catulong0(&value, argc, 0); break; } /* $* substitution */ case S_ARGV: { char** s; for(s = argv; *s;) { stralloc_cats(&n->narg.stra, *s); if(*++s) stralloc_catc(&n->narg.stra, ' '); } break; } /* $@ substitution */ case S_ARGVS: { unsigned int i = 0; while(i < argc) { param->flag &= ~S_SPECIAL; param->flag |= S_ARG; param->numb = 1 + i; n = expand_param(param, nptr, varstack, argv, exitcode,flags); if(++i < argc) nptr = &n->list.next; } return n; } /* $? substitution */ case S_EXITCODE: { stralloc_catulong0(&value, exitcode, 0); break; } /* $- substitution */ case S_FLAGS: break; /* $! substitution */ case S_BGEXCODE: break; /* $[0-9] arg subst */ case S_ARG: { if(param->numb == 0) { /* stralloc_cats(&value, sh_argv0); */ } else if(param->numb - 1 < argc) { stralloc_cats(&value, argv[param->numb - 1]); } break; } /* $$ arg subst */ case S_PID: { stralloc_catulong0(&value, getpid(), 0); break; } } /* special parameters are always set */ if(value.len) { stralloc_nul(&value); v = value.s; } vlen = value.len; } /* ..and variable substitutions */ else { size_t offset; /* look for the variable. if the S_NULL flag is set and we have a var which is null set v to NULL */ if((v = var_get(varstack, param->name, &offset))) { if(v[offset] == '\0' && (param->flag & S_NULL)) { v = NULL; vlen = 0; } else { v = &v[offset]; vlen = str_len(v); } } } /* check for S_STRLEN substitution */ if(param->flag & S_STRLEN) { char lstr[FMT_ULONG]; n = expand_cat(lstr, fmt_ulong(lstr, vlen), nptr, varstack, flags); stralloc_free(&value); return n; } str = str_ndup(v, vlen); /* otherwise expand the apropriate variable/word subst */ switch(param->flag & S_VAR) { /* return word if parameter unset (or null) */ case S_DEFAULT: { if(v) n = expand_cat(v, vlen, nptr, varstack, flags); /* unset, substitute */ else n = expand_arg(¶m->word->narg, nptr, varstack, argv, exitcode, flags); break; } /* if parameter unset (or null) then expand word to it and substitute paramter */ case S_ASGNDEF: { if(v) n = expand_cat(v, vlen, nptr, varstack, flags); else { n = expand_arg(¶m->word->narg, nptr, varstack, argv, exitcode, flags | X_NOSPLIT); var_setvsa(param->name, /* BUG */ &n->narg.stra, V_DEFAULT); } break; } /* indicate error if null or unset */ case S_ERRNULL: { if(v) n = expand_cat(v, vlen, nptr, varstack, flags); else { union node* tmpnode = NULL; n = expand_arg(¶m->word->narg, &tmpnode, varstack, argv, exitcode, flags); errmsg_warn((n && n->narg.stra.s) ? n->narg.stra.s : "parameter null or not set", 0); if(tmpnode) tree_free(tmpnode); } break; } /* if parameter unset (or null) then substitute null, otherwise substitute word */ case S_ALTERNAT: { if(v) n = expand_arg(¶m->word->narg, nptr, varstack, argv, exitcode, flags); break; /* remove smallest matching suffix */ case S_RSSFX: { int i; stralloc sa; if(v && vlen) { expand_copysa(param->word, &sa, varstack, argv, exitcode, 0); stralloc_nul(&sa); for(i = vlen - 1; i >= 0; i--) if(fnmatch(sa.s, str + i, FNM_PERIOD) == 0) break; n = expand_cat(v, (i < 0 ? vlen : i), nptr, varstack, flags); } break; } } /* remove largest matching suffix */ case S_RLSFX: { unsigned int i; stralloc sa; if(v && vlen) { expand_copysa(param->word, &sa, varstack, argv, exitcode, 0); stralloc_nul(&sa); for(i = 0; i <= vlen; i++) if(fnmatch(sa.s, str + i, FNM_PERIOD) == 0) break; n = expand_cat(v, (i > vlen ? vlen : i), nptr, varstack, flags); } break; } /* remove smallest matching prefix */ case S_RSPFX: { unsigned int i; stralloc sa; if(v && vlen) { expand_copysa(param->word, &sa, varstack, argv, exitcode, 0); stralloc_nul(&sa); for(i = 1; i <= vlen; i++) { str_copyn(str, v, i); if(fnmatch(sa.s, (char*)v, FNM_PERIOD) == 0) break; } if(i > vlen) i = 0; n = expand_cat(v + i, vlen - i, nptr, varstack, flags); str_copy(str, v); } break; } /* remove largest matching prefix */ case S_RLPFX: { unsigned int i; stralloc sa; if(v && vlen) { expand_copysa(param->word, &sa, varstack, argv, exitcode, 0); stralloc_nul(&sa); for(i = vlen; i > 0; i--) { str_copyn(str, v, i); if(fnmatch(sa.s, (char*)v, FNM_PERIOD) == 0) break; } if(i == 0) i = vlen; n = expand_cat(v + i, vlen - i, nptr, varstack, flags); str_copy(str, v); } break; } } free(str); stralloc_free(&value); return n; }
/* 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; } }
/* change working directory * ----------------------------------------------------------------------- */ int builtin_cd(int argc, char **argv) { int c; int ok = 0; int symbolic = 1; const char *arg; unsigned long len; unsigned long n; stralloc newcwd; /* check options, -L for symlink, -P for physical path */ while((c = shell_getopt(argc, argv, "LP")) > 0) { switch(c) { case 'L': symbolic = 1; break; case 'P': symbolic = 0; break; default: builtin_invopt(argv); return 1; } } arg = argv[shell_optind]; stralloc_init(&newcwd); /* empty argument means chdir(HOME) */ if(arg == NULL) { arg = var_value("HOME", &len); if(arg[0] == '\0') { sh_msg("HOME variable not set!"); return 1; } } len = str_len(arg); /* when it isn't an absolute path we have to check CDPATH */ if(arg[0] != '/') { char path[PATH_MAX + 1]; const char *cdpath; /* loop through colon-separated CDPATH variable */ cdpath = var_value("CDPATH", NULL); do { /* too much, too much :) */ if((n = str_chr(cdpath, ':')) + len + 1 > PATH_MAX) { /* set error code and print the longer string in the error msg */ errno = ENAMETOOLONG; return builtin_errmsgn(argv, (n > len ? cdpath : arg), (n > len ? n : len), strerror(errno)); } /* copy path prefix from cdpath if present */ if(n) { byte_copy(path, n, cdpath); cdpath += n; path[n++] = '/'; } /* copy the argument and canonicalize */ str_copy(&path[n], arg); ok = shell_realpath(path, &newcwd, symbolic, &sh->cwd); /* skip the colon */ if(*cdpath == ':') cdpath++; } while(*cdpath && !ok); } /* absolute path */ else { /* last cdpath length set to 0, because we're not using cdpath here */ n = 0; ok = shell_canonicalize(arg, &newcwd, symbolic); } stralloc_nul(&newcwd); /* try to chdir() if everything's ok */ if(ok && chdir(newcwd.s) == 0) { /* print path if prefix was taken from cdpath */ if(n) { buffer_putsa(fd_out->w, &newcwd); buffer_putnlflush(fd_out->w); } /* set the path */ stralloc_move(&sh->cwd, &newcwd); /* if the path has symlinks then set sh->cwdsym */ sh->cwdsym = (ok > 1); return 0; } /* we failed */ builtin_error(argv, newcwd.s); stralloc_free(&newcwd); return 1; }
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; } } }