summaryrefslogtreecommitdiffstats
path: root/src/service/util/serviceutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/util/serviceutil.c')
-rw-r--r--src/service/util/serviceutil.c262
1 files changed, 262 insertions, 0 deletions
diff --git a/src/service/util/serviceutil.c b/src/service/util/serviceutil.c
new file mode 100644
index 0000000..829d0ec
--- /dev/null
+++ b/src/service/util/serviceutil.c
@@ -0,0 +1,262 @@
+/*
+ * serviceutil.c
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Based on syslogserviceutil.c from sblim-cmpi-syslog written by
+ * R Sharada <sharada@in.ibm.com>, Copyright (c) IBM Corp. 2003, 2009
+ *
+ * Red Hat Author(s): Vitezslav Crhonek <vcrhonek@redhat.com>
+ *
+ */
+
+#define _GNU_SOURCE
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include "serviceutil.h"
+
+#define OPERATION_BUFSIZE 300
+#define STATUS_BUFSIZE 2000
+#define MAX_SLIST_CNT 1000
+
+/* FIXME don't use tmpnam function */
+
+char *suscript = "serviceutil.sh";
+char *sdscript = "servicedisc.sh";
+
+typedef struct {
+ FILE *fp;
+ char name[L_tmpnam];
+ FILE *fp2;
+ char name2[L_tmpnam];
+} Control;
+
+void
+Service_Free_SList(SList *slist)
+{
+ int i;
+
+ if (slist == NULL)
+ return;
+
+ for(i = 0; i < slist->cnt; i++)
+ free(slist->name[i]);
+ free(slist->name);
+ free(slist);
+
+ return;
+}
+
+SList *
+Service_Find_All(void)
+{
+ char svname[256];
+ char cmdbuffer[STATUS_BUFSIZE];
+ Control *cc = malloc(sizeof(Control));
+ SList *slist;
+
+ if (cc && tmpnam(cc->name))
+ {
+ snprintf(cmdbuffer, STATUS_BUFSIZE, "%s > %s", sdscript, cc->name);
+ if (system(cmdbuffer) == 0)
+ cc->fp = fopen(cc->name, "r");
+ else
+ {
+ free(cc);
+ cc=NULL;
+ return NULL;
+ }
+ slist = malloc(sizeof(SList));
+ slist->name = malloc(MAX_SLIST_CNT * sizeof(char *));
+ slist->cnt = 0;
+ while (fgets(svname, sizeof(svname), cc->fp) != NULL)
+ {
+ slist->name[slist->cnt] = strndup(svname, strlen(svname) - 1);
+ slist->cnt++;
+ }
+ return slist;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+void *
+Service_Begin_Enum(const char *service)
+{
+ char cmdbuffer[STATUS_BUFSIZE];
+ Control *cc = malloc(sizeof(Control));
+
+ memset(&cmdbuffer, '\0', sizeof(cmdbuffer));
+
+ if (cc && tmpnam(cc->name) && tmpnam(cc->name2))
+ {
+ snprintf(cmdbuffer, STATUS_BUFSIZE, "%s status %s > %s", suscript, service, cc->name);
+ if (system(cmdbuffer) == 0)
+ {
+ cc->fp = fopen(cc->name, "r");
+ snprintf(cmdbuffer, STATUS_BUFSIZE, "%s is-enabled %s > %s", suscript, service, cc->name2);
+ if (system(cmdbuffer) == 0)
+ {
+ cc->fp2 = fopen(cc->name2, "r");
+ }
+ else
+ {
+ free(cc);
+ cc=NULL;
+ }
+ }
+ else
+ {
+ free(cc);
+ cc=NULL;
+ }
+ }
+
+ return cc;
+}
+
+int
+Service_Next_Enum(void *handle, Service* svc, const char *service)
+{
+ char result[2000];
+ char svname[256];
+ int pid = 0;
+ Control *cc = (Control *) handle;
+ int state = 0, ret = 0;
+
+ memset(&result, '\0', sizeof(result));
+ memset(&svname, '\0', sizeof(svname));
+
+ if (cc && svc)
+ {
+ svc->svEnabledDefault = 5;
+ while (fgets(result, sizeof(result), cc->fp) != NULL)
+ {
+ if (strncmp(result, "stopped", 7) == 0)
+ {
+ svc->pid = 0;
+ ret = 1;
+ }
+ else
+ {
+ state = sscanf(result,"%d %s", &pid, svname);
+ svc->pid = pid;
+ if (state) ret = 1;
+ }
+ }
+ svc->svName = strdup(service);
+
+ while (fgets(result, sizeof(result), cc->fp2) != NULL)
+ {
+ if (strncmp(result, "enabled", 7) == 0)
+ svc->svEnabledDefault = 2;
+ if (strncmp(result, "disabled", 8) == 0)
+ svc->svEnabledDefault = 3;
+ }
+ }
+
+ if (svc)
+ {
+ if (svc->pid)
+ {
+ svc->svStarted = 1;
+ svc->svStatus = strdup("OK");
+ }
+ else
+ {
+ svc->svStarted = 0;
+ svc->svStatus = strdup("Stopped");
+ }
+ }
+
+ return ret;
+}
+
+void
+Service_End_Enum(void *handle)
+{
+ Control *cc = (Control *) handle;
+
+ if (cc) {
+ fclose(cc->fp);
+ fclose(cc->fp2);
+ remove(cc->name);
+ remove(cc->name2);
+ free(cc);
+ }
+}
+
+int
+Service_Operation(const char *service, const char *method, char *result, int resultlen)
+{
+ char cmdbuffer[OPERATION_BUFSIZE];
+ FILE *fcmdout = NULL;
+ char *op = NULL;
+ char *cmdout;
+ int fd;
+
+ memset(&cmdbuffer, '\0', sizeof(cmdbuffer));
+ memset(&cmdout, '\0', sizeof(cmdout));
+ asprintf(&cmdout, "%s", "/tmp/Service_OperationXXXXXX");
+
+ if (!strcasecmp(method, "startservice"))
+ op="start";
+ else if (!strcasecmp(method, "stopservice"))
+ op="stop";
+ else if (!strcasecmp(method, "reloadservice"))
+ op="reload";
+ else if (!strcasecmp(method, "restartservice"))
+ op="restart";
+ else if (!strcasecmp(method, "tryrestartservice"))
+ op="try-restart";
+ else if (!strcasecmp(method, "condrestartservice"))
+ op="condrestart";
+ else if (!strcasecmp(method, "reloadorrestartservice"))
+ op="reload-or-restart";
+ else if (!strcasecmp(method, "reloadortryrestartservice"))
+ op="reload-or-try-restart";
+ else if (!strcasecmp(method, "turnserviceon"))
+ op="enable";
+ else if (!strcasecmp(method, "turnserviceoff"))
+ op="disable";
+ else
+ return -1;
+
+ if (op && ((fd = mkstemp(cmdout)) != -1))
+ {
+ snprintf(cmdbuffer, OPERATION_BUFSIZE, "%s %s %s > %s", suscript, op, service, cmdout);
+ if (system(cmdbuffer) == 0)
+ {
+ /* we got some output? */
+ if ((fcmdout = fopen(cmdout, "r")) && fgets(result, resultlen, fcmdout))
+ {
+ fclose(fcmdout);
+ }
+ close(fd);
+ return 0;
+ }
+ }
+
+ return 1;
+}