static void bs_cmd_set(sourceinfo_t *si, int parc, char *parv[]) { char *dest; char *cmd; command_t *c; if (parc < 3) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET"); command_fail(si, fault_needmoreparams, _("Syntax: SET <destination> <setting> <parameters>")); return; } dest = parv[0]; cmd = parv[1]; c = command_find(&bs_set_cmdtree, cmd); if (c == NULL) { command_fail(si, fault_badparams, _("Invalid command. Use \2/%s%s help\2 for a command listing."), (ircd->uses_rcommand == false) ? "msg " : "", si->service->disp); return; } parv[1] = dest; command_exec(si->service, si, c, parc - 1, parv + 1); }
static void DPKG_ATTR_SENTINEL fd_fd_filter(int fd_in, int fd_out, const char *desc, const char *delenv[], const char *file, ...) { va_list args; struct command cmd; pid_t pid; int i; pid = subproc_fork(); if (pid == 0) { if (fd_in != 0) { m_dup2(fd_in, 0); close(fd_in); } if (fd_out != 1) { m_dup2(fd_out, 1); close(fd_out); } for (i = 0; delenv[i]; i++) unsetenv(delenv[i]); command_init(&cmd, file, desc); command_add_arg(&cmd, file); va_start(args, file); command_add_argv(&cmd, args); va_end(args); command_exec(&cmd); } subproc_reap(pid, desc, 0); }
void execbackend(const char *const *argv) { struct command cmd; char *arg; command_init(&cmd, cipaction->parg, NULL); command_add_arg(&cmd, cipaction->parg); /* * Special case: dpkg-query takes the --admindir option, and if dpkg itself * was given a different admin directory, we need to pass it along to it. */ if (strcmp(cipaction->parg, DPKGQUERY) == 0 && strcmp(admindir, ADMINDIR) != 0) { arg = m_malloc((strlen("--admindir=") + strlen(admindir) + 1)); sprintf(arg, "--admindir=%s", admindir); command_add_arg(&cmd, arg); } arg = m_malloc(2 + strlen(cipaction->olong) + 1); sprintf(arg, "--%s", cipaction->olong); command_add_arg(&cmd, arg); /* Exlicitely separate arguments from options as any user-supplied * separator got stripped by the option parser */ command_add_arg(&cmd, "--"); command_add_argl(&cmd, (const char **)argv); command_exec(&cmd); }
static void cs_cmd_clear(sourceinfo_t *si, int parc, char *parv[]) { char *chan; char *cmd; command_t *c; if (parc < 2) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "CLEAR"); command_fail(si, fault_needmoreparams, _("Syntax: CLEAR <#channel> <command> [parameters]")); return; } if (parv[0][0] == '#') chan = parv[0], cmd = parv[1]; else if (parv[1][0] == '#') cmd = parv[0], chan = parv[1]; else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "CLEAR"); command_fail(si, fault_badparams, _("Syntax: CLEAR <#channel> <command> [parameters]")); return; } c = command_find(&cs_clear_cmds, cmd); if (c == NULL) { command_fail(si, fault_badparams, _("Invalid command. Use \2/%s%s help\2 for a command listing."), (ircd->uses_rcommand == false) ? "msg " : "", si->service->disp); return; } parv[1] = chan; command_exec(si->service, si, c, parc - 1, parv + 1); }
static int do_script(struct pkginfo *pkg, struct pkgbin *pif, struct command *cmd, struct stat *stab, int warn) { pid_t pid; int r; setexecute(cmd->filename, stab); push_cleanup(cu_post_script_tasks, ehflag_bombout, NULL, 0, 0); pid = subproc_fork(); if (pid == 0) { if (setenv("DPKG_MAINTSCRIPT_PACKAGE", pkg->set->name, 1) || setenv("DPKG_MAINTSCRIPT_ARCH", pif->arch->name, 1) || setenv("DPKG_MAINTSCRIPT_NAME", cmd->argv[0], 1) || setenv("DPKG_RUNNING_VERSION", PACKAGE_VERSION, 1)) ohshite(_("unable to setenv for maintainer script")); cmd->filename = cmd->argv[0] = preexecscript(cmd); command_exec(cmd); } subproc_signals_setup(cmd->name); /* This does a push_cleanup(). */ r = subproc_wait_check(pid, cmd->name, warn); pop_cleanup(ehflag_normaltidy); pop_cleanup(ehflag_normaltidy); return r; }
/* SET <!group> <setting> <parameters> */ static void gs_cmd_set(sourceinfo_t *si, int parc, char *parv[]) { char *group; char *cmd; command_t *c; if (parc < 2) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET"); command_fail(si, fault_needmoreparams, _("Syntax: SET <!group> <setting> [parameters]")); return; } if (parv[0][0] == '!') group = parv[0], cmd = parv[1]; else if (parv[1][0] == '!') cmd = parv[0], group = parv[1]; else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET"); command_fail(si, fault_badparams, _("Syntax: SET <!group> <setting> [parameters]")); return; } c = command_find(gs_set_cmdtree, cmd); if (c == NULL) { command_fail(si, fault_badparams, _("Invalid command. Use \2/%s%s help\2 for a command listing."), (ircd->uses_rcommand == false) ? "msg " : "", si->service->disp); return; } parv[1] = group; command_exec(si->service, si, c, parc - 1, parv + 1); }
int command_env(char **argv, t_sh *datas) { static t_sh datas_sub; int i; char *tmp; int ret; int first; if (argv[1] == NULL) return (command_env_aff(datas)); datas_sub.envp[0] = NULL; first = 0; if (ft_strcmp(argv[1], "-i")) init(&datas_sub, datas->envp); else ++first; i = 1 + first; while ((argv[i]) && (strchr(argv[i], '=') != NULL)) ++i; tmp = argv[i]; argv[i] = NULL; command_setenv(argv + first, &datas_sub); argv[i] = tmp; command_getenv("PATH", datas); ret = command_exec(argv + i, datas->var, &datas_sub); if (FOR(i = 0, datas_sub.envp[++i] != NULL, i++)) free(datas_sub.envp[i]); return (ret); }
void client_command_cancel(struct client_command_context **_cmd) { struct client_command_context *cmd = *_cmd; bool cmd_ret; switch (cmd->state) { case CLIENT_COMMAND_STATE_WAIT_INPUT: /* a bit kludgy check: cancel command only if it has context set. currently only append command matches this check. all other commands haven't even started the processing yet. */ if (cmd->context == NULL) break; /* fall through */ case CLIENT_COMMAND_STATE_WAIT_EXTERNAL: case CLIENT_COMMAND_STATE_WAIT_OUTPUT: cmd->cancel = TRUE; break; case CLIENT_COMMAND_STATE_WAIT_UNAMBIGUITY: case CLIENT_COMMAND_STATE_WAIT_SYNC: /* commands haven't started yet */ break; case CLIENT_COMMAND_STATE_DONE: i_unreached(); } cmd_ret = !cmd->cancel || cmd->func == NULL ? TRUE : command_exec(cmd); if (!cmd_ret) { if (cmd->client->output->closed) i_panic("command didn't cancel itself: %s", cmd->name); } else { client_command_free(*_cmd != NULL ? _cmd : &cmd); } }
static void client_input_append(struct client_command_context *cmd) { struct cmd_append_context *ctx = cmd->context; struct client *client = cmd->client; const char *reason; bool finished; uoff_t lit_offset; i_assert(!client->destroyed); client->last_input = ioloop_time; timeout_reset(client->to_idle); switch (i_stream_read(client->input)) { case -1: /* disconnected */ lit_offset = ctx->litinput == NULL ? 0 : ctx->litinput->v_offset; reason = get_disconnect_reason(ctx, lit_offset); cmd_append_finish(cmd->context); /* Reset command so that client_destroy() doesn't try to call cmd_append_continue_message() anymore. */ client_command_free(&cmd); client_destroy(client, reason); return; case -2: if (ctx->message_input) { /* message data, this is handled internally by mailbox_save_continue() */ break; } cmd_append_finish(cmd->context); /* parameter word is longer than max. input buffer size. this is most likely an error, so skip the new data until newline is found. */ client->input_skip_line = TRUE; if (!ctx->failed) client_send_command_error(cmd, "Too long argument."); cmd->param_error = TRUE; client_command_free(&cmd); return; } o_stream_cork(client->output); finished = command_exec(cmd); if (!finished) (void)client_handle_unfinished_cmd(cmd); else client_command_free(&cmd); cmd_sync_delayed(client); o_stream_uncork(client->output); if (client->disconnected) client_destroy(client, NULL); else client_continue_pending_input(client); }
void ekg_loop() { g_main_context_iteration(NULL, FALSE); { #ifdef WATCHES_FIXME { /* przejrzyj deskryptory */ list_t l; for (l = watches; l; l = l->next) { watch_t *w = l->data; if (!w) continue; if (!FD_ISSET(w->fd, &rd) && !FD_ISSET(w->fd, &wd)) { /* timeout checking */ if (w->timeout < 1 || (tv.tv_sec - w->started) < w->timeout) continue; w->removed = -1; if (w->buf) { int (*handler)(int, int, char*, void*) = w->handler; if (handler(2, w->fd, NULL, w->data) == -1 || w->removed == 1) { w->removed = 0; watch_free(w); continue; } } else { int (*handler)(int, int, int, void*) = w->handler; if (handler(2, w->fd, w->type, w->data) == -1 || w->removed == 1) { w->removed = 0; watch_free(w); continue; } } w->removed = 0; continue; } if (w->fd == 0) { session_t *s; for (s = sessions; s; s = s->next) { if (!s->connected || !s->autoaway) continue; if (session_int_get(s, "auto_back") == 2) command_exec(NULL, s, ("/_autoback"), 2); } } } } #endif } #undef tv return; }
static PyObject* ekg_cmd_command(PyObject *self, PyObject *args) { char *command = NULL; if (!PyArg_ParseTuple(args, "s", &command)) return NULL; command_exec(NULL, command, 0); return Py_BuildValue(""); }
PyObject *ekg_cmd_command(PyObject * self, PyObject * args) { char *command = NULL; if (!PyArg_ParseTuple(args, "s", &command)) { return NULL; } command_exec(NULL, NULL, command, 0); // run command for current session Py_INCREF(Py_None); return Py_None; }
static BINDING_FUNCTION(binding_window_kill) { /* rfc2811: "Channels names are strings (beginning with a '&', '#', '+' or '!' character)..." */ const char *pfx = "&#+!"; char * ptr; ptr = xstrstr(window_current->target, "irc:"); if (ptr && ptr == window_current->target && xstrchr(pfx, ptr[4]) && !config_kill_irc_window ) { print("cant_kill_irc_window"); return; } command_exec(window_current->target, window_current->session, ("/window kill"), 0); }
static void command_run() { char cmd[256]; int cmdlen = 0; for (;;) { halt(); key_t key; bool avail; while ((avail = kb_getkey(&key)) != false) { // If a printable character was typed, append it to the command. if (key.ch >= 32 && key.ch < 127) { if (cmdlen < arrsize(cmd) - 1) { cmd[cmdlen] = key.ch; tty_printc(TTY_CONSOLE, cmd[cmdlen]); cmdlen++; } } // Handle special keys (like enter, backspace). else if (key.brk == KEYBRK_DOWN) { if (key.code == KEY_ENTER) { tty_printc(TTY_CONSOLE, '\n'); // Strip trailing whitespace. while (cmdlen > 0 && cmd[cmdlen - 1] == ' ') cmdlen--; cmd[cmdlen] = 0; // Execute the command. bool cont = command_exec(cmd); cmdlen = 0; if (cont) command_prompt(); else return; } else if (key.code == KEY_BACKSPACE && cmdlen > 0) { tty_printc(TTY_CONSOLE, '\b'); cmdlen--; } } } } }
static PyObject* ekg_cmd_disconnect(PyObject *self, PyObject *args) { char *reason = NULL, *tmp; if (!PyArg_ParseTuple(args, "|s", &reason)) return NULL; tmp = saprintf("disconnect %s", ((reason) ? reason : "")); command_exec(NULL, tmp, 0); xfree(tmp); return Py_BuildValue(""); }
static void client_output_cmd(struct client_command_context *cmd) { bool finished; /* continue processing command */ finished = command_exec(cmd); if (!finished) (void)client_handle_unfinished_cmd(cmd); else { /* command execution was finished */ client_command_free(&cmd); } }
/** * ekg_autoaway_timer() * * * less important things which don't need to be checked every main loop iteration * e.g. autoaways * * executed each second. */ static TIMER(ekg_autoaway_timer) { session_t *sl; time_t t; if (type) return 0; t = time(NULL); /* sprawd¼ autoawaye ró¿nych sesji */ for (sl = sessions; sl; sl = sl->next) { session_t *s = sl; int tmp; if (!s->connected || (s->status < EKG_STATUS_AWAY)) /* lowest autostatus is autoxa, so from xa and lower ones we can't go further */ continue; do { if ((s->status == EKG_STATUS_AWAY) || (tmp = session_int_get(s, "auto_away")) < 1 || !s->activity) break; if (t - s->activity > tmp) command_exec(NULL, s, ("/_autoaway"), 0); } while (0); do { if ((tmp = session_int_get(s, "auto_xa")) < 1 || !s->activity) break; if (t - s->activity > tmp) command_exec(NULL, s, ("/_autoxa"), 0); } while (0); } return 0; }
void run_shell(void) { int cnt; while (1) { puts("eash$> "); while ((cnt = kbd_read(buff, 254)) <= 0) ; buff[--cnt] = 0; if (*buff) if (command_exec(buff) == -1) puts("Command not found.\n"); } }
int execbackend(const char *const *argv) { struct command cmd; command_init(&cmd, cipaction->arg_ptr, NULL); command_add_arg(&cmd, cipaction->arg_ptr); command_add_arg(&cmd, str_fmt("--%s", cipaction->olong)); /* Exlicitely separate arguments from options as any user-supplied * separator got stripped by the option parser */ command_add_arg(&cmd, "--"); command_add_argl(&cmd, (const char **)argv); command_exec(&cmd); }
int main(){ int n,i=0; char *com; scanf("%d",&n); if(n==0)return 0; build_buffer(n); while(1){ com=(char*)malloc(sizeof(char)*10); scanf("%[^\n]s",com); command_exec(com); } return 0; }
/** @brief 执行命令 */ static void execute_cmd(char * line_buffer) { void * cmd; /* 立马按了回车键 */ if (!strlen(line_buffer)) return; // printf("执行命令:%s(%d个字节)。\n", line_buffer, max_size); cmd = command_find(line_buffer, true); if (!cmd) { printf("没有找到您输入的命令。\n"); return; } if (command_exec(cmd, line_buffer)) { printf("命令执行失败。\n"); } }
static BINDING_FUNCTION(binding_toggle_input) { if (input_size == 1) { input_size = MULTILINE_INPUT_SIZE; ncurses_input_update(line_index); } else { string_t s = string_init(("")); char *p, *tmp; int i; for (i = 0; lines[i]; i++) { char *tmp; string_append(s, (tmp = wcs_to_normal(lines[i]))); free_utf(tmp); if (lines[i + 1]) string_append(s, ("\r\n")); } tmp = string_free(s, 0); add_to_history(); input_size = 1; ncurses_input_update(0); for (p=tmp; *p && isspace(*p); p++); if (*p || config_send_white_lines) command_exec(window_current->target, window_current->session, tmp, 0); if (!tmp[0] || tmp[0] == '/' || !window_current->target) ncurses_typing_mod = 1; else { ncurses_typing_win = NULL; window_current->out_active = 1; } curs_set(1); xfree(tmp); } }
static COMMAND(xmsg_connect) { if (session_connected_get(session)) { printq("already_connected", session_name(session)); return -1; } if (command_exec(NULL, session, "/session --lock", 0) == -1) return -1; if (xmsg_add_watch(session, session_uid_get(session)+XMSG_UID_DIROFFSET)) { print("conn_failed", format_find("xmsg_addwatch_failed"), session_name(session)); return -1; } session_status_set(session, EKG_STATUS_AVAIL); protocol_connected_emit(session); xmsg_iterate_dir(0, (void*) session); xmsg_timer_change(session, "rescan_timer"); return 0; }
void file_show(const char *filename) { pid_t pid; if (filename == NULL) internerr("file '%s' does not exist", filename); pid = subproc_fork(); if (pid == 0) { struct command cmd; const char *pager; pager = command_get_pager(); command_init(&cmd, pager, _("showing file on pager")); command_add_arg(&cmd, pager); command_add_arg(&cmd, filename); command_exec(&cmd); } subproc_wait(pid, _("showing file on pager")); }
/* SET <setting> <parameters> */ static void os_cmd_set(sourceinfo_t *si, int parc, char *parv[]) { char *setting = parv[0]; command_t *c; if (setting == NULL) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET"); command_fail(si, fault_needmoreparams, _("Syntax: SET <setting> <parameters>")); return; } /* take the command through the hash table */ if ((c = command_find(os_set_cmdtree, setting))) { command_exec(si->service, si, c, parc - 1, parv + 1); } else { command_fail(si, fault_badparams, _("Invalid set command. Use \2/%s%s HELP SET\2 for a command listing."), (ircd->uses_rcommand == false) ? "msg " : "", si->service->nick); } }
static BINDING_FUNCTION(binding_accept_line) { char *p, *txt; if (ncurses_noecho) { /* we are running ui-password-input */ ncurses_noecho = 0; ncurses_passbuf = xwcsdup(line); line[0] = 0; line_adjust(); return; } if (lines) { int i; lines = xrealloc(lines, (array_count((char **) lines) + 2) * sizeof(CHAR_T *)); for (i = array_count((char **) lines); i > lines_index; i--) lines[i + 1] = lines[i]; lines[lines_index + 1] = xmalloc(LINE_MAXLEN*sizeof(CHAR_T)); xwcscpy(lines[lines_index + 1], line + line_index); line[line_index] = 0; line_index = 0; line_start = 0; lines_index++; lines_adjust(); return; } if (arg != BINDING_HISTORY_NOEXEC) { txt = wcs_to_normal(line); for (p=txt; *p && isspace(*p); p++); if (*p || config_send_white_lines) command_exec(window_current->target, window_current->session, txt, 0); free_utf(txt); } if (ncurses_plugin_destroyed) return; if (!line[0] || line[0] == '/' || !window_current->target) /* if empty or command, just mark as modified */ ncurses_typing_mod = 1; else { /* if message, assume that its' handler has already disabled <composing/> */ ncurses_typing_win = NULL; window_current->out_active = 1; /* but also remember that it should have set <active/> chatstate */ } if (xwcscmp(line, TEXT(""))) { if (config_history_savedups || xwcscmp(line, history[1])) add_to_history(); } else { if (config_enter_scrolls) print("none", ""); } history[0] = line; history_index = 0; *line = 0; line_adjust(); }
/* command_line_exec(cmdlist) * * Execute the command list. * * Execute each individual command with 'command_exec'. * String commands together depending on the 'cmdlist->controlop' operators. * Returns the exit status of the entire command list, which equals the * exit status of the last completed command. * * The operators have the following behavior: * * CMD_END, CMD_SEMICOLON * Wait for command to exit. Proceed to next command * regardless of status. * CMD_AND Wait for command to exit. Proceed to next command * only if this command exited with status 0. Otherwise * exit the whole command line. * CMD_OR Wait for command to exit. Proceed to next command * only if this command exited with status != 0. * Otherwise exit the whole command line. * CMD_BACKGROUND, CMD_PIPE * Do not wait for this command to exit. Pretend it * had status 0, for the purpose of returning a value * from command_line_exec. */ int command_line_exec(command_t *cmdlist) { int cmd_status = 0; // status of last command executed int pipefd = STDIN_FILENO; // read end of last pipe while (cmdlist) { int wp_status; // Hint: use for waitpid's status argument! // Read the manual page for waitpid() to // see how to get the command's exit // status (cmd_status) from this value. // EXERCISE: Fill out this function! // If an error occurs in command_exec, feel free to abort(). if (cmdlist->argv[0] != NULL && strcmp(cmdlist->argv[0], "makeq") == 0) { MKQ = makeq_alloc(); if (cmdlist->argv[1] != NULL) { MKQ->name = strdup(cmdlist->argv[1]); } else { goto error; } if (cmdlist->argv[2] != NULL) { MKQ->max_jobs = atoi(cmdlist->argv[2]); } else { goto error; } if (cmdlist->argv[3] != NULL) goto error; } else if (cmdlist->argv[0] != NULL && strcmp(cmdlist->argv[0], "waitq") == 0) { //printf("we are here\n"); if (cmdlist->argv[1] != NULL && MKQ != NULL && strcmp(cmdlist->argv[1], MKQ->name) == 0) wait_queue(); else fprintf(stderr, "Could not find makeq with that name\n"); } else { pid_t id = command_exec(cmdlist, &pipefd); if (id <= 0) abort(); switch(cmdlist->controlop) { case CMD_END: case CMD_SEMICOLON: if (cmdlist->argv[0] == NULL || strcmp(cmdlist->argv[0], "q") != 0) { waitpid(id, &wp_status, 0); cmd_status = WEXITSTATUS(wp_status); } break; case CMD_AND: waitpid(id, &wp_status, 0); if (WEXITSTATUS(wp_status) != 0) { cmd_status = WEXITSTATUS(wp_status); goto done; } break; case CMD_OR: waitpid(id, &wp_status, 0); if (WEXITSTATUS(wp_status) == 0) { cmd_status = 0; // EXIT_SUCCESS goto done; } break; case CMD_BACKGROUND: case CMD_PIPE: cmd_status = 0; break; } } cmdlist = cmdlist->next; } done: return cmd_status; error: //makeq_free(MKQ); return 1; }
/* main services client routine */ void oservice(char *origin, uint8_t parc, char *parv[]) { char *cmd, *s; char orig[BUFSIZE]; if (!origin) { slog(LG_DEBUG, "services(): recieved a request with no origin!"); return; } /* this should never happen */ if (parv[0][0] == '&') { slog(LG_ERROR, "services(): got parv with local channel: %s", parv[0]); return; } /* make a copy of the original for debugging */ strlcpy(orig, parv[parc - 1], BUFSIZE); /* lets go through this to get the command */ cmd = strtok(parv[parc - 1], " "); if (!cmd) return; /* ctcp? case-sensitive as per rfc */ if (!strcmp(cmd, "\001PING")) { if (!(s = strtok(NULL, " "))) s = " 0 "; strip(s); notice(opersvs.nick, origin, "\001PING %s\001", s); return; } else if (!strcmp(cmd, "\001VERSION\001")) { notice(opersvs.nick, origin, "\001VERSION atheme-%s. %s %s %s%s%s%s%s%s%s%s%s TS5ow\001", version, revision, me.name, (match_mapping) ? "A" : "", (me.loglevel & LG_DEBUG) ? "d" : "", (me.auth) ? "e" : "", (config_options.flood_msgs) ? "F" : "", (config_options.leave_chans) ? "l" : "", (config_options.join_chans) ? "j" : "", (!match_mapping) ? "R" : "", (config_options.raw) ? "r" : "", (runflags & RF_LIVE) ? "n" : ""); return; } else if (!strcmp(cmd, "\001CLIENTINFO\001")) { /* easter egg :X */ notice(opersvs.nick, origin, "\001CLIENTINFO 114 97 107 97 117 114\001"); return; } /* ctcps we don't care about are ignored */ else if (*cmd == '\001') return; /* take the command through the hash table */ command_exec(opersvs.me, origin, cmd, &os_cmdtree); }
void extracthalf(const char *debar, const char *dir, enum dpkg_tar_options taroption, int admininfo) { struct dpkg_error err; const char *errstr; char versionbuf[40]; struct deb_version version; off_t ctrllennum, memberlen = 0; ssize_t r; int dummy; pid_t c1=0,c2,c3; int p1[2], p2[2]; int p2_out; int arfd; struct stat stab; char nlc; int adminmember = -1; bool header_done; enum compressor_type decompressor = COMPRESSOR_TYPE_GZIP; if (strcmp(debar, "-") == 0) arfd = STDIN_FILENO; else arfd = open(debar, O_RDONLY); if (arfd < 0) ohshite(_("failed to read archive '%.255s'"), debar); if (fstat(arfd, &stab)) ohshite(_("failed to fstat archive")); r = read_line(arfd, versionbuf, strlen(DPKG_AR_MAGIC), sizeof(versionbuf) - 1); if (r < 0) read_fail(r, debar, _("archive magic version number")); if (strcmp(versionbuf, DPKG_AR_MAGIC) == 0) { ctrllennum= 0; header_done = false; for (;;) { struct ar_hdr arh; r = fd_read(arfd, &arh, sizeof(arh)); if (r != sizeof(arh)) read_fail(r, debar, _("archive member header")); dpkg_ar_normalize_name(&arh); if (dpkg_ar_member_is_illegal(&arh)) ohshit(_("file '%.250s' is corrupt - bad archive header magic"), debar); memberlen = dpkg_ar_member_get_size(debar, &arh); if (!header_done) { char *infobuf; if (strncmp(arh.ar_name, DEBMAGIC, sizeof(arh.ar_name)) != 0) ohshit(_("file '%.250s' is not a debian binary archive (try dpkg-split?)"), debar); infobuf= m_malloc(memberlen+1); r = fd_read(arfd, infobuf, memberlen + (memberlen & 1)); if (r != (memberlen + (memberlen & 1))) read_fail(r, debar, _("archive information header member")); infobuf[memberlen] = '\0'; if (strchr(infobuf, '\n') == NULL) ohshit(_("archive has no newlines in header")); errstr = deb_version_parse(&version, infobuf); if (errstr) ohshit(_("archive has invalid format version: %s"), errstr); if (version.major != 2) ohshit(_("archive is format version %d.%d; get a newer dpkg-deb"), version.major, version.minor); free(infobuf); header_done = true; } else if (arh.ar_name[0] == '_') { /* Members with ‘_’ are noncritical, and if we don't understand * them we skip them. */ if (fd_skip(arfd, memberlen + (memberlen & 1), &err) < 0) ohshit(_("cannot skip archive member from '%s': %s"), debar, err.str); } else { if (strncmp(arh.ar_name, ADMINMEMBER, strlen(ADMINMEMBER)) == 0) { const char *extension = arh.ar_name + strlen(ADMINMEMBER); adminmember = 1; decompressor = compressor_find_by_extension(extension); if (decompressor != COMPRESSOR_TYPE_NONE && decompressor != COMPRESSOR_TYPE_GZIP && decompressor != COMPRESSOR_TYPE_XZ) ohshit(_("archive '%s' uses unknown compression for member '%.*s', " "giving up"), debar, (int)sizeof(arh.ar_name), arh.ar_name); } else { if (adminmember != 1) ohshit(_("archive '%s' has premature member '%.*s' before '%s', " "giving up"), debar, (int)sizeof(arh.ar_name), arh.ar_name, ADMINMEMBER); if (strncmp(arh.ar_name, DATAMEMBER, strlen(DATAMEMBER)) == 0) { const char *extension = arh.ar_name + strlen(DATAMEMBER); adminmember= 0; decompressor = compressor_find_by_extension(extension); if (decompressor == COMPRESSOR_TYPE_UNKNOWN) ohshit(_("archive '%s' uses unknown compression for member '%.*s', " "giving up"), debar, (int)sizeof(arh.ar_name), arh.ar_name); } else { ohshit(_("archive '%s' has premature member '%.*s' before '%s', " "giving up"), debar, (int)sizeof(arh.ar_name), arh.ar_name, DATAMEMBER); } } if (adminmember == 1) { if (ctrllennum != 0) ohshit(_("archive '%.250s' contains two control members, giving up"), debar); ctrllennum= memberlen; } if (!adminmember != !admininfo) { if (fd_skip(arfd, memberlen + (memberlen & 1), &err) < 0) ohshit(_("cannot skip archive member from '%s': %s"), debar, err.str); } else { /* Yes! - found it. */ break; } } } if (admininfo >= 2) { printf(_(" new debian package, version %d.%d.\n" " size %jd bytes: control archive=%jd bytes.\n"), version.major, version.minor, (intmax_t)stab.st_size, (intmax_t)ctrllennum); m_output(stdout, _("<standard output>")); } } else if (strncmp(versionbuf, "0.93", 4) == 0) { char ctrllenbuf[40]; int l; l = strlen(versionbuf); if (strchr(versionbuf, '\n') == NULL) ohshit(_("archive has no newlines in header")); errstr = deb_version_parse(&version, versionbuf); if (errstr) ohshit(_("archive has invalid format version: %s"), errstr); r = read_line(arfd, ctrllenbuf, 1, sizeof(ctrllenbuf) - 1); if (r < 0) read_fail(r, debar, _("archive control member size")); if (sscanf(ctrllenbuf, "%jd%c%d", &ctrllennum, &nlc, &dummy) != 2 || nlc != '\n') ohshit(_("archive has malformatted control member size '%s'"), ctrllenbuf); if (admininfo) { memberlen = ctrllennum; } else { memberlen = stab.st_size - ctrllennum - strlen(ctrllenbuf) - l; if (fd_skip(arfd, ctrllennum, &err) < 0) ohshit(_("cannot skip archive control member from '%s': %s"), debar, err.str); } if (admininfo >= 2) { printf(_(" old debian package, version %d.%d.\n" " size %jd bytes: control archive=%jd, main archive=%jd.\n"), version.major, version.minor, (intmax_t)stab.st_size, (intmax_t)ctrllennum, (intmax_t)(stab.st_size - ctrllennum - strlen(ctrllenbuf) - l)); m_output(stdout, _("<standard output>")); } } else { if (strncmp(versionbuf, "!<arch>", 7) == 0) { notice(_("file looks like it might be an archive which has been\n" " corrupted by being downloaded in ASCII mode")); } ohshit(_("'%.255s' is not a debian format archive"), debar); } m_pipe(p1); c1 = subproc_fork(); if (!c1) { close(p1[0]); if (fd_fd_copy(arfd, p1[1], memberlen, &err) < 0) ohshit(_("cannot copy archive member from '%s' to decompressor pipe: %s"), debar, err.str); if (close(p1[1])) ohshite(_("cannot close decompressor pipe")); exit(0); } close(p1[1]); if (taroption) { m_pipe(p2); p2_out = p2[1]; } else { p2_out = 1; } c2 = subproc_fork(); if (!c2) { if (taroption) close(p2[0]); decompress_filter(decompressor, p1[0], p2_out, _("decompressing archive member")); exit(0); } close(p1[0]); close(arfd); if (taroption) close(p2[1]); if (taroption) { c3 = subproc_fork(); if (!c3) { struct command cmd; command_init(&cmd, TAR, "tar"); command_add_arg(&cmd, "tar"); if ((taroption & DPKG_TAR_LIST) && (taroption & DPKG_TAR_EXTRACT)) command_add_arg(&cmd, "-xv"); else if (taroption & DPKG_TAR_EXTRACT) command_add_arg(&cmd, "-x"); else if (taroption & DPKG_TAR_LIST) command_add_arg(&cmd, "-tv"); else internerr("unknown or missing tar action '%d'", taroption); if (taroption & DPKG_TAR_PERMS) command_add_arg(&cmd, "-p"); if (taroption & DPKG_TAR_NOMTIME) command_add_arg(&cmd, "-m"); command_add_arg(&cmd, "-f"); command_add_arg(&cmd, "-"); command_add_arg(&cmd, "--warning=no-timestamp"); m_dup2(p2[0],0); close(p2[0]); unsetenv("TAR_OPTIONS"); if (dir) { if (chdir(dir)) { if (errno != ENOENT) ohshite(_("failed to chdir to directory")); if (mkdir(dir, 0777)) ohshite(_("failed to create directory")); if (chdir(dir)) ohshite(_("failed to chdir to directory after creating it")); } } command_exec(&cmd); } close(p2[0]); subproc_reap(c3, "tar", 0); } subproc_reap(c2, _("<decompress>"), SUBPROC_NOPIPE); if (c1 != -1) subproc_reap(c1, _("paste"), 0); if (version.major == 0 && admininfo) { /* Handle the version as a float to preserve the behaviour of old code, * because even if the format is defined to be padded by 0's that might * not have been always true for really ancient versions... */ while (version.minor && (version.minor % 10) == 0) version.minor /= 10; if (version.minor == 931) movecontrolfiles(OLDOLDDEBDIR); else if (version.minor == 932 || version.minor == 933) movecontrolfiles(OLDDEBDIR); } }
int main(int argc, char *argv[]) { char cwd[PATH_MAX] = { '\0' }; char *dir = NULL; enum dpkg_tar_options taroption = DPKG_TAR_EXTRACT | DPKG_TAR_NOMTIME; int admininfo = 0; char *debar = argv[1]; int arfd = -1; struct stat stab; char versionbuf[40] = { '\0' }; ssize_t r; off_t ctrllennum, memberlen = 0; bool header_done; char *infobuf = NULL; struct dpkg_error err; const char *errstr; struct deb_version version; int adminmember = -1; enum compressor_type decompressor = COMPRESSOR_TYPE_GZIP; char nlc; int dummy; int p1[2], p2[2]; pid_t c1 = 0, c2, c3; int p2_out; if (getcwd(cwd, PATH_MAX)) { dir = m_malloc(PATH_MAX); snprintf(dir, PATH_MAX - 1, "%s/extract", cwd); } arfd = open(debar, O_RDONLY); if (arfd < 0) ohshite("failed to read archive %s", debar); if (fstat(arfd, &stab)) ohshite("failed to fstat archive"); r = read_line(arfd, versionbuf, strlen(DPKG_AR_MAGIC), sizeof(versionbuf) - 1); if (r < 0) read_fail(r, debar, "archive magic version number"); if (strcmp(versionbuf, DPKG_AR_MAGIC) == 0) { ctrllennum = 0; header_done = false; for (;;) { struct ar_hdr arh; r = fd_read(arfd, &arh, sizeof(arh)); if (r != sizeof(arh)) read_fail(r, debar, "archive member header"); dpkg_ar_normalize_name(&arh); if (dpkg_ar_member_is_illegal(&arh)) { ohshit("file '%.250s' is corrupt - bad archive header magic", debar); } memberlen = dpkg_ar_member_get_size(debar, &arh); if (!header_done) { infobuf = NULL; if (strncmp(arh.ar_name, DEBMAGIC, sizeof(arh.ar_name)) != 0) { ohshit("file '%.250s' is not a debian binary archive " "(try dpkg-split?)", debar); } infobuf = m_malloc(memberlen + 1); r = fd_read(arfd, infobuf, memberlen + (memberlen & 1)); if (r != (memberlen + (memberlen & 1))) read_fail(r, debar, "archive information header member"); infobuf[memberlen] = '\0'; if (strchr(infobuf, '\n') == NULL) ohshit("archive has no newlines in header"); errstr = deb_version_parse(&version, infobuf); if (errstr) ohshit("archive has invalid format version: %s", errstr); if (version.major != 2) { ohshit("archive is format version %d.%d; get a newer dpkg-deb", version.major, version.minor); } if (infobuf) { free(infobuf); infobuf = NULL; } header_done = true; } else if (arh.ar_name[0] == '_') { if (fd_skip(arfd, memberlen + (memberlen & 1), &err) < 0) { ohshit("cannot skip archive member from '%s': %s", debar, err.str); } } else { if (strncmp(arh.ar_name, ADMINMEMBER, strlen(ADMINMEMBER)) == 0) { const char *extension = arh.ar_name + strlen(ADMINMEMBER); adminmember = 1; decompressor = compressor_find_by_extension(extension); if (decompressor != COMPRESSOR_TYPE_NONE && decompressor != COMPRESSOR_TYPE_GZIP && decompressor != COMPRESSOR_TYPE_XZ) { ohshit("ERROR: archive '%s' uses unknown compression " "for member '%.*s', giving up", debar, (int)sizeof(arh.ar_name), arh.ar_name); } } else { if (adminmember != 1) { ohshit("archive '%s' has premature member '%.*s' " "before '%s', giving up", debar, (int)sizeof(arh.ar_name), arh.ar_name, ADMINMEMBER); } if (strncmp(arh.ar_name, DATAMEMBER, strlen(DATAMEMBER)) == 0) { const char *extension = arh.ar_name + strlen(DATAMEMBER); adminmember = 0; decompressor = compressor_find_by_extension(extension); if (decompressor == COMPRESSOR_TYPE_UNKNOWN) { ohshit("archive '%s' uses unknown " "compression for member '%.*s', giving up", debar, (int)sizeof(arh.ar_name), arh.ar_name); } } else { ohshit("archive '%s' has premature member '%.*s' " "before '%s', giving up", debar, (int)sizeof(arh.ar_name), arh.ar_name, DATAMEMBER); } } if (adminmember == 1) { if (ctrllennum != 0) { ohshit("archive '%.250s' contains two control members, giving up", debar); } ctrllennum = memberlen; } if (!adminmember != !admininfo) { if (fd_skip(arfd, memberlen + (memberlen & 1), &err) < 0) { ohshit("cannot skip archive member from '%s': %s", debar, err.str); } } else { break; } } } if (admininfo >= 2) { printf(" new debian package, version %d.%d.\n" " size %jd bytes: control archive=%jd bytes.\n", version.major, version.minor, (intmax_t)stab.st_size, (intmax_t)ctrllennum); m_output(stdout, "<standard output>"); } } else if (strncmp(versionbuf, "0.93", 4) == 0) { char ctrllenbuf[40] = { '\0' }; int l; l = strlen(versionbuf); if (strchr(versionbuf, '\n') == NULL) ohshit("archive has no newlines in header"); errstr = deb_version_parse(&version, versionbuf); if (errstr) ohshit("archive has invalid format version: %s", errstr); r = read_line(arfd, ctrllenbuf, 1, sizeof(ctrllenbuf)); if (r < 0) read_fail(r, debar, "archive control member size"); if (sscanf(ctrllenbuf, "%jd%c%d", &ctrllennum, &nlc, &dummy) != 2 || nlc != '\n') { ohshit("archive has malformatted control member size '%s'", ctrllenbuf); } if (admininfo) { memberlen = ctrllennum; } else { memberlen = stab.st_size - ctrllennum - strlen(ctrllenbuf) - l; if (fd_skip(arfd, ctrllennum, &err) < 0) { ohshit("cannot skip archive control member from '%s': %s", debar, err.str); } } if (admininfo >= 2) { printf(" old debian package, version %d.%d.\n" " size %jd bytes: control archive=%jd, main archive=%jd.\n", version.major, version.minor, (intmax_t)stab.st_size, (intmax_t)ctrllennum, (intmax_t)(stab.st_size - ctrllennum - strlen(ctrllenbuf) - l)); m_output(stdout, "<standard output>"); } } else { if (strncmp(versionbuf, "!<arch>", 7) == 0) { notice("file looks like it might be an archive which has been\n" " corrupted by being downloaded in ASCII mode"); } ohshit("'%.255s' is not a debian format archive", debar); } m_pipe(p1); c1 = subproc_fork(); if (!c1) { close(p1[0]); if (fd_fd_copy(arfd, p1[1], memberlen, &err) < 0) ohshit("cannot copy archive member from '%s' to decompressor pipe: %s", debar, err.str); if (close(p1[1])) ohshite("cannot close decompressor pipe"); exit(0); } close(p1[1]); if (taroption) { m_pipe(p2); p2_out = p2[1]; } else { p2_out = 1; } c2 = subproc_fork(); if (!c2) { if (taroption) close(p2[0]); decompress_filter(decompressor, p1[0], p2_out, "decompressing archive member"); exit(0); } close(p1[0]); close(arfd); if (taroption) close(p2[1]); if (taroption) { c3 = subproc_fork(); if (!c3) { struct command cmd; command_init(&cmd, TAR, "tar"); command_add_arg(&cmd, "tar"); if ((taroption & DPKG_TAR_LIST) && (taroption & DPKG_TAR_EXTRACT)) command_add_arg(&cmd, "-xv"); else if (taroption & DPKG_TAR_EXTRACT) command_add_arg(&cmd, "-x"); else if (taroption & DPKG_TAR_LIST) command_add_arg(&cmd, "-tv"); else internerr("unknown or missing tar action '%d'", taroption); if (taroption & DPKG_TAR_PERMS) command_add_arg(&cmd, "-p"); if (taroption & DPKG_TAR_NOMTIME) command_add_arg(&cmd, "-m"); command_add_arg(&cmd, "-f"); command_add_arg(&cmd, "-"); command_add_arg(&cmd, "--warning=no-timestamp"); m_dup2(p2[0],0); close(p2[0]); unsetenv("TAR_OPTIONS"); if (dir) { if (chdir(dir)) { if (errno != ENOENT) ohshite("failed to chdir to directory"); if (mkdir(dir, 0777)) ohshite("failed to create directory"); if (chdir(dir)) ohshite("failed to chdir to directory after creating it"); } } command_exec(&cmd); } close(p2[0]); subproc_reap(c3, "tar", 0); } subproc_reap(c2, "<decompress>", SUBPROC_NOPIPE); if (c1 != -1) subproc_reap(c1, "paste", 0); if (version.major == 0 && admininfo) { while (version.minor && (version.minor % 10) == 0) version.minor /= 10; if (version.minor == 931) movecontrolfiles(OLDOLDDEBDIR); else if (version.minor == 932 || version.minor == 933) movecontrolfiles(OLDDEBDIR); } return 0; }