Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11d3a8bead | ||
|
|
e36e9a30eb | ||
|
|
7da99d77b5 | ||
|
|
01c34c28e6 | ||
|
|
56ddda54b5 | ||
|
|
3a803b3135 | ||
|
|
72df51e17b | ||
|
|
b2f5531194 | ||
|
|
19bf49a710 | ||
|
|
64354831da | ||
|
|
e14edd765f | ||
|
|
f9d41243d8 | ||
|
|
be7ad06d4a | ||
|
|
a616516895 | ||
|
|
04721ece03 | ||
|
|
c7e8f1133a | ||
|
|
47e4bfae57 | ||
|
|
8a945194af | ||
|
|
aa4a004c29 |
116
ChangeLog
116
ChangeLog
@@ -1,3 +1,119 @@
|
|||||||
|
commit e36e9a30eb830ea27b467383fa2ae02cd2b0d9d4
|
||||||
|
Author: Holger Hoffstätte <holger@applied-asynchrony.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
rc-status: initialize uptime pointer to prevent memory corruption
|
||||||
|
|
||||||
|
This fixes #231.
|
||||||
|
|
||||||
|
commit 7da99d77b5bbd789cb84be347d8b8d96d21f85c4
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
version 0.38.1
|
||||||
|
|
||||||
|
commit 01c34c28e6d6d7bfecc0f88bdf1fb15e97ab8823
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
Update ChangeLog
|
||||||
|
|
||||||
|
commit 56ddda54b5aa01474bf563d5a662075c35152858
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
supervise-daemon.c: clean up memory leaks
|
||||||
|
|
||||||
|
commit 3a803b3135837665d51ef4dd7a8b913c78e71ff6
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
librc-daemon.c: fix memory leaks
|
||||||
|
|
||||||
|
commit 72df51e17ba0e1a0f94451b4bbfb338288c4625c
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
librc-daemon: convert most snprintf calls to xasprintf
|
||||||
|
|
||||||
|
commit b2f5531194e33c229462e9f52fa1d9388463f7b7
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
librc-misc: convert snprintf calls to xasprintf
|
||||||
|
|
||||||
|
commit 19bf49a710f27d4774ed4c6372d87d6ba15f189e
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
libeinfo: convert remaining snprintf calls to xasprintf
|
||||||
|
|
||||||
|
commit 64354831da2adeba5cb2f91a81fa0f56e1ce4ed9
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
openrc: convert snprintf calls to xasprintf
|
||||||
|
|
||||||
|
commit e14edd765fdc4ed43356d2eef35fa99228e5d461
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
supervise-daemon: convert snprintf calls to xasprintf
|
||||||
|
|
||||||
|
commit f9d41243d8499c5d7027177d5aa716d5b5859cd6
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
start-stop-daemon: convert snprintf calls to xasprintf
|
||||||
|
|
||||||
|
commit be7ad06d4a0efce2a1144b2cf6f0cc361f2a81e4
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
rc-status: convert snprintf calls to xasprintf
|
||||||
|
|
||||||
|
commit a6165168953b9c7a62c089ce946476b23b73fb12
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
rc-status: fix gcc 7 warnings
|
||||||
|
|
||||||
|
commit 04721ece03b15503aa220f60e7c6159d01ee75e1
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
start-stop-daemon: fix gcc 7 warnings
|
||||||
|
|
||||||
|
commit c7e8f1133a42152cc293e6b637985f81bcf8b310
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
checkpath: fix gcc 7 warnings
|
||||||
|
|
||||||
|
commit 47e4bfae57402eedd017d6098b432c2c411cd374
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
fix gcc 7 warnings in pipe routines
|
||||||
|
|
||||||
|
commit 8a945194afb106428bc700e751078ef9944ee617
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
libeinfo: clean up gcc 7 compiler warnings
|
||||||
|
|
||||||
|
commit aa4a004c297ec7a1fb794ad2e53ef3ac8b3f4fd1
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
version 0.38
|
||||||
|
|
||||||
|
commit 9ec5d36bdddf5bb0e96b0c561bc5d013a8a2da2a
|
||||||
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|
||||||
|
Update ChangeLog
|
||||||
|
|
||||||
commit a097933edab9d7221df1831e098415d604437c98
|
commit a097933edab9d7221df1831e098415d604437c98
|
||||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
NAME= openrc
|
NAME= openrc
|
||||||
VERSION= 0.37
|
VERSION= 0.38.1
|
||||||
PKG= ${NAME}-${VERSION}
|
PKG= ${NAME}-${VERSION}
|
||||||
|
|||||||
@@ -883,7 +883,7 @@ eindent(void)
|
|||||||
{
|
{
|
||||||
char *env = getenv("EINFO_INDENT");
|
char *env = getenv("EINFO_INDENT");
|
||||||
int amount = 0;
|
int amount = 0;
|
||||||
char num[10];
|
char *num;
|
||||||
|
|
||||||
if (env) {
|
if (env) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
@@ -894,8 +894,9 @@ eindent(void)
|
|||||||
amount += INDENT_WIDTH;
|
amount += INDENT_WIDTH;
|
||||||
if (amount > INDENT_MAX)
|
if (amount > INDENT_MAX)
|
||||||
amount = INDENT_MAX;
|
amount = INDENT_MAX;
|
||||||
snprintf(num, 10, "%08d", amount);
|
xasprintf(&num, "%08d", amount);
|
||||||
setenv("EINFO_INDENT", num, 1);
|
setenv("EINFO_INDENT", num, 1);
|
||||||
|
free(num);
|
||||||
}
|
}
|
||||||
hidden_def(eindent)
|
hidden_def(eindent)
|
||||||
|
|
||||||
@@ -903,7 +904,7 @@ void eoutdent(void)
|
|||||||
{
|
{
|
||||||
char *env = getenv("EINFO_INDENT");
|
char *env = getenv("EINFO_INDENT");
|
||||||
int amount = 0;
|
int amount = 0;
|
||||||
char num[10];
|
char *num = NULL;
|
||||||
int serrno = errno;
|
int serrno = errno;
|
||||||
|
|
||||||
if (!env)
|
if (!env)
|
||||||
@@ -917,8 +918,9 @@ void eoutdent(void)
|
|||||||
if (amount <= 0)
|
if (amount <= 0)
|
||||||
unsetenv("EINFO_INDENT");
|
unsetenv("EINFO_INDENT");
|
||||||
else {
|
else {
|
||||||
snprintf(num, 10, "%08d", amount);
|
xasprintf(&num, "%08d", amount);
|
||||||
setenv("EINFO_INDENT", num, 1);
|
setenv("EINFO_INDENT", num, 1);
|
||||||
|
free(num);
|
||||||
}
|
}
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,13 +23,13 @@
|
|||||||
static bool
|
static bool
|
||||||
pid_is_exec(pid_t pid, const char *exec)
|
pid_is_exec(pid_t pid, const char *exec)
|
||||||
{
|
{
|
||||||
char buffer[32];
|
char *buffer = NULL;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int c;
|
int c;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
exec = basename_c(exec);
|
exec = basename_c(exec);
|
||||||
snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
|
xasprintf(&buffer, "/proc/%d/stat", pid);
|
||||||
if ((fp = fopen(buffer, "r"))) {
|
if ((fp = fopen(buffer, "r"))) {
|
||||||
while ((c = getc(fp)) != EOF && c != '(')
|
while ((c = getc(fp)) != EOF && c != '(')
|
||||||
;
|
;
|
||||||
@@ -41,23 +41,27 @@ pid_is_exec(pid_t pid, const char *exec)
|
|||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
free(buffer);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
pid_is_argv(pid_t pid, const char *const *argv)
|
pid_is_argv(pid_t pid, const char *const *argv)
|
||||||
{
|
{
|
||||||
char cmdline[32];
|
char *cmdline = NULL;
|
||||||
int fd;
|
int fd;
|
||||||
char buffer[PATH_MAX];
|
char buffer[PATH_MAX];
|
||||||
char *p;
|
char *p;
|
||||||
ssize_t bytes;
|
ssize_t bytes;
|
||||||
|
|
||||||
snprintf(cmdline, sizeof(cmdline), "/proc/%u/cmdline", pid);
|
xasprintf(&cmdline, "/proc/%u/cmdline", pid);
|
||||||
if ((fd = open(cmdline, O_RDONLY)) < 0)
|
if ((fd = open(cmdline, O_RDONLY)) < 0) {
|
||||||
|
free(cmdline);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
bytes = read(fd, buffer, sizeof(buffer));
|
bytes = read(fd, buffer, sizeof(buffer));
|
||||||
close(fd);
|
close(fd);
|
||||||
|
free(cmdline);
|
||||||
if (bytes == -1)
|
if (bytes == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -88,7 +92,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
|
|||||||
char proc_ns[30];
|
char proc_ns[30];
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
pid_t p;
|
pid_t p;
|
||||||
char buffer[PATH_MAX];
|
char *buffer = NULL;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
pid_t openrc_pid = 0;
|
pid_t openrc_pid = 0;
|
||||||
char *pp;
|
char *pp;
|
||||||
@@ -149,18 +153,22 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
|
|||||||
continue;
|
continue;
|
||||||
if (pid != 0 && pid != p)
|
if (pid != 0 && pid != p)
|
||||||
continue;
|
continue;
|
||||||
snprintf(buffer, sizeof(buffer), "/proc/%d/ns/pid", p);
|
xasprintf(&buffer, "/proc/%d/ns/pid", p);
|
||||||
if (exists(buffer)) {
|
if (exists(buffer)) {
|
||||||
rc = readlink(buffer, proc_ns, sizeof(proc_ns));
|
rc = readlink(buffer, proc_ns, sizeof(proc_ns));
|
||||||
if (rc <= 0)
|
if (rc <= 0)
|
||||||
proc_ns[0] = '\0';
|
proc_ns[0] = '\0';
|
||||||
}
|
}
|
||||||
|
free(buffer);
|
||||||
if (strlen(my_ns) && strlen (proc_ns) && strcmp(my_ns, proc_ns))
|
if (strlen(my_ns) && strlen (proc_ns) && strcmp(my_ns, proc_ns))
|
||||||
continue;
|
continue;
|
||||||
if (uid) {
|
if (uid) {
|
||||||
snprintf(buffer, sizeof(buffer), "/proc/%d", p);
|
xasprintf(&buffer, "/proc/%d", p);
|
||||||
if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
|
if (stat(buffer, &sb) != 0 || sb.st_uid != uid) {
|
||||||
|
free(buffer);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
}
|
}
|
||||||
if (exec && !pid_is_exec(p, exec))
|
if (exec && !pid_is_exec(p, exec))
|
||||||
continue;
|
continue;
|
||||||
@@ -169,9 +177,10 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
|
|||||||
continue;
|
continue;
|
||||||
/* If this is an OpenVZ host, filter out container processes */
|
/* If this is an OpenVZ host, filter out container processes */
|
||||||
if (openvz_host) {
|
if (openvz_host) {
|
||||||
snprintf(buffer, sizeof(buffer), "/proc/%d/status", p);
|
xasprintf(&buffer, "/proc/%d/status", p);
|
||||||
if (exists(buffer)) {
|
if (exists(buffer)) {
|
||||||
fp = fopen(buffer, "r");
|
fp = fopen(buffer, "r");
|
||||||
|
free(buffer);
|
||||||
if (! fp)
|
if (! fp)
|
||||||
continue;
|
continue;
|
||||||
while (! feof(fp)) {
|
while (! feof(fp)) {
|
||||||
@@ -315,12 +324,13 @@ _match_daemon(const char *path, const char *file, RC_STRINGLIST *match)
|
|||||||
{
|
{
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char ffile[PATH_MAX];
|
char *ffile = NULL;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
RC_STRING *m;
|
RC_STRING *m;
|
||||||
|
|
||||||
snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
|
xasprintf(&ffile, "%s/%s", path, file);
|
||||||
fp = fopen(ffile, "r");
|
fp = fopen(ffile, "r");
|
||||||
|
free(ffile);
|
||||||
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
return false;
|
return false;
|
||||||
@@ -346,29 +356,22 @@ _match_list(const char *exec, const char *const *argv, const char *pidfile)
|
|||||||
{
|
{
|
||||||
RC_STRINGLIST *match = rc_stringlist_new();
|
RC_STRINGLIST *match = rc_stringlist_new();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
size_t l;
|
|
||||||
char *m;
|
char *m;
|
||||||
|
|
||||||
if (exec) {
|
if (exec) {
|
||||||
l = strlen(exec) + 6;
|
xasprintf(&m, "exec=%s", exec);
|
||||||
m = xmalloc(sizeof(char) * l);
|
|
||||||
snprintf(m, l, "exec=%s", exec);
|
|
||||||
rc_stringlist_add(match, m);
|
rc_stringlist_add(match, m);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (argv && argv[i]) {
|
while (argv && argv[i]) {
|
||||||
l = strlen(*argv) + strlen("argv_=") + 16;
|
xasprintf(&m, "argv_0=%s", argv[i++]);
|
||||||
m = xmalloc(sizeof(char) * l);
|
|
||||||
snprintf(m, l, "argv_0=%s", argv[i++]);
|
|
||||||
rc_stringlist_add(match, m);
|
rc_stringlist_add(match, m);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pidfile) {
|
if (pidfile) {
|
||||||
l = strlen(pidfile) + 9;
|
xasprintf(&m, "pidfile=%s", pidfile);
|
||||||
m = xmalloc(sizeof(char) * l);
|
|
||||||
snprintf(m, l, "pidfile=%s", pidfile);
|
|
||||||
rc_stringlist_add(match, m);
|
rc_stringlist_add(match, m);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
@@ -381,8 +384,8 @@ rc_service_daemon_set(const char *service, const char *exec,
|
|||||||
const char *const *argv,
|
const char *const *argv,
|
||||||
const char *pidfile, bool started)
|
const char *pidfile, bool started)
|
||||||
{
|
{
|
||||||
char dirpath[PATH_MAX];
|
char *dirpath = NULL;
|
||||||
char file[PATH_MAX];
|
char *file = NULL;
|
||||||
int nfiles = 0;
|
int nfiles = 0;
|
||||||
char oldfile[PATH_MAX] = { '\0' };
|
char oldfile[PATH_MAX] = { '\0' };
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
@@ -397,8 +400,7 @@ rc_service_daemon_set(const char *service, const char *exec,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
xasprintf(&dirpath, RC_SVCDIR "/daemons/%s", basename_c(service));
|
||||||
basename_c(service));
|
|
||||||
|
|
||||||
/* Regardless, erase any existing daemon info */
|
/* Regardless, erase any existing daemon info */
|
||||||
if ((dp = opendir(dirpath))) {
|
if ((dp = opendir(dirpath))) {
|
||||||
@@ -407,8 +409,7 @@ rc_service_daemon_set(const char *service, const char *exec,
|
|||||||
if (d->d_name[0] == '.')
|
if (d->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
snprintf(file, sizeof(file), "%s/%s",
|
xasprintf(&file, "%s/%s", dirpath, d->d_name);
|
||||||
dirpath, d->d_name);
|
|
||||||
nfiles++;
|
nfiles++;
|
||||||
|
|
||||||
if (!*oldfile) {
|
if (!*oldfile) {
|
||||||
@@ -421,6 +422,7 @@ rc_service_daemon_set(const char *service, const char *exec,
|
|||||||
rename(file, oldfile);
|
rename(file, oldfile);
|
||||||
strlcpy(oldfile, file, sizeof(oldfile));
|
strlcpy(oldfile, file, sizeof(oldfile));
|
||||||
}
|
}
|
||||||
|
free(file);
|
||||||
}
|
}
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
rc_stringlist_free(match);
|
rc_stringlist_free(match);
|
||||||
@@ -429,8 +431,7 @@ rc_service_daemon_set(const char *service, const char *exec,
|
|||||||
/* Now store our daemon info */
|
/* Now store our daemon info */
|
||||||
if (started) {
|
if (started) {
|
||||||
if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
|
if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
|
||||||
snprintf(file, sizeof(file), "%s/%03d",
|
xasprintf(&file, "%s/%03d", dirpath, nfiles + 1);
|
||||||
dirpath, nfiles + 1);
|
|
||||||
if ((fp = fopen(file, "w"))) {
|
if ((fp = fopen(file, "w"))) {
|
||||||
fprintf(fp, "exec=");
|
fprintf(fp, "exec=");
|
||||||
if (exec)
|
if (exec)
|
||||||
@@ -446,10 +447,12 @@ rc_service_daemon_set(const char *service, const char *exec,
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
retval = true;
|
retval = true;
|
||||||
}
|
}
|
||||||
|
free(file);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
|
free(dirpath);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_daemon_set)
|
librc_hidden_def(rc_service_daemon_set)
|
||||||
@@ -458,8 +461,8 @@ bool
|
|||||||
rc_service_started_daemon(const char *service,
|
rc_service_started_daemon(const char *service,
|
||||||
const char *exec, const char *const *argv, int indx)
|
const char *exec, const char *const *argv, int indx)
|
||||||
{
|
{
|
||||||
char dirpath[PATH_MAX];
|
char *dirpath = NULL;
|
||||||
char file[16];
|
char *file = NULL;
|
||||||
RC_STRINGLIST *match;
|
RC_STRINGLIST *match;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
@@ -468,13 +471,13 @@ rc_service_started_daemon(const char *service,
|
|||||||
if (!service || !exec)
|
if (!service || !exec)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
xasprintf(&dirpath, RC_SVCDIR "/daemons/%s", basename_c(service));
|
||||||
basename_c(service));
|
|
||||||
match = _match_list(exec, argv, NULL);
|
match = _match_list(exec, argv, NULL);
|
||||||
|
|
||||||
if (indx > 0) {
|
if (indx > 0) {
|
||||||
snprintf(file, sizeof(file), "%03d", indx);
|
xasprintf(&file, "%03d", indx);
|
||||||
retval = _match_daemon(dirpath, file, match);
|
retval = _match_daemon(dirpath, file, match);
|
||||||
|
free(file);
|
||||||
} else {
|
} else {
|
||||||
if ((dp = opendir(dirpath))) {
|
if ((dp = opendir(dirpath))) {
|
||||||
while ((d = readdir(dp))) {
|
while ((d = readdir(dp))) {
|
||||||
@@ -489,6 +492,7 @@ rc_service_started_daemon(const char *service,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc_stringlist_free(match);
|
rc_stringlist_free(match);
|
||||||
|
free(dirpath);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_started_daemon)
|
librc_hidden_def(rc_service_started_daemon)
|
||||||
|
|||||||
@@ -237,13 +237,9 @@ static void rc_config_set_value(RC_STRINGLIST *config, char *value)
|
|||||||
if (token[i] == '\n')
|
if (token[i] == '\n')
|
||||||
token[i] = 0;
|
token[i] = 0;
|
||||||
|
|
||||||
i = strlen(entry) + strlen(token) + 2;
|
xasprintf(&newline, "%s=%s", entry, token);
|
||||||
newline = xmalloc(sizeof(char) * i);
|
|
||||||
snprintf(newline, i, "%s=%s", entry, token);
|
|
||||||
} else {
|
} else {
|
||||||
i = strlen(entry) + 2;
|
xasprintf(&newline, "%s=", entry);
|
||||||
newline = xmalloc(sizeof(char) * i);
|
|
||||||
snprintf(newline, i, "%s=", entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
replaced = false;
|
replaced = false;
|
||||||
@@ -300,8 +296,7 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
|
|||||||
|
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
len = varlen + strlen(value) + 2;
|
len = varlen + strlen(value) + 2;
|
||||||
tmp = xmalloc(sizeof(char) * len);
|
xasprintf(&tmp, "%s=%s", override->value, value);
|
||||||
snprintf(tmp, len, "%s=%s", override->value, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -269,11 +269,13 @@ int main(int argc, char **argv)
|
|||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'D':
|
case 'D':
|
||||||
trunc = true;
|
trunc = true;
|
||||||
|
/* falls through */
|
||||||
case 'd':
|
case 'd':
|
||||||
type = inode_dir;
|
type = inode_dir;
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
trunc = true;
|
trunc = true;
|
||||||
|
/* falls through */
|
||||||
case 'f':
|
case 'f':
|
||||||
type = inode_file;
|
type = inode_file;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -37,21 +37,20 @@ int rc_pipe_command(char *cmd)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid < 0)
|
if (pid > 0) {
|
||||||
return -1;
|
|
||||||
else if (pid > 0) {
|
|
||||||
/* parent */
|
/* parent */
|
||||||
close(pfd[0]);
|
close(pfd[pipe_read_end]);
|
||||||
return pfd[pipe_write_end];
|
return pfd[pipe_write_end];
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
/* child */
|
/* child */
|
||||||
close(pfd[pipe_write_end]);
|
close(pfd[pipe_write_end]);
|
||||||
if (pfd[0] != STDIN_FILENO) {
|
if (pfd[pipe_read_end] != STDIN_FILENO) {
|
||||||
if (dup2(pfd[0], STDIN_FILENO) < 0)
|
if (dup2(pfd[pipe_read_end], STDIN_FILENO) < 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
close(pfd[0]);
|
close(pfd[pipe_read_end]);
|
||||||
}
|
}
|
||||||
execl("/bin/sh", "sh", "-c", cmd, NULL);
|
execl("/bin/sh", "sh", "-c", cmd, NULL);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ print_level(const char *prefix, const char *level)
|
|||||||
printf("%s\n", level);
|
printf("%s\n", level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_uptime(const char *service, char *uptime, int uptime_size)
|
static char *get_uptime(const char *service)
|
||||||
{
|
{
|
||||||
RC_SERVICE state = rc_service_state(service);
|
RC_SERVICE state = rc_service_state(service);
|
||||||
char *start_count;
|
char *start_count;
|
||||||
@@ -87,8 +87,8 @@ static void get_uptime(const char *service, char *uptime, int uptime_size)
|
|||||||
time_t diff_hours = (time_t) 0;
|
time_t diff_hours = (time_t) 0;
|
||||||
time_t diff_mins = (time_t) 0;
|
time_t diff_mins = (time_t) 0;
|
||||||
time_t diff_secs = (time_t) 0;
|
time_t diff_secs = (time_t) 0;
|
||||||
|
char *uptime = NULL;
|
||||||
|
|
||||||
uptime[0] = '\0';
|
|
||||||
if (state & RC_SERVICE_STARTED) {
|
if (state & RC_SERVICE_STARTED) {
|
||||||
start_count = rc_service_value_get(service, "start_count");
|
start_count = rc_service_value_get(service, "start_count");
|
||||||
start_time_string = rc_service_value_get(service, "start_time");
|
start_time_string = rc_service_value_get(service, "start_time");
|
||||||
@@ -110,23 +110,24 @@ static void get_uptime(const char *service, char *uptime, int uptime_size)
|
|||||||
diff_secs %= diff_mins * (time_t) 60;
|
diff_secs %= diff_mins * (time_t) 60;
|
||||||
}
|
}
|
||||||
if (diff_days > 0)
|
if (diff_days > 0)
|
||||||
snprintf(uptime, uptime_size,
|
xasprintf(&uptime,
|
||||||
"%ld day(s) %02ld:%02ld:%02ld (%s)",
|
"%ld day(s) %02ld:%02ld:%02ld (%s)",
|
||||||
diff_days, diff_hours, diff_mins, diff_secs,
|
diff_days, diff_hours, diff_mins, diff_secs,
|
||||||
start_count);
|
start_count);
|
||||||
else
|
else
|
||||||
snprintf(uptime, uptime_size,
|
xasprintf(&uptime,
|
||||||
"%02ld:%02ld:%02ld (%s)",
|
"%02ld:%02ld:%02ld (%s)",
|
||||||
diff_hours, diff_mins, diff_secs, start_count);
|
diff_hours, diff_mins, diff_secs, start_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return uptime;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_service(const char *service)
|
print_service(const char *service)
|
||||||
{
|
{
|
||||||
char status[60];
|
char *status = NULL;
|
||||||
char uptime [40];
|
char *uptime = NULL;
|
||||||
char *child_pid = NULL;
|
char *child_pid = NULL;
|
||||||
char *start_time = NULL;
|
char *start_time = NULL;
|
||||||
int cols = printf(" %s", service);
|
int cols = printf(" %s", service);
|
||||||
@@ -135,12 +136,12 @@ print_service(const char *service)
|
|||||||
ECOLOR color = ECOLOR_BAD;
|
ECOLOR color = ECOLOR_BAD;
|
||||||
|
|
||||||
if (state & RC_SERVICE_STOPPING)
|
if (state & RC_SERVICE_STOPPING)
|
||||||
snprintf(status, sizeof(status), "stopping ");
|
xasprintf(&status, "stopping ");
|
||||||
else if (state & RC_SERVICE_STARTING) {
|
else if (state & RC_SERVICE_STARTING) {
|
||||||
snprintf(status, sizeof(status), "starting ");
|
xasprintf(&status, "starting ");
|
||||||
color = ECOLOR_WARN;
|
color = ECOLOR_WARN;
|
||||||
} else if (state & RC_SERVICE_INACTIVE) {
|
} else if (state & RC_SERVICE_INACTIVE) {
|
||||||
snprintf(status, sizeof(status), "inactive ");
|
xasprintf(&status, "inactive ");
|
||||||
color = ECOLOR_WARN;
|
color = ECOLOR_WARN;
|
||||||
} else if (state & RC_SERVICE_STARTED) {
|
} else if (state & RC_SERVICE_STARTED) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
@@ -149,26 +150,31 @@ print_service(const char *service)
|
|||||||
child_pid = rc_service_value_get(service, "child_pid");
|
child_pid = rc_service_value_get(service, "child_pid");
|
||||||
start_time = rc_service_value_get(service, "start_time");
|
start_time = rc_service_value_get(service, "start_time");
|
||||||
if (start_time && child_pid)
|
if (start_time && child_pid)
|
||||||
snprintf(status, sizeof(status), " unsupervised ");
|
xasprintf(&status, " unsupervised ");
|
||||||
else
|
else
|
||||||
snprintf(status, sizeof(status), " crashed ");
|
xasprintf(&status, " crashed ");
|
||||||
free(child_pid);
|
free(child_pid);
|
||||||
free(start_time);
|
free(start_time);
|
||||||
} else {
|
} else {
|
||||||
get_uptime(service, uptime, 40);
|
uptime = get_uptime(service);
|
||||||
snprintf(status, sizeof(status), " started %s", uptime);
|
if (uptime) {
|
||||||
|
xasprintf(&status, " started %s", uptime);
|
||||||
|
free(uptime);
|
||||||
|
} else
|
||||||
|
xasprintf(&status, " started ");
|
||||||
color = ECOLOR_GOOD;
|
color = ECOLOR_GOOD;
|
||||||
}
|
}
|
||||||
} else if (state & RC_SERVICE_SCHEDULED) {
|
} else if (state & RC_SERVICE_SCHEDULED) {
|
||||||
snprintf(status, sizeof(status), "scheduled");
|
xasprintf(&status, "scheduled");
|
||||||
color = ECOLOR_WARN;
|
color = ECOLOR_WARN;
|
||||||
} else
|
} else
|
||||||
snprintf(status, sizeof(status), " stopped ");
|
xasprintf(&status, " stopped ");
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (c && *c && isatty(fileno(stdout)))
|
if (c && *c && isatty(fileno(stdout)))
|
||||||
printf("\n");
|
printf("\n");
|
||||||
ebracket(cols, color, status);
|
ebracket(cols, color, status);
|
||||||
|
free(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
40
src/rc/rc.c
40
src/rc/rc.c
@@ -101,7 +101,6 @@ clean_failed(void)
|
|||||||
{
|
{
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
size_t l;
|
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
/* Clean the failed services state dir now */
|
/* Clean the failed services state dir now */
|
||||||
@@ -112,16 +111,11 @@ clean_failed(void)
|
|||||||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
|
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
l = strlen(RC_SVCDIR "/failed/") +
|
xasprintf(&path, RC_SVCDIR "/failed/%s", d->d_name);
|
||||||
strlen(d->d_name) + 1;
|
if (unlink(path))
|
||||||
path = xmalloc(sizeof(char) * l);
|
eerror("%s: unlink `%s': %s",
|
||||||
snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name);
|
applet, path, strerror(errno));
|
||||||
if (path) {
|
free(path);
|
||||||
if (unlink(path))
|
|
||||||
eerror("%s: unlink `%s': %s",
|
|
||||||
applet, path, strerror(errno));
|
|
||||||
free(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
}
|
}
|
||||||
@@ -391,7 +385,7 @@ static void
|
|||||||
handle_signal(int sig)
|
handle_signal(int sig)
|
||||||
{
|
{
|
||||||
int serrno = errno;
|
int serrno = errno;
|
||||||
char signame[10] = { '\0' };
|
char *signame = NULL;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
RC_PID *pi;
|
RC_PID *pi;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
@@ -422,16 +416,16 @@ handle_signal(int sig)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
if (!signame[0])
|
if (!signame)
|
||||||
snprintf(signame, sizeof(signame), "SIGINT");
|
xasprintf(&signame, "SIGINT");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
if (!signame[0])
|
if (!signame)
|
||||||
snprintf(signame, sizeof(signame), "SIGTERM");
|
xasprintf(&signame, "SIGTERM");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SIGQUIT:
|
case SIGQUIT:
|
||||||
if (!signame[0])
|
if (!signame)
|
||||||
snprintf(signame, sizeof(signame), "SIGQUIT");
|
xasprintf(&signame, "SIGQUIT");
|
||||||
eerrorx("%s: caught %s, aborting", applet, signame);
|
eerrorx("%s: caught %s, aborting", applet, signame);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
case SIGUSR1:
|
case SIGUSR1:
|
||||||
@@ -512,14 +506,11 @@ runlevel_config(const char *service, const char *level)
|
|||||||
{
|
{
|
||||||
char *init = rc_service_resolve(service);
|
char *init = rc_service_resolve(service);
|
||||||
char *conf, *dir;
|
char *conf, *dir;
|
||||||
size_t l;
|
|
||||||
bool retval;
|
bool retval;
|
||||||
|
|
||||||
dir = dirname(init);
|
dir = dirname(init);
|
||||||
dir = dirname(init);
|
dir = dirname(init);
|
||||||
l = strlen(dir) + strlen(level) + strlen(service) + 10;
|
xasprintf(&conf, "%s/conf.d/%s.%s", dir, service, level);
|
||||||
conf = xmalloc(sizeof(char) * l);
|
|
||||||
snprintf(conf, l, "%s/conf.d/%s.%s", dir, service, level);
|
|
||||||
retval = exists(conf);
|
retval = exists(conf);
|
||||||
free(conf);
|
free(conf);
|
||||||
free(init);
|
free(init);
|
||||||
@@ -744,7 +735,7 @@ int main(int argc, char **argv)
|
|||||||
bool going_down = false;
|
bool going_down = false;
|
||||||
int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
|
int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
|
||||||
char *krunlevel = NULL;
|
char *krunlevel = NULL;
|
||||||
char pidstr[10];
|
char *pidstr = NULL;
|
||||||
int opt;
|
int opt;
|
||||||
bool parallel;
|
bool parallel;
|
||||||
int regen = 0;
|
int regen = 0;
|
||||||
@@ -844,8 +835,9 @@ int main(int argc, char **argv)
|
|||||||
setenv("EINFO_LOG", "openrc", 1);
|
setenv("EINFO_LOG", "openrc", 1);
|
||||||
|
|
||||||
/* Export our PID */
|
/* Export our PID */
|
||||||
snprintf(pidstr, sizeof(pidstr), "%d", getpid());
|
xasprintf(&pidstr, "%d", getpid());
|
||||||
setenv("RC_PID", pidstr, 1);
|
setenv("RC_PID", pidstr, 1);
|
||||||
|
free(pidstr);
|
||||||
|
|
||||||
/* Create a list of all services which should be started for the new or
|
/* Create a list of all services which should be started for the new or
|
||||||
* current runlevel including those in boot, sysinit and hotplugged
|
* current runlevel including those in boot, sysinit and hotplugged
|
||||||
|
|||||||
@@ -167,20 +167,20 @@ handle_signal(int sig)
|
|||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
int serrno = errno;
|
int serrno = errno;
|
||||||
char signame[10] = { '\0' };
|
char *signame = NULL;
|
||||||
|
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
if (!signame[0])
|
if (!signame)
|
||||||
snprintf(signame, sizeof(signame), "SIGINT");
|
xasprintf(&signame, "SIGINT");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
if (!signame[0])
|
if (!signame)
|
||||||
snprintf(signame, sizeof(signame), "SIGTERM");
|
xasprintf(&signame, "SIGTERM");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SIGQUIT:
|
case SIGQUIT:
|
||||||
if (!signame[0])
|
if (!signame)
|
||||||
snprintf(signame, sizeof(signame), "SIGQUIT");
|
xasprintf(&signame, "SIGQUIT");
|
||||||
eerrorx("%s: caught %s, aborting", applet, signame);
|
eerrorx("%s: caught %s, aborting", applet, signame);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
|
|
||||||
@@ -199,6 +199,9 @@ handle_signal(int sig)
|
|||||||
eerror("%s: caught unknown signal %d", applet, sig);
|
eerror("%s: caught unknown signal %d", applet, sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* free signame */
|
||||||
|
free(signame);
|
||||||
|
|
||||||
/* Restore errno */
|
/* Restore errno */
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
}
|
}
|
||||||
@@ -207,7 +210,6 @@ static char *
|
|||||||
expand_home(const char *home, const char *path)
|
expand_home(const char *home, const char *path)
|
||||||
{
|
{
|
||||||
char *opath, *ppath, *p, *nh;
|
char *opath, *ppath, *p, *nh;
|
||||||
size_t len;
|
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
||||||
if (!path || *path != '~')
|
if (!path || *path != '~')
|
||||||
@@ -238,9 +240,7 @@ expand_home(const char *home, const char *path)
|
|||||||
return xstrdup(home);
|
return xstrdup(home);
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(ppath) + strlen(home) + 1;
|
xasprintf(&nh, "%s%s", home, ppath);
|
||||||
nh = xmalloc(len);
|
|
||||||
snprintf(nh, len, "%s%s", home, ppath);
|
|
||||||
free(opath);
|
free(opath);
|
||||||
return nh;
|
return nh;
|
||||||
}
|
}
|
||||||
@@ -386,6 +386,7 @@ int main(int argc, char **argv)
|
|||||||
case 'c': /* --chuid <username>|<uid> */
|
case 'c': /* --chuid <username>|<uid> */
|
||||||
/* DEPRECATED */
|
/* DEPRECATED */
|
||||||
ewarn("WARNING: -c/--chuid is deprecated and will be removed in the future, please use -u/--user instead");
|
ewarn("WARNING: -c/--chuid is deprecated and will be removed in the future, please use -u/--user instead");
|
||||||
|
/* falls through */
|
||||||
case 'u': /* --user <username>|<uid> */
|
case 'u': /* --user <username>|<uid> */
|
||||||
{
|
{
|
||||||
p = optarg;
|
p = optarg;
|
||||||
|
|||||||
@@ -186,7 +186,6 @@ static void handle_signal(int sig)
|
|||||||
static char * expand_home(const char *home, const char *path)
|
static char * expand_home(const char *home, const char *path)
|
||||||
{
|
{
|
||||||
char *opath, *ppath, *p, *nh;
|
char *opath, *ppath, *p, *nh;
|
||||||
size_t len;
|
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
||||||
if (!path || *path != '~')
|
if (!path || *path != '~')
|
||||||
@@ -217,9 +216,7 @@ static char * expand_home(const char *home, const char *path)
|
|||||||
return xstrdup(home);
|
return xstrdup(home);
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(ppath) + strlen(home) + 1;
|
xasprintf(&nh, "%s%s", home, ppath);
|
||||||
nh = xmalloc(len);
|
|
||||||
snprintf(nh, len, "%s%s", home, ppath);
|
|
||||||
free(opath);
|
free(opath);
|
||||||
return nh;
|
return nh;
|
||||||
}
|
}
|
||||||
@@ -863,10 +860,13 @@ int main(int argc, char **argv)
|
|||||||
varbuf = NULL;
|
varbuf = NULL;
|
||||||
xasprintf(&varbuf, "%i", respawn_delay);
|
xasprintf(&varbuf, "%i", respawn_delay);
|
||||||
rc_service_value_set(svcname, "respawn_delay", varbuf);
|
rc_service_value_set(svcname, "respawn_delay", varbuf);
|
||||||
|
free(varbuf);
|
||||||
xasprintf(&varbuf, "%i", respawn_max);
|
xasprintf(&varbuf, "%i", respawn_max);
|
||||||
rc_service_value_set(svcname, "respawn_max", varbuf);
|
rc_service_value_set(svcname, "respawn_max", varbuf);
|
||||||
|
free(varbuf);
|
||||||
xasprintf(&varbuf, "%i", respawn_period);
|
xasprintf(&varbuf, "%i", respawn_period);
|
||||||
rc_service_value_set(svcname, "respawn_period", varbuf);
|
rc_service_value_set(svcname, "respawn_period", varbuf);
|
||||||
|
free(varbuf);
|
||||||
child_pid = fork();
|
child_pid = fork();
|
||||||
if (child_pid == -1)
|
if (child_pid == -1)
|
||||||
eerrorx("%s: fork: %s", applet, strerror(errno));
|
eerrorx("%s: fork: %s", applet, strerror(errno));
|
||||||
@@ -894,6 +894,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
xasprintf(&varbuf, "%d", x);
|
xasprintf(&varbuf, "%d", x);
|
||||||
rc_service_value_set(svcname, "argc", varbuf);
|
rc_service_value_set(svcname, "argc", varbuf);
|
||||||
|
free(varbuf);
|
||||||
rc_service_value_set(svcname, "exec", exec);
|
rc_service_value_set(svcname, "exec", exec);
|
||||||
supervisor(exec, argv);
|
supervisor(exec, argv);
|
||||||
} else
|
} else
|
||||||
|
|||||||
Reference in New Issue
Block a user