#include "sd-daemon.h"
#include "alloc-util.h"
+#include "build.h"
#include "conf-parser.h"
+#include "daemon-util.h"
#include "def.h"
+#include "env-file.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
#include "glob-util.h"
#include "journal-upload.h"
#include "log.h"
+#include "main-func.h"
#include "mkdir.h"
#include "parse-util.h"
+#include "pretty-print.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "sigbus.h"
#include "signal-util.h"
#include "string-util.h"
-#include "terminal-util.h"
+#include "strv.h"
+#include "tmpfile-util.h"
#include "util.h"
#define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-upload.pem"
if (nmemb && !u->answer) {
u->answer = strndup(buf, size*nmemb);
if (!u->answer)
- log_warning_errno(ENOMEM, "Failed to store server answer (%zu bytes): %m",
- size*nmemb);
+ log_warning("Failed to store server answer (%zu bytes): out of memory", size*nmemb);
}
return size * nmemb;
if (!u->state_file)
return 0;
- r = parse_env_file(NULL, u->state_file, NEWLINE,
- "LAST_CURSOR", &u->last_cursor,
- NULL);
-
+ r = parse_env_file(NULL, u->state_file, "LAST_CURSOR", &u->last_cursor);
if (r == -ENOENT)
log_debug("State file %s is not present.", u->state_file);
else if (r < 0)
CURL *curl;
curl = curl_easy_init();
- if (!curl) {
- log_error("Call to curl_easy_init failed.");
- return -ENOSR;
- }
+ if (!curl)
+ return log_error_errno(SYNTHETIC_ERRNO(ENOSR),
+ "Call to curl_easy_init failed.");
/* tell it to POST to the URL */
easy_setopt(curl, CURLOPT_POST, 1L,
easy_setopt(curl, CURLOPT_VERBOSE, 1L, LOG_WARNING, );
easy_setopt(curl, CURLOPT_USERAGENT,
- "systemd-journal-upload " PACKAGE_STRING,
+ "systemd-journal-upload " GIT_VERSION,
LOG_WARNING, );
if (arg_key || startswith(u->url, "https://")) {
/* upload to this place */
code = curl_easy_setopt(u->easy, CURLOPT_URL, u->url);
- if (code) {
- log_error("curl_easy_setopt CURLOPT_URL failed: %s",
- curl_easy_strerror(code));
- return -EXFULL;
- }
+ if (code)
+ return log_error_errno(SYNTHETIC_ERRNO(EXFULL),
+ "curl_easy_setopt CURLOPT_URL failed: %s",
+ curl_easy_strerror(code));
u->uploading = true;
assert(u);
assert(url);
- memzero(u, sizeof(Uploader));
- u->input = -1;
+ *u = (Uploader) {
+ .input = -1
+ };
- if (!(host = startswith(url, "http://")) && !(host = startswith(url, "https://"))) {
+ host = STARTSWITH_SET(url, "http://", "https://");
+ if (!host) {
host = url;
proto = "https://";
}
}
code = curl_easy_getinfo(u->easy, CURLINFO_RESPONSE_CODE, &status);
- if (code) {
- log_error("Failed to retrieve response code: %s",
- curl_easy_strerror(code));
- return -EUCLEAN;
- }
-
- if (status >= 300) {
- log_error("Upload to %s failed with code %ld: %s",
- u->url, status, strna(u->answer));
- return -EIO;
- } else if (status < 200) {
- log_error("Upload to %s finished with unexpected code %ld: %s",
- u->url, status, strna(u->answer));
- return -EIO;
- } else
+ if (code)
+ return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN),
+ "Failed to retrieve response code: %s",
+ curl_easy_strerror(code));
+
+ if (status >= 300)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO),
+ "Upload to %s failed with code %ld: %s",
+ u->url, status, strna(u->answer));
+ else if (status < 200)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO),
+ "Upload to %s finished with unexpected code %ld: %s",
+ u->url, status, strna(u->answer));
+ else
log_debug("Upload finished successfully with code %ld: %s",
status, strna(u->answer));
return version();
case 'u':
- if (arg_url) {
- log_error("cannot use more than one --url");
- return -EINVAL;
- }
+ if (arg_url)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "cannot use more than one --url");
arg_url = optarg;
break;
case ARG_KEY:
- if (arg_key) {
- log_error("cannot use more than one --key");
- return -EINVAL;
- }
+ if (arg_key)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "cannot use more than one --key");
arg_key = optarg;
break;
case ARG_CERT:
- if (arg_cert) {
- log_error("cannot use more than one --cert");
- return -EINVAL;
- }
+ if (arg_cert)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "cannot use more than one --cert");
arg_cert = optarg;
break;
case ARG_TRUST:
- if (arg_trust) {
- log_error("cannot use more than one --trust");
- return -EINVAL;
- }
+ if (arg_trust)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "cannot use more than one --trust");
arg_trust = optarg;
break;
break;
case 'M':
- if (arg_machine) {
- log_error("cannot use more than one --machine/-M");
- return -EINVAL;
- }
+ if (arg_machine)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "cannot use more than one --machine/-M");
arg_machine = optarg;
break;
case 'D':
- if (arg_directory) {
- log_error("cannot use more than one --directory/-D");
- return -EINVAL;
- }
+ if (arg_directory)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "cannot use more than one --directory/-D");
arg_directory = optarg;
break;
break;
case ARG_CURSOR:
- if (arg_cursor) {
- log_error("cannot use more than one --cursor/--after-cursor");
- return -EINVAL;
- }
+ if (arg_cursor)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "cannot use more than one --cursor/--after-cursor");
arg_cursor = optarg;
break;
case ARG_AFTER_CURSOR:
- if (arg_cursor) {
- log_error("cannot use more than one --cursor/--after-cursor");
- return -EINVAL;
- }
+ if (arg_cursor)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "cannot use more than one --cursor/--after-cursor");
arg_cursor = optarg;
arg_after_cursor = true;
case ARG_FOLLOW:
if (optarg) {
r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --follow= parameter.");
- return -EINVAL;
- }
+ if (r < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to parse --follow= parameter.");
arg_follow = !!r;
} else
break;
case '?':
- log_error("Unknown option %s.", argv[optind-1]);
- return -EINVAL;
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Unknown option %s.",
+ argv[optind - 1]);
case ':':
- log_error("Missing argument to %s.", argv[optind-1]);
- return -EINVAL;
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Missing argument to %s.",
+ argv[optind - 1]);
default:
assert_not_reached("Unhandled option code.");
}
- if (!arg_url) {
- log_error("Required --url/-u option missing.");
- return -EINVAL;
- }
+ if (!arg_url)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Required --url/-u option missing.");
- if (!!arg_key != !!arg_cert) {
- log_error("Options --key and --cert must be used together.");
- return -EINVAL;
- }
+ if (!!arg_key != !!arg_cert)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Options --key and --cert must be used together.");
- if (optind < argc && (arg_directory || arg_file || arg_machine || arg_journal_type)) {
- log_error("Input arguments make no sense with journal input.");
- return -EINVAL;
- }
+ if (optind < argc && (arg_directory || arg_file || arg_machine || arg_journal_type))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Input arguments make no sense with journal input.");
return 1;
}
return r;
}
-int main(int argc, char **argv) {
- Uploader u;
- int r;
+static int run(int argc, char **argv) {
+ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
+ _cleanup_(destroy_uploader) Uploader u = {};
bool use_journal;
+ int r;
log_show_color(true);
log_parse_environment();
+ /* The journal merging logic potentially needs a lot of fds. */
+ (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
+
r = parse_config();
if (r < 0)
- goto finish;
+ return r;
r = parse_argv(argc, argv);
if (r <= 0)
- goto finish;
+ return r;
sigbus_install();
r = setup_uploader(&u, arg_url, arg_save_state);
if (r < 0)
- goto cleanup;
+ return r;
sd_event_set_watchdog(u.events, true);
r = check_cursor_updating(&u);
if (r < 0)
- goto cleanup;
+ return r;
log_debug("%s running as pid "PID_FMT,
program_invocation_short_name, getpid_cached());
sd_journal *j;
r = open_journal(&j);
if (r < 0)
- goto finish;
+ return r;
r = open_journal_for_upload(&u, j,
arg_cursor ?: u.last_cursor,
arg_cursor ? arg_after_cursor : true,
!!arg_follow);
if (r < 0)
- goto finish;
+ return r;
}
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing input...");
+ notify_message = notify_start("READY=1\n"
+ "STATUS=Processing input...",
+ NOTIFY_STOPPING);
for (;;) {
r = sd_event_get_state(u.events);
if (r < 0)
- break;
+ return r;
if (r == SD_EVENT_FINISHED)
- break;
+ return 0;
if (use_journal) {
if (!u.journal)
- break;
+ return 0;
r = check_journal_input(&u);
} else if (u.input < 0 && !use_journal) {
if (optind >= argc)
- break;
+ return 0;
log_debug("Using %s as input.", argv[optind]);
r = open_file_for_upload(&u, argv[optind++]);
}
if (r < 0)
- goto cleanup;
+ return r;
if (u.uploading) {
r = perform_upload(&u);
if (r < 0)
- break;
+ return r;
}
r = sd_event_run(u.events, u.timeout);
- if (r < 0) {
- log_error_errno(r, "Failed to run event loop: %m");
- break;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to run event loop: %m");
}
-
-cleanup:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
-
- destroy_uploader(&u);
-
-finish:
- return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
+
+DEFINE_MAIN_FUNCTION(run);