pid_t pipecmdv(int *fd_fromchild, int *fd_tochild, int *fd_errfromchild, const char *cmd, va_list ap) { char **arr = gather_args(cmd, ap); pid_t ret; if (!arr) { errno = ENOMEM; return -1; } ret = pipecmdarr(fd_fromchild, fd_tochild, fd_errfromchild, arr); free_noerr(arr); return ret; }
/* * Expand a token sequence * If skip_defined is true then the defined() keyword is not processed * The caller is used for registering invocations from one macro to another * This is an implementation of Dave Prosser's algorithm, listed in * X3J11/86-196 */ PtokenSequence macro_expand(PtokenSequence ts, bool get_more, bool skip_defined, const Macro *caller) { PtokenSequence r; // Return value if (DP()) cout << "Expanding: " << ts << endl; while (!ts.empty()) { const Ptoken head(ts.front()); ts.pop_front(); if (head.get_code() != IDENTIFIER) { // Only attempt to expand identifiers (not e.g. string literals) r.push_back(head); continue; } if (skip_defined && head.get_code() == IDENTIFIER && head.get_val() == "defined") { // Skip the arguments of the defined operator, if needed PtokenSequence da(gather_defined_operator(ts)); r.push_back(head); r.splice(r.end(), da); continue; } const string name = head.get_val(); mapMacro::const_iterator mi(Pdtoken::macros_find(name)); if (!Pdtoken::macro_is_defined(mi)) { // Nothing to do if the identifier is not a macro r.push_back(head); continue; } const Macro& m = mi->second; if (head.hideset_contains(m.get_name_token())) { // Skip the head token if it is in the hideset if (DP()) cout << "Skipping (head is in HS)" << endl; r.push_back(head); continue; } if (DP()) cout << "replacing for " << name << " tokens " << ts << endl; PtokenSequence removed_spaces; if (!m.is_function) { // Object-like macro Token::unify((*mi).second.name_token, head); HideSet hs(head.get_hideset()); hs.insert(m.get_name_token()); PtokenSequence s(subst(m, m.value, mapArgval(), hs, skip_defined, caller)); ts.splice(ts.begin(), s); caller = &m; } else if (fill_in(ts, get_more, removed_spaces) && ts.front().get_code() == '(') { // Application of a function-like macro Token::unify((*mi).second.name_token, head); mapArgval args; // Map from formal name to value if (DP()) cout << "Expanding " << m << " inside " << caller << "\n"; if (caller && caller->is_function) // Macro to macro call Call::register_call(caller->get_mcall(), m.get_mcall()); else // Function to macro call Call::register_call(m.get_mcall()); ts.pop_front(); Ptoken close; if (!gather_args(name, ts, m.formal_args, args, get_more, m.is_vararg, close)) continue; // Attempt to bail-out on error HideSet hs; set_intersection(head.get_hideset().begin(), head.get_hideset().end(), close.get_hideset().begin(), close.get_hideset().end(), inserter(hs, hs.begin())); hs.insert(m.get_name_token()); PtokenSequence s(subst(m, m.value, args, hs, skip_defined, caller)); ts.splice(ts.begin(), s); caller = &m; } else { // Function-like macro name lacking a ( if (DP()) cout << "splicing: [" << removed_spaces << ']' << endl; ts.splice(ts.begin(), removed_spaces); r.push_back(head); } } return (r); }
int main(int argc, char **argv) { int i, ret, abi_flag, pargc; const char *user, *service, *authtok, *old_authtok, **pargv; char **envlist; struct passwd *pwd; struct pam_conv conv; pam_handle_t *pamh; if (argc < 2) { fprintf(stderr, "Usage: %s [flags]\n" "\t--debug\n" "\t--toggle-abi\n" "\t--setservice SERVICE\n" "\t--setuser USER\n" "\t--setauthtok AUTHTOK\n" "\t--setoldauthtok OLD_AUTHTOK\n" "\t--restart\n" "\t--run [cmd]\n" "\t--auth [args...]\n" "\t--open-session [args...]\n" "\t--setcred-establish [args...]\n" "\t--setcred-reinitialize [args...]\n" "\t--setcred-delete [args...]\n" "\t--close-session [args...]\n" "\t--acct-mgmt [args...]\n" "\t--chauthtok-prelim [args...]\n" "\t--chauthtok-update [args...]\n", argv[0]); return 1; } pwd = getpwuid(getuid()); if (pwd == NULL) { fprintf(stderr, "Unable to determine name of current user!\n"); return 1; } user = pwd->pw_name; service = "login"; authtok = NULL; old_authtok = NULL; ret = 0; pamh = NULL; memset(&conv, 0, sizeof(conv)); conv.conv = local_conv; abi_flag = 0; conv.appdata_ptr = &abi_flag; pargc = 0; pargv = NULL; for (i = 1; i < argc; i++) { fflush(stdout); if (strcmp(argv[i], "--debug") == 0) { log_options.debug++; continue; } if (strcmp(argv[i], "--toggle-abi") == 0) { abi_flag = !abi_flag; continue; } if (strcmp(argv[i], "--setservice") == 0) { service = argv[i + 1]; i++; continue; } if (strcmp(argv[i], "--setuser") == 0) { user = argv[i + 1]; i++; continue; } if (strcmp(argv[i], "--setauthtok") == 0) { authtok = argv[i + 1]; i++; continue; } if (strcmp(argv[i], "--setoldauthtok") == 0) { old_authtok = argv[i + 1]; i++; continue; } if (pamh == NULL) { ret = pam_start(service, user, &conv, &pamh); printf("start: %d\n", ret); #ifdef __LINUX_PAM__ /* Linux-PAM *actively* tries to break us. */ ((struct linux_pam_handle*)pamh)->caller = 1; #endif if (authtok != NULL) { ret = pam_set_item(pamh, PAM_AUTHTOK, authtok); printf("set authtok: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); } if (old_authtok != NULL) { ret = pam_set_item(pamh, PAM_OLDAUTHTOK, old_authtok); printf("set old authtok: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); } } if (strcmp(argv[i], "--restart") == 0) { #ifdef __LINUX_PAM__ /* Linux-PAM *actively* tries to break us. */ ((struct linux_pam_handle*)pamh)->caller = 2; #endif ret = pam_end(pamh, 0); printf("end: %d\n", ret); pamh = NULL; ret = pam_start(service, user, &conv, &pamh); printf("start: %d\n", ret); #ifdef __LINUX_PAM__ /* Linux-PAM *actively* tries to break us. */ ((struct linux_pam_handle*)pamh)->caller = 1; #endif continue; } if (strcmp(argv[i], "--auth") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_authenticate(pamh, 0, pargc, pargv); free_args(&pargc, &pargv); printf("authenticate: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--run") == 0) { envlist = pam_getenvlist(pamh); if (envlist != NULL) { while (*envlist != NULL) { putenv(*envlist); envlist++; } } ret = system(argv[i + 1]); printf("run(\"%s\"): %d%s %s\n", argv[i + 1], WEXITSTATUS(ret), WEXITSTATUS(ret) ? ":" : "", WEXITSTATUS(ret) ? strerror(WEXITSTATUS(ret)) : ""); i++; continue; } if (strcmp(argv[i], "--open-session") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_open_session(pamh, 0, pargc, pargv); free_args(&pargc, &pargv); printf("open session: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--setcred-establish") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_setcred(pamh, PAM_ESTABLISH_CRED, pargc, pargv); free_args(&pargc, &pargv); printf("setcred: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--setcred-reinitialize") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_setcred(pamh, PAM_REINITIALIZE_CRED, pargc, pargv); free_args(&pargc, &pargv); printf("setcred: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--setcred-delete") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_setcred(pamh, PAM_DELETE_CRED, pargc, pargv); free_args(&pargc, &pargv); printf("setcred: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--close-session") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_close_session(pamh, 0, pargc, pargv); free_args(&pargc, &pargv); printf("close session: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--acct-mgmt") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_acct_mgmt(pamh, 0, pargc, pargv); free_args(&pargc, &pargv); printf("acct mgmt: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--chauthtok-prelim") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_chauthtok(pamh, PAM_PRELIM_CHECK, pargc, pargv); free_args(&pargc, &pargv); printf("chauthtok-prelim: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--chauthtok-update") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_chauthtok(pamh, PAM_UPDATE_AUTHTOK, pargc, pargv); free_args(&pargc, &pargv); printf("chauthtok-update: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } fprintf(stderr, "Unrecognized argument: %s\n", argv[i]); break; } if (pamh != NULL) { #ifdef __LINUX_PAM__ /* Linux-PAM *actively* tries to break us. */ ((struct linux_pam_handle*)pamh)->caller = 2; #endif ret = pam_end(pamh, 0); printf("end: %d\n", ret); pamh = NULL; } return ret; }
/* Parenthesize an expression. Set expr to the node after the first full * expression. */ NODE *paren_expr(NODE **expr, BOOLEAN inparen) { NODE *first = NIL, *tree = NIL, *pproc, *retval; NODE **ifnode = (NODE **)NIL; if (*expr == NIL) { if (inparen) err_logo(PAREN_MISMATCH, NIL); return *expr; } first = car(*expr); pop(*expr); if (nodetype(first) == CASEOBJ && !numberp(first)) { if (first == Left_Paren) { tree = paren_expr(expr, TRUE); tree = paren_infix(tree, expr, -1, TRUE); if (*expr == NIL) err_logo(PAREN_MISMATCH, NIL); else if (car(*expr) != Right_Paren) { /* throw the rest away */ int parens; for (parens = 0; *expr; pop(*expr)) { if (car(*expr) == Left_Paren) parens++; else if (car(*expr) == Right_Paren) if (parens-- == 0) { pop(*expr); break; } } first = tree /* car(tree) */ ; /* 6.0 */ tree = cons(Not_Enough_Node, NIL); /* tell eval */ tree_dk_how=UNBOUND; if (is_list(first)) first = car(first); if (nodetype(first) != CASEOBJ || procnode__caseobj(first) == UNDEFINED) err_logo(DK_HOW, first); else err_logo(TOO_MUCH, first); } else pop(*expr); retval = tree; } else if (first == Right_Paren) { err_logo(UNEXPECTED_PAREN, NIL); if (inparen) push(first, *expr); retval = NIL; } else if (first == Minus_Sign) { push(Minus_Tight, *expr); retval = paren_infix(make_intnode((FIXNUM) 0), expr, -1, inparen); } else { /* it must be a procedure */ check_library(first); pproc = procnode__caseobj(first); if (pproc == UNDEFINED) { if (missing_space(first)) { push(missing_numeric, *expr); first = missing_alphabetic; pproc = procnode__caseobj(first); retval = gather_args(first, pproc, expr, inparen, ifnode); if (retval != UNBOUND) { retval = cons(first, retval); } } else if (is_setter(first)) { retval = gather_some_args(0, 1, expr, inparen, ifnode); if (retval != UNBOUND) { retval = cons(first, retval); } } else { retval = cons(first, NIL); tree_dk_how = first; } } else if (nodetype(pproc) == INFIX && NOT_THROWING) { err_logo(NOT_ENOUGH, first); retval = cons(first, NIL); } else { /* Kludge follows to turn IF to IFELSE sometimes. */ if (isName(first, Name_if)) { ifnode = &first; } retval = gather_args(first, pproc, expr, inparen, ifnode); if (retval != UNBOUND) { retval = cons(first, retval); } } } } else if (is_list(first)) { /* quoted list */ retval = make_quote(first); } else { return first; } return retval; }