static expr *parse_primary(void) { switch(tok_cur){ case tok_ident: tok_next(); return expr_ident(); case tok_num: tok_next(); return expr_num(tok_cur_num); case tok_lparen: { expr *e; tok_next(); e = parse(); if(tok_cur != tok_rparen) CPP_DIE("close paren expected"); tok_next(); return e; } case tok_not: case tok_bnot: case tok_minus: { const e_op op = tok_cur; tok_next(); return expr_new_uop(op, parse_primary()); } default: break; } { char s[2]; *s = tok_cur, s[1] = '\0'; CPP_DIE("expression expected (got %s)", tok_cur == tok_eof ? "eof" : s); } }
static int do_indexfrom(const char *fromfile) { int r; FILE *fp; unsigned lineno = 0; const char *p; tok_t tok; const char *mboxname; uint32_t uid; char buf[MAX_MAILBOX_BUFFER+128]; rx = search_begin_update(verbose); if (rx == NULL) /* no indexer defined */ return 0; fp = fopen(fromfile, "r"); if (!fp) { r = errno; perror(fromfile); goto out; } while (fgets(buf, sizeof(buf), fp)) { lineno++; if (buf[0] == '#') continue; tok_initm(&tok, buf, "\t", TOK_EMPTY|TOK_TRIMRIGHT); /* first token is an mboxname */ mboxname = tok_next(&tok); if (!mboxname) { syntax_error: fprintf(stderr, "%s:%u: syntax error, skipping\n", fromfile, lineno); continue; } /* 2nd token is a uid */ p = tok_next(&tok); if (!p) goto syntax_error; uid = strtoul(p, NULL, 0); if (!uid) goto syntax_error; /* no more tokens on the line */ p = tok_next(&tok); if (p) goto syntax_error; r = index_single_message(mboxname, uid); if (r) { fprintf(stderr, "Failed to index mailbox \"%s\" uid %u: %s\n", mboxname, uid, error_message(r)); /* ignore errors */ r = 0; } } out: if (fp) fclose(fp); search_end_update(rx); return r; }
static syn_node_t * term_rest(syn_node_t *left) { syn_node_t *right, *result; int op; result = left; while(TRUE) { switch (current_tok) { case TOK_MUL: op = OP_MUL; break; case TOK_DIV: op = OP_DIV; break; default: return result; } tok_next(); right = factor(); if (right == NULL) { nerrors++; print_warn("uncomplited term expression\n"); right = syn_node_stub_new(); } result = syn_node_op_new(result, right, op); } }
syn_node_t * expr_rest(syn_node_t *left) { syn_node_t *right, *result; int op; result = left; while(TRUE) { switch (current_tok) { case TOK_PLUS: op = OP_PLUS; break; case TOK_MINUS: op = OP_MINUS; break; default: return result; } tok_next(); right = term(); if (right == NULL) { nerrors++; print_warn("uncomplited expr expression\n"); right = syn_node_stub_new(); } result = syn_node_op_new(result, right, op); } }
static syn_node_t * equity() { syn_node_t *right, *result; opcode_t op; result = rel_op(); if (result == NULL) return NULL; while (TRUE) { switch (current_tok) { case TOK_EQ: op = OP_EQ; break; case TOK_NEQ: op = OP_NEQ; break; default: return result; } tok_next(); right = rel_op(); if (right == NULL) { nerrors++; print_warn("uncomplited eq expression\n"); right = syn_node_stub_new(); } result = syn_node_op_new(result, right, op); } return result; }
void history_t::add_with_file_detection(const wcstring &str) { ASSERT_IS_MAIN_THREAD(); path_list_t potential_paths; tokenizer tokenizer; for( tok_init( &tokenizer, str.c_str(), TOK_SQUASH_ERRORS ); tok_has_next( &tokenizer ); tok_next( &tokenizer ) ) { int type = tok_last_type( &tokenizer ); if (type == TOK_STRING) { const wchar_t *token_cstr = tok_last(&tokenizer); if (token_cstr) { wcstring potential_path = token_cstr; if (unescape_string(potential_path, false) && string_could_be_path(potential_path)) { potential_paths.push_front(potential_path); } } } } tok_destroy(&tokenizer); if (! potential_paths.empty()) { /* We have some paths. Make a context. */ file_detection_context_t *context = new file_detection_context_t(this, str); /* Store the potential paths. Reverse them to put them in the same order as in the command. */ potential_paths.reverse(); context->potential_paths.swap(potential_paths); iothread_perform(threaded_perform_file_detection, perform_file_detection_done, context); } }
/* * Add iCalendar recur-rule-parts to a structured element. */ void icalrecurrencetype_add_as_xxx(struct icalrecurrencetype *recur, void *obj, void (*add_int)(void *, const char *, int), void (*add_str)(void *, const char *, const char *)) { char *rrule, *rpart; tok_t rparts; /* generate an iCal RRULE string */ rrule = icalrecurrencetype_as_string_r(recur); /* split string into rparts & values */ tok_initm(&rparts, rrule, "=;", TOK_TRIMLEFT|TOK_TRIMRIGHT); while ((rpart = tok_next(&rparts))) { if (!strcmp(rpart, "UNTIL")) { /* need to translate date format to ISO */ struct icaltimetype until = icaltime_from_string(tok_next(&rparts)); add_str(obj, "until", icaltime_as_iso_string(until)); } else { /* assume the rpart has multiple values - split them */ tok_t vlist; char *val, *p; tok_init(&vlist, tok_next(&rparts), ",", TOK_TRIMLEFT|TOK_TRIMRIGHT); while ((val = tok_next(&vlist))) { if (add_int) { /* try converting value to integer */ int n = strtol(val, &p, 10); if (n && !*p) { add_int(obj, lcase(rpart), n); continue; } } add_str(obj, lcase(rpart), val); } tok_fini(&vlist); } } tok_fini(&rparts); free(rrule); }
/** Output the specified selection. \param begin start of selection \param end end of selection \param cut_at_cursor whether printing should stop at the surrent cursor position \param tokenize whether the string should be tokenized, printing one string token on every line and skipping non-string tokens */ static void write_part(const wchar_t *begin, const wchar_t *end, int cut_at_cursor, int tokenize) { wcstring out; wchar_t *buff; size_t pos; pos = get_cursor_pos()-(begin-get_buffer()); if (tokenize) { buff = wcsndup(begin, end-begin); // fwprintf( stderr, L"Subshell: %ls, end char %lc\n", buff, *end ); out.clear(); tokenizer_t tok(buff, TOK_ACCEPT_UNFINISHED); for (; tok_has_next(&tok); tok_next(&tok)) { if ((cut_at_cursor) && (tok_get_pos(&tok)+wcslen(tok_last(&tok)) >= pos)) break; switch (tok_last_type(&tok)) { case TOK_STRING: { out.append(escape_string(tok_last(&tok), UNESCAPE_INCOMPLETE)); out.push_back(L'\n'); break; } default: { break; } } } stdout_buffer.append(out); free(buff); } else { if (cut_at_cursor) { end = begin+pos; } // debug( 0, L"woot2 %ls -> %ls", buff, esc ); stdout_buffer.append(begin, end - begin); stdout_buffer.append(L"\n"); } }
static expr *parse_rhs(expr *lhs, int priority) { for(;;){ int this_pri, next_pri; e_op op; expr *rhs; op = tok_cur; if(!is_op(op)) return lhs; /* eof, rparen and colon covered here */ this_pri = PRECEDENCE(op); if(this_pri > priority) return lhs; /* eat the op */ tok_next(); /* special case for ternary */ if(op == tok_question){ expr *if_t = parse(); if(tok_cur != tok_colon) CPP_DIE("colon expected for ternary-? operator"); tok_next(); rhs = parse(); lhs = expr_new_top(lhs, if_t, rhs); }else{ rhs = parse_primary(); /* now on the next op, or eof (in which case, precedence returns -1 */ next_pri = PRECEDENCE(tok_cur); if(next_pri < this_pri) { /* next is tighter, give it our rhs as its lhs */ rhs = parse_rhs(rhs, next_pri); } lhs = expr_op(op, lhs, rhs); } } }
static inline boolean_t match(const tok_t expect) { if (current_tok == expect) { tok_next(); return TRUE; } return FALSE; }
Cookie* cook_parse(char* s,char isSetCookie) { Cookie* c = (Cookie*)ecalloc(1,sizeof(Cookie)); Tokenizer* ctok = tok_createCTok(s,';'); char* curtok; while((curtok = tok_next(ctok)) != NULL){ char* varn = NULL,*varnTrimmed=NULL; char* varv = NULL,*varvTrimmed=NULL; if(mxstr_indexOf(curtok,'=') != -1) { varn = mxstr_substring(curtok,0,mxstr_indexOf(curtok,'=')); varv = mxstr_substr(curtok,mxstr_indexOf(curtok,'=')+1); } else { varn=curtok; } varnTrimmed = mxstr_trim(varn); varvTrimmed = mxstr_trim(varv); /* Pick off open and close quotes */ if(varvTrimmed[0]=='\"' && varvTrimmed[strlen(varvTrimmed)-1]=='\"'){ char* tmp = varvTrimmed; varvTrimmed = mxstr_substring(varvTrimmed,1,strlen(varvTrimmed)-1); free(tmp); } if(!strcasecmp((!isSetCookie?"$path":"path"),varnTrimmed)){ c->path = varvTrimmed; } else if (!strcasecmp((!isSetCookie?"$domain":"domain"),varnTrimmed)){ c->domain = varvTrimmed; } else if (!strcasecmp((!isSetCookie?"$version":"version"),varnTrimmed)){ c->version = varvTrimmed; } else if (isSetCookie && !strcasecmp("max-age",varnTrimmed)){ c->maxage = varvTrimmed; } else if (isSetCookie && !strcasecmp("comment",varnTrimmed)){ c->comment = varvTrimmed; } else if (isSetCookie && !strcasecmp("secure",varnTrimmed)){ c->secure = '\1'; } else { c->name = estrdup(varnTrimmed); c->value = varvTrimmed; } free(varn); free(varv); free(varnTrimmed); free(curtok); } tok_free(ctok); return c; }
static void do_launch_menu(FILE *rc, void *menu, item_func make_item_cb) { char buf[BUF_SIZE], token[BUF_SIZE], *p; while (rc_getl(buf, sizeof buf, rc)) { p = buf; while (tok_next(&p, token)) { if (strcmp(token, "menu") == 0) { void *newmenu; if (tok_next(&p, token)) { newmenu = make_item_cb(menu, token, NULL); do_launch_menu(rc, newmenu, make_item_cb); } } if (strcmp(token, "cmd") == 0) { if (tok_next(&p, token)) { char *label = strdup(token); if (tok_next(&p, token)) make_item_cb(menu, label, strdup(token)); free(label); } } if (strcmp(token, "include") == 0) { if (tok_next(&p, token)) { FILE *f = fopen(token, "r"); if (f) { do_launch_menu(f, menu, make_item_cb); fclose(f); } } } if (strcmp(token, "end") == 0) return; } } }
expr *expr_parse(char *str) { expr *e; expr_init(); debug_push_line(str); tok_begin(str); tok_next(); e = parse(); if(tok_cur != tok_eof) CPP_DIE("'%s' at end of expression", tok_last()); debug_pop_line(); return e; }
static syn_node_t * factor() { syn_node_t *stat; if (match(TOK_ID)) { return identifier(); } else if (match(TOK_NUM)) { return syn_node_num_new(lex_item_prev.num); } else if (match(TOK_LPAR)) { stat = statesment(); if (match(TOK_RPAR) == FALSE) { print_warn("right parenthesis missed\n"); nerrors++; return stat; } return stat; } else if (current_tok == TOK_EOL) { return NULL; } else if (current_tok == TOK_EOF) { syntax_is_eof = 1; return NULL; } nerrors++; print_warn("unsupported token tryed to factor\n"); tok_next(); stat = syn_node_stub_new(); return stat; }
ret_t program_start(syn_node_t **tree) { nerrors = 0; *tree = NULL; tok_next(); *tree = statesment(); if (nerrors != 0) { //now we must flush tree if (*tree != NULL) { syn_node_unref(*tree); *tree = NULL; } return ret_err; } return ret_ok; }
static syn_node_t * rel_op() { syn_node_t *right, *result; int op; result = expr(); if (result == NULL) return NULL; while (TRUE) { switch (current_tok) { case TOK_GR: op = OP_GR; break; case TOK_GE: op = OP_GE; break; case TOK_LO: op = OP_LO; break; case TOK_LE: op = OP_LE; break; default: return result; } tok_next(); right = expr(); if (right == NULL) { nerrors++; print_warn("uncomplited rel expression\n"); right = syn_node_stub_new(); } result = syn_node_op_new(result, right, op); } }
/* * Add the proper XML element for an iCalendar value. */ static void icalproperty_add_value_as_xml_element(xmlNodePtr xprop, icalproperty *prop) { const char *type, *str = NULL; xmlNodePtr xtype; const icalvalue *value; char buf[40]; /* Add type */ type = lcase(icalmemory_tmp_copy( icalproperty_value_kind_as_string(prop))); xtype = xmlNewChild(xprop, NULL, BAD_CAST type, NULL); /* Add value */ value = icalproperty_get_value(prop); switch (icalvalue_isa(value)) { case ICAL_DATE_VALUE: str = icaltime_as_iso_string(icalvalue_get_date(value)); break; case ICAL_DATETIME_VALUE: str = icaltime_as_iso_string(icalvalue_get_datetime(value)); break; case ICAL_DATETIMEPERIOD_VALUE: { struct icaldatetimeperiodtype dtp = icalvalue_get_datetimeperiod(value); if (!icaltime_is_null_time(dtp.time)) { str = icaltime_as_iso_string(dtp.time); break; } else { icalperiodtype_add_as_xml_element(xtype, dtp.period); return; } } case ICAL_GEO_VALUE: { struct icalgeotype geo = icalvalue_get_geo(value); snprintf(buf, sizeof(buf), "%f", geo.lat); xmlNewTextChild(xtype, NULL, BAD_CAST "latitude", BAD_CAST buf); snprintf(buf, sizeof(buf), "%f", geo.lon); xmlNewTextChild(xtype, NULL, BAD_CAST "longitude", BAD_CAST buf); return; } case ICAL_PERIOD_VALUE: icalperiodtype_add_as_xml_element(xtype, icalvalue_get_period(value)); return; case ICAL_RECUR_VALUE: { struct icalrecurrencetype recur = icalvalue_get_recur(value); icalrecurrencetype_add_as_xxx(&recur, xtype, NULL, &icalrecur_add_string_as_xml_element); return; } case ICAL_REQUESTSTATUS_VALUE: { struct icalreqstattype stat = icalvalue_get_requeststatus(value); if (!stat.desc) stat.desc = icalenum_reqstat_desc(stat.code); snprintf(buf, sizeof(buf), "%u.%u", icalenum_reqstat_major(stat.code), icalenum_reqstat_minor(stat.code)); xmlNewTextChild(xtype, NULL, BAD_CAST "code", BAD_CAST buf); xmlNewTextChild(xtype, NULL, BAD_CAST "description", BAD_CAST stat.desc); if (stat.debug) xmlNewTextChild(xtype, NULL, BAD_CAST "data", BAD_CAST stat.debug); return; } case ICAL_TRIGGER_VALUE: { struct icaltriggertype trig = icalvalue_get_trigger(value); if (!icaltime_is_null_time(trig.time)) str = icaltime_as_iso_string(trig.time); else str = icaldurationtype_as_ical_string(trig.duration); break; } case ICAL_UTCOFFSET_VALUE: str = icalvalue_utcoffset_as_iso_string(value); break; default: str = icalvalue_as_ical_string(value); switch (icalproperty_isa(prop)) { case ICAL_CATEGORIES_PROPERTY: case ICAL_RESOURCES_PROPERTY: case ICAL_POLLPROPERTIES_PROPERTY: if (strchr(str, ',')) { /* Handle multi-valued properties */ tok_t tok; tok_init(&tok, str, ",", TOK_TRIMLEFT|TOK_TRIMRIGHT|TOK_EMPTY); str = tok_next(&tok); xmlAddChild(xtype, xmlNewText(BAD_CAST str)); while ((str = tok_next(&tok))) { if (*str) { xtype = xmlNewChild(xprop, NULL, BAD_CAST type, NULL); xmlAddChild(xtype, xmlNewText(BAD_CAST str)); } } tok_fini(&tok); return; } default: break; } break; } if (str) xmlAddChild(xtype, xmlNewText(BAD_CAST str)); }
void parse_util_get_parameter_info(const wcstring &cmd, const size_t pos, wchar_t *quote, size_t *offset, int *type) { size_t prev_pos=0; wchar_t last_quote = '\0'; int unfinished; tokenizer_t tok(cmd.c_str(), TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS); for (; tok_has_next(&tok); tok_next(&tok)) { if (tok_get_pos(&tok) > pos) break; if (tok_last_type(&tok) == TOK_STRING) last_quote = get_quote(tok_last(&tok), pos - tok_get_pos(&tok)); if (type != NULL) *type = tok_last_type(&tok); prev_pos = tok_get_pos(&tok); } wchar_t *cmd_tmp = wcsdup(cmd.c_str()); cmd_tmp[pos]=0; size_t cmdlen = wcslen(cmd_tmp); unfinished = (cmdlen==0); if (!unfinished) { unfinished = (quote != 0); if (!unfinished) { if (wcschr(L" \t\n\r", cmd_tmp[cmdlen-1]) != 0) { if ((cmdlen == 1) || (cmd_tmp[cmdlen-2] != L'\\')) { unfinished=1; } } } } if (quote) *quote = last_quote; if (offset != 0) { if (!unfinished) { while ((cmd_tmp[prev_pos] != 0) && (wcschr(L";|",cmd_tmp[prev_pos])!= 0)) prev_pos++; *offset = prev_pos; } else { *offset = pos; } } free(cmd_tmp); }
void parse_util_token_extent(const wchar_t *buff, size_t cursor_pos, const wchar_t **tok_begin, const wchar_t **tok_end, const wchar_t **prev_begin, const wchar_t **prev_end) { const wchar_t *a = NULL, *b = NULL, *pa = NULL, *pb = NULL; CHECK(buff,); assert(cursor_pos >= 0); const wchar_t *cmdsubst_begin, *cmdsubst_end; parse_util_cmdsubst_extent(buff, cursor_pos, &cmdsubst_begin, &cmdsubst_end); if (!cmdsubst_end || !cmdsubst_begin) { return; } /* pos is equivalent to cursor_pos within the range of the command substitution {begin, end} */ long offset_within_cmdsubst = cursor_pos - (cmdsubst_begin - buff); a = cmdsubst_begin + offset_within_cmdsubst; b = a; pa = cmdsubst_begin + offset_within_cmdsubst; pb = pa; assert(cmdsubst_begin >= buff); assert(cmdsubst_begin <= (buff+wcslen(buff))); assert(cmdsubst_end >= cmdsubst_begin); assert(cmdsubst_end <= (buff+wcslen(buff))); const wcstring buffcpy = wcstring(cmdsubst_begin, cmdsubst_end-cmdsubst_begin); tokenizer_t tok(buffcpy.c_str(), TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS); for (; tok_has_next(&tok); tok_next(&tok)) { size_t tok_begin = tok_get_pos(&tok); size_t tok_end = tok_begin; /* Calculate end of token */ if (tok_last_type(&tok) == TOK_STRING) { tok_end += wcslen(tok_last(&tok)); } /* Cursor was before beginning of this token, means that the cursor is between two tokens, so we set it to a zero element string and break */ if (tok_begin > offset_within_cmdsubst) { a = b = cmdsubst_begin + offset_within_cmdsubst; break; } /* If cursor is inside the token, this is the token we are looking for. If so, set a and b and break */ if ((tok_last_type(&tok) == TOK_STRING) && (tok_end >= offset_within_cmdsubst)) { a = cmdsubst_begin + tok_get_pos(&tok); b = a + wcslen(tok_last(&tok)); break; } /* Remember previous string token */ if (tok_last_type(&tok) == TOK_STRING) { pa = cmdsubst_begin + tok_get_pos(&tok); pb = pa + wcslen(tok_last(&tok)); } } if (tok_begin) { *tok_begin = a; } if (tok_end) { *tok_end = b; } if (prev_begin) { *prev_begin = pa; } if (prev_end) { *prev_end = pb; } assert(pa >= buff); assert(pa <= (buff+wcslen(buff))); assert(pb >= pa); assert(pb <= (buff+wcslen(buff))); }
/** Get the beginning and end of the job or process definition under the cursor */ static void job_or_process_extent(const wchar_t *buff, size_t cursor_pos, const wchar_t **a, const wchar_t **b, int process) { const wchar_t *begin, *end; long pos; wchar_t *buffcpy; int finished=0; CHECK(buff,); if (a) { *a=0; } if (b) { *b = 0; } parse_util_cmdsubst_extent(buff, cursor_pos, &begin, &end); if (!end || !begin) { return; } pos = cursor_pos - (begin - buff); if (a) { *a = begin; } if (b) { *b = end; } buffcpy = wcsndup(begin, end-begin); if (!buffcpy) { DIE_MEM(); } tokenizer_t tok(buffcpy, TOK_ACCEPT_UNFINISHED); for (; tok_has_next(&tok) && !finished; tok_next(&tok)) { int tok_begin = tok_get_pos(&tok); switch (tok_last_type(&tok)) { case TOK_PIPE: { if (!process) { break; } } case TOK_END: case TOK_BACKGROUND: { if (tok_begin >= pos) { finished=1; if (b) { *b = (wchar_t *)begin + tok_begin; } } else { if (a) { *a = (wchar_t *)begin + tok_begin+1; } } break; } default: { break; } } } free(buffcpy); }
EXPORTED struct backend *backend_connect(struct backend *ret_backend, const char *server, struct protocol_t *prot, const char *userid, sasl_callback_t *cb, const char **auth_status, int logfd) { /* need to (re)establish connection to server or create one */ int sock = -1; int r; int err = -1; int do_tls = 0; int noauth = 0; struct addrinfo hints, *res0 = NULL, *res; struct sockaddr_un sunsock; struct backend *ret; if (!ret_backend) { ret = xzmalloc(sizeof(struct backend)); strlcpy(ret->hostname, server, sizeof(ret->hostname)); ret->timeout = NULL; } else ret = ret_backend; if (server[0] == '/') { /* unix socket */ res0 = &hints; memset(res0, 0, sizeof(struct addrinfo)); res0->ai_family = PF_UNIX; res0->ai_socktype = SOCK_STREAM; res0->ai_addr = (struct sockaddr *) &sunsock; res0->ai_addrlen = sizeof(sunsock.sun_family) + strlen(server) + 1; #ifdef SIN6_LEN res0->ai_addrlen += sizeof(sunsock.sun_len); sunsock.sun_len = res0->ai_addrlen; #endif sunsock.sun_family = AF_UNIX; strlcpy(sunsock.sun_path, server, sizeof(sunsock.sun_path)); if (!strcmp(prot->sasl_service, "lmtp") || !strcmp(prot->sasl_service, "csync")) { noauth = 1; } } else { /* inet socket */ char host[1024], *p; const char *service = prot->service; /* Parse server string for possible port and options */ strlcpy(host, server, sizeof(host)); if ((p = strchr(host, ':'))) { *p++ = '\0'; service = p; if ((p = strchr(service, '/'))) { tok_t tok; char *opt; *p++ = '\0'; tok_initm(&tok, p, "/", 0); while ((opt = tok_next(&tok))) { if (!strcmp(opt, "tls")) do_tls = 1; else if (!strcmp(opt, "noauth")) noauth = 1; } tok_fini(&tok); } } memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; err = getaddrinfo(host, service, &hints, &res0); if (err) { syslog(LOG_ERR, "getaddrinfo(%s) failed: %s", server, gai_strerror(err)); goto error; } } for (res = res0; res; res = res->ai_next) { sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sock < 0) continue; /* Do a non-blocking connect() */ nonblock(sock, 1); if (!connect(sock, res->ai_addr, res->ai_addrlen)) { /* connect() succeeded immediately */ break; } else if (errno == EINPROGRESS) { /* connect() in progress */ int n; fd_set wfds, rfds; time_t now = time(NULL); time_t timeout = now + config_getint(IMAPOPT_CLIENT_TIMEOUT); struct timeval waitfor; /* select() socket for writing until we succeed, fail, or timeout */ do { FD_ZERO(&wfds); FD_SET(sock, &wfds); rfds = wfds; waitfor.tv_sec = timeout - now; waitfor.tv_usec = 0; n = select(sock + 1, &rfds, &wfds, NULL, &waitfor); now = time(NULL); /* Retry select() if interrupted */ } while (n < 0 && errno == EINTR && now < timeout); if (!n) { /* select() timed out */ errno = ETIMEDOUT; } else if (FD_ISSET(sock, &rfds) || FD_ISSET(sock, &wfds)) { /* Socket is ready for I/O - get SO_ERROR to determine status */ socklen_t errlen = sizeof(err); if (!getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &errlen) && !(errno = err)) { /* connect() succeeded */ break; } } } close(sock); sock = -1; } if (sock < 0) { if (res0 != &hints) freeaddrinfo(res0); syslog(LOG_ERR, "connect(%s) failed: %m", server); goto error; } /* Reset socket to blocking */ nonblock(sock, 0); memcpy(&ret->addr, res->ai_addr, res->ai_addrlen); if (res0 != &hints) freeaddrinfo(res0); ret->in = prot_new(sock, 0); ret->out = prot_new(sock, 1); ret->sock = sock; prot_settimeout(ret->in, config_getint(IMAPOPT_CLIENT_TIMEOUT)); prot_setflushonread(ret->in, ret->out); ret->prot = prot; /* use literal+ to send literals */ prot_setisclient(ret->in, 1); prot_setisclient(ret->out, 1); /* Start TLS if required */ if (do_tls) r = backend_starttls(ret, NULL, NULL, NULL); /* Login to the server */ if (prot->type == TYPE_SPEC) r = prot->u.spec.login(ret, userid, cb, auth_status, noauth); else r = backend_login(ret, userid, cb, auth_status, noauth); if (r) goto error; if (logfd >= 0) { prot_setlog(ret->in, logfd); prot_setlog(ret->out, logfd); } else prot_settimeout(ret->in, 0); return ret; error: forget_capabilities(ret); if (ret->in) { prot_free(ret->in); ret->in = NULL; } if (ret->out) { prot_free(ret->out); ret->out = NULL; } if (sock >= 0) close(sock); if (ret->saslconn) { sasl_dispose(&ret->saslconn); ret->saslconn = NULL; } if (!ret_backend) free(ret); return NULL; }
/* * Construct a JSON array for an iCalendar property. */ static json_t *icalproperty_as_json_array(icalproperty *prop) { icalproperty_kind prop_kind; const char *x_name, *property_name = NULL; icalparameter *param; const char *type = NULL; const icalvalue *value; json_t *jprop, *jparams; if (!prop) return NULL; prop_kind = icalproperty_isa(prop); x_name = icalproperty_get_x_name(prop); if (prop_kind == ICAL_X_PROPERTY && x_name) property_name = x_name; else property_name = icalproperty_kind_to_string(prop_kind); if (!property_name) { icalerror_warn("Got a property of an unknown kind."); return NULL; } /* Create property array */ jprop = json_array(); /* Add property name */ json_array_append_new(jprop, json_string(lcase(icalmemory_tmp_copy(property_name)))); /* Add parameters */ jparams = json_object(); for (param = icalproperty_get_first_parameter(prop, ICAL_ANY_PARAMETER); param != 0; param = icalproperty_get_next_parameter(prop, ICAL_ANY_PARAMETER)) { if (icalparameter_isa(param) == ICAL_VALUE_PARAMETER) continue; icalparameter_as_json_object_member(param, jparams); } json_array_append_new(jprop, jparams); /* Add type */ type = icalproperty_value_kind_as_string(prop); json_array_append_new(jprop, json_string(lcase(icalmemory_tmp_copy(type)))); /* Add value */ value = icalproperty_get_value(prop); if (value) { switch (icalproperty_isa(prop)) { case ICAL_CATEGORIES_PROPERTY: case ICAL_RESOURCES_PROPERTY: case ICAL_POLLPROPERTIES_PROPERTY: if (icalvalue_isa(value) == ICAL_TEXT_VALUE) { /* Handle multi-valued properties */ const char *str = icalvalue_as_ical_string(value); tok_t tok; tok_init(&tok, str, ",", TOK_TRIMLEFT|TOK_TRIMRIGHT|TOK_EMPTY); while ((str = tok_next(&tok))) { if (*str) json_array_append_new(jprop, json_string(str)); } tok_fini(&tok); break; } default: json_array_append_new(jprop, icalvalue_as_json_object(value)); break; } } return jprop; }
/** Indent the specified input */ static int indent(wcstring &out, const wcstring &in, int flags) { int res=0; int is_command = 1; int indent = 0; int do_indent = 1; int prev_type = 0; int prev_prev_type = 0; tokenizer_t tok(in.c_str(), TOK_SHOW_COMMENTS); for (; tok_has_next(&tok); tok_next(&tok)) { int type = tok_last_type(&tok); const wchar_t *last = tok_last(&tok); switch (type) { case TOK_STRING: { if (is_command) { int next_indent = indent; is_command = 0; wcstring unesc; unescape_string(last, &unesc, UNESCAPE_SPECIAL); if (parser_keywords_is_block(unesc)) { next_indent++; } else if (unesc == L"else") { indent--; } /* case should have the same indent level as switch*/ else if (unesc == L"case") { indent--; } else if (unesc == L"end") { indent--; next_indent--; } if (do_indent && flags && prev_type != TOK_PIPE) { insert_tabs(out, indent); } append_format(out, L"%ls", last); indent = next_indent; } else { if (prev_type != TOK_REDIRECT_FD) out.append(L" "); out.append(last); } break; } case TOK_END: { if (prev_type != TOK_END || prev_prev_type != TOK_END) out.append(L"\n"); do_indent = 1; is_command = 1; break; } case TOK_PIPE: { out.append(L" "); if (last[0] == '2' && !last[1]) { out.append(L"^"); } else if (last[0] != '1' || last[1]) { out.append(last); out.append(L">"); } out.append(L" | "); is_command = 1; break; } case TOK_REDIRECT_OUT: { out.append(L" "); if (wcscmp(last, L"2") == 0) { out.append(L"^"); } else { if (wcscmp(last, L"1") != 0) out.append(last); out.append(L"> "); } break; } case TOK_REDIRECT_APPEND: { out.append(L" "); if (wcscmp(last, L"2") == 0) { out.append(L"^^"); } else { if (wcscmp(last, L"1") != 0) out.append(last); out.append(L">> "); } break; } case TOK_REDIRECT_IN: { out.append(L" "); if (wcscmp(last, L"0") != 0) out.append(last); out.append(L"< "); break; } case TOK_REDIRECT_FD: { out.append(L" "); if (wcscmp(last, L"1") != 0) out.append(last); out.append(L">& "); break; } case TOK_BACKGROUND: { out.append(L"&\n"); do_indent = 1; is_command = 1; break; } case TOK_COMMENT: { if (do_indent && flags) { insert_tabs(out, indent); } append_format(out, L"%ls", last); do_indent = 1; break; } default: { debug(0, L"Unknown token '%ls'", last); exit(1); } } prev_prev_type = prev_type; prev_type = type; } return res; }
static int squatter_build_query(search_builder_t *bx, const char *query) { tok_t tok = TOK_INITIALIZER(query, NULL, 0); char *p; char *q; int r = 0; int part; int utf8 = charset_lookupname("utf-8"); while ((p = tok_next(&tok))) { if (!strncasecmp(p, "__begin:", 8)) { q = p + 8; if (!strcasecmp(q, "and")) bx->begin_boolean(bx, SEARCH_OP_AND); else if (!strcasecmp(q, "or")) bx->begin_boolean(bx, SEARCH_OP_OR); else if (!strcasecmp(q, "not")) bx->begin_boolean(bx, SEARCH_OP_NOT); else goto error; continue; } if (!strncasecmp(p, "__end:", 6)) { q = p + 6; if (!strcasecmp(q, "and")) bx->end_boolean(bx, SEARCH_OP_AND); else if (!strcasecmp(q, "or")) bx->end_boolean(bx, SEARCH_OP_OR); else if (!strcasecmp(q, "not")) bx->end_boolean(bx, SEARCH_OP_NOT); else goto error; continue; } /* everything else is a ->match() of some kind */ q = strchr(p, ':'); if (q) q++; if (!q) { part = SEARCH_PART_ANY; q = p; } else if (!strncasecmp(p, "to:", 3)) part = SEARCH_PART_TO; else if (!strncasecmp(p, "from:", 5)) part = SEARCH_PART_FROM; else if (!strncasecmp(p, "cc:", 3)) part = SEARCH_PART_CC; else if (!strncasecmp(p, "bcc:", 4)) part = SEARCH_PART_BCC; else if (!strncasecmp(p, "subject:", 8)) part = SEARCH_PART_SUBJECT; else if (!strncasecmp(p, "listid:", 7)) part = SEARCH_PART_LISTID; else if (!strncasecmp(p, "contenttype:", 12)) part = SEARCH_PART_TYPE; else if (!strncasecmp(p, "header:", 7)) part = SEARCH_PART_HEADERS; else if (!strncasecmp(p, "body:", 5)) part = SEARCH_PART_BODY; else goto error; q = charset_convert(q, utf8, charset_flags); bx->match(bx, part, q); free(q); } r = 0; out: tok_fini(&tok); return r; error: syslog(LOG_ERR, "bad query expression at \"%s\"", p); r = IMAP_PROTOCOL_ERROR; goto out; }
/** Output the specified selection. \param begin start of selection \param end end of selection \param cut_at_cursor whether printing should stop at the surrent cursor position \param tokenize whether the string should be tokenized, printing one string token on every line and skipping non-string tokens */ static void write_part( const wchar_t *begin, const wchar_t *end, int cut_at_cursor, int tokenize ) { tokenizer tok; string_buffer_t out; wchar_t *buff; int pos; pos = get_cursor_pos()-(begin-get_buffer()); if( tokenize ) { buff = wcsndup( begin, end-begin ); // fwprintf( stderr, L"Subshell: %ls, end char %lc\n", buff, *end ); sb_init( &out ); for( tok_init( &tok, buff, TOK_ACCEPT_UNFINISHED ); tok_has_next( &tok ); tok_next( &tok ) ) { if( (cut_at_cursor) && (tok_get_pos( &tok)+wcslen(tok_last( &tok)) >= pos) ) break; switch( tok_last_type( &tok ) ) { case TOK_STRING: { wchar_t *tmp = unescape( tok_last( &tok ), UNESCAPE_INCOMPLETE ); sb_append( &out, tmp, L"\n", (void *)0 ); free( tmp ); break; } } } sb_append( sb_out, (wchar_t *)out.buff ); free( buff ); tok_destroy( &tok ); sb_destroy( &out ); } else { wchar_t *buff, *esc; if( cut_at_cursor ) { end = begin+pos; } buff = wcsndup( begin, end-begin ); esc = unescape( buff, UNESCAPE_INCOMPLETE ); // debug( 0, L"woot2 %ls -> %ls", buff, esc ); sb_append( sb_out, esc ); sb_append( sb_out, L"\n" ); free( esc ); free( buff ); } }
/* read the next token */ static int tok_read(void) { char *s = tok; char *e = tok + sizeof(tok) - 2; int c, c2; int i; *s = '\0'; c = tok_next(); if (c <= 0) return 1; tok_prevsep = tok_cursep; tok_cursep = def_chopped(c); if (tok_cursep) tok_prevsep = 1; if (c == ' ' || c == '\n') { while (c > 0 && (c == ' ' || c == '\n')) c = tok_next(); tok_back(c); *s++ = ' '; *s = '\0'; tok_curtype = T_SPACE; return 0; } if (c == '\t') { *s++ = '\t'; *s = '\0'; tok_curtype = T_TAB; return 0; } if (tok_prevsep) { if (c == '$') { c2 = tok_next(); if (c2 >= '1' && c2 <= '9' && !src_arg(c2 - '0')) { tok_cursep = 1; return tok_read(); } tok_back(c2); } tok_back(c); if (!tok_keyword()) { tok_curtype = T_KEYWORD; tok_cursep = 1; return 0; } if (!tok_expand()) { tok_cursep = 1; return tok_read(); } c = tok_next(); } if (strchr(T_SOFTSEP, c)) { *s++ = c; if (c == '\\') { c = tok_next(); if (c == '(') { *s++ = c; *s++ = tok_next(); *s++ = tok_next(); } else if (c == '[') { while (c && c != ']') { if (s < e) *s++ = c; c = tok_next(); } *s++ = ']'; } } else if (c == '"') { c = tok_next(); while (c > 0 && c != '"') { if (c == '\\') { c2 = tok_next(); if (c2 == '"') c = '"'; else tok_back(c2); } if (s < e) *s++ = c; c = tok_next(); } *s++ = '"'; } else { /* two-character operators */ c2 = tok_next(); switch (T_BIN(c, c2)) { case T_BIN('<', '='): case T_BIN('>', '='): case T_BIN('=', '='): case T_BIN('!', '='): case T_BIN('>', '>'): case T_BIN('<', '<'): case T_BIN(':', '='): case T_BIN('-', '>'): case T_BIN('<', '-'): case T_BIN('-', '+'): *s++ = c2; break; default: tok_back(c2); } } *s = '\0'; tok_curtype = char_type(tok); return 0; } *s++ = c; i = utf8len(c); while (--i > 0 && s < e) *s++ = tok_next(); *s = '\0'; tok_curtype = char_type(tok); return 0; }
/* Parse a command line. Return by reference the last command, its arguments, and the offset in the string of the beginning of the last argument. This is used by autosuggestions */ static bool autosuggest_parse_command(const wcstring &str, wcstring *out_command, wcstring_list_t *out_arguments, int *out_last_arg_pos) { if (str.empty()) return false; wcstring cmd; wcstring_list_t args; int arg_pos = -1; bool had_cmd = false; tokenizer tok; for (tok_init( &tok, str.c_str(), TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS); tok_has_next(&tok); tok_next(&tok)) { int last_type = tok_last_type(&tok); switch( last_type ) { case TOK_STRING: { if( had_cmd ) { /* Parameter to the command. We store these escaped. */ args.push_back(tok_last(&tok)); arg_pos = tok_get_pos(&tok); } else { /* Command. First check that the command actually exists. */ wcstring local_cmd = tok_last( &tok ); bool expanded = expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES); if (! expanded || has_expand_reserved(cmd.c_str())) { /* We can't expand this cmd, ignore it */ } else { bool is_subcommand = false; int mark = tok_get_pos(&tok); if (parser_keywords_is_subcommand(cmd)) { int sw; tok_next( &tok ); sw = parser_keywords_is_switch( tok_last( &tok ) ); if( !parser_keywords_is_block( cmd ) && sw == ARG_SWITCH ) { /* It's an argument to the subcommand itself */ } else { if( sw == ARG_SKIP ) mark = tok_get_pos( &tok ); is_subcommand = true; } tok_set_pos( &tok, mark ); } if (!is_subcommand) { /* It's really a command */ had_cmd = true; cmd = local_cmd; } } } break; } case TOK_REDIRECT_NOCLOB: case TOK_REDIRECT_OUT: case TOK_REDIRECT_IN: case TOK_REDIRECT_APPEND: case TOK_REDIRECT_FD: { if( !had_cmd ) { break; } tok_next( &tok ); break; } case TOK_PIPE: case TOK_BACKGROUND: case TOK_END: { had_cmd = false; cmd.empty(); args.empty(); arg_pos = -1; break; } case TOK_COMMENT: case TOK_ERROR: default: { break; } } } tok_destroy( &tok ); /* Remember our command if we have one */ if (had_cmd) { if (out_command) out_command->swap(cmd); if (out_arguments) out_arguments->swap(args); if (out_last_arg_pos) *out_last_arg_pos = arg_pos; } return had_cmd; }
void parse_util_token_extent( const wchar_t *buff, int cursor_pos, const wchar_t **tok_begin, const wchar_t **tok_end, const wchar_t **prev_begin, const wchar_t **prev_end ) { const wchar_t *begin, *end; int pos; wchar_t *buffcpy; tokenizer tok; const wchar_t *a = NULL, *b = NULL, *pa = NULL, *pb = NULL; CHECK( buff, ); assert( cursor_pos >= 0 ); parse_util_cmdsubst_extent( buff, cursor_pos, &begin, &end ); if( !end || !begin ) { return; } pos = cursor_pos - (begin - buff); a = buff + pos; b = a; pa = buff + pos; pb = pa; assert( begin >= buff ); assert( begin <= (buff+wcslen(buff) ) ); assert( end >= begin ); assert( end <= (buff+wcslen(buff) ) ); buffcpy = wcsndup( begin, end-begin ); if( !buffcpy ) { DIE_MEM(); } for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS ); tok_has_next( &tok ); tok_next( &tok ) ) { int tok_begin = tok_get_pos( &tok ); int tok_end=tok_begin; /* Calculate end of token */ if( tok_last_type( &tok ) == TOK_STRING ) { tok_end +=wcslen(tok_last(&tok)); } /* Cursor was before beginning of this token, means that the cursor is between two tokens, so we set it to a zero element string and break */ if( tok_begin > pos ) { a = b = (wchar_t *)buff + pos; break; } /* If cursor is inside the token, this is the token we are looking for. If so, set a and b and break */ if( (tok_last_type( &tok ) == TOK_STRING) && (tok_end >= pos ) ) { a = begin + tok_get_pos( &tok ); b = a + wcslen(tok_last(&tok)); break; } /* Remember previous string token */ if( tok_last_type( &tok ) == TOK_STRING ) { pa = begin + tok_get_pos( &tok ); pb = pa + wcslen(tok_last(&tok)); } } free( buffcpy); tok_destroy( &tok ); if( tok_begin ) { *tok_begin = a; } if( tok_end ) { *tok_end = b; } if( prev_begin ) { *prev_begin = pa; } if( prev_end ) { *prev_end = pb; } assert( pa >= buff ); assert( pa <= (buff+wcslen(buff) ) ); assert( pb >= pa ); assert( pb <= (buff+wcslen(buff) ) ); }
/* * userdeny() checks to see if 'user' is denied access to 'service' * Returns 1 if a matching deny entry exists in DB, otherwise returns 0. */ EXPORTED int userdeny(const char *user, const char *service, char *msgbuf, size_t bufsiz) { int r, ret = 0; /* allow access by default */ const char *data = NULL; size_t datalen; struct buf buf = BUF_INITIALIZER; char *wild = NULL; const char *msg = NULL; tok_t tok; char *pat; int not; if (!denydb) denydb_open(/*create*/0); if (!denydb) return 0; memset(&tok, 0, sizeof(tok)); /* fetch entry for user */ syslog(LOG_DEBUG, "fetching user_deny.db entry for '%s'", user); do { r = cyrusdb_fetch(denydb, user, strlen(user), &data, &datalen, NULL); } while (r == CYRUSDB_AGAIN); /* XXX Should we try to reopen the DB if we get IOERROR? This might be necessary when using SQL backend and we lose the connection. */ if (r || !data || !datalen) { /* ignore non-existent/empty entry, report all other errors */ if (r != CYRUSDB_NOTFOUND) { syslog(LOG_WARNING, "DENYDB_ERROR: error reading entry '%s': %s", user, cyrusdb_strerror(r)); } goto out; } buf_init_ro(&buf, data, datalen); /* parse the data */ r = parse_record(&buf, &wild, &msg); if (r) { syslog(LOG_WARNING, "DENYDB_ERROR: invalid entry for '%s'", user); goto out; } /* scan wildmat right to left for a match against our service */ syslog(LOG_DEBUG, "wild: '%s' service: '%s'", wild, service); tok_initm(&tok, wild, ",", 0); while ((pat = tok_next(&tok))) { /* XXX trim leading & trailing whitespace? */ /* is it a negated pattern? */ not = (*pat == '!'); if (not) ++pat; syslog(LOG_DEBUG, "pat %d:'%s'", not, pat); /* see if pattern matches our service */ if (wildmat(service, pat)) { /* match ==> we're done */ ret = !not; if (msgbuf) strlcpy(msgbuf, msg, bufsiz); break; } } out: tok_fini(&tok); buf_free(&buf); return ret; }
// This function does I/O static void tokenize( const wchar_t * const buff, std::vector<int> &color, const int pos, wcstring_list_t *error, const wcstring &working_directory, const env_vars_snapshot_t &vars) { ASSERT_IS_BACKGROUND_THREAD(); wcstring cmd; int had_cmd=0; wcstring last_cmd; int len; int accept_switches = 1; int use_function = 1; int use_command = 1; int use_builtin = 1; CHECK( buff, ); len = wcslen(buff); if( !len ) return; std::fill(color.begin(), color.end(), -1); tokenizer tok; for( tok_init( &tok, buff, TOK_SHOW_COMMENTS | TOK_SQUASH_ERRORS ); tok_has_next( &tok ); tok_next( &tok ) ) { int last_type = tok_last_type( &tok ); switch( last_type ) { case TOK_STRING: { if( had_cmd ) { /*Parameter */ wchar_t *param = tok_last( &tok ); if( param[0] == L'-' ) { if (wcscmp( param, L"--" ) == 0 ) { accept_switches = 0; color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM; } else if( accept_switches ) { if( complete_is_valid_option( last_cmd.c_str(), param, error, false /* no autoload */ ) ) color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM; else color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR; } else { color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM; } } else { color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM; } if( cmd == L"cd" ) { wcstring dir = tok_last( &tok ); if (expand_one(dir, EXPAND_SKIP_CMDSUBST)) { int is_help = string_prefixes_string(dir, L"--help") || string_prefixes_string(dir, L"-h"); if( !is_help && ! is_potential_cd_path(dir, working_directory, PATH_EXPAND_TILDE, NULL)) { color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR; } } } /* Highlight the parameter. highlight_param wants to write one more color than we have characters (hysterical raisins) so allocate one more in the vector. But don't copy it back. */ const wcstring param_str = param; int tok_pos = tok_get_pos(&tok); std::vector<int>::const_iterator where = color.begin() + tok_pos; std::vector<int> subcolors(where, where + param_str.size()); subcolors.push_back(-1); highlight_param(param_str, subcolors, pos-tok_pos, error); /* Copy the subcolors back into our colors array */ std::copy(subcolors.begin(), subcolors.begin() + param_str.size(), color.begin() + tok_pos); } else { /* Command. First check that the command actually exists. */ cmd = tok_last( &tok ); bool expanded = expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES); if (! expanded || has_expand_reserved(cmd.c_str())) { color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR; } else { bool is_cmd = false; int is_subcommand = 0; int mark = tok_get_pos( &tok ); color.at(tok_get_pos( &tok )) = HIGHLIGHT_COMMAND; if( parser_keywords_is_subcommand( cmd ) ) { int sw; if( cmd == L"builtin") { use_function = 0; use_command = 0; use_builtin = 1; } else if( cmd == L"command") { use_command = 1; use_function = 0; use_builtin = 0; } tok_next( &tok ); sw = parser_keywords_is_switch( tok_last( &tok ) ); if( !parser_keywords_is_block( cmd ) && sw == ARG_SWITCH ) { /* The 'builtin' and 'command' builtins are normally followed by another command, but if they are invoked with a switch, they aren't. */ use_command = 1; use_function = 1; use_builtin = 2; } else { if( sw == ARG_SKIP ) { color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM; mark = tok_get_pos( &tok ); } is_subcommand = 1; } tok_set_pos( &tok, mark ); } if( !is_subcommand ) { /* OK, this is a command, it has been successfully expanded and everything looks ok. Lets check if the command exists. */ /* First check if it is a builtin or function, since we don't have to stat any files for that */ if (! is_cmd && use_builtin ) is_cmd = builtin_exists( cmd ); if (! is_cmd && use_function ) is_cmd = function_exists_no_autoload( cmd, vars ); /* Moving on to expensive tests */ /* Check if this is a regular command */ if (! is_cmd && use_command ) { is_cmd = path_get_path( cmd, NULL, vars ); } /* Maybe it is a path for a implicit cd command. */ if (! is_cmd) { if (use_builtin || (use_function && function_exists_no_autoload( L"cd", vars))) is_cmd = path_can_be_implicit_cd(cmd, NULL, working_directory.c_str(), vars); } if( is_cmd ) { color.at(tok_get_pos( &tok )) = HIGHLIGHT_COMMAND; } else { if( error ) { error->push_back(format_string(L"Unknown command \'%ls\'", cmd.c_str())); } color.at(tok_get_pos( &tok )) = (HIGHLIGHT_ERROR); } had_cmd = 1; } if( had_cmd ) { last_cmd = tok_last( &tok ); } } } break; } case TOK_REDIRECT_NOCLOB: case TOK_REDIRECT_OUT: case TOK_REDIRECT_IN: case TOK_REDIRECT_APPEND: case TOK_REDIRECT_FD: { if( !had_cmd ) { color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR; if( error ) error->push_back(L"Redirection without a command"); break; } wcstring target_str; const wchar_t *target=NULL; color.at(tok_get_pos( &tok )) = HIGHLIGHT_REDIRECTION; tok_next( &tok ); /* Check that we are redirecting into a file */ switch( tok_last_type( &tok ) ) { case TOK_STRING: { target_str = tok_last( &tok ); if (expand_one(target_str, EXPAND_SKIP_CMDSUBST)) { target = target_str.c_str(); } /* Redirect filename may contain a cmdsubst. If so, it will be ignored/not flagged. */ } break; default: { size_t pos = tok_get_pos(&tok); if (pos < color.size()) { color.at(pos) = HIGHLIGHT_ERROR; } if( error ) error->push_back(L"Invalid redirection"); } } if( target != 0 ) { wcstring dir = target; size_t slash_idx = dir.find_last_of(L'/'); struct stat buff; /* If file is in directory other than '.', check that the directory exists. */ if( slash_idx != wcstring::npos ) { dir.resize(slash_idx); if( wstat( dir, &buff ) == -1 ) { color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR; if( error ) error->push_back(format_string(L"Directory \'%ls\' does not exist", dir.c_str())); } } /* If the file is read from or appended to, check if it exists. */ if( last_type == TOK_REDIRECT_IN || last_type == TOK_REDIRECT_APPEND ) { if( wstat( target, &buff ) == -1 ) { color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR; if( error ) error->push_back(format_string(L"File \'%ls\' does not exist", target)); } } if( last_type == TOK_REDIRECT_NOCLOB ) { if( wstat( target, &buff ) != -1 ) { color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR; if( error ) error->push_back(format_string(L"File \'%ls\' exists", target)); } } } break; } case TOK_PIPE: case TOK_BACKGROUND: { if( had_cmd ) { color.at(tok_get_pos( &tok )) = HIGHLIGHT_END; had_cmd = 0; use_command = 1; use_function = 1; use_builtin = 1; accept_switches = 1; } else { color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR; if( error ) error->push_back(L"No job to put in background" ); } break; } case TOK_END: { color.at(tok_get_pos( &tok )) = HIGHLIGHT_END; had_cmd = 0; use_command = 1; use_function = 1; use_builtin = 1; accept_switches = 1; break; } case TOK_COMMENT: { color.at(tok_get_pos( &tok )) = HIGHLIGHT_COMMENT; break; } case TOK_ERROR: default: { /* If the tokenizer reports an error, highlight it as such. */ if( error ) error->push_back(tok_last( &tok)); color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR; break; } } } tok_destroy( &tok ); }