From cd23e1cfc125684553a165fb83c6993326acdfc6 Mon Sep 17 00:00:00 2001 From: jonathan santis Date: Mon, 12 May 2025 14:47:49 +0200 Subject: [PATCH] initial commit --- Readme.md | 1 + comile.sh | 1 + compile_flags.txt | 4 + config | 8 + config.c | 123 +++++++++ config.h | 2 + dep.C_INCLUDE_PATH | 1 + main.c | 565 +++++++++++++++++++++++++++++++++++++++++ makefile | 13 + systemd-gotify.service | 13 + 10 files changed, 731 insertions(+) create mode 100644 Readme.md create mode 100644 comile.sh create mode 100644 compile_flags.txt create mode 100644 config create mode 100644 config.c create mode 100644 config.h create mode 100644 dep.C_INCLUDE_PATH create mode 100644 main.c create mode 100644 makefile create mode 100644 systemd-gotify.service diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..c89d6f8 --- /dev/null +++ b/Readme.md @@ -0,0 +1 @@ +TODO: diff --git a/comile.sh b/comile.sh new file mode 100644 index 0000000..90d1b8a --- /dev/null +++ b/comile.sh @@ -0,0 +1 @@ +gcc main.c config.c -lcurl -Wall -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -ldbus-1 -o systemd-gotify.bin diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000..92c7f39 --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,4 @@ +-lcurl +-I/usr/include/dbus-1.0 +-I/usr/lib/dbus-1.0/include +-ldbus-1 diff --git a/config b/config new file mode 100644 index 0000000..da3ec9f --- /dev/null +++ b/config @@ -0,0 +1,8 @@ +[Host] +Hostname = https://5ccppi.org:4433 +[Services] +/org/freedesktop/systemd1/unit/NetworkManager_2dwait_2donline_2eservice +/org/freedesktop/systemd1/unit/NetworkManager_2eservice +/org/freedesktop/systemd1/unit/httpd_2eservice +[APP] +Intervall = 5 diff --git a/config.c b/config.c new file mode 100644 index 0000000..12818a7 --- /dev/null +++ b/config.c @@ -0,0 +1,123 @@ +#include"config.h" +#include +#include +#include + +int loadConfig(char *str_file, char **str_entry,char **host,int *intervall,int size) +{ + int i=0; + FILE *f_config; + char temp_str[256]; + char *ret = NULL; + + printf("\nopening config file\n"); + f_config = fopen(str_file,"r"); + if(f_config != NULL) + { + ret = fgets(temp_str,256,f_config); + while(ret!=NULL) + { + temp_str[strcspn(temp_str,"\n")]=0; + printf("first temp_str:%s\n",temp_str); + if(strcmp(temp_str,"[Host]")==0) + { + printf("temp_str host:%s\n",temp_str); + while(ret!=NULL) + { + printf("temp_str:%s\n",temp_str); + ret = fgets(temp_str,256,f_config); + if(strchr(temp_str,'[')==NULL) + { + printf("strchr\n"); + if(strstr(temp_str,"Hostname")!=NULL) + { + char *ptr_host = strrchr(temp_str,'=')+1;//Without = + ptr_host[strcspn(ptr_host,"\n")]=0; + while(ptr_host[0]==' ') //Potential segfault?? + { + if(ptr_host < (temp_str + strlen(temp_str))) + { + ptr_host = ptr_host + 1; + }else{ + break; + } + } + *host = strdup(ptr_host); + printf("my host is:%s\n",*host); + } + }else{ + break; + } + } + } + else if(strcmp(temp_str,"[Services]")==0) + { + for(i=0;i +#include +#include +#include +#include +#include +#include +#include +#include + +#include"config.h" + +#define HELP_TEXT "requires a command\n--\ngetSendStatus [objectpath]\nlistUnits\nconfig [configfile / -d]\nset token with GOTIFY_TOKEN=\"sjdfoiasfd\"\n--\n" + +typedef struct service +{ + char *name; + char *targetPath; + char *host; + bool alerted; + int priority; +} Service; + +int gotify_message(char *,char *,char *); +int systemdCall(DBusConnection *,char *, char *); +int checkIsActive(DBusConnection *connection, char *service_name); +int systemdUnitCall(DBusConnection *connection,char *target,char *method,char *param,char **result); +int GetSendStatus(DBusConnection *connection,char *objectpath); +int ServiceGetSendStatus(DBusConnection *connection,Service *service); +int checkState(char *ServiceName,char *result,Service *service); +int getPath(char *configPath,int size); +/* + *sytemctl show gotify-server | grep PID + *sudo busctl tree org.freedesktop.systemd1 > get object paths + //org/freedesktop/systemd1 + //gotify_message("https://5ccppi.org:4433/message?token=","anothertitle","anothermessage"); + * */ + +int main(int argc,char *argv[]) +{ + DBusConnection *connection=NULL; + DBusError error; + clock_t time; + + char *str_entry[64]={'\0'}; + char *host=NULL; + int i=0; + int intervall=10; + Service services[64]={'\0'}; + char *ptr_name=NULL; + char path[256]; + + time = clock(); + curl_global_init(CURL_GLOBAL_DEFAULT); + + printf("time:%f\n",(float)time / CLOCKS_PER_SEC); + + dbus_error_init(&error); + connection = dbus_bus_get(DBUS_BUS_SYSTEM,&error);//DBUS_BUS_SYSTEM DBUS_BUS_SESSION + if(dbus_error_is_set(&error)) + { + fprintf(stderr,"%s",error.message); + dbus_error_free(&error); + return -1; + } + printf("This is my unique dbus name: %s\n",dbus_bus_get_unique_name(connection)); + + if(argc>1) + { + if(strcmp(argv[1],"getSendStatus")==0) + { + if(argc>2) + { + if(argv[2][0]=='/') + { + GetSendStatus(connection,argv[2]); + } + else + { + fprintf(stderr,"\n must be in the form of /org.freedesktop.systemd1/...\n"); + return 1; + } + } + else + { + fprintf(stderr,"%s needs 1 argument\n",argv[1]); + return 2; + } + } + else if(strcmp(argv[1],"listUnits")==0) + { + systemdCall(connection,"ListUnits",NULL); + } + else if(strcmp(argv[1],"config")==0) + { + if(argc==3 && strcmp(argv[2],"-d")!=0) + { + loadConfig(argv[2],str_entry,&host,&intervall,64); + printf("[main]intervall:%d\n",intervall); + for(i=0;str_entry[i];i++) + { + printf("entry in config:%s\n",str_entry[i]); + GetSendStatus(connection,str_entry[i]); + } + } + else if(argc==3 && strcmp(argv[2],"-d")==0) + { + printf("Running as a daemon\n"); + + getPath(path,256); + printf("[main]configPath:%s\n",path); + + loadConfig(path,str_entry,&host,&intervall,64); + printf("[main]host:%s\n",host); + printf("[main]intervall:%d\n",intervall); + for(i=0;str_entry[i];i++) + { + services[i].targetPath = strdup(str_entry[i]); + ptr_name = strrchr(services[i].targetPath,'/'); + if(ptr_name!=NULL) + { + services[i].name = strdup(ptr_name); + services[i].name = services[i].name + 1; + } + else{ + fprintf(stderr,"does not seem to be a valid target\n"); + services[i].name = strdup("Undefined"); + } + services[i].alerted = false; + services[i].priority = 6; + services[i].host = host; + printf("Name:%s\ntarget:%s\n",services[i].name,services[i].targetPath); + } + if(services[0].name) + { + while(true) + { + for(i=0;services[i].name;i++) + { + printf("entry in config:%s\n",services[i].name); + ServiceGetSendStatus(connection,&services[i]); + } + sleep(intervall); + } + }else + { + fprintf(stderr,"No service found in config file, please check %s\n",path); + } + } + else + { + fprintf(stderr,"config requires a config file as argument\nAppend -d for daemonizing\n"); + } + } + else + { + fprintf(stderr,"Unknown command\n%s",HELP_TEXT); + } + } + else + { + fprintf(stderr,HELP_TEXT); + } + curl_global_cleanup(); + return 0; +} +int getPath(char *configPath,int size) +{ + uid_t myid = getuid(); + printf("My uid:%d\n",myid); + struct passwd *info = getpwuid(myid); + printf("My dir:%s\n",info->pw_dir); + snprintf(configPath,size,"%s/.config/systemd-gotify/config",info->pw_dir); + printf("ConfigPath:%s\n",configPath); + return 0; +} +int DBusOptions(DBusConnection *connection,DBusError **error) //not tested check pointer of error!! +{ + int ret=0,i=0; + dbus_bool_t allow_user=0; + char **objects = NULL; + unsigned long uid; + + ret = dbus_bus_request_name(connection,"test.method.client",DBUS_NAME_FLAG_REPLACE_EXISTING,*error); + if(dbus_error_is_set(*error)) + { + fprintf(stderr,"%s",(**error).message); + dbus_error_free(*error); + return -1; + }else + { + printf("name requested from dbus: %d\n",ret); + } + + dbus_connection_set_allow_anonymous(connection,allow_user); + printf("user auth dbus requ: %d\n",allow_user); + if(!dbus_connection_list_registered(connection,"/",&objects)) + { + for(i=0;objects[i];i++) + { + printf("\nobject dbus: %s",objects[i]); + } + }else{ + printf("dbus_connection_list_registered error\n"); + } + + if((ret=dbus_connection_get_unix_user(connection,&uid))==1) + { + printf("found USERID:%ld",uid); + }else + { + printf("NO userID set in dbus session, servers normali do not authenthicate against users/slaves: %d\n",ret); + } + return 0; +} + +int GetSendStatus(DBusConnection *connection,char *objectpath) +{ + char *result=0; + int ret = systemdUnitCall(connection,objectpath,"Get","SubState",&result); + if(ret == 0) + { + //checkState(objectpath,result,NULL); + } else + { + fprintf(stderr,"could not call systemdunit\n"); + } + return ret; +} +int ServiceGetSendStatus(DBusConnection *connection,Service *service) +{ + char *result=0; + char *objectpath = service->targetPath; + int ret = systemdUnitCall(connection,objectpath,"Get","SubState",&result); + if(ret == 0) + { + checkState(service->name,result,service); + } else { + fprintf(stderr,"could not call systemdunit\n"); + } + return ret; +} + +int checkState(char *ServiceName,char *result,Service *service) +{ + int i=0; + char *error_strings[]={"dead","inactive","exited"}; + printf("result systemdUnitCall: %s\n",result); + for(i=0;i<(sizeof(error_strings)/sizeof(error_strings[0]));i++) + { + //printf("%s %ld\n",error_strings[i],sizeof(error_strings)/sizeof(error_strings[0])); + if(strcmp(result,error_strings[i])==0 && service->alerted == false) + { + service->alerted=true; + gotify_message(service->host,ServiceName,"is not running"); + printf("!!system unit died!! Alert gotify server!\n"); + } + else if(strcmp(result,"active")==0 || strcmp(result,"running")==0) + { + if(service->alerted == true) + { + gotify_message(service->host,ServiceName,"Running again, after crash"); + } + service->alerted=false; + printf("service seems okay!!\n"); + return 0; + } + } + return 1; +} + +int gotify_message(char *url,char *title,char *message) +{ + int ret; + CURL *curl; + CURLcode res,res2; + char post_buffer[128]; + char url_buffer[128]; + long response_code; + + curl = curl_easy_init(); + + const char* token = NULL; + if(NULL==(token = getenv("GOTIFY_TOKEN"))) + { + fprintf(stderr,"Pleas set a token using GOTIFY_TOKEN=\"abcde123\"\n"); + } + else + { + printf("Got token from env\n"); + ret = snprintf(url_buffer,sizeof(url_buffer),"%s/message?token=%s",url,token); + if(ret < sizeof(url_buffer)) + { + printf("url:%s",url); + } + else + { + fprintf(stderr,"error connecting strings for url and token\n"); + } + } + + ret = snprintf(post_buffer,sizeof(post_buffer),"title=%s&message=%s&priority=6",title,message); + if(ret < sizeof(post_buffer)) + { + printf("%s %d\n",post_buffer,ret); + if(curl) + { + curl_easy_setopt(curl,CURLOPT_URL,url_buffer); + curl_easy_setopt(curl,CURLOPT_POSTFIELDS,post_buffer); + curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1L); + + res = curl_easy_perform(curl); + if(res != CURLE_OK) + { + fprintf(stderr,"curl_easy_perform failed: %s\n",curl_easy_strerror(res)); + } + res2 = curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&response_code); + if((res2 == CURLE_OK) && response_code) + { + printf("Server returned:%ld\n",response_code); + }else + { + fprintf(stderr,"Error getting info; %ld\n",(long int)res2); + } + + curl_easy_cleanup(curl); + }else + { + fprintf(stderr,"Error initializing curl context\n"); + } + }else + { + printf("Error on string concelblalbla: %d\n",ret); + } + curl_easy_cleanup(curl); + return 0; +} + +int systemdCall(DBusConnection *connection,char *method,char *param) +{ + + DBusError error; + DBusMessage *msg; + DBusMessage *ret_msg; + DBusMessageIter iter; + DBusMessageIter array_iter; + + char *reply_msg=NULL; + int ret1,ret2; + + dbus_error_init(&error); + + msg = dbus_message_new_method_call("org.freedesktop.systemd1","/org/freedesktop/systemd1","org.freedesktop.systemd1.Manager",method); + if(NULL == msg) + { + fprintf(stderr,"Message null, no message created\n"); + return 1; + } + else + { + printf("message created!\n"); + } + + + if(param != NULL) + { + dbus_message_iter_init_append(msg,&iter); + if(!dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,¶m)) + { + fprintf(stderr,"Error appending\n"); + return -1; + } + } + + ret_msg = dbus_connection_send_with_reply_and_block(connection,msg,DBUS_TIMEOUT_INFINITE,&error); + if(ret_msg == NULL) + { + fprintf(stderr,"error on receiving message from peer\n"); + } + else + { + DBusMessageIter reply_iter; + dbus_message_iter_init(ret_msg,&reply_iter); + ret1=dbus_message_iter_get_arg_type(&reply_iter); + + while(ret1 != DBUS_TYPE_INVALID) + { + if(ret1 == *DBUS_TYPE_OBJECT_PATH_AS_STRING) + { + printf("succesfull received message\narg type %c\n",ret1); + dbus_message_iter_get_basic(&reply_iter,&reply_msg); + printf("returned value: %s\n",reply_msg); + } + if(ret1 == DBUS_TYPE_STRING) + { + printf("succesfull received message\narg type %c\n",ret1); + dbus_message_iter_get_basic(&reply_iter,&reply_msg); + printf("Received message:%s\n",reply_msg); + } + if(ret1 == DBUS_TYPE_ARRAY) + { + int element_count = dbus_message_iter_get_element_count(&reply_iter); + printf("Array:Elem count %d\n",element_count); + //ret2 = dbus_message_iter_get_element_type(&reply_iter); + dbus_message_iter_recurse(&reply_iter,&array_iter); + int i2=0; + ret2 = dbus_message_iter_get_arg_type(&array_iter); + while(ret2 != DBUS_TYPE_INVALID) + { + DBusMessageIter sub_iter; + int ret3; + + ret2 = dbus_message_iter_get_arg_type(&array_iter); + dbus_message_iter_recurse(&array_iter,&sub_iter); + ret3 = dbus_message_iter_get_arg_type(&sub_iter); + while(ret3 != DBUS_TYPE_INVALID) + { + ret3 = dbus_message_iter_get_arg_type(&sub_iter); + //printf("arr_sub_iter:%c\n",ret3); + if(ret3 == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic(&sub_iter,&reply_msg); + printf("%s\n",reply_msg); + } + ret3=dbus_message_iter_next(&sub_iter); + } + ret2=dbus_message_iter_next(&array_iter); + i2++; + } + } + ret1=dbus_message_iter_next(&reply_iter); + } + } + if(dbus_error_is_set(&error)) + { + fprintf(stderr,"%s\n",error.message); + dbus_error_free(&error); + return -1; + } + return 0; +} + +int systemdUnitCall(DBusConnection *connection,char *target,char *method,char *param,char **result) +{ + + DBusError error; + DBusMessage *msg; + DBusMessage *ret_msg; + DBusMessageIter iter; + DBusMessageIter array_iter; + DBusMessageIter variant_iter; + DBusMessageIter sub_iter; + int ret3; + char *reply_msg=NULL; + int ret1,ret2; + char *param2 = "org.freedesktop.systemd1.Unit"; + + dbus_error_init(&error); + //dest(servcice/bus) ,path(object) ,iface method + msg = dbus_message_new_method_call("org.freedesktop.systemd1",target,"org.freedesktop.DBus.Properties",method); + if(NULL == msg) + { + fprintf(stderr,"Message null, no message created\n"); + dbus_message_unref(msg); + return 1; + } + + if(param2 != NULL) + { + dbus_message_iter_init_append(msg,&iter); + if(!dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,¶m2)) + { + fprintf(stderr,"Error appending\n"); + dbus_message_unref(msg); + return -1; + } + if(!dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,¶m)) + { + fprintf(stderr,"Error appending\n"); + dbus_message_unref(msg); + return -1; + } + } + + ret_msg = dbus_connection_send_with_reply_and_block(connection,msg,DBUS_TIMEOUT_INFINITE,&error); + if(ret_msg == NULL) + { + fprintf(stderr,"error ond receiving message from peer\n"); + dbus_message_unref(msg); + dbus_message_unref(ret_msg); + return 1; + } + else + { + DBusMessageIter reply_iter; + dbus_message_iter_init(ret_msg,&reply_iter); + ret1=dbus_message_iter_get_arg_type(&reply_iter); + while(ret1 != DBUS_TYPE_INVALID) + { + if(ret1 == DBUS_TYPE_OBJECT_PATH) + { + printf("succesfull received message\narg type %c\n",ret1); + dbus_message_iter_get_basic(&reply_iter,&reply_msg); + printf("returned value: %s\n",reply_msg); + } + if(ret1 == DBUS_TYPE_STRING) + { + printf("succesfull received message\narg type %c\n",ret1); + printf("[func]reply_msg:%p , &reply_msg:%p , *reply_msg:%d\n", reply_msg,&reply_msg,*reply_msg); + dbus_message_iter_get_basic(&reply_iter,&reply_msg); + printf("Received message:%s\n",reply_msg); + } + if(ret1 == DBUS_TYPE_VARIANT) + { + dbus_message_iter_recurse(&reply_iter,&variant_iter); + char *type = dbus_message_iter_get_signature(&variant_iter); + //printf("str_val:%s\n",type); + if(type[0] == DBUS_TYPE_STRING) + { + //printf("[func]&result:%p , result:%p\n",&result,result); + dbus_message_iter_get_basic(&variant_iter,result); + //printf("*result:%s\n",*result); + } + dbus_free(type); + } + if(ret1 == DBUS_TYPE_ARRAY) + { + int element_count = dbus_message_iter_get_element_count(&reply_iter); + printf("Array:Elem count %d\n",element_count); + dbus_message_iter_recurse(&reply_iter,&array_iter); + ret2 = dbus_message_iter_get_arg_type(&array_iter); + while(ret2 != DBUS_TYPE_INVALID) + { + ret2 = dbus_message_iter_get_arg_type(&array_iter); + dbus_message_iter_recurse(&array_iter,&sub_iter); + ret3 = dbus_message_iter_get_arg_type(&sub_iter); + while(ret3 != DBUS_TYPE_INVALID) + { + ret3 = dbus_message_iter_get_arg_type(&sub_iter); + if(ret3 == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic(&sub_iter,&reply_msg); + //printf("%s\n",reply_msg); + } + ret3=dbus_message_iter_next(&sub_iter); + } + ret2=dbus_message_iter_next(&array_iter); + } + } + ret1=dbus_message_iter_next(&reply_iter); + } + } + if(dbus_error_is_set(&error)) + { + fprintf(stderr,"%s\n",error.message); + dbus_error_free(&error); + dbus_message_unref(msg); + dbus_message_unref(ret_msg); + return 1; + } + dbus_message_unref(msg); + dbus_message_unref(ret_msg); + return 0; +} + diff --git a/makefile b/makefile new file mode 100644 index 0000000..91470d5 --- /dev/null +++ b/makefile @@ -0,0 +1,13 @@ +default: + gcc main.c config.c -lcurl -Wall -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -ldbus-1 -o systemd-gotify.bin +install: + sudo cp ./systemd-gotify.bin /usr/local/bin/systemd-gotify + mkdir -p $${HOME}/.config/systemd-gotify/ + cp -i config $${HOME}/.config/systemd-gotify/config +uninstall: + sudo rm /usr/local/bin/systemd-gotify + rm $${HOME}/.config/systemd-gotify/config + rm $${HOME}/.config/systemd-gotify/ -r +service-files: + mkdir -p $${HOME}/.config/systemd/user/ + cp -i ./systemd-gotify.service $${HOME}/.config/systemd/user/systemd-gotify.service diff --git a/systemd-gotify.service b/systemd-gotify.service new file mode 100644 index 0000000..03f56b2 --- /dev/null +++ b/systemd-gotify.service @@ -0,0 +1,13 @@ +[Unit] +Description=Check for running systemd daemons and send notification to gotify +User=ccppi + +[Service] +Environment="GOTIFY_TOKEN=" +ExecStart=/usr/local/bin/systemd-gotify config -d +StandardOutput=journal +SysLogLevel=debug +LogRateLimitIntervalSec=3s +LogRateLimitBurst=10000 +[Install] +WantedBy=default.target