options -a, -d. factoring: parse_args. dependency to argv for many functions removed.
This commit is contained in:
parent
60e1aec248
commit
34e5e6a378
112
coredump.c
112
coredump.c
|
@ -1,3 +1,4 @@
|
||||||
|
// vim: set noet sw=2 ts=2 sts=2:
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -11,8 +12,6 @@
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
typedef struct argv_t {
|
typedef struct argv_t {
|
||||||
char *_self;
|
|
||||||
char *coredir;
|
|
||||||
char *pid; // %p
|
char *pid; // %p
|
||||||
char *global_pid; // %P
|
char *global_pid; // %P
|
||||||
char *tid; // %i
|
char *tid; // %i
|
||||||
|
@ -30,7 +29,8 @@ typedef struct argv_t {
|
||||||
char *cpu; // %C
|
char *cpu; // %C
|
||||||
} argv_t;
|
} argv_t;
|
||||||
|
|
||||||
const char const expected_pattern[] = "|%s <DESTINATION-PATH> %%p %%P %%i %%I %%u %%g %%d %%s %%t %%h %%e %%f %%E %%c %%C";
|
const char const expected_pattern[] = "|%s [-d DESTDIR] [-a EXEPATH] %%p %%P %%i %%I %%u %%g %%d %%s %%t %%h %%e %%f %%E %%c %%C";
|
||||||
|
const unsigned int const expected_argc = 15;
|
||||||
|
|
||||||
typedef char *path_t;
|
typedef char *path_t;
|
||||||
|
|
||||||
|
@ -52,6 +52,8 @@ typedef struct args_t {
|
||||||
path_t exepath;
|
path_t exepath;
|
||||||
size_t max_size;
|
size_t max_size;
|
||||||
uint cpu;
|
uint cpu;
|
||||||
|
path_t after;
|
||||||
|
char corefile[1024];
|
||||||
} args_t;
|
} args_t;
|
||||||
// if max_size is 0 or bigger than MAX_SIZE, then MAX_SIZE (1GiB):
|
// if max_size is 0 or bigger than MAX_SIZE, then MAX_SIZE (1GiB):
|
||||||
#define MAX_SIZE 1073741824
|
#define MAX_SIZE 1073741824
|
||||||
|
@ -82,7 +84,6 @@ int prsint( long unsigned int *dst, char *src) {
|
||||||
|
|
||||||
int argv2args( argv_t *v, args_t *s) {
|
int argv2args( argv_t *v, args_t *s) {
|
||||||
long unsigned int b;
|
long unsigned int b;
|
||||||
TOSTR( coredir);
|
|
||||||
TOINT( pid);
|
TOINT( pid);
|
||||||
TOINT( global_pid);
|
TOINT( global_pid);
|
||||||
TOINT( tid);
|
TOINT( tid);
|
||||||
|
@ -100,8 +101,8 @@ int argv2args( argv_t *v, args_t *s) {
|
||||||
TOINT( cpu);
|
TOINT( cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
int proc_filename( char *dest, size_t len, argv_t *argv, char* fn) {
|
int proc_filename( char *dest, size_t len, args_t *args, char* fn) {
|
||||||
size_t destl = snprintf( dest, len, "/proc/%s/%s", argv->pid, fn);
|
size_t destl = snprintf( dest, len, "/proc/%i/%s", args->pid, fn);
|
||||||
if( destl < 0) {
|
if( destl < 0) {
|
||||||
fprintf( stderr, "ERROR: gen path for %s: %s (%i)\n", fn, strerror( errno), errno);
|
fprintf( stderr, "ERROR: gen path for %s: %s (%i)\n", fn, strerror( errno), errno);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -113,8 +114,8 @@ int proc_filename( char *dest, size_t len, argv_t *argv, char* fn) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int core_filename( char *dest, size_t len, argv_t *argv, char* ext) {
|
int core_filename( char *dest, size_t len, args_t *args, char* ext) {
|
||||||
size_t destl = snprintf( dest, len, "%s/core%s.%s", argv->coredir, ext, argv->pid);
|
size_t destl = snprintf( dest, len, "%s/core%s.%u", args->coredir, ext, args->pid);
|
||||||
if( destl < 0) {
|
if( destl < 0) {
|
||||||
fprintf( stderr, "ERROR: gen path for core%s: %s (%i)\n", ext, strerror( errno), errno);
|
fprintf( stderr, "ERROR: gen path for core%s: %s (%i)\n", ext, strerror( errno), errno);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -145,25 +146,23 @@ void show_opened_files() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int dump_core( argv_t *argv, args_t *args) {
|
int dump_core( args_t *args) {
|
||||||
// Concept: Once used, not necessary anymore, we cen reuse the space again.
|
// Concept: Once used, not necessary anymore, we cen reuse the space again.
|
||||||
char path[1024]; // For any paths.
|
|
||||||
int rfd; // read file handler.
|
|
||||||
int wfd; // write file handler.
|
int wfd; // write file handler.
|
||||||
struct stat stat; // Needed for determine size of file.
|
struct stat stat; // Needed for determine size of file.
|
||||||
|
|
||||||
// copy stdin -> core.pid
|
// copy stdin -> core.pid
|
||||||
if( core_filename( path, sizeof path, argv, ""))
|
if( core_filename( args->corefile, sizeof args->corefile, args, ""))
|
||||||
return 1;
|
return 1;
|
||||||
if( -1 == (wfd = open( path, O_WRONLY | O_CREAT | O_TRUNC, 0600))) {
|
if( -1 == (wfd = open( args->corefile, O_WRONLY | O_CREAT | O_TRUNC, 0600))) {
|
||||||
fprintf( stderr, "ERROR: Cannot open file %s: %s (%i)\n", path, strerror( errno), errno);
|
fprintf( stderr, "ERROR: Cannot open file %s: %s (%i)\n", args->corefile, strerror( errno), errno);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if( -1 == splice(
|
if( -1 == splice(
|
||||||
STDIN_FILENO, 0,
|
STDIN_FILENO, 0,
|
||||||
wfd, 0,
|
wfd, 0,
|
||||||
(args->max_size || MAX_SIZE < args->max_size) ? args->max_size : MAX_SIZE, 0)) {
|
(args->max_size || MAX_SIZE < args->max_size) ? args->max_size : MAX_SIZE, 0)) {
|
||||||
fprintf( stderr, "ERROR: Cannot write core to file %s: %s (%i)\n", path, strerror( errno), errno);
|
fprintf( stderr, "ERROR: Cannot write core to file %s: %s (%i)\n", args->corefile, strerror( errno), errno);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
close( wfd);
|
close( wfd);
|
||||||
|
@ -185,7 +184,7 @@ int copy_fd_to_fd( int infd, int outfd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int dump_cmdline( argv_t *argv, args_t *args) {
|
int dump_cmdline( args_t *args) {
|
||||||
// Concept: Once used, not necessary anymore, we cen reuse the space again.
|
// Concept: Once used, not necessary anymore, we cen reuse the space again.
|
||||||
char path[1024]; // For any paths.
|
char path[1024]; // For any paths.
|
||||||
int rfd; // read file handler.
|
int rfd; // read file handler.
|
||||||
|
@ -193,7 +192,7 @@ int dump_cmdline( argv_t *argv, args_t *args) {
|
||||||
struct stat stat; // Needed for determine size of file.
|
struct stat stat; // Needed for determine size of file.
|
||||||
|
|
||||||
// copy /proc/pid/cmdline -> core-cmdline.pid
|
// copy /proc/pid/cmdline -> core-cmdline.pid
|
||||||
if( proc_filename( path, sizeof path, argv, "cmdline")) return 1;
|
if( proc_filename( path, sizeof path, args, "cmdline")) return 1;
|
||||||
if( -1 == (rfd = open( path, O_RDONLY, 0644))) {
|
if( -1 == (rfd = open( path, O_RDONLY, 0644))) {
|
||||||
fprintf( stderr, "ERROR: Cannot open file %s: %s (%i)\n", path, strerror( errno), errno);
|
fprintf( stderr, "ERROR: Cannot open file %s: %s (%i)\n", path, strerror( errno), errno);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -202,7 +201,7 @@ int dump_cmdline( argv_t *argv, args_t *args) {
|
||||||
fprintf( stderr, "ERROR: Cannot stat of file %s: %s (%i)\n", path, strerror( errno), errno);
|
fprintf( stderr, "ERROR: Cannot stat of file %s: %s (%i)\n", path, strerror( errno), errno);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if( core_filename( path, sizeof path, argv, "-cmdline")) return 1;
|
if( core_filename( path, sizeof path, args, "-cmdline")) return 1;
|
||||||
if( -1 == (wfd = open( path, O_WRONLY | O_CREAT | O_TRUNC, 0644))) {
|
if( -1 == (wfd = open( path, O_WRONLY | O_CREAT | O_TRUNC, 0644))) {
|
||||||
fprintf( stderr, "ERROR: Cannot open file %s: %s (%i)\n", path, strerror( errno), errno);
|
fprintf( stderr, "ERROR: Cannot open file %s: %s (%i)\n", path, strerror( errno), errno);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -223,13 +222,13 @@ int dump_cmdline( argv_t *argv, args_t *args) {
|
||||||
fprintf( stderr, "ERROR: Cannot write to file %s: %s (%i)\n", path, strerror( errno), errno); \
|
fprintf( stderr, "ERROR: Cannot write to file %s: %s (%i)\n", path, strerror( errno), errno); \
|
||||||
return 1; \
|
return 1; \
|
||||||
}
|
}
|
||||||
int dump_md( argv_t *argv) {
|
int dump_md( argv_t *argv, args_t *args) {
|
||||||
// Concept: Once used, not necessary anymore, we cen reuse the space again.
|
// Concept: Once used, not necessary anymore, we cen reuse the space again.
|
||||||
char path[1024]; // For any paths.
|
char path[1024]; // For any paths.
|
||||||
FILE *wfh;
|
FILE *wfh;
|
||||||
|
|
||||||
// write argv -> core-md.pid
|
// write argv -> core-md.pid
|
||||||
if( core_filename( path, sizeof path, argv, "-md")) return 1;
|
if( core_filename( path, sizeof path, args, "-md")) return 1;
|
||||||
umask( 0133);
|
umask( 0133);
|
||||||
if( NULL == (wfh = fopen( path, "w"))) {
|
if( NULL == (wfh = fopen( path, "w"))) {
|
||||||
fprintf( stderr, "ERROR: Cannot open file %s: %s (%i)\n", path, strerror( errno), errno);
|
fprintf( stderr, "ERROR: Cannot open file %s: %s (%i)\n", path, strerror( errno), errno);
|
||||||
|
@ -255,31 +254,78 @@ int dump_md( argv_t *argv) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main( size_t argc, argv_t *argv) {
|
int usage( args_t *args) {
|
||||||
args_t *args = malloc( sizeof (args_t));
|
fprintf( stderr, "Usage in kernel.core_pattern=\"");
|
||||||
args->_self = realpath( argv->_self, NULL);
|
|
||||||
|
|
||||||
if( (sizeof (argv_t))/(sizeof (char*)) > argc) {
|
|
||||||
fprintf( stderr, "ERROR: %li arguments expected. Exect value of kernel.core_pattern must be: `", (sizeof (argv_t))/(sizeof (char*)));
|
|
||||||
fprintf( stderr, expected_pattern, args->_self);
|
fprintf( stderr, expected_pattern, args->_self);
|
||||||
fprintf( stderr, "`. Given: %li\n", argc-1);
|
fprintf( stderr, "\"\n");
|
||||||
if( '/' != args->_self[0])
|
if( '/' != args->_self[0])
|
||||||
fprintf( stderr, "\tAttention: Absolut path instead of %s should be used!\n", args->_self);
|
fprintf( stderr, "\tAttention: Absolut path instead of %s should be used!\n", args->_self);
|
||||||
return 2;
|
fprintf( stderr, "\n -a EXEPATH\tExecutes EXEPATH after dumping core as child process, before itself exits.\n");
|
||||||
|
fprintf( stderr, "\t\tAs arguments, the path to core-file will be provided.\n");
|
||||||
|
fprintf( stderr, " -d DESTDIR\tDestination directory for core-files and additional files. (default: /var/cores)\n");
|
||||||
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
argv2args( argv, args);
|
void run_after( args_t *args) {
|
||||||
|
if( args->after) {
|
||||||
|
pid_t child = fork();
|
||||||
|
switch( child) {
|
||||||
|
case -1:
|
||||||
|
fprintf( stderr, "ERROR: error while forking: %s (%i)\n", strerror( errno), errno);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
execl( args->after, args->after, args->corefile, NULL);
|
||||||
|
fprintf( stderr, "ERROR: Executing after-program failed: %s (%i)\n", strerror( errno), errno);
|
||||||
|
exit( 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_args( size_t argc, char** _argv, argv_t **argv, args_t *args) {
|
||||||
|
args->after = NULL;
|
||||||
|
args->coredir = "/var/cores";
|
||||||
|
args->_self = realpath( _argv[0], NULL);
|
||||||
|
|
||||||
|
char opt;
|
||||||
|
while( -1 != (opt = getopt( argc, _argv, "hd:a:"))) {
|
||||||
|
switch( opt) {
|
||||||
|
case 'h': usage( args); break;
|
||||||
|
case 'a': args->after = optarg; break;
|
||||||
|
case 'd': args->coredir = optarg; break;
|
||||||
|
default:
|
||||||
|
fprintf( stderr, "ERROR: Unknown option: -%c\n", opt);
|
||||||
|
usage( args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( expected_argc > argc-optind+1) {
|
||||||
|
fprintf( stderr, "ERROR: %u arguments expected. Given: %li\n", expected_argc, argc-optind+1);
|
||||||
|
usage( args);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
*argv = (argv_t*) (_argv + optind);
|
||||||
|
argv2args( *argv, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( size_t argc, char **_argv) {
|
||||||
|
argv_t *argv = malloc( sizeof (argv_t));
|
||||||
|
args_t *args = malloc( sizeof (args_t));
|
||||||
|
parse_args( argc, _argv, &argv, args);
|
||||||
|
|
||||||
//fprintf( stderr, "dump core...\n");
|
//fprintf( stderr, "dump core...\n");
|
||||||
dump_core( argv, args);
|
dump_core( args);
|
||||||
// That's all, core dump written. :)
|
// That's all, core dump written. :)
|
||||||
// But, hold on, now the funny things will follow, which are the differences to a simple core-dump.
|
// But, hold on, now the funny things will follow, which are the differences to a simple core-dump.
|
||||||
|
|
||||||
//fprintf( stderr, "dump cmdline...\n");
|
//fprintf( stderr, "dump cmdline...\n");
|
||||||
dump_cmdline( argv, args);
|
dump_cmdline( args);
|
||||||
//fprintf( stderr, "dump metadata...\n");
|
//fprintf( stderr, "dump metadata...\n");
|
||||||
dump_md( argv);
|
dump_md( argv, args);
|
||||||
//fprintf( stderr, "exit...\n");
|
|
||||||
|
|
||||||
|
//fprintf( stderr, "run after program...\n");
|
||||||
|
run_after( args);
|
||||||
|
|
||||||
|
//fprintf( stderr, "exit...\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue