void main (int argc, char **argv) { int i; expand_argv (&argc, &argv, EXP_RESPONSE); for (i = 0; i < argc; i++) printf ("%d: `%s'\n", i, argv[i]); }
static rc_t add_string_to_argv( tokenzr *t, const char * str, size_t len ) { rc_t rc = expand_argv( t ); if ( rc == 0 ) { int argc = *(t->argc); char ** pargv = *(t->argv); pargv[ argc ] = string_dup ( str, len ); if ( pargv[ argc ] == NULL ) rc = RC( rcApp, rcNoTarg, rcConstructing, rcMemory, rcExhausted ); else { ( *(t->argc) )++; *(t->argv) = pargv; t->used = 0; } } return rc; }
/* evaluate a simple command (3.9.1) * * this function doesn't put stuff in background, it always wait()s, so * it only needs to fork() real programs * ----------------------------------------------------------------------- */ int eval_simple_command(struct eval *e, struct ncmd *ncmd) { union node *nptr; int argc; char **argv; int status; union node *args = NULL; union node *assigns = NULL; union command cmd = { NULL }; enum hash_id id = H_BUILTIN; struct vartab vars; /* struct fdstack io;*/ union node *r; union node *redir = ncmd->rdir; /* expand arguments, if there are arguments we start a hashed search for the command */ if(expand_args(ncmd->args, &args, 0)) { stralloc_nul(&args->narg.stra); cmd = exec_hash(args->narg.stra.s, &id); } /* expand and set the variables, mark them for export if we're gonna execute a command */ if(expand_vars(ncmd->vars, &assigns)) { /* if we don't exit after the command, have a command and not a special builtin the variable changes should be temporary */ if(!(e->flags & E_EXIT) && cmd.ptr && id != H_SBUILTIN) vartab_push(&vars); for(nptr = assigns; nptr; nptr = nptr->list.next) var_setsa(&nptr->narg.stra, (cmd.ptr ? V_EXPORT : V_DEFAULT)); tree_free(assigns); } /* do redirections if present */ /* if(redir && id != H_SBUILTIN && id != H_EXEC) fdstack_push(&io);*/ if(redir/* && id != H_PROGRAM*/) { for(r = redir; r; r = r->list.next) { struct fd *fd = NULL; /* if its the exec special builtin the new fd needs to be persistent */ if(id != H_EXEC) fd_alloca(fd); /* return if a redirection failed */ if(redir_eval(&r->nredir, fd, (id == H_EXEC ? R_NOW : 0))) { status = 1; goto end; } /* check if we need to initialize fd buffers for the new redirection */ if(fd_needbuf(r->nredir.fd)) { /* if its not exec then set up buffers for temporary redirections on the stack */ if(id != H_EXEC) fd_setbuf(r->nredir.fd, alloca(FD_BUFSIZE), FD_BUFSIZE); else fd_allocbuf(r->nredir.fd, FD_BUFSIZE); } } } /* if there is no command we can return after setting the vars and doing the redirections */ if(args == NULL) { status = 0; goto end; } /* when the command wasn't found we abort */ if(cmd.ptr == NULL) { sh_error(args->narg.stra.s); status = exec_error(); goto end; } /* assemble argument list */ argc = tree_count(args); argv = alloca((argc + 1) * sizeof(char *)); expand_argv(args, argv); /* execute the command, this may or may not return, depending on E_EXIT */ status = exec_command(id, cmd, argc, argv, (e->flags & E_EXIT), redir); end: /* restore variable stack */ if(varstack == &vars) vartab_pop(&vars); if(args) tree_free(args); /* undo redirections */ if(id != H_EXEC) { for(r = redir; r; r = r->list.next) fd_pop(r->nredir.fd); } /* if(fdstack == &io) fdstack_pop(&io);*/ return status; }
static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv) { const char *myname = "deliver_message"; static PIPE_PARAMS conf; static PIPE_ATTR attr; RECIPIENT_LIST *rcpt_list = &request->rcpt_list; DSN_BUF *why = dsb_create(); VSTRING *buf; ARGV *expanded_argv = 0; int deliver_status; int command_status; ARGV *export_env; const char *sender; #define DELIVER_MSG_CLEANUP() { \ dsb_free(why); \ if (expanded_argv) argv_free(expanded_argv); \ } if (msg_verbose) msg_info("%s: from <%s>", myname, request->sender); /* * Sanity checks. The get_service_params() and get_service_attr() * routines also do some sanity checks. Look up service attributes and * config information only once. This is safe since the information comes * from a trusted source, not from the delivery request. */ if (request->nexthop[0] == 0) msg_fatal("empty nexthop hostname"); if (rcpt_list->len <= 0) msg_fatal("recipient count: %d", rcpt_list->len); if (attr.command == 0) { get_service_params(&conf, service); get_service_attr(&attr, argv); } /* * The D flag cannot be specified for multi-recipient deliveries. */ if ((attr.flags & MAIL_COPY_DELIVERED) && (rcpt_list->len > 1)) { dsb_simple(why, "4.3.5", "mail system configuration error"); deliver_status = eval_command_status(PIPE_STAT_DEFER, service, request, &attr, why); msg_warn("pipe flag `D' requires %s_destination_recipient_limit = 1", service); DELIVER_MSG_CLEANUP(); return (deliver_status); } /* * The O flag cannot be specified for multi-recipient deliveries. */ if ((attr.flags & MAIL_COPY_ORIG_RCPT) && (rcpt_list->len > 1)) { dsb_simple(why, "4.3.5", "mail system configuration error"); deliver_status = eval_command_status(PIPE_STAT_DEFER, service, request, &attr, why); msg_warn("pipe flag `O' requires %s_destination_recipient_limit = 1", service); DELIVER_MSG_CLEANUP(); return (deliver_status); } /* * Check that this agent accepts messages this large. */ if (attr.size_limit != 0 && request->data_size > attr.size_limit) { if (msg_verbose) msg_info("%s: too big: size_limit = %ld, request->data_size = %ld", myname, (long) attr.size_limit, request->data_size); dsb_simple(why, "5.2.3", "message too large"); deliver_status = eval_command_status(PIPE_STAT_BOUNCE, service, request, &attr, why); DELIVER_MSG_CLEANUP(); return (deliver_status); } /* * Don't deliver a trace-only request. */ if (DEL_REQ_TRACE_ONLY(request->flags)) { RECIPIENT *rcpt; int status; int n; deliver_status = 0; dsb_simple(why, "2.0.0", "delivers to command: %s", attr.command[0]); (void) DSN_FROM_DSN_BUF(why); for (n = 0; n < request->rcpt_list.len; n++) { rcpt = request->rcpt_list.info + n; status = sent(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id, &request->msg_stats, rcpt, service, &why->dsn); if (status == 0 && (request->flags & DEL_REQ_FLAG_SUCCESS)) deliver_completed(request->fp, rcpt->offset); deliver_status |= status; } DELIVER_MSG_CLEANUP(); return (deliver_status); } /* * Report mail delivery loops. By definition, this requires * single-recipient delivery. Don't silently lose recipients. */ if (attr.flags & MAIL_COPY_DELIVERED) { DELIVERED_HDR_INFO *info; RECIPIENT *rcpt; int loop_found; if (request->rcpt_list.len > 1) msg_panic("%s: delivered-to enabled with multi-recipient request", myname); info = delivered_hdr_init(request->fp, request->data_offset, FOLD_ADDR_ALL); rcpt = request->rcpt_list.info; loop_found = delivered_hdr_find(info, rcpt->address); delivered_hdr_free(info); if (loop_found) { dsb_simple(why, "5.4.6", "mail forwarding loop for %s", rcpt->address); deliver_status = eval_command_status(PIPE_STAT_BOUNCE, service, request, &attr, why); DELIVER_MSG_CLEANUP(); return (deliver_status); } } /* * Deliver. Set the nexthop and sender variables, and expand the command * argument vector. Recipients will be expanded on the fly. XXX Rewrite * envelope and header addresses according to transport-specific * rewriting rules. */ if (vstream_fseek(request->fp, request->data_offset, SEEK_SET) < 0) msg_fatal("seek queue file %s: %m", VSTREAM_PATH(request->fp)); /* * A non-empty null sender replacement is subject to the 'q' flag. */ buf = vstring_alloc(10); sender = *request->sender ? request->sender : STR(attr.null_sender); if (*sender && (attr.flags & PIPE_OPT_QUOTE_LOCAL)) { quote_822_local(buf, sender); dict_update(PIPE_DICT_TABLE, PIPE_DICT_SENDER, STR(buf)); } else dict_update(PIPE_DICT_TABLE, PIPE_DICT_SENDER, sender); if (attr.flags & PIPE_OPT_FOLD_HOST) { vstring_strcpy(buf, request->nexthop); lowercase(STR(buf)); dict_update(PIPE_DICT_TABLE, PIPE_DICT_NEXTHOP, STR(buf)); } else dict_update(PIPE_DICT_TABLE, PIPE_DICT_NEXTHOP, request->nexthop); vstring_sprintf(buf, "%ld", (long) request->data_size); dict_update(PIPE_DICT_TABLE, PIPE_DICT_SIZE, STR(buf)); dict_update(PIPE_DICT_TABLE, PIPE_DICT_CLIENT_ADDR, request->client_addr); dict_update(PIPE_DICT_TABLE, PIPE_DICT_CLIENT_HELO, request->client_helo); dict_update(PIPE_DICT_TABLE, PIPE_DICT_CLIENT_NAME, request->client_name); dict_update(PIPE_DICT_TABLE, PIPE_DICT_CLIENT_PORT, request->client_port); dict_update(PIPE_DICT_TABLE, PIPE_DICT_CLIENT_PROTO, request->client_proto); dict_update(PIPE_DICT_TABLE, PIPE_DICT_SASL_METHOD, request->sasl_method); dict_update(PIPE_DICT_TABLE, PIPE_DICT_SASL_USERNAME, request->sasl_username); dict_update(PIPE_DICT_TABLE, PIPE_DICT_SASL_SENDER, request->sasl_sender); dict_update(PIPE_DICT_TABLE, PIPE_DICT_QUEUE_ID, request->queue_id); vstring_free(buf); if ((expanded_argv = expand_argv(service, attr.command, rcpt_list, attr.flags)) == 0) { dsb_simple(why, "4.3.5", "mail system configuration error"); deliver_status = eval_command_status(PIPE_STAT_DEFER, service, request, &attr, why); DELIVER_MSG_CLEANUP(); return (deliver_status); } export_env = argv_split(var_export_environ, ", \t\r\n"); command_status = pipe_command(request->fp, why, PIPE_CMD_UID, attr.uid, PIPE_CMD_GID, attr.gid, PIPE_CMD_SENDER, sender, PIPE_CMD_COPY_FLAGS, attr.flags, PIPE_CMD_ARGV, expanded_argv->argv, PIPE_CMD_TIME_LIMIT, conf.time_limit, PIPE_CMD_EOL, STR(attr.eol), PIPE_CMD_EXPORT, export_env->argv, PIPE_CMD_CWD, attr.exec_dir, PIPE_CMD_CHROOT, attr.chroot_dir, PIPE_CMD_ORIG_RCPT, rcpt_list->info[0].orig_addr, PIPE_CMD_DELIVERED, rcpt_list->info[0].address, PIPE_CMD_END); argv_free(export_env); deliver_status = eval_command_status(command_status, service, request, &attr, why); /* * Clean up. */ DELIVER_MSG_CLEANUP(); return (deliver_status); }
int main (int argc, char *argv[]) { int use_stdin = 0; FILE *newsfile; FILE *newsfile_copy; char *bodyfile_name = NULL; FILE *bodyfile_r; FILE *bodyfile_w; char *mergefile_name = NULL; FILE *mergefile; #if defined(MAINLOOP) volatile int w = 1; while (w); #endif parse_commandline (argc, argv); if (printversion) { printf ("%s (" PACKAGE ") " VERSION "\n", Name); return 0; } if (!strcmp (newsfile_name, "-")) { use_stdin = 1; newsfile_name = nb_tmpnam (); newsfile_copy = open_write (newsfile_name); newsfile = stdin; mergefile = stdout; } else { newsfile_copy = NULL; newsfile = open_read (newsfile_name); mergefile_name = nb_tmpnam (); mergefile = open_write (mergefile_name); } if (filter) { expand_argv (new_argv, "-"); exec_filter (new_argv, &bodyfile_w, &bodyfile_r); writebody (newsfile, newsfile_copy, bodyfile_w, remove_header, remove_quote, remove_sig, keep); newsfile = open_read (newsfile_name); readbody (newsfile, bodyfile_r, mergefile, remove_header, remove_quote, remove_sig, keep); check_child (); } else { bodyfile_name = nb_tmpnam (); bodyfile_w = open_write (bodyfile_name); expand_argv (new_argv, bodyfile_name); writebody (newsfile, newsfile_copy, bodyfile_w, remove_header, remove_quote, remove_sig, keep); exec_program (new_argv); check_child (); newsfile = open_read (newsfile_name); bodyfile_r = open_read (bodyfile_name); readbody (newsfile, bodyfile_r, mergefile, remove_header, remove_quote, remove_sig, keep); } if (use_stdin) nb_unlink (newsfile_name); else nb_rename (mergefile_name, newsfile_name); if (!filter) nb_unlink (bodyfile_name); return 0; }