Compare commits

..

3 Commits

Author SHA1 Message Date
b002e6237b refactor: rename argument to avoid C++ keyword conflict
Some checks failed
CI / Check coding style (pull_request) Successful in 31s
CI / Check spelling (pull_request) Successful in 18s
CI / Linux (fedora) (pull_request) Failing after 2m57s
CI / Linux (ubuntu) (pull_request) Successful in 13m49s
CI / Linux (debian) (pull_request) Successful in 13m46s
CI / Linux (arch) (pull_request) Successful in 16m59s
The parameter `template` in format_call_external_argv() was renamed
to `template_fmt` to avoid collision with the `template` keyword in
C++. This improves compatibility when the header is included in
C++ code.
2025-07-19 18:32:33 +00:00
30504faf54 fix: add missing parameter types to function declarations
Some functions were declared without parameters in header files,
despite their implementations specifying arguments. This mismatch
is deprecated in all versions of C and is disallowed in C23.

This change updates the declarations to match their definitions,
ensuring compatibility with C standards, avoiding potential
undefined behavior, and improving support in tools and editors.
2025-07-19 18:32:33 +00:00
6e84db20d4 build: add missing includes to header files
This change adds necessary `#include` directives that were previously
omitted in some header files. Without these includes, compilation
could fail or produce undefined behavior when the headers are used
in isolation (i.e., before their dependencies are included elsewhere).

Ensures better modularity and reliability of header usage.
2025-07-19 18:32:33 +00:00
17 changed files with 80 additions and 260 deletions

View File

@@ -9527,7 +9527,16 @@ cmd_change_password(ProfWin* window, const char* const command, gchar** args)
gboolean
cmd_editor(ProfWin* window, const char* const command, gchar** args)
{
get_message_from_editor_async(NULL);
auto_gchar gchar* message = NULL;
if (get_message_from_editor(NULL, &message)) {
return TRUE;
}
rl_insert_text(message);
ui_resize();
rl_point = rl_end;
rl_forced_update_display();
return TRUE;
}

View File

@@ -655,17 +655,17 @@ call_external(gchar** argv)
*
* This function constructs an argument vector (argv) based on the provided template string, replacing placeholders ("%u" and "%p") with the provided URL and filename, respectively.
*
* @param template The template string with placeholders.
* @param url The URL to replace "%u" (or NULL to skip).
* @param filename The filename to replace "%p" (or NULL to skip).
* @return The constructed argument vector (argv) as a null-terminated array of strings.
* @param template_fmt The template string with placeholders.
* @param url The URL to replace "%u" (or NULL to skip).
* @param filename The filename to replace "%p" (or NULL to skip).
* @return The constructed argument vector (argv) as a null-terminated array of strings.
*
* @note Remember to free the returned argument vector using `auto_gcharv` or `g_strfreev()`.
*/
gchar**
format_call_external_argv(const char* template, const char* url, const char* filename)
format_call_external_argv(const char* template_fmt, const char* url, const char* filename)
{
gchar** argv = g_strsplit(template, " ", 0);
gchar** argv = g_strsplit(template_fmt, " ", 0);
guint num_args = 0;
while (argv[num_args]) {
@@ -674,7 +674,7 @@ format_call_external_argv(const char* template, const char* url, const char* fil
argv[num_args] = g_strdup(url);
} else if (0 == g_strcmp0(argv[num_args], "%p") && filename != NULL) {
g_free(argv[num_args]);
argv[num_args] = strdup(filename);
argv[num_args] = g_strdup(filename);
}
num_args++;
}

View File

@@ -171,8 +171,6 @@ typedef enum {
RESOURCE_XA
} resource_presence_t;
extern gboolean background_mode;
gboolean string_to_verbosity(const char* cmd, int* verbosity, gchar** err_msg);
gboolean create_dir(const char* name);
@@ -198,7 +196,7 @@ void get_file_paths_recursive(const char* directory, GSList** contents);
char* get_random_string(int length);
gboolean call_external(gchar** argv);
gchar** format_call_external_argv(const char* template, const char* url, const char* filename);
gchar** format_call_external_argv(const char* template_fmt, const char* url, const char* filename);
gchar* unique_filename_from_url(const char* url, const char* path);
gchar* get_expanded_path(const char* path);

View File

@@ -36,6 +36,8 @@
#ifndef EVENT_COMMON_H
#define EVENT_COMMON_H
#include "glib.h"
void ev_disconnect_cleanup(void);
void ev_inc_connection_counter(void);
void ev_reset_connection_counter(void);

View File

@@ -36,6 +36,8 @@
#ifndef PGP_GPG_H
#define PGP_GPG_H
#include "glib.h"
typedef struct pgp_key_t
{
char* id;

View File

@@ -59,7 +59,6 @@
#include "config/tlscerts.h"
#include "config/scripts.h"
#include "command/cmd_defs.h"
#include "tools/editor.h"
#include "plugins/plugins.h"
#include "event/client_events.h"
#include "ui/ui.h"
@@ -94,9 +93,6 @@ static void _connect_default(const char* const account);
pthread_mutex_t lock;
static gboolean force_quit = FALSE;
// main.c (prof_run section)
gboolean background_mode = FALSE;
void
prof_run(gchar* log_level, gchar* account_name, gchar* config_file, gchar* log_file, gchar* theme_name, gchar** commands)
{
@@ -122,44 +118,42 @@ prof_run(gchar* log_level, gchar* account_name, gchar* config_file, gchar* log_f
log_stderr_handler();
session_check_autoaway();
if (!background_mode) {
line = commands ? *commands : inp_readline();
if (commands && line && memcmp(line, "/sleep", 6) == 0) {
if (!g_timer_is_active(waittimer)) {
gchar* err_msg;
if (strtoi_range(line + 7, &waittime, 0, 300, &err_msg)) {
g_timer_start(waittimer);
/* Increase the minimal runtime by the waiting time
* so we can be sure there's runtime left after executing
* the last command.
*/
min_runtime += waittime;
} else {
log_error(err_msg);
g_free(err_msg);
commands = NULL;
}
} else if (g_timer_elapsed(waittimer, NULL) >= waittime) {
g_timer_stop(waittimer);
commands++;
if (!(*commands))
commands = NULL;
}
cont = TRUE;
} else if (line) {
ProfWin* window = wins_get_current();
cont = cmd_process_input(window, line);
if (commands) {
commands++;
if (!(*commands))
commands = NULL;
line = commands ? *commands : inp_readline();
if (commands && line && memcmp(line, "/sleep", 6) == 0) {
if (!g_timer_is_active(waittimer)) {
gchar* err_msg;
if (strtoi_range(line + 7, &waittime, 0, 300, &err_msg)) {
g_timer_start(waittimer);
/* Increase the minimal runtime by the waiting time
* so we can be sure there's runtime left after executing
* the last command.
*/
min_runtime += waittime;
} else {
free(line);
line = NULL;
log_error(err_msg);
g_free(err_msg);
commands = NULL;
}
} else {
cont = TRUE;
} else if (g_timer_elapsed(waittimer, NULL) >= waittime) {
g_timer_stop(waittimer);
commands++;
if (!(*commands))
commands = NULL;
}
cont = TRUE;
} else if (line) {
ProfWin* window = wins_get_current();
cont = cmd_process_input(window, line);
if (commands) {
commands++;
if (!(*commands))
commands = NULL;
} else {
free(line);
line = NULL;
}
} else {
cont = TRUE;
}
#ifdef HAVE_LIBOTR
@@ -169,12 +163,7 @@ prof_run(gchar* log_level, gchar* account_name, gchar* config_file, gchar* log_f
notify_remind();
session_process_events();
iq_autoping_check();
editor_process(wins_get_current());
if (!background_mode) {
ui_update();
}
ui_update();
#ifdef HAVE_GTK
tray_update();
#endif

View File

@@ -36,7 +36,9 @@
#ifndef BOOKMARK_IGNORE_H
#define BOOKMARK_IGNORE_H
void bookmark_ignore_on_connect();
#include "xmpp/xmpp.h"
void bookmark_ignore_on_connect(const char* const barejid);
void bookmark_ignore_on_disconnect();
gboolean bookmark_ignored(Bookmark* bookmark);
gchar** bookmark_ignore_list(gsize* len);

View File

@@ -38,200 +38,15 @@
#include <fcntl.h>
#include <glib.h>
#include <errno.h>
#include <stdio.h> // necessary for readline
#include <readline/readline.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pthread.h>
#include "config/files.h"
#include "config/preferences.h"
#include "editor.h"
#include "log.h"
#include "common.h"
#include "ncurses.h"
#include "ui/ui.h"
#include "xmpp/xmpp.h"
EditorTask editor_task = { 0, FALSE, NULL, NULL, PTHREAD_MUTEX_INITIALIZER, 0, NULL, NULL };
void*
editor_thread(void* arg)
{
EditorTask* task = (EditorTask*)arg;
auto_gcharv gchar** argv = g_strsplit(task->editor_cmd, " ", 0);
pid_t pid = fork();
if (pid == 0) {
execvp(argv[0], argv);
log_error("[Editor] Failed to exec %s", argv[0]);
_exit(EXIT_FAILURE);
}
pthread_mutex_lock(&task->mutex);
if (pid > 0) {
task->pid = pid;
int status;
// Unlock mutex to avoid deadlock on the main loop
pthread_mutex_unlock(&task->mutex);
waitpid(pid, &status, 0);
pthread_mutex_lock(&task->mutex);
gsize length;
if (!g_file_get_contents(task->filename, &task->result, &length, &task->error)) {
log_error("[Editor] could not read from %s: %s", task->filename,
task->error ? task->error->message : "No GLib error given");
task->result = g_strdup(""); // Ensure valid result
} else {
g_strchomp(task->result);
if (remove(task->filename) != 0) {
log_error("[Editor] error during file deletion of %s", task->filename);
} else {
log_debug("[Editor] deleted file: %s", task->filename);
}
}
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
task->error = g_error_new(G_FILE_ERROR, G_FILE_ERROR_FAILED,
"Editor process failed with status %d", WEXITSTATUS(status));
}
} else {
task->error = g_error_new(G_FILE_ERROR, G_FILE_ERROR_FAILED, "Fork failed: %s", strerror(errno));
task->result = g_strdup(""); // Ensure valid result
}
task->active = FALSE;
pthread_mutex_unlock(&task->mutex);
return NULL;
}
// Returns true if an error occurred
gboolean
get_message_from_editor_async(gchar* message)
{
// Check if editor is already running
pthread_mutex_lock(&editor_task.mutex);
if (editor_task.active) {
pthread_mutex_unlock(&editor_task.mutex);
log_error("[Editor] Editor already running");
return TRUE;
}
pthread_mutex_unlock(&editor_task.mutex);
// Create temporary file
auto_gchar gchar* filename = NULL;
GError* glib_error = NULL;
const char* jid = connection_get_barejid();
if (jid) {
filename = files_file_in_account_data_path(DIR_EDITOR, jid, "compose.md");
} else {
log_debug("[Editor] could not get JID");
auto_gchar gchar* data_dir = files_get_data_path(DIR_EDITOR);
if (!create_dir(data_dir)) {
log_error("[Editor] could not create directory %s", data_dir);
return TRUE;
}
filename = g_strdup_printf("%s/compose.md", data_dir);
}
if (!filename) {
log_error("[Editor] something went wrong while creating compose file");
return TRUE;
}
// Write message to file
gsize messagelen = message ? strlen(message) : 0;
if (!g_file_set_contents(filename, message ? message : "", messagelen, &glib_error)) {
log_error("[Editor] could not write to %s: %s", filename,
glib_error ? glib_error->message : "No GLib error given");
if (glib_error) {
g_error_free(glib_error);
}
return TRUE;
}
// Prepare editor command
auto_gchar gchar* editor = prefs_get_string(PREF_COMPOSE_EDITOR);
auto_gchar gchar* editor_with_filename = g_strdup_printf("%s %s", editor, filename);
// Suspend NCurses
def_prog_mode();
endwin();
// Initialize thread task
pthread_mutex_lock(&editor_task.mutex);
editor_task.active = TRUE;
editor_task.result = NULL;
editor_task.error = NULL;
g_free(editor_task.filename);
g_free(editor_task.editor_cmd);
editor_task.filename = g_strdup(filename);
editor_task.editor_cmd = g_strdup(editor_with_filename);
pthread_mutex_unlock(&editor_task.mutex);
// Set background mode
background_mode = TRUE;
log_debug("[Editor] Entering background mode");
// Start editor thread
if (pthread_create(&editor_task.thread, NULL, editor_thread, &editor_task) != 0) {
pthread_mutex_lock(&editor_task.mutex);
editor_task.active = FALSE;
editor_task.error = g_error_new(G_FILE_ERROR, G_FILE_ERROR_FAILED,
"Failed to create editor thread: %s", strerror(errno));
g_free(editor_task.filename);
g_free(editor_task.editor_cmd);
editor_task.filename = NULL;
editor_task.editor_cmd = NULL;
pthread_mutex_unlock(&editor_task.mutex);
background_mode = FALSE;
log_debug("[Editor] Exiting background mode");
reset_prog_mode();
doupdate();
log_error("[Editor] Failed to create editor thread");
return TRUE;
}
return FALSE;
}
void
editor_process(ProfWin* window)
{
pthread_mutex_lock(&editor_task.mutex);
if (editor_task.active) {
pthread_mutex_unlock(&editor_task.mutex);
return;
}
if (!editor_task.result) {
pthread_mutex_unlock(&editor_task.mutex);
return;
}
g_strchomp(editor_task.result);
rl_replace_line(editor_task.result, 0);
rl_point = rl_end;
rl_forced_update_display();
reset_prog_mode();
doupdate();
ui_resize();
g_free(editor_task.result);
g_free(editor_task.filename);
g_free(editor_task.editor_cmd);
editor_task.result = NULL;
editor_task.filename = NULL;
editor_task.editor_cmd = NULL;
if (editor_task.error) {
log_error("[Editor] %s", editor_task.error->message);
g_error_free(editor_task.error);
editor_task.error = NULL;
}
pthread_mutex_unlock(&editor_task.mutex);
background_mode = FALSE;
log_debug("[Editor] Exiting background mode");
}
// Deprecated synchronous editor call. Returns a message as returned_message.
// Please avoid using it, since it blocks execution of the message handling and other important functionality until the editor is closed.
// Returns true if an error occurred
gboolean
get_message_from_editor(gchar* message, gchar** returned_message)

View File

@@ -37,24 +37,8 @@
#ifndef TOOLS_EDITOR_H
#define TOOLS_EDITOR_H
#include "ui/win_types.h"
#include <glib.h>
typedef struct
{
pid_t pid; // Editor process PID
gboolean active; // Thread running
gchar* result; // Edited message
GError* error; // Error if any
pthread_mutex_t mutex; // Protect access
pthread_t thread; // Editor thread
gchar* filename; // Temporary file path
gchar* editor_cmd; // Editor command with filename
} EditorTask;
extern EditorTask editor_task;
gboolean get_message_from_editor(gchar* message, gchar** returned_message);
gboolean get_message_from_editor_async(gchar* message);
void editor_process(ProfWin* window);
#endif

View File

@@ -974,7 +974,14 @@ _inp_rl_send_to_editor(int count, int key)
auto_gchar gchar* message = NULL;
get_message_from_editor_async(rl_line_buffer);
if (get_message_from_editor(rl_line_buffer, &message)) {
return 0;
}
rl_replace_line(message, 0);
ui_resize();
rl_point = rl_end;
rl_forced_update_display();
return 0;
}

View File

@@ -36,6 +36,8 @@
#ifndef UI_TITLEBAR_H
#define UI_TITLEBAR_H
#include "glib.h"
void create_title_bar(void);
void free_title_bar(void);
void title_bar_update_virtual(void);

View File

@@ -289,7 +289,7 @@ void cons_show_disco_info(const char* from, GSList* identities, GSList* features
void cons_show_disco_contact_information(GHashTable* addresses);
void cons_show_qrcode();
void cons_show_qrcode(const char* const text);
void cons_show_room_invite(const char* const invitor, const char* const room, const char* const reason);
void cons_check_version(gboolean not_available_msg);

View File

@@ -36,6 +36,8 @@
#ifndef XMPP_BLOCKING_H
#define XMPP_BLOCKING_H
#include <strophe.h>
void blocking_request(void);
int blocked_set_handler(xmpp_stanza_t* stanza);

View File

@@ -36,6 +36,8 @@
#ifndef XMPP_IQ_H
#define XMPP_IQ_H
#include <strophe.h>
typedef int (*ProfIqCallback)(xmpp_stanza_t* const stanza, void* const userdata);
typedef void (*ProfIqFreeCallback)(void* userdata);

View File

@@ -33,6 +33,8 @@
*
*/
#include "glib.h"
/*!
* \page OX OX Implementation
*

View File

@@ -36,6 +36,9 @@
#ifndef XMPP_ROSTER_H
#define XMPP_ROSTER_H
#include "glib.h"
#include <strophe.h>
void roster_request(void);
void roster_set_handler(xmpp_stanza_t* const stanza);
void roster_result_handler(xmpp_stanza_t* const stanza);

View File

@@ -38,6 +38,7 @@
#include "ui/win_types.h"
#include "xmpp/vcard.h"
#include <strophe.h>
vCard* vcard_new();
void vcard_free(vCard* vcard);