blob: 669f1a35be971bfef7264c8e05be597478690d09 [file] [log] [blame] [raw]
/* service - toolbox
Copyright 2015 libdll.so
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.
*/
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <getopt.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#define INIT_D_PATH "/etc/init.d/"
static char *env_names[] = {
"LANG", "PATH", "TERM"
};
static void print_usage(const char *name) {
fprintf(stderr, "Usage: %s <service> [<action>] [<options>]\n", name);
}
static char service_script[PATH_MAX+1];
static size_t name_len;
static char *env[sizeof env_names / sizeof(char *) + 1];
static int status_all() {
struct dirent *de;
struct stat s;
char tmp[1024];
DIR *d = opendir(INIT_D_PATH);
while(de = readdir(d)) {
if((strcmp(de->d_name, ".") == 0) || (strcmp(de->d_name, "..") == 0)) continue;
//const char slash = "/";
snprintf(tmp,sizeof(tmp),INIT_D_PATH"%s",de->d_name);
if(lstat(tmp, &s) < 0) {
fprintf(stderr, "stat: %s failed: %s", tmp, strerror(errno));
return -1;
}
if((s.st_mode & S_IFMT) != S_IFDIR) {
if(access(tmp, X_OK) == 0)
fprintf(stdout, "%s\n", de->d_name);
}
}
return 0;
}
int service_main(int argc, char **argv) {
/* TODO USE getoptlong */
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"status-all", no_argument, 0, 0},
{0, 0, 0, 0}
};
while(1) {
int option_index = 0;
int c = getopt_long(argc, argv, "h", long_options, &option_index);
if(c==-1) break;
switch(c) {
case 'h':
print_usage(argv[0]);
return -1;
case 0:
//printf("%s\n", long_options[option_index].name);
if(strcmp(long_options[option_index].name, "status-all")== 0) {
// TODO
status_all();
return 1;
}
break;
case '?':
return -1;
default:
print_usage(argv[0]);
return 0;
}
}
/* Check if no option, Avoid Segmentation fault */
if(optind == argc) {
print_usage(argv[0]);
return 0;
}
if(sizeof INIT_D_PATH + name_len > sizeof service_script) {
fprintf(stderr, "%s: Service name too long\n", argv[0]);
return 1;
}
memcpy(service_script + sizeof INIT_D_PATH - 1, argv[1], name_len + 1);
if(access(service_script, X_OK) < 0) {
fprintf(stderr, "%s: %s: Unrecognized service\n", argv[0], argv[1]);
return 1;
}
int i;
/* Copy the value of TERM LANG PATH to env point */
name_len = strlen(argv[1]);
service_script[PATH_MAX+1] = INIT_D_PATH;
char **p = env;
/* How many options the env_names have. */
for(i = 0; i < sizeof env_names / sizeof(char *); i++) {
char *e = getenv(env_names[i]);
/* Copy HEAD to env[i] */
if(e) *p++ = e;
}
*p = NULL;
//execle(service_script, argv[0], argv[2], NULL, env);
//perror(argv[1]);
argv++;
execve(service_script, argv, env);
perror(argv[0]);
return 1;
}