Player::Player(SOCKET hClnt, char* name){ this->hClnt= hClnt; memset(this->name, 0, sizeof(this->name)); memcpy(this->name, name, 30); NextNode= NULL; connected= true; Posx= Posy= 0; memset(arena, 0, sizeof(arena)); char query[100]; memset(query, 0, sizeof(0)); sprintf(query, "select * from BR_Characters where CharName= \'%s\'", name); MYSQL_RES* res; int fields; MYSQL_ROW row; printf("init Call SendQuery()\n"); SendQuery(query, &res, &fields); if(res== NULL){ printf("error at 1 res is NULL\n"); } printf("init call fetch_row()\n"); row= mysql_fetch_row(res); printf("init arena is %s\n", row[7]); strcpy(arena, row[7]); printf("init call mysql_free_result()\n"); mysql_free_result(res); }
void QueryServ::PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc) { std::string query = StringFormat( "INSERT INTO `qs_player_events` (event, char_id, event_desc, time) VALUES (%i, %i, '%s', UNIX_TIMESTAMP(now()))", Event_Type, Character_ID, EscapeString(Event_Desc).c_str()); SendQuery(query); }
NMErr OTIPEnumerator::IdleEnumeration(void) { OSStatus status = kNMNoError; NMUInt32 timeSinceLastIdle; if (! bActive) return kNMNoError; if (bDataWaiting) status = ReceiveDatagram(); if (bFirstIdle) { timeSinceLastIdle = 0; bFirstIdle = false; } else { timeSinceLastIdle = OTElapsedMilliseconds(&mLastIdleTimeStamp); } OTGetTimeStamp(&mLastIdleTimeStamp); IdleList(timeSinceLastIdle); if (OTElapsedMilliseconds(&mLastQueryTimeStamp) > mEnumPeriod) { if (mEnumPeriod < kMaxTimeBetweenPings) mEnumPeriod *= 2; SendQuery(); } return status; }
bool PostgreDatabase::WaitExecute(const char* QueryString, ...) { if(QueryString == NULL) return false; va_list vlist; va_start(vlist, QueryString); mSearchMutex.acquire(); uint32 Connection = GetConnection(); InUseMarkers[Connection] = true; mSearchMutex.release(); vsprintf(QueryBuffer[Connection], QueryString, vlist); PGresult * res = SendQuery(Connection, QueryBuffer[Connection], false); if(res == 0) return false; InUseMarkers[Connection] = false; ExecStatusType result = PQresultStatus(res); bool passed = false; if(result == PGRES_TUPLES_OK || result == PGRES_COMMAND_OK) passed = true; else sLog.outError("Execute failed because of [%s]", PQresultErrorMessage(res)); // free up the memory PQclear(res); return passed; }
QueryResult * PostgreDatabase::Query(const char* QueryString, ...) { if(QueryString == NULL) return NULL; va_list vlist; va_start(vlist, QueryString); mSearchMutex.acquire(); // Find a free connection uint32 i = GetConnection(); // Mark the connection as busy InUseMarkers[i] = true; mSearchMutex.release(); // Apply parameters vsprintf(QueryBuffer[i], QueryString, vlist); va_end(vlist); // Send the query PGresult * res = SendQuery(i, QueryBuffer[i], false); InUseMarkers[i] = false; // Get the error code ExecStatusType result = PQresultStatus(res); if(result != PGRES_TUPLES_OK) { sLog.outError("Query failed: %s", PQresultErrorMessage(res)); // command failed. PQclear(res); return 0; } // Better check the row count.. we don't want to return an empty query.. if(PQntuples(res) == 0) { // oh noes! PQclear(res); return 0; } // get number of columns uint32 FieldCount = PQnfields(res); // get number of rows uint32 RowCount = PQntuples(res); // Create the QueryResult PostgreQueryResult * qResult = new PostgreQueryResult(res, FieldCount, RowCount); return qResult; }
void CISESession::QueryUserType() { CISEQueryUserInfo qDQ30; CISEAnswer aDQ30; uint64_t uiTransactionID; uint64_t uiOrderID; qDQ30.segment_number_n = 0; try { uint16 nItems; do { qDQ30.segment_number_n++; SendQuery(qDQ30, m_uiBaseFacility + FACILITY_EP0, aDQ30, uiTransactionID, uiOrderID); EgAssert(aDQ30.m_uiLen <= sizeof(answer_user_type_info_t)); CAutoLock UserLock(&m_User); CS2S(aDQ30.m_Data.m_UserType.ust_id_s, m_User.m_sType); // Type m_User.m_bIsInternal = (aDQ30.m_Data.m_UserType.ext_or_int_c == USERTYPE_INTERNAL); m_User.m_bIsTrader = (aDQ30.m_Data.m_UserType.is_trader_c == USERTYPE_TRADER); nItems = aDQ30.m_Data.m_UserType.items_n; for(uint16 nIndex = 0; nIndex < nItems; nIndex++) { const answer_user_type_info_item_t& Item = aDQ30.m_Data.m_UserType.item[nIndex]; CMessageID TranID; TranID.m_Type = Item.transaction_type; TranID.m_bIsBroadcast = (Item.trans_or_bdx_c == TRANTYPE_BROADCAST); m_User.m_AllowedMessages.push_back(TranID); } }while(aDQ30.m_Data.m_UserType.segment_number_n != 0 && nItems != 0); } catch(CISEException& e) { e.AddDescription("Failed to query user type."); throw; } }
void Player::Disconnect(){ connected= false; close(hClnt); char query[100]; memset(query, 0, sizeof(query)); sprintf(query, "update BR_Characters set Arena= '%s', PosX= %d, PosY= %d where CharName= \'%s\';", arena ,Posx, Posy, name); printf("Send Query %s\n", query); MYSQL_RES* res; int fields; SendQuery(query, &res, &fields); printf("call mysql_free_result()\n"); mysql_free_result(res); }
/* * Main processing loop for reading lines of input * and sending them to the backend. * * This loop is re-entrant. May be called by \i command * which reads input from a file. */ int MainLoop(FILE *source) { PsqlScanState scan_state; /* lexer working state */ volatile PQExpBuffer query_buf; /* buffer for query being accumulated */ volatile PQExpBuffer previous_buf; /* if there isn't anything in the new * buffer yet, use this one for \e, * etc. */ PQExpBuffer history_buf; /* earlier lines of a multi-line command, not * yet saved to readline history */ char *line; /* current line of input */ int added_nl_pos; bool success; bool line_saved_in_history; volatile int successResult = EXIT_SUCCESS; volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN; volatile promptStatus_t prompt_status = PROMPT_READY; volatile int count_eof = 0; volatile bool die_on_error = false; /* Save the prior command source */ FILE *prev_cmd_source; bool prev_cmd_interactive; uint64 prev_lineno; /* Save old settings */ prev_cmd_source = pset.cur_cmd_source; prev_cmd_interactive = pset.cur_cmd_interactive; prev_lineno = pset.lineno; /* Establish new source */ pset.cur_cmd_source = source; pset.cur_cmd_interactive = ((source == stdin) && !pset.notty); pset.lineno = 0; /* Create working state */ scan_state = psql_scan_create(); query_buf = createPQExpBuffer(); previous_buf = createPQExpBuffer(); history_buf = createPQExpBuffer(); if (PQExpBufferBroken(query_buf) || PQExpBufferBroken(previous_buf) || PQExpBufferBroken(history_buf)) { psql_error("out of memory\n"); exit(EXIT_FAILURE); } /* main loop to get queries and execute them */ while (successResult == EXIT_SUCCESS) { /* * Clean up after a previous Control-C */ if (cancel_pressed) { if (!pset.cur_cmd_interactive) { /* * You get here if you stopped a script with Ctrl-C. */ successResult = EXIT_USER; break; } cancel_pressed = false; } /* * Establish longjmp destination for exiting from wait-for-input. We * must re-do this each time through the loop for safety, since the * jmpbuf might get changed during command execution. */ if (sigsetjmp(sigint_interrupt_jmp, 1) != 0) { /* got here with longjmp */ /* reset parsing state */ psql_scan_finish(scan_state); psql_scan_reset(scan_state); resetPQExpBuffer(query_buf); resetPQExpBuffer(history_buf); count_eof = 0; slashCmdStatus = PSQL_CMD_UNKNOWN; prompt_status = PROMPT_READY; cancel_pressed = false; if (pset.cur_cmd_interactive) putc('\n', stdout); else { successResult = EXIT_USER; break; } } fflush(stdout); /* * get another line */ if (pset.cur_cmd_interactive) { /* May need to reset prompt, eg after \r command */ if (query_buf->len == 0) prompt_status = PROMPT_READY; line = gets_interactive(get_prompt(prompt_status)); } else { line = gets_fromFile(source); if (!line && ferror(source)) successResult = EXIT_FAILURE; } /* * query_buf holds query already accumulated. line is the malloc'd * new line of input (note it must be freed before looping around!) */ /* No more input. Time to quit, or \i done */ if (line == NULL) { if (pset.cur_cmd_interactive) { /* This tries to mimic bash's IGNOREEOF feature. */ count_eof++; if (count_eof < GetVariableNum(pset.vars, "IGNOREEOF", 0, 10, false)) { if (!pset.quiet) printf(_("Use \"\\q\" to leave %s.\n"), pset.progname); continue; } puts(pset.quiet ? "" : "\\q"); } break; } count_eof = 0; pset.lineno++; /* ignore UTF-8 Unicode byte-order mark */ if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0) memmove(line, line + 3, strlen(line + 3) + 1); /* nothing left on line? then ignore */ if (line[0] == '\0' && !psql_scan_in_quote(scan_state)) { free(line); continue; } /* A request for help? Be friendly and give them some guidance */ if (pset.cur_cmd_interactive && query_buf->len == 0 && pg_strncasecmp(line, "help", 4) == 0 && (line[4] == '\0' || line[4] == ';' || isspace((unsigned char) line[4]))) { free(line); puts(_("You are using psql, the command-line interface to PostgreSQL.")); printf(_("Type: \\copyright for distribution terms\n" " \\h for help with SQL commands\n" " \\? for help with psql commands\n" " \\g or terminate with semicolon to execute query\n" " \\q to quit\n")); fflush(stdout); continue; } /* echo back if flag is set */ if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive) puts(line); fflush(stdout); /* insert newlines into query buffer between source lines */ if (query_buf->len > 0) { appendPQExpBufferChar(query_buf, '\n'); added_nl_pos = query_buf->len; } else added_nl_pos = -1; /* flag we didn't add one */ /* Setting this will not have effect until next line. */ die_on_error = pset.on_error_stop; /* * Parse line, looking for command separators. */ psql_scan_setup(scan_state, line, strlen(line)); success = true; line_saved_in_history = false; while (success || !die_on_error) { PsqlScanResult scan_result; promptStatus_t prompt_tmp = prompt_status; scan_result = psql_scan(scan_state, query_buf, &prompt_tmp); prompt_status = prompt_tmp; if (PQExpBufferBroken(query_buf)) { psql_error("out of memory\n"); exit(EXIT_FAILURE); } /* * Send command if semicolon found, or if end of line and we're in * single-line mode. */ if (scan_result == PSCAN_SEMICOLON || (scan_result == PSCAN_EOL && pset.singleline)) { /* * Save query in history. We use history_buf to accumulate * multi-line queries into a single history entry. */ if (pset.cur_cmd_interactive && !line_saved_in_history) { pg_append_history(line, history_buf); pg_send_history(history_buf); line_saved_in_history = true; } /* execute query */ success = SendQuery(query_buf->data); slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR; /* transfer query to previous_buf by pointer-swapping */ { PQExpBuffer swap_buf = previous_buf; previous_buf = query_buf; query_buf = swap_buf; } resetPQExpBuffer(query_buf); added_nl_pos = -1; /* we need not do psql_scan_reset() here */ } else if (scan_result == PSCAN_BACKSLASH) { /* handle backslash command */ /* * If we added a newline to query_buf, and nothing else has * been inserted in query_buf by the lexer, then strip off the * newline again. This avoids any change to query_buf when a * line contains only a backslash command. Also, in this * situation we force out any previous lines as a separate * history entry; we don't want SQL and backslash commands * intermixed in history if at all possible. */ if (query_buf->len == added_nl_pos) { query_buf->data[--query_buf->len] = '\0'; pg_send_history(history_buf); } added_nl_pos = -1; /* save backslash command in history */ if (pset.cur_cmd_interactive && !line_saved_in_history) { pg_append_history(line, history_buf); pg_send_history(history_buf); line_saved_in_history = true; } /* execute backslash command */ slashCmdStatus = HandleSlashCmds(scan_state, query_buf->len > 0 ? query_buf : previous_buf); success = slashCmdStatus != PSQL_CMD_ERROR; if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT) && query_buf->len == 0) { /* copy previous buffer to current for handling */ appendPQExpBufferStr(query_buf, previous_buf->data); } if (slashCmdStatus == PSQL_CMD_SEND) { success = SendQuery(query_buf->data); /* transfer query to previous_buf by pointer-swapping */ { PQExpBuffer swap_buf = previous_buf; previous_buf = query_buf; query_buf = swap_buf; } resetPQExpBuffer(query_buf); /* flush any paren nesting info after forced send */ psql_scan_reset(scan_state); } else if (slashCmdStatus == PSQL_CMD_NEWEDIT) { /* rescan query_buf as new input */ psql_scan_finish(scan_state); free(line); line = pg_strdup(query_buf->data); resetPQExpBuffer(query_buf); /* reset parsing state since we are rescanning whole line */ psql_scan_reset(scan_state); psql_scan_setup(scan_state, line, strlen(line)); line_saved_in_history = false; prompt_status = PROMPT_READY; } else if (slashCmdStatus == PSQL_CMD_TERMINATE) break; } /* fall out of loop if lexer reached EOL */ if (scan_result == PSCAN_INCOMPLETE || scan_result == PSCAN_EOL) break; } /* Add line to pending history if we didn't execute anything yet */ if (pset.cur_cmd_interactive && !line_saved_in_history) pg_append_history(line, history_buf); psql_scan_finish(scan_state); free(line); if (slashCmdStatus == PSQL_CMD_TERMINATE) { successResult = EXIT_SUCCESS; break; } if (!pset.cur_cmd_interactive) { if (!success && die_on_error) successResult = EXIT_USER; /* Have we lost the db connection? */ else if (!pset.db) successResult = EXIT_BADCONN; } } /* while !endoffile/session */ /* * Process query at the end of file without a semicolon */ if (query_buf->len > 0 && !pset.cur_cmd_interactive && successResult == EXIT_SUCCESS) { /* save query in history */ if (pset.cur_cmd_interactive) pg_send_history(history_buf); /* execute query */ success = SendQuery(query_buf->data); if (!success && die_on_error) successResult = EXIT_USER; else if (pset.db == NULL) successResult = EXIT_BADCONN; } /* * Let's just make real sure the SIGINT handler won't try to use * sigint_interrupt_jmp after we exit this routine. If there is an outer * MainLoop instance, it will reset sigint_interrupt_jmp to point to * itself at the top of its loop, before any further interactive input * happens. */ sigint_interrupt_enabled = false; destroyPQExpBuffer(query_buf); destroyPQExpBuffer(previous_buf); destroyPQExpBuffer(history_buf); psql_scan_destroy(scan_state); pset.cur_cmd_source = prev_cmd_source; pset.cur_cmd_interactive = prev_cmd_interactive; pset.lineno = prev_lineno; return successResult; } /* MainLoop() */
/* * Execute a \copy command (frontend copy). We have to open a file (or execute * a command), then submit a COPY query to the backend and either feed it data * from the file or route its response into the file. */ bool do_copy(const char *args) { PQExpBufferData query; FILE *copystream; struct copy_options *options; bool success; /* parse options */ options = parse_slash_copy(args); if (!options) return false; /* prepare to read or write the target file */ if (options->file && !options->program) canonicalize_path(options->file); if (options->from) { if (options->file) { if (options->program) { fflush(stdout); fflush(stderr); errno = 0; copystream = popen(options->file, PG_BINARY_R); } else copystream = fopen(options->file, PG_BINARY_R); } else if (!options->psql_inout) copystream = pset.cur_cmd_source; else copystream = stdin; } else { if (options->file) { if (options->program) { fflush(stdout); fflush(stderr); errno = 0; #ifndef WIN32 pqsignal(SIGPIPE, SIG_IGN); #endif copystream = popen(options->file, PG_BINARY_W); } else copystream = fopen(options->file, PG_BINARY_W); } else if (!options->psql_inout) copystream = pset.queryFout; else copystream = stdout; } if (!copystream) { if (options->program) psql_error("could not execute command \"%s\": %s\n", options->file, strerror(errno)); else psql_error("%s: %s\n", options->file, strerror(errno)); free_copy_options(options); return false; } if (!options->program) { struct stat st; int result; /* make sure the specified file is not a directory */ if ((result = fstat(fileno(copystream), &st)) < 0) psql_error("could not stat file \"%s\": %s\n", options->file, strerror(errno)); if (result == 0 && S_ISDIR(st.st_mode)) psql_error("%s: cannot copy from/to a directory\n", options->file); if (result < 0 || S_ISDIR(st.st_mode)) { fclose(copystream); free_copy_options(options); return false; } } /* build the command we will send to the backend */ initPQExpBuffer(&query); printfPQExpBuffer(&query, "COPY "); appendPQExpBufferStr(&query, options->before_tofrom); if (options->from) appendPQExpBufferStr(&query, " FROM STDIN "); else appendPQExpBufferStr(&query, " TO STDOUT "); if (options->after_tofrom) appendPQExpBufferStr(&query, options->after_tofrom); /* run it like a user command, but with copystream as data source/sink */ pset.copyStream = copystream; success = SendQuery(query.data); pset.copyStream = NULL; termPQExpBuffer(&query); if (options->file != NULL) { if (options->program) { int pclose_rc = pclose(copystream); if (pclose_rc != 0) { if (pclose_rc < 0) psql_error("could not close pipe to external command: %s\n", strerror(errno)); else { char *reason = wait_result_to_str(pclose_rc); psql_error("%s: %s\n", options->file, reason ? reason : ""); if (reason) free(reason); } success = false; } #ifndef WIN32 pqsignal(SIGPIPE, SIG_DFL); #endif } else { if (fclose(copystream) != 0) { psql_error("%s: %s\n", options->file, strerror(errno)); success = false; } } } free_copy_options(options); return success; }
/* * Execute a \copy command (frontend copy). We have to open a file, then * submit a COPY query to the backend and either feed it data from the * file or route its response into the file. */ bool do_copy(const char *args) { PQExpBufferData query; FILE *copystream; FILE *save_file; FILE **override_file; struct copy_options *options; bool success; struct stat st; /* parse options */ options = parse_slash_copy(args); if (!options) return false; /* prepare to read or write the target file */ if (options->file) canonicalize_path(options->file); if (options->from) { override_file = &pset.cur_cmd_source; if (options->file) copystream = fopen(options->file, PG_BINARY_R); else if (!options->psql_inout) copystream = pset.cur_cmd_source; else copystream = stdin; } else { override_file = &pset.queryFout; if (options->file) copystream = fopen(options->file, PG_BINARY_W); else if (!options->psql_inout) copystream = pset.queryFout; else copystream = stdout; } if (!copystream) { psql_error("%s: %s\n", options->file, strerror(errno)); free_copy_options(options); return false; } /* make sure the specified file is not a directory */ fstat(fileno(copystream), &st); if (S_ISDIR(st.st_mode)) { fclose(copystream); psql_error("%s: cannot copy from/to a directory\n", options->file); free_copy_options(options); return false; } /* build the command we will send to the backend */ initPQExpBuffer(&query); printfPQExpBuffer(&query, "COPY "); appendPQExpBufferStr(&query, options->before_tofrom); if (options->from) appendPQExpBuffer(&query, " FROM STDIN "); else appendPQExpBuffer(&query, " TO STDOUT "); if (options->after_tofrom) appendPQExpBufferStr(&query, options->after_tofrom); /* Run it like a user command, interposing the data source or sink. */ save_file = *override_file; *override_file = copystream; success = SendQuery(query.data); *override_file = save_file; termPQExpBuffer(&query); if (options->file != NULL) { if (fclose(copystream) != 0) { psql_error("%s: %s\n", options->file, strerror(errno)); success = false; } } free_copy_options(options); return success; }
/* * * main * */ int main(int argc, char *argv[]) { struct adhoc_opts options; int successResult; char *password = NULL; char *password_prompt = NULL; bool new_pass; set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql")); if (argc > 1) { if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) { usage(); exit(EXIT_SUCCESS); } if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) { showVersion(); exit(EXIT_SUCCESS); } } #ifdef WIN32 setvbuf(stderr, NULL, _IONBF, 0); #endif setup_cancel_handler(); pset.progname = get_progname(argv[0]); pset.db = NULL; setDecimalLocale(); pset.encoding = PQenv2encoding(); pset.queryFout = stdout; pset.queryFoutPipe = false; pset.cur_cmd_source = stdin; pset.cur_cmd_interactive = false; /* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */ pset.popt.topt.format = PRINT_ALIGNED; pset.popt.topt.border = 1; pset.popt.topt.pager = 1; pset.popt.topt.start_table = true; pset.popt.topt.stop_table = true; pset.popt.default_footer = true; /* We must get COLUMNS here before readline() sets it */ pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0; pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout))); pset.getPassword = TRI_DEFAULT; EstablishVariableSpace(); SetVariable(pset.vars, "VERSION", PG_VERSION_STR); /* Default values for variables */ SetVariableBool(pset.vars, "AUTOCOMMIT"); SetVariable(pset.vars, "VERBOSITY", "default"); SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1); SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2); SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3); parse_psql_options(argc, argv, &options); if (!pset.popt.topt.fieldSep) pset.popt.topt.fieldSep = pg_strdup(DEFAULT_FIELD_SEP); if (!pset.popt.topt.recordSep) pset.popt.topt.recordSep = pg_strdup(DEFAULT_RECORD_SEP); if (options.username == NULL) password_prompt = pg_strdup(_("Password: "******"Password for user %s: ")) - 2 + strlen(options.username) + 1); sprintf(password_prompt, _("Password for user %s: "), options.username); } if (pset.getPassword == TRI_YES) password = simple_prompt(password_prompt, 100, false); /* loop until we have a password if requested by backend */ do { new_pass = false; pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.action == ACT_LIST_DB && options.dbname == NULL ? "postgres" : options.dbname, options.username, password); if (PQstatus(pset.db) == CONNECTION_BAD && PQconnectionNeedsPassword(pset.db) && password == NULL && pset.getPassword != TRI_NO) { PQfinish(pset.db); password = simple_prompt(password_prompt, 100, false); new_pass = true; } } while (new_pass); free(password); free(password_prompt); if (PQstatus(pset.db) == CONNECTION_BAD) { fprintf(stderr, "%s: %s", pset.progname, PQerrorMessage(pset.db)); PQfinish(pset.db); exit(EXIT_BADCONN); } PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL); SyncVariables(); if (options.action == ACT_LIST_DB) { int success = listAllDbs(false); PQfinish(pset.db); exit(success ? EXIT_SUCCESS : EXIT_FAILURE); } if (options.logfilename) { pset.logfile = fopen(options.logfilename, "a"); if (!pset.logfile) fprintf(stderr, _("%s: could not open log file \"%s\": %s\n"), pset.progname, options.logfilename, strerror(errno)); } /* * Now find something to do */ /* * process file given by -f */ if (options.action == ACT_FILE && strcmp(options.action_string, "-") != 0) { if (!options.no_psqlrc) process_psqlrc(argv[0]); successResult = process_file(options.action_string, options.single_txn); } /* * process slash command if one was given to -c */ else if (options.action == ACT_SINGLE_SLASH) { PsqlScanState scan_state; if (pset.echo == PSQL_ECHO_ALL) puts(options.action_string); scan_state = psql_scan_create(); psql_scan_setup(scan_state, options.action_string, strlen(options.action_string)); successResult = HandleSlashCmds(scan_state, NULL) != PSQL_CMD_ERROR ? EXIT_SUCCESS : EXIT_FAILURE; psql_scan_destroy(scan_state); } /* * If the query given to -c was a normal one, send it */ else if (options.action == ACT_SINGLE_QUERY) { if (pset.echo == PSQL_ECHO_ALL) puts(options.action_string); successResult = SendQuery(options.action_string) ? EXIT_SUCCESS : EXIT_FAILURE; } /* * or otherwise enter interactive main loop */ else { if (!options.no_psqlrc) process_psqlrc(argv[0]); connection_warnings(); if (!pset.quiet && !pset.notty) printf(_("Type \"help\" for help.\n\n")); if (!pset.notty) initializeInput(options.no_readline ? 0 : 1); if (options.action_string) /* -f - was used */ pset.inputfile = "<stdin>"; successResult = MainLoop(stdin); } /* clean up */ if (pset.logfile) fclose(pset.logfile); PQfinish(pset.db); setQFout(NULL); return successResult; }
/* * ExecQueryTuples: assuming query result is OK, execute each query * result field as a SQL statement * * Returns true if successful, false otherwise. */ static bool ExecQueryTuples(const PGresult *result) { bool success = true; int nrows = PQntuples(result); int ncolumns = PQnfields(result); int r, c; /* * We must turn off gexec_flag to avoid infinite recursion. Note that * this allows ExecQueryUsingCursor to be applied to the individual query * results. SendQuery prevents it from being applied when fetching the * queries-to-execute, because it can't handle recursion either. */ pset.gexec_flag = false; for (r = 0; r < nrows; r++) { for (c = 0; c < ncolumns; c++) { if (!PQgetisnull(result, r, c)) { const char *query = PQgetvalue(result, r, c); /* Abandon execution if cancel_pressed */ if (cancel_pressed) goto loop_exit; /* * ECHO_ALL mode should echo these queries, but SendQuery * assumes that MainLoop did that, so we have to do it here. */ if (pset.echo == PSQL_ECHO_ALL && !pset.singlestep) { puts(query); fflush(stdout); } if (!SendQuery(query)) { /* Error - abandon execution if ON_ERROR_STOP */ success = false; if (pset.on_error_stop) goto loop_exit; } } } } loop_exit: /* * Restore state. We know gexec_flag was on, else we'd not be here. (We * also know it'll get turned off at end of command, but that's not ours * to do here.) */ pset.gexec_flag = true; /* Return true if all queries were successful */ return success; }
/* * Main processing loop for reading lines of input * and sending them to the backend. * * This loop is re-entrant. May be called by \i command * which reads input from a file. */ int MainLoop(FILE *source) { PsqlScanState scan_state; /* lexer working state */ PQExpBuffer query_buf; /* buffer for query being accumulated */ PQExpBuffer previous_buf; /* if there isn't anything in the new * buffer yet, use this one for \e, etc. */ char *line; /* current line of input */ int added_nl_pos; bool success; volatile int successResult = EXIT_SUCCESS; volatile backslashResult slashCmdStatus = CMD_UNKNOWN; volatile promptStatus_t prompt_status = PROMPT_READY; volatile int count_eof = 0; volatile bool die_on_error = false; /* Save the prior command source */ FILE *prev_cmd_source; bool prev_cmd_interactive; unsigned int prev_lineno; /* Save old settings */ prev_cmd_source = pset.cur_cmd_source; prev_cmd_interactive = pset.cur_cmd_interactive; prev_lineno = pset.lineno; /* Establish new source */ pset.cur_cmd_source = source; pset.cur_cmd_interactive = ((source == stdin) && !pset.notty); pset.lineno = 0; /* Create working state */ scan_state = psql_scan_create(); query_buf = createPQExpBuffer(); previous_buf = createPQExpBuffer(); if (!query_buf || !previous_buf) { psql_error("out of memory\n"); exit(EXIT_FAILURE); } /* main loop to get queries and execute them */ while (successResult == EXIT_SUCCESS) { /* * Welcome code for Control-C */ if (cancel_pressed) { if (!pset.cur_cmd_interactive) { /* * You get here if you stopped a script with Ctrl-C and a * query cancel was issued. In that case we don't do the * longjmp, so the query routine can finish nicely. */ successResult = EXIT_USER; break; } cancel_pressed = false; } #ifndef WIN32 if (sigsetjmp(main_loop_jmp, 1) != 0) { /* got here with longjmp */ /* reset parsing state */ resetPQExpBuffer(query_buf); psql_scan_finish(scan_state); psql_scan_reset(scan_state); count_eof = 0; slashCmdStatus = CMD_UNKNOWN; prompt_status = PROMPT_READY; if (pset.cur_cmd_interactive) putc('\n', stdout); else { successResult = EXIT_USER; break; } } /* * establish the control-C handler only after main_loop_jmp is * ready */ pqsignal(SIGINT, handle_sigint); /* control-C => cancel */ #else /* WIN32 */ setup_cancel_handler(); #endif fflush(stdout); if (slashCmdStatus == CMD_NEWEDIT) { /* * just returned from editing the line? then just copy to the * input buffer */ line = pg_strdup(query_buf->data); /* reset parsing state since we are rescanning whole line */ resetPQExpBuffer(query_buf); psql_scan_reset(scan_state); slashCmdStatus = CMD_UNKNOWN; prompt_status = PROMPT_READY; } /* * otherwise, get another line */ else if (pset.cur_cmd_interactive) { /* May need to reset prompt, eg after \r command */ if (query_buf->len == 0) prompt_status = PROMPT_READY; line = gets_interactive(get_prompt(prompt_status)); } else line = gets_fromFile(source); /* * query_buf holds query already accumulated. line is the * malloc'd new line of input (note it must be freed before * looping around!) */ /* No more input. Time to quit, or \i done */ if (line == NULL) { if (pset.cur_cmd_interactive) { /* This tries to mimic bash's IGNOREEOF feature. */ count_eof++; if (count_eof < GetVariableNum(pset.vars, "IGNOREEOF", 0, 10, false)) { if (!QUIET()) printf(gettext("Use \"\\q\" to leave %s.\n"), pset.progname); continue; } puts(QUIET() ? "" : "\\q"); } break; } count_eof = 0; pset.lineno++; /* nothing left on line? then ignore */ if (line[0] == '\0' && !psql_scan_in_quote(scan_state)) { free(line); continue; } /* echo back if flag is set */ if (!pset.cur_cmd_interactive && VariableEquals(pset.vars, "ECHO", "all")) puts(line); fflush(stdout); /* insert newlines into query buffer between source lines */ if (query_buf->len > 0) { appendPQExpBufferChar(query_buf, '\n'); added_nl_pos = query_buf->len; } else added_nl_pos = -1; /* flag we didn't add one */ /* Setting this will not have effect until next line. */ die_on_error = GetVariableBool(pset.vars, "ON_ERROR_STOP"); /* * Parse line, looking for command separators. */ psql_scan_setup(scan_state, line, strlen(line)); success = true; while (success || !die_on_error) { PsqlScanResult scan_result; promptStatus_t prompt_tmp = prompt_status; scan_result = psql_scan(scan_state, query_buf, &prompt_tmp); prompt_status = prompt_tmp; /* * Send command if semicolon found, or if end of line and * we're in single-line mode. */ if (scan_result == PSCAN_SEMICOLON || (scan_result == PSCAN_EOL && GetVariableBool(pset.vars, "SINGLELINE"))) { /* execute query */ success = SendQuery(query_buf->data); slashCmdStatus = success ? CMD_SEND : CMD_ERROR; resetPQExpBuffer(previous_buf); appendPQExpBufferStr(previous_buf, query_buf->data); resetPQExpBuffer(query_buf); added_nl_pos = -1; /* we need not do psql_scan_reset() here */ } else if (scan_result == PSCAN_BACKSLASH) { /* handle backslash command */ /* * If we added a newline to query_buf, and nothing else * has been inserted in query_buf by the lexer, then strip * off the newline again. This avoids any change to * query_buf when a line contains only a backslash * command. */ if (query_buf->len == added_nl_pos) query_buf->data[--query_buf->len] = '\0'; added_nl_pos = -1; slashCmdStatus = HandleSlashCmds(scan_state, query_buf->len > 0 ? query_buf : previous_buf); success = slashCmdStatus != CMD_ERROR; if ((slashCmdStatus == CMD_SEND || slashCmdStatus == CMD_NEWEDIT) && query_buf->len == 0) { /* copy previous buffer to current for handling */ appendPQExpBufferStr(query_buf, previous_buf->data); } if (slashCmdStatus == CMD_SEND) { success = SendQuery(query_buf->data); resetPQExpBuffer(previous_buf); appendPQExpBufferStr(previous_buf, query_buf->data); resetPQExpBuffer(query_buf); /* flush any paren nesting info after forced send */ psql_scan_reset(scan_state); } if (slashCmdStatus == CMD_TERMINATE) break; } /* fall out of loop if lexer reached EOL */ if (scan_result == PSCAN_INCOMPLETE || scan_result == PSCAN_EOL) break; } psql_scan_finish(scan_state); free(line); if (slashCmdStatus == CMD_TERMINATE) { successResult = EXIT_SUCCESS; break; } if (!pset.cur_cmd_interactive) { if (!success && die_on_error) successResult = EXIT_USER; /* Have we lost the db connection? */ else if (!pset.db) successResult = EXIT_BADCONN; } } /* while !endoffile/session */ /* * Process query at the end of file without a semicolon */ if (query_buf->len > 0 && !pset.cur_cmd_interactive && successResult == EXIT_SUCCESS) { success = SendQuery(query_buf->data); if (!success && die_on_error) successResult = EXIT_USER; else if (pset.db == NULL) successResult = EXIT_BADCONN; } /* * Reset SIGINT handler because main_loop_jmp will be invalid as soon * as we exit this routine. If there is an outer MainLoop instance, * it will re-enable ^C catching as soon as it gets back to the top of * its loop and resets main_loop_jmp to point to itself. */ #ifndef WIN32 pqsignal(SIGINT, SIG_DFL); #endif destroyPQExpBuffer(query_buf); destroyPQExpBuffer(previous_buf); psql_scan_destroy(scan_state); pset.cur_cmd_source = prev_cmd_source; pset.cur_cmd_interactive = prev_cmd_interactive; pset.lineno = prev_lineno; return successResult; } /* MainLoop() */
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static uint32_t lanLastPing = 0; static HFONT _hFont = 0; switch (message) { case WM_CREATE: { HFONT hFont = 0; NONCLIENTMETRICS ncm = { sizeof(ncm) }; if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) { hFont = CreateFontIndirect(&ncm.lfMessageFont); _hFont = hFont; } if (!hFont) hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); RECT rcClient; GetClientRect(hWnd, &rcClient); g_hWndListViewServers = CreateWindow(WC_LISTVIEW, nullptr, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_OWNERDATA, 1, 21, rcClient.right - UI_PLAYERLIST_WIDTH - 4, rcClient.bottom - UI_SERVERINFO_HEIGHT - 21 - 2, hWnd, nullptr, g_hInst, nullptr); if (g_hWndListViewServers) { SetWindowTheme(g_hWndListViewServers, L"Explorer", nullptr); ListView_SetExtendedListViewStyle(g_hWndListViewServers, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); LVCOLUMN lvc; lvc.mask = LVCF_WIDTH; lvc.cx = 30; ListView_InsertColumn(g_hWndListViewServers, 0, &lvc); lvc.mask = LVCF_WIDTH | LVCF_TEXT; lvc.cx = 240; lvc.pszText = LoadStr(L"Server Name", IDS_SERVERNAME); ListView_InsertColumn(g_hWndListViewServers, 1, &lvc); lvc.cx = 60; lvc.pszText = LoadStr(L"Ping", IDS_PING); ListView_InsertColumn(g_hWndListViewServers, 2, &lvc); lvc.cx = 80; lvc.pszText = LoadStr(L"Players", IDS_PLAYERS); ListView_InsertColumn(g_hWndListViewServers, 3, &lvc); lvc.cx = 70; lvc.pszText = LoadStr(L"Version", IDS_VERSION); ListView_InsertColumn(g_hWndListViewServers, 4, &lvc); lvc.cx = 120; lvc.pszText = LoadStr(L"Gamemode", IDS_GAMEMODE); ListView_InsertColumn(g_hWndListViewServers, 5, &lvc); lvc.cx = 100; lvc.pszText = LoadStr(L"Map Name", IDS_MAPNAME); ListView_InsertColumn(g_hWndListViewServers, 6, &lvc); } g_hWndListViewHistory = CreateWindow(WC_LISTVIEW, nullptr, WS_CHILD | WS_CLIPSIBLINGS | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_OWNERDATA, 1, 21, rcClient.right - UI_PLAYERLIST_WIDTH - 4, rcClient.bottom - UI_SERVERINFO_HEIGHT - 21 - 2, hWnd, nullptr, g_hInst, nullptr); if (g_hWndListViewHistory) { SetWindowTheme(g_hWndListViewHistory, L"Explorer", nullptr); ListView_SetExtendedListViewStyle(g_hWndListViewHistory, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); LVCOLUMN lvc; lvc.mask = LVCF_WIDTH; lvc.cx = 30; ListView_InsertColumn(g_hWndListViewHistory, 0, &lvc); lvc.mask = LVCF_WIDTH | LVCF_TEXT; lvc.cx = 220; lvc.pszText = LoadStr(L"Server Name", IDS_SERVERNAME); ListView_InsertColumn(g_hWndListViewHistory, 1, &lvc); lvc.cx = 60; lvc.pszText = LoadStr(L"Ping", IDS_PING); ListView_InsertColumn(g_hWndListViewHistory, 2, &lvc); lvc.cx = 80; lvc.pszText = LoadStr(L"Players", IDS_PLAYERS); ListView_InsertColumn(g_hWndListViewHistory, 3, &lvc); lvc.cx = 70; lvc.pszText = LoadStr(L"Version", IDS_VERSION); ListView_InsertColumn(g_hWndListViewHistory, 4, &lvc); lvc.cx = 100; lvc.pszText = LoadStr(L"Gamemode", IDS_GAMEMODE); ListView_InsertColumn(g_hWndListViewHistory, 5, &lvc); lvc.cx = 160; lvc.pszText = LoadStr(L"Last Played", IDS_LASTPLAYED); ListView_InsertColumn(g_hWndListViewHistory, 6, &lvc); } g_hWndTab = CreateWindow(WC_TABCONTROL, nullptr, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, 0, 0, rcClient.right - UI_PLAYERLIST_WIDTH, rcClient.bottom - UI_SERVERINFO_HEIGHT, hWnd, nullptr, g_hInst, nullptr); if (g_hWndTab) { SetWindowFont(g_hWndTab, hFont, FALSE); HIMAGELIST hTabIml = ImageList_Create(16, 16, ILC_COLOR32, 0, 0); if (hTabIml) { for (int i = IDI_FAVORITE; i <= IDI_HISTORY; ++i) ImageList_AddIcon(hTabIml, LoadIcon(g_hInst, MAKEINTRESOURCE(i))); TabCtrl_SetImageList(g_hWndTab, hTabIml); } TCITEM tie; tie.mask = TCIF_TEXT | TCIF_IMAGE; tie.iImage = 0; tie.pszText = LoadStr(L"Favorites", IDS_FAVORITES); TabCtrl_InsertItem(g_hWndTab, 0, &tie); tie.iImage = 1; tie.pszText = LoadStr(L"Internet", IDS_INTERNET); TabCtrl_InsertItem(g_hWndTab, 1, &tie); tie.iImage = 1; tie.pszText = LoadStr(L"Official", IDS_OFFICIAL); TabCtrl_InsertItem(g_hWndTab, 2, &tie); tie.iImage = 2; tie.pszText = LoadStr(L"Lan", IDS_LAN); TabCtrl_InsertItem(g_hWndTab, 3, &tie); tie.iImage = 3; tie.pszText = LoadStr(L"History", IDS_HISTORY); TabCtrl_InsertItem(g_hWndTab, 4, &tie); } g_hWndListViewPlayers = CreateWindowEx(0, WC_LISTVIEW, nullptr, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_SINGLESEL | LVS_OWNERDATA, rcClient.right - UI_PLAYERLIST_WIDTH + 1, 18, UI_PLAYERLIST_WIDTH - 2, rcClient.bottom - UI_SERVERINFO_HEIGHT - 18 - 2, hWnd, nullptr, g_hInst, nullptr); if (g_hWndListViewPlayers) { SetWindowTheme(g_hWndListViewPlayers, L"Explorer", nullptr); ListView_SetExtendedListViewStyle(g_hWndListViewPlayers, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); LVCOLUMN lvc; lvc.mask = LVCF_WIDTH; lvc.cx = UI_PLAYERLIST_WIDTH - 2; ListView_InsertColumn(g_hWndListViewPlayers, 0, &lvc); } g_hWndGroupBox1 = CreateWindow(WC_BUTTON, LoadStr(L"Players", IDS_PLAYERSLIST), WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | BS_GROUPBOX, rcClient.right - UI_PLAYERLIST_WIDTH, 0, UI_PLAYERLIST_WIDTH, rcClient.bottom - UI_SERVERINFO_HEIGHT, hWnd, nullptr, g_hInst, nullptr); if (g_hWndGroupBox1) { SetWindowFont(g_hWndGroupBox1, hFont, FALSE); } g_hWndGroupBox2 = CreateWindow(WC_BUTTON, LoadStr(L"Server Info", IDS_SERVERINFO), WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | BS_GROUPBOX, 0, rcClient.bottom - UI_SERVERINFO_HEIGHT, rcClient.right, 118, hWnd, nullptr, g_hInst, nullptr); if (g_hWndGroupBox2) { SetWindowFont(g_hWndGroupBox2, hFont, FALSE); int y = 18; #define LINE_GAP 20 HWND hStatic = CreateWindow(WC_STATIC, LoadStr(L"Server Name:", IDS_SERVERNAME_), WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SS_RIGHT, 10, y, 100, 16, g_hWndGroupBox2, nullptr, g_hInst, nullptr); if (hStatic) SetWindowFont(hStatic, hFont, FALSE); HWND hEdit = CreateWindow(WC_EDIT, nullptr, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | ES_READONLY, 112, y, 300, 16, g_hWndGroupBox2, (HMENU)1001, g_hInst, nullptr); if (hEdit) SetWindowFont(hEdit, hFont, FALSE); y += LINE_GAP; hStatic = CreateWindow(WC_STATIC, LoadStr(L"Server IP:", IDS_SERVERIP), WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SS_RIGHT, 10, y, 100, 16, g_hWndGroupBox2, nullptr, g_hInst, nullptr); if (hStatic) SetWindowFont(hStatic, hFont, FALSE); hEdit = CreateWindow(WC_EDIT, nullptr, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | ES_READONLY, 112, y, 300, 16, g_hWndGroupBox2, (HMENU)1002, g_hInst, nullptr); if (hEdit) SetWindowFont(hEdit, hFont, FALSE); y += LINE_GAP; hStatic = CreateWindow(WC_STATIC, LoadStr(L"Server Players:", IDS_SERVERPLAYERS), WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SS_RIGHT, 10, y, 100, 16, g_hWndGroupBox2, nullptr, g_hInst, nullptr); if (hStatic) SetWindowFont(hStatic, hFont, FALSE); hEdit = CreateWindow(WC_EDIT, nullptr, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | ES_READONLY, 112, y, 300, 16, g_hWndGroupBox2, (HMENU)1003, g_hInst, nullptr); if (hEdit) SetWindowFont(hEdit, hFont, FALSE); y += LINE_GAP; hStatic = CreateWindow(WC_STATIC, LoadStr(L"Server Ping:", IDS_SERVERPING), WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SS_RIGHT, 10, y, 100, 16, g_hWndGroupBox2, nullptr, g_hInst, nullptr); if (hStatic) SetWindowFont(hStatic, hFont, FALSE); hEdit = CreateWindow(WC_EDIT, nullptr, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | ES_READONLY, 112, y, 300, 16, g_hWndGroupBox2, (HMENU)1004, g_hInst, nullptr); if (hEdit) SetWindowFont(hEdit, hFont, FALSE); y += LINE_GAP; hStatic = CreateWindow(WC_STATIC, LoadStr(L"Server Gamemode:", IDS_SERVERGAMEMODE), WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SS_RIGHT, 10, y, 100, 16, g_hWndGroupBox2, nullptr, g_hInst, nullptr); if (hStatic) SetWindowFont(hStatic, hFont, FALSE); hEdit = CreateWindow(WC_EDIT, nullptr, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | ES_READONLY, 112, y, 300, 16, g_hWndGroupBox2, (HMENU)1005, g_hInst, nullptr); if (hEdit) SetWindowFont(hEdit, hFont, FALSE); } g_hWndStatusBar = CreateWindow(STATUSCLASSNAME, nullptr, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hWnd, nullptr, g_hInst, nullptr); do { g_UDPSocket = socket(AF_INET, SOCK_DGRAM, 0); if (g_UDPSocket == INVALID_SOCKET) break; uint32_t timeout = 2000; setsockopt(g_UDPSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); struct sockaddr_in bindaddr = { AF_INET }; if (bind(g_UDPSocket, (sockaddr *)&bindaddr, 16) != NO_ERROR) { closesocket(g_UDPSocket); break; } if (WSAAsyncSelect(g_UDPSocket, hWnd, WM_SOCKET, FD_READ) == SOCKET_ERROR) { closesocket(g_UDPSocket); break; } return 0; } while (0); } break; case WM_COMMAND: { int wmId = LOWORD(wParam); switch (wmId) { case IDM_TOOLS_SETTINGS: ShowSettings(); break; case IDM_ABOUT: DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_NOTIFY: { switch (((LPNMHDR)lParam)->code) { case TCN_SELCHANGE: { g_currentTab = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom); switch (g_currentTab) { case 0: // Favorites case 1: // Internet case 2: // Official case 3: // Lan ListView_DeleteAllItems(g_hWndListViewServers); ListView_DeleteAllItems(g_hWndListViewPlayers); g_serversList.clear(); ShowWindow(g_hWndListViewServers, SW_SHOW); ShowWindow(g_hWndListViewHistory, SW_HIDE); UpdateWindow(g_hWndListViewServers); if (g_currentTab == 1 || g_currentTab == 2) { HWND hDialog = CreateDialog(g_hInst, MAKEINTRESOURCEW(IDD_LOADING), hWnd, nullptr); SetWindowPos(hDialog, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); UpdateWindow(hDialog); if (g_serversMasterList) { delete g_serversMasterList; g_serversMasterList = nullptr; } std::string data; data.reserve(2048); const char *url; if (g_currentTab == 1) url = (g_browserSettings.masterlistURL + "/servers").c_str(); else url = (g_browserSettings.masterlistURL + "/official").c_str(); CURLcode curlRet = CurlRequset(url, data, "VCMP/0.4"); if (curlRet == CURLE_OK) { serverMasterList serversList; if (ParseJson(data.data(), serversList)) { for (auto it = serversList.begin(); it != serversList.end(); ++it) { SendQuery(it->address, 'i'); it->lastPing = GetTickCount(); } g_serversMasterList = new serverMasterList(serversList); } else { MessageBox(hWnd, LoadStr(L"Can't parse master list data.", IDS_MASTERLISTDATA), LoadStr(L"Error", IDS_ERROR), MB_ICONWARNING); } } else { wchar_t message[512]; swprintf_s(message, LoadStr(L"Can't get information from master list.\n%hs", IDS_MASTERLISTFAILED), curl_easy_strerror(curlRet)); MessageBox(hWnd, message, LoadStr(L"Error", IDS_ERROR), MB_ICONWARNING); } DestroyWindow(hDialog); } else if (g_currentTab == 3) { BOOL broadcast = TRUE; setsockopt(g_UDPSocket, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); for (uint16_t port = 8000; port <= 8200; ++port) { serverAddress address = { INADDR_BROADCAST, port }; SendQuery(address, 'i'); } broadcast = FALSE; setsockopt(g_UDPSocket, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); lanLastPing = GetTickCount(); } break; case 4: // History ShowWindow(g_hWndListViewHistory, SW_SHOW); ShowWindow(g_hWndListViewServers, SW_HIDE); break; } } break; case LVN_GETDISPINFO: { LPNMLVDISPINFOW di = (LPNMLVDISPINFOW)lParam; if (di->hdr.hwndFrom == g_hWndListViewServers) { size_t i = di->item.iItem; if (g_serversList.size() > i) { if (di->item.iSubItem == 0 && di->item.mask & LVIF_IMAGE) di->item.iImage = 0; if (di->item.mask & LVIF_TEXT) { switch (di->item.iSubItem) { case 0: // Icon break; case 1: // Server Name if (di->item.cchTextMax > 0 && di->item.pszText) { MultiByteToWideChar(CP_ACP, 0, g_serversList[i].info.serverName.c_str(), -1, di->item.pszText, di->item.cchTextMax); } break; case 2: // Ping { uint32_t ping = g_serversList[i].lastRecv - g_serversList[i].lastPing[1]; _itow_s(ping, di->item.pszText, di->item.cchTextMax, 10); } break; case 3: // Players swprintf_s(di->item.pszText, di->item.cchTextMax, L"%hu/%hu", g_serversList[i].info.players, g_serversList[i].info.maxPlayers); break; case 4: // Version { MultiByteToWideChar(CP_ACP, 0, g_serversList[i].info.versionName, -1, di->item.pszText, di->item.cchTextMax); } break; case 5: // Gamemode { MultiByteToWideChar(CP_ACP, 0, g_serversList[i].info.gameMode.c_str(), -1, di->item.pszText, di->item.cchTextMax); } break; case 6: // Map name { MultiByteToWideChar(CP_ACP, 0, g_serversList[i].info.mapName.c_str(), -1, di->item.pszText, di->item.cchTextMax); } break; } } } } else if (di->hdr.hwndFrom == g_hWndListViewHistory) // FIXME { } else if (di->hdr.hwndFrom == g_hWndListViewPlayers) { size_t i = ListView_GetSelectionMark(g_hWndListViewServers); if (g_serversList.size() > i) { serverPlayers &players = g_serversList[i].players; size_t j = di->item.iItem; if (players.size() > j) { if (di->item.mask & LVIF_TEXT) { MultiByteToWideChar(CP_ACP, 0, players[j].name, -1, di->item.pszText, di->item.cchTextMax); } } } } } break; case NM_CUSTOMDRAW: { LPNMLVCUSTOMDRAW nmcd = (LPNMLVCUSTOMDRAW)lParam; if (nmcd->nmcd.hdr.hwndFrom == g_hWndListViewServers) { switch (nmcd->nmcd.dwDrawStage) { case CDDS_PREPAINT: return CDRF_NOTIFYITEMDRAW; case CDDS_ITEMPREPAINT: { COLORREF crText; size_t i = nmcd->nmcd.dwItemSpec; if (g_serversList.size() > i && g_serversList[i].isOfficial) crText = g_browserSettings.officialColor; else crText = 0; nmcd->clrText = crText; return CDRF_DODEFAULT; } } } } break; case LVN_ITEMCHANGED: { LPNMITEMACTIVATE nmitem = (LPNMITEMACTIVATE)lParam; if (nmitem->hdr.hwndFrom == g_hWndListViewServers) { size_t i = nmitem->iItem; if (i != -1 && g_serversList.size() > i) { if (g_serversList[i].info.players == 0) ListView_DeleteAllItems(g_hWndListViewPlayers); std::wstring wstr; ConvertCharset(g_serversList[i].info.serverName.c_str(), wstr); SetDlgItemText(g_hWndGroupBox2, 1001, wstr.c_str()); // Server Name wchar_t ipstr[22]; char *ip = (char *)&(g_serversList[i].address.ip); swprintf_s(ipstr, L"%hhu.%hhu.%hhu.%hhu:%hu", ip[0], ip[1], ip[2], ip[3], g_serversList[i].address.port); SetDlgItemText(g_hWndGroupBox2, 1002, ipstr); // Server IP wchar_t playersstr[12]; swprintf_s(playersstr, L"%hu/%hu", g_serversList[i].info.players, g_serversList[i].info.maxPlayers); SetDlgItemText(g_hWndGroupBox2, 1003, playersstr); // Server Players wchar_t pingsstr[12]; uint32_t ping = g_serversList[i].lastRecv - g_serversList[i].lastPing[1]; _itow_s(ping, pingsstr, 10); SetDlgItemText(g_hWndGroupBox2, 1004, pingsstr); // Server Ping ConvertCharset(g_serversList[i].info.gameMode.c_str(), wstr); SetDlgItemText(g_hWndGroupBox2, 1005, wstr.c_str()); // Server Gamemode SendQuery(g_serversList[i].address, 'i'); SendQuery(g_serversList[i].address, 'c'); g_serversList[i].lastPing[0] = GetTickCount(); } else { ListView_DeleteAllItems(g_hWndListViewPlayers); for (int i = 1001; i <= 1005; ++i) SetDlgItemText(g_hWndGroupBox2, i, nullptr); } } } break; case LVN_ITEMACTIVATE: { LPNMITEMACTIVATE nmia = (LPNMITEMACTIVATE)lParam; if (nmia->hdr.hwndFrom == g_hWndListViewServers) { size_t i = nmia->iItem; if (i != -1 && g_serversList.size() > i) { char ipstr[16]; char *ip = (char *)&(g_serversList[i].address.ip); snprintf(ipstr, sizeof(ipstr), "%hhu.%hhu.%hhu.%hhu", ip[0], ip[1], ip[2], ip[3]); char vcmpDll[MAX_PATH]; snprintf(vcmpDll, sizeof(vcmpDll), "%ls%s\\vcmp-game.dll", g_exePath, g_serversList[i].info.versionName); LaunchVCMP(ipstr, g_serversList[i].address.port, g_browserSettings.playerName, nullptr, g_browserSettings.gamePath, vcmpDll); } } } break; } } break; case WM_SIZE: { int clientWidth = GET_X_LPARAM(lParam), clientHeight = GET_Y_LPARAM(lParam); SetWindowPos(g_hWndTab, 0, 0, 0, clientWidth - UI_PLAYERLIST_WIDTH, clientHeight - UI_SERVERINFO_HEIGHT, SWP_NOZORDER); SetWindowPos(g_hWndListViewServers, 0, 1, 21, clientWidth - UI_PLAYERLIST_WIDTH - 4, clientHeight - UI_SERVERINFO_HEIGHT - 21 - 2, SWP_NOZORDER); SetWindowPos(g_hWndListViewHistory, 0, 1, 21, clientWidth - UI_PLAYERLIST_WIDTH - 4, clientHeight - UI_SERVERINFO_HEIGHT - 21 - 2, SWP_NOZORDER); SetWindowPos(g_hWndGroupBox1, 0, clientWidth - UI_PLAYERLIST_WIDTH, 0, UI_PLAYERLIST_WIDTH, clientHeight - UI_SERVERINFO_HEIGHT, SWP_NOZORDER); SetWindowPos(g_hWndListViewPlayers, 0, clientWidth - UI_PLAYERLIST_WIDTH + 1, 18, UI_PLAYERLIST_WIDTH - 2, clientHeight - UI_SERVERINFO_HEIGHT - 18 - 2, SWP_NOZORDER); SetWindowPos(g_hWndGroupBox2, 0, 0, clientHeight - UI_SERVERINFO_HEIGHT, clientWidth, 118, SWP_NOZORDER); SendMessage(g_hWndStatusBar, WM_SIZE, 0, 0); } break; case WM_GETMINMAXINFO: ((LPMINMAXINFO)lParam)->ptMinTrackSize = { 750, 500 }; break; case WM_DESTROY: if (_hFont) DeleteObject(_hFont); PostQuitMessage(0); break; case WM_SOCKET: { if (WSAGETSELECTEVENT(lParam) == FD_READ) { char *recvBuf = (char *)calloc(1024, sizeof(char)); if (recvBuf) { struct sockaddr_in recvAddr; int addrLen = sizeof(recvAddr); int recvLen = recvfrom(g_UDPSocket, recvBuf, 1024, 0, (sockaddr *)&recvAddr, &addrLen); if (recvLen != -1 && recvLen >= 11) { if (recvLen > 1024) recvLen = 1024; if (*(int *)recvBuf == 0x3430504D) // MP04 { char opcode = recvBuf[10]; if (opcode == 'i' || opcode == 'c') { uint32_t ip = recvAddr.sin_addr.s_addr; uint16_t port = ntohs(recvAddr.sin_port); bool found = false; serverMasterListInfo masterInfo; if (g_currentTab == 1 || g_currentTab == 2) { for (auto it = g_serversMasterList->begin(); it != g_serversMasterList->end(); ++it) { if (it->address.ip == ip && it->address.port == port) { found = true; masterInfo = *it; break; } } } else if (g_currentTab == 3) // Lan { found = true; masterInfo.address = { ip, port }; masterInfo.isOfficial = false; masterInfo.lastPing = lanLastPing; } if (found) { switch (opcode) { case 'i': { serverInfo info; if (GetServerInfo(recvBuf, recvLen, info)) { bool inList = false; for (auto it = g_serversList.begin(); it != g_serversList.end(); ++it) { if (it->address.ip == ip && it->address.port == port) { inList = true; it->lastRecv = GetTickCount(); it->lastPing[1] = it->lastPing[0]; it->info = info; auto i = it - g_serversList.begin(); ListView_Update(g_hWndListViewServers, i); break; } } if (!inList) { serverAllInfo allInfo; allInfo.address = masterInfo.address; allInfo.info = info; allInfo.isOfficial = masterInfo.isOfficial; allInfo.lastPing[0] = masterInfo.lastPing; allInfo.lastPing[1] = masterInfo.lastPing; allInfo.lastRecv = GetTickCount(); g_serversList.push_back(allInfo); LVITEM lvi = { 0 }; ListView_InsertItem(g_hWndListViewServers, &lvi); } } } break; case 'c': { serverPlayers players; if (GetServerPlayers(recvBuf, recvLen, players)) { for (auto it = g_serversList.begin(); it != g_serversList.end(); ++it) { if (it->address.ip == ip && it->address.port == port) { it->lastRecv = GetTickCount(); it->lastPing[1] = it->lastPing[0]; it->players = players; auto i = it - g_serversList.begin(); ListView_SetItemCount(g_hWndListViewPlayers, players.size()); break; } } } } break; } } } } } free(recvBuf); } } } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
NMErr OTIPEnumerator::StartEnumeration(void) { TEndpointInfo info; NMErr status = kNMNoError; TBind request; TOption optBuf; //NMUInt8 optBuf[64]; //NMUInt8 fooBuf[32]; TOptMgmt cmd; //NMUInt8 *foo = fooBuf; // If they don't want us to actively get the enumeration, there is nothing to do if (! bActive) return kNMNoError; // first clear out any current items (mCallback)(mContext, kNMEnumClear, NULL); // [Edmark/PBE] 11/16/99 added bFirstIdle = true; // Create an OT endpoint mEP = OTOpenEndpoint(OTCreateConfiguration(kUDPName), 0, &info, &status); if (status) goto error; // fill in the option request cmd.flags = T_NEGOTIATE; cmd.opt.len = kOTFourByteOptionSize; cmd.opt.maxlen = kOTFourByteOptionSize; cmd.opt.buf = (NMUInt8*)&optBuf; // fill in the toption struct optBuf.len = sizeof(TOption); optBuf.level = INET_IP; optBuf.name = kIP_BROADCAST; optBuf.status = 0; optBuf.value[0] = 1; /* cmd.opt.len = 0; cmd.opt.maxlen = 64; cmd.opt.buf = (NMUInt8*)optBuf; cmd.flags = T_NEGOTIATE; // Option management kinda sucks strcpy((char *) fooBuf, "Broadcast = 1"); status = OTCreateOptions(kRawIPName, (char **)&foo, &cmd.opt); */ status = OTOptionManagement(mEP, &cmd, &cmd); if (status) goto error; // Allocate the buffer for receiving the endpoint mIncomingData.udata.buf = (NMUInt8 *) InterruptSafe_alloc(info.tsdu); if (mIncomingData.udata.buf == NULL){ status = kNSpMemAllocationErr; goto error; } mIncomingData.udata.maxlen = info.tsdu; // Bind it request.addr.buf = NULL; request.addr.len = 0; request.addr.maxlen = 0; request.qlen = 0; status = OTBind(mEP, &request, NULL); if (status) goto error; OTSetNonBlocking(mEP); // Get our interface info (for the broadcast address) // Do this after we bind so that we know the interface is live if (! bGotInterfaceInfo) { status = OTInetGetInterfaceInfo(&mInterfaceInfo, kDefaultInetInterface); if (status) goto error; bGotInterfaceInfo = true; } // Install notifier status = OTInstallNotifier(mEP, mNotifier.fUPP, this); if (status) goto error; // Make is asynchronous status = OTSetAsynchronous(mEP); if (status) goto error; // Send out the query mEnumPeriod = 250; status = SendQuery(); error: if (status) { if (mEP) { OTCloseProvider(mEP); // ignore errors mEP = kOTInvalidEndpointRef; } } return status; }
void CBanList::Refresh() { SendQuery(); }
/* * * main * */ int main(int argc, char *argv[]) { struct adhoc_opts options; int successResult; char *password = NULL; char *password_prompt = NULL; bool new_pass; set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql")); if (argc > 1) { if ((strcmp(argv[1], "-?") == 0) || (argc == 2 && (strcmp(argv[1], "--help") == 0))) { usage(NOPAGER); exit(EXIT_SUCCESS); } if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) { showVersion(); exit(EXIT_SUCCESS); } } #ifdef WIN32 setvbuf(stderr, NULL, _IONBF, 0); #endif pset.progname = get_progname(argv[0]); pset.db = NULL; setDecimalLocale(); pset.encoding = PQenv2encoding(); pset.queryFout = stdout; pset.queryFoutPipe = false; pset.copyStream = NULL; pset.cur_cmd_source = stdin; pset.cur_cmd_interactive = false; /* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */ pset.popt.topt.format = PRINT_ALIGNED; pset.popt.topt.border = 1; pset.popt.topt.pager = 1; pset.popt.topt.pager_min_lines = 0; pset.popt.topt.start_table = true; pset.popt.topt.stop_table = true; pset.popt.topt.default_footer = true; pset.popt.topt.unicode_border_linestyle = UNICODE_LINESTYLE_SINGLE; pset.popt.topt.unicode_column_linestyle = UNICODE_LINESTYLE_SINGLE; pset.popt.topt.unicode_header_linestyle = UNICODE_LINESTYLE_SINGLE; refresh_utf8format(&(pset.popt.topt)); /* We must get COLUMNS here before readline() sets it */ pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0; pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout))); pset.getPassword = TRI_DEFAULT; EstablishVariableSpace(); SetVariable(pset.vars, "VERSION", PG_VERSION_STR); /* Default values for variables */ SetVariableBool(pset.vars, "AUTOCOMMIT"); SetVariable(pset.vars, "VERBOSITY", "default"); SetVariable(pset.vars, "SHOW_CONTEXT", "errors"); SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1); SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2); SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3); parse_psql_options(argc, argv, &options); /* * If no action was specified and we're in non-interactive mode, treat it * as if the user had specified "-f -". This lets single-transaction mode * work in this case. */ if (options.action == ACT_NOTHING && pset.notty) { options.action = ACT_FILE; options.action_string = NULL; } /* Bail out if -1 was specified but will be ignored. */ if (options.single_txn && options.action != ACT_FILE && options.action == ACT_NOTHING) { fprintf(stderr, _("%s: -1 can only be used in non-interactive mode\n"), pset.progname); exit(EXIT_FAILURE); } if (!pset.popt.topt.fieldSep.separator && !pset.popt.topt.fieldSep.separator_zero) { pset.popt.topt.fieldSep.separator = pg_strdup(DEFAULT_FIELD_SEP); pset.popt.topt.fieldSep.separator_zero = false; } if (!pset.popt.topt.recordSep.separator && !pset.popt.topt.recordSep.separator_zero) { pset.popt.topt.recordSep.separator = pg_strdup(DEFAULT_RECORD_SEP); pset.popt.topt.recordSep.separator_zero = false; } if (options.username == NULL) password_prompt = pg_strdup(_("Password: "******"Password for user %s: "), options.username); if (pset.getPassword == TRI_YES) password = simple_prompt(password_prompt, 100, false); /* loop until we have a password if requested by backend */ do { #define PARAMS_ARRAY_SIZE 8 const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords)); const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values)); keywords[0] = "host"; values[0] = options.host; keywords[1] = "port"; values[1] = options.port; keywords[2] = "user"; values[2] = options.username; keywords[3] = "password"; values[3] = password; keywords[4] = "dbname"; values[4] = (options.action == ACT_LIST_DB && options.dbname == NULL) ? "postgres" : options.dbname; keywords[5] = "fallback_application_name"; values[5] = pset.progname; keywords[6] = "client_encoding"; values[6] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto"; keywords[7] = NULL; values[7] = NULL; new_pass = false; pset.db = PQconnectdbParams(keywords, values, true); free(keywords); free(values); if (PQstatus(pset.db) == CONNECTION_BAD && PQconnectionNeedsPassword(pset.db) && password == NULL && pset.getPassword != TRI_NO) { PQfinish(pset.db); password = simple_prompt(password_prompt, 100, false); new_pass = true; } } while (new_pass); free(password); free(password_prompt); if (PQstatus(pset.db) == CONNECTION_BAD) { fprintf(stderr, "%s: %s", pset.progname, PQerrorMessage(pset.db)); PQfinish(pset.db); exit(EXIT_BADCONN); } setup_cancel_handler(); PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL); SyncVariables(); if (options.action == ACT_LIST_DB) { int success; if (!options.no_psqlrc) process_psqlrc(argv[0]); success = listAllDbs(NULL, false); PQfinish(pset.db); exit(success ? EXIT_SUCCESS : EXIT_FAILURE); } if (options.logfilename) { pset.logfile = fopen(options.logfilename, "a"); if (!pset.logfile) fprintf(stderr, _("%s: could not open log file \"%s\": %s\n"), pset.progname, options.logfilename, strerror(errno)); } /* * Now find something to do */ /* * process file given by -f */ if (options.action == ACT_FILE) { if (!options.no_psqlrc) process_psqlrc(argv[0]); successResult = process_file(options.action_string, options.single_txn, false); } /* * process slash command if one was given to -c */ else if (options.action == ACT_SINGLE_SLASH) { PsqlScanState scan_state; if (pset.echo == PSQL_ECHO_ALL) puts(options.action_string); scan_state = psql_scan_create(); psql_scan_setup(scan_state, options.action_string, strlen(options.action_string)); successResult = HandleSlashCmds(scan_state, NULL) != PSQL_CMD_ERROR ? EXIT_SUCCESS : EXIT_FAILURE; psql_scan_destroy(scan_state); } /* * If the query given to -c was a normal one, send it */ else if (options.action == ACT_SINGLE_QUERY) { if (pset.echo == PSQL_ECHO_ALL) puts(options.action_string); successResult = SendQuery(options.action_string) ? EXIT_SUCCESS : EXIT_FAILURE; } /* * or otherwise enter interactive main loop */ else { if (!options.no_psqlrc) process_psqlrc(argv[0]); connection_warnings(true); if (!pset.quiet) printf(_("Type \"help\" for help.\n\n")); initializeInput(options.no_readline ? 0 : 1); successResult = MainLoop(stdin); } /* clean up */ if (pset.logfile) fclose(pset.logfile); PQfinish(pset.db); setQFout(NULL); return successResult; }
/* * Main processing loop for reading lines of input * and sending them to the backend. * * This loop is re-entrant. May be called by \i command * which reads input from a file. */ int MainLoop(FILE *source) { PsqlScanState scan_state; /* lexer working state */ ConditionalStack cond_stack; /* \if status stack */ volatile PQExpBuffer query_buf; /* buffer for query being accumulated */ volatile PQExpBuffer previous_buf; /* if there isn't anything in the new * buffer yet, use this one for \e, * etc. */ PQExpBuffer history_buf; /* earlier lines of a multi-line command, not * yet saved to readline history */ char *line; /* current line of input */ int added_nl_pos; bool success; bool line_saved_in_history; volatile int successResult = EXIT_SUCCESS; volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN; volatile promptStatus_t prompt_status = PROMPT_READY; volatile int count_eof = 0; volatile bool die_on_error = false; FILE *prev_cmd_source; bool prev_cmd_interactive; uint64 prev_lineno; /* Save the prior command source */ prev_cmd_source = pset.cur_cmd_source; prev_cmd_interactive = pset.cur_cmd_interactive; prev_lineno = pset.lineno; /* pset.stmt_lineno does not need to be saved and restored */ /* Establish new source */ pset.cur_cmd_source = source; pset.cur_cmd_interactive = ((source == stdin) && !pset.notty); pset.lineno = 0; pset.stmt_lineno = 1; /* Create working state */ scan_state = psql_scan_create(&psqlscan_callbacks); cond_stack = conditional_stack_create(); psql_scan_set_passthrough(scan_state, (void *) cond_stack); query_buf = createPQExpBuffer(); previous_buf = createPQExpBuffer(); history_buf = createPQExpBuffer(); if (PQExpBufferBroken(query_buf) || PQExpBufferBroken(previous_buf) || PQExpBufferBroken(history_buf)) { psql_error("out of memory\n"); exit(EXIT_FAILURE); } /* main loop to get queries and execute them */ while (successResult == EXIT_SUCCESS) { /* * Clean up after a previous Control-C */ if (cancel_pressed) { if (!pset.cur_cmd_interactive) { /* * You get here if you stopped a script with Ctrl-C. */ successResult = EXIT_USER; break; } cancel_pressed = false; } /* * Establish longjmp destination for exiting from wait-for-input. We * must re-do this each time through the loop for safety, since the * jmpbuf might get changed during command execution. */ if (sigsetjmp(sigint_interrupt_jmp, 1) != 0) { /* got here with longjmp */ /* reset parsing state */ psql_scan_finish(scan_state); psql_scan_reset(scan_state); resetPQExpBuffer(query_buf); resetPQExpBuffer(history_buf); count_eof = 0; slashCmdStatus = PSQL_CMD_UNKNOWN; prompt_status = PROMPT_READY; pset.stmt_lineno = 1; cancel_pressed = false; if (pset.cur_cmd_interactive) { putc('\n', stdout); /* * if interactive user is in an \if block, then Ctrl-C will * exit from the innermost \if. */ if (!conditional_stack_empty(cond_stack)) { psql_error("\\if: escaped\n"); conditional_stack_pop(cond_stack); } } else { successResult = EXIT_USER; break; } } fflush(stdout); /* * get another line */ if (pset.cur_cmd_interactive) { /* May need to reset prompt, eg after \r command */ if (query_buf->len == 0) prompt_status = PROMPT_READY; line = gets_interactive(get_prompt(prompt_status, cond_stack), query_buf); } else { line = gets_fromFile(source); if (!line && ferror(source)) successResult = EXIT_FAILURE; } /* * query_buf holds query already accumulated. line is the malloc'd * new line of input (note it must be freed before looping around!) */ /* No more input. Time to quit, or \i done */ if (line == NULL) { if (pset.cur_cmd_interactive) { /* This tries to mimic bash's IGNOREEOF feature. */ count_eof++; if (count_eof < pset.ignoreeof) { if (!pset.quiet) printf(_("Use \"\\q\" to leave %s.\n"), pset.progname); continue; } puts(pset.quiet ? "" : "\\q"); } break; } count_eof = 0; pset.lineno++; /* ignore UTF-8 Unicode byte-order mark */ if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0) memmove(line, line + 3, strlen(line + 3) + 1); /* Detect attempts to run custom-format dumps as SQL scripts */ if (pset.lineno == 1 && !pset.cur_cmd_interactive && strncmp(line, "PGDMP", 5) == 0) { free(line); puts(_("The input is a PostgreSQL custom-format dump.\n" "Use the pg_restore command-line client to restore this dump to a database.\n")); fflush(stdout); successResult = EXIT_FAILURE; break; } /* no further processing of empty lines, unless within a literal */ if (line[0] == '\0' && !psql_scan_in_quote(scan_state)) { free(line); continue; } /* A request for help? Be friendly and give them some guidance */ if (pset.cur_cmd_interactive && query_buf->len == 0 && pg_strncasecmp(line, "help", 4) == 0 && (line[4] == '\0' || line[4] == ';' || isspace((unsigned char) line[4]))) { free(line); puts(_("You are using psql, the command-line interface to PostgreSQL.")); printf(_("Type: \\copyright for distribution terms\n" " \\h for help with SQL commands\n" " \\? for help with psql commands\n" " \\g or terminate with semicolon to execute query\n" " \\q to quit\n")); fflush(stdout); continue; } /* echo back if flag is set, unless interactive */ if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive) { puts(line); fflush(stdout); } /* insert newlines into query buffer between source lines */ if (query_buf->len > 0) { appendPQExpBufferChar(query_buf, '\n'); added_nl_pos = query_buf->len; } else added_nl_pos = -1; /* flag we didn't add one */ /* Setting this will not have effect until next line. */ die_on_error = pset.on_error_stop; /* * Parse line, looking for command separators. */ psql_scan_setup(scan_state, line, strlen(line), pset.encoding, standard_strings()); success = true; line_saved_in_history = false; while (success || !die_on_error) { PsqlScanResult scan_result; promptStatus_t prompt_tmp = prompt_status; size_t pos_in_query; char *tmp_line; pos_in_query = query_buf->len; scan_result = psql_scan(scan_state, query_buf, &prompt_tmp); prompt_status = prompt_tmp; if (PQExpBufferBroken(query_buf)) { psql_error("out of memory\n"); exit(EXIT_FAILURE); } /* * Increase statement line number counter for each linebreak added * to the query buffer by the last psql_scan() call. There only * will be ones to add when navigating to a statement in * readline's history containing newlines. */ tmp_line = query_buf->data + pos_in_query; while (*tmp_line != '\0') { if (*(tmp_line++) == '\n') pset.stmt_lineno++; } if (scan_result == PSCAN_EOL) pset.stmt_lineno++; /* * Send command if semicolon found, or if end of line and we're in * single-line mode. */ if (scan_result == PSCAN_SEMICOLON || (scan_result == PSCAN_EOL && pset.singleline)) { /* * Save line in history. We use history_buf to accumulate * multi-line queries into a single history entry. Note that * history accumulation works on input lines, so it doesn't * matter whether the query will be ignored due to \if. */ if (pset.cur_cmd_interactive && !line_saved_in_history) { pg_append_history(line, history_buf); pg_send_history(history_buf); line_saved_in_history = true; } /* execute query unless we're in an inactive \if branch */ if (conditional_active(cond_stack)) { success = SendQuery(query_buf->data); slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR; pset.stmt_lineno = 1; /* transfer query to previous_buf by pointer-swapping */ { PQExpBuffer swap_buf = previous_buf; previous_buf = query_buf; query_buf = swap_buf; } resetPQExpBuffer(query_buf); added_nl_pos = -1; /* we need not do psql_scan_reset() here */ } else { /* if interactive, warn about non-executed query */ if (pset.cur_cmd_interactive) psql_error("query ignored; use \\endif or Ctrl-C to exit current \\if block\n"); /* fake an OK result for purposes of loop checks */ success = true; slashCmdStatus = PSQL_CMD_SEND; pset.stmt_lineno = 1; /* note that query_buf doesn't change state */ } } else if (scan_result == PSCAN_BACKSLASH) { /* handle backslash command */ /* * If we added a newline to query_buf, and nothing else has * been inserted in query_buf by the lexer, then strip off the * newline again. This avoids any change to query_buf when a * line contains only a backslash command. Also, in this * situation we force out any previous lines as a separate * history entry; we don't want SQL and backslash commands * intermixed in history if at all possible. */ if (query_buf->len == added_nl_pos) { query_buf->data[--query_buf->len] = '\0'; pg_send_history(history_buf); } added_nl_pos = -1; /* save backslash command in history */ if (pset.cur_cmd_interactive && !line_saved_in_history) { pg_append_history(line, history_buf); pg_send_history(history_buf); line_saved_in_history = true; } /* execute backslash command */ slashCmdStatus = HandleSlashCmds(scan_state, cond_stack, query_buf, previous_buf); success = slashCmdStatus != PSQL_CMD_ERROR; /* * Resetting stmt_lineno after a backslash command isn't * always appropriate, but it's what we've done historically * and there have been few complaints. */ pset.stmt_lineno = 1; if (slashCmdStatus == PSQL_CMD_SEND) { /* should not see this in inactive branch */ Assert(conditional_active(cond_stack)); success = SendQuery(query_buf->data); /* transfer query to previous_buf by pointer-swapping */ { PQExpBuffer swap_buf = previous_buf; previous_buf = query_buf; query_buf = swap_buf; } resetPQExpBuffer(query_buf); /* flush any paren nesting info after forced send */ psql_scan_reset(scan_state); } else if (slashCmdStatus == PSQL_CMD_NEWEDIT) { /* should not see this in inactive branch */ Assert(conditional_active(cond_stack)); /* rescan query_buf as new input */ psql_scan_finish(scan_state); free(line); line = pg_strdup(query_buf->data); resetPQExpBuffer(query_buf); /* reset parsing state since we are rescanning whole line */ psql_scan_reset(scan_state); psql_scan_setup(scan_state, line, strlen(line), pset.encoding, standard_strings()); line_saved_in_history = false; prompt_status = PROMPT_READY; } else if (slashCmdStatus == PSQL_CMD_TERMINATE) break; } /* fall out of loop if lexer reached EOL */ if (scan_result == PSCAN_INCOMPLETE || scan_result == PSCAN_EOL) break; } /* Add line to pending history if we didn't execute anything yet */ if (pset.cur_cmd_interactive && !line_saved_in_history) pg_append_history(line, history_buf); psql_scan_finish(scan_state); free(line); if (slashCmdStatus == PSQL_CMD_TERMINATE) { successResult = EXIT_SUCCESS; break; } if (!pset.cur_cmd_interactive) { if (!success && die_on_error) successResult = EXIT_USER; /* Have we lost the db connection? */ else if (!pset.db) successResult = EXIT_BADCONN; } } /* while !endoffile/session */ /* * If we have a non-semicolon-terminated query at the end of file, we * process it unless the input source is interactive --- in that case it * seems better to go ahead and quit. Also skip if this is an error exit. */ if (query_buf->len > 0 && !pset.cur_cmd_interactive && successResult == EXIT_SUCCESS) { /* save query in history */ /* currently unneeded since we don't use this block if interactive */ #ifdef NOT_USED if (pset.cur_cmd_interactive) pg_send_history(history_buf); #endif /* execute query unless we're in an inactive \if branch */ if (conditional_active(cond_stack)) { success = SendQuery(query_buf->data); } else { if (pset.cur_cmd_interactive) psql_error("query ignored; use \\endif or Ctrl-C to exit current \\if block\n"); success = true; } if (!success && die_on_error) successResult = EXIT_USER; else if (pset.db == NULL) successResult = EXIT_BADCONN; } /* * Check for unbalanced \if-\endifs unless user explicitly quit, or the * script is erroring out */ if (slashCmdStatus != PSQL_CMD_TERMINATE && successResult != EXIT_USER && !conditional_stack_empty(cond_stack)) { psql_error("reached EOF without finding closing \\endif(s)\n"); if (die_on_error && !pset.cur_cmd_interactive) successResult = EXIT_USER; } /* * Let's just make real sure the SIGINT handler won't try to use * sigint_interrupt_jmp after we exit this routine. If there is an outer * MainLoop instance, it will reset sigint_interrupt_jmp to point to * itself at the top of its loop, before any further interactive input * happens. */ sigint_interrupt_enabled = false; destroyPQExpBuffer(query_buf); destroyPQExpBuffer(previous_buf); destroyPQExpBuffer(history_buf); psql_scan_destroy(scan_state); conditional_stack_destroy(cond_stack); pset.cur_cmd_source = prev_cmd_source; pset.cur_cmd_interactive = prev_cmd_interactive; pset.lineno = prev_lineno; return successResult; } /* MainLoop() */