pgrep: add pwait
This commit is contained in:
parent
9f33a6bcd0
commit
c8384e682c
1
.gitignore
vendored
1
.gitignore
vendored
@ -37,6 +37,7 @@ pgrep
|
|||||||
pidof
|
pidof
|
||||||
pkill
|
pkill
|
||||||
pmap
|
pmap
|
||||||
|
pwait
|
||||||
procps-ng-*.tar.xz
|
procps-ng-*.tar.xz
|
||||||
proc/.depend
|
proc/.depend
|
||||||
proc/libprocps.la
|
proc/libprocps.la
|
||||||
|
10
Makefile.am
10
Makefile.am
@ -54,6 +54,9 @@ bin_PROGRAMS = \
|
|||||||
uptime \
|
uptime \
|
||||||
vmstat \
|
vmstat \
|
||||||
w
|
w
|
||||||
|
if BUILD_PWAIT
|
||||||
|
bin_PROGRAMS += pwait
|
||||||
|
endif
|
||||||
else
|
else
|
||||||
usrbin_exec_PROGRAMS += \
|
usrbin_exec_PROGRAMS += \
|
||||||
ps/pscommand \
|
ps/pscommand \
|
||||||
@ -88,6 +91,10 @@ dist_man_MANS += \
|
|||||||
sysctl.8 \
|
sysctl.8 \
|
||||||
sysctl.conf.5 \
|
sysctl.conf.5 \
|
||||||
ps/ps.1
|
ps/ps.1
|
||||||
|
|
||||||
|
if BUILD_PWAIT
|
||||||
|
dist_man_MANS += pwait.1
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
@ -201,6 +208,9 @@ free_SOURCES = free.c lib/strutils.c lib/fileutils.c
|
|||||||
pgrep_SOURCES = pgrep.c lib/fileutils.c lib/signals.c
|
pgrep_SOURCES = pgrep.c lib/fileutils.c lib/signals.c
|
||||||
pkill_SOURCES = pgrep.c lib/fileutils.c lib/signals.c
|
pkill_SOURCES = pgrep.c lib/fileutils.c lib/signals.c
|
||||||
pmap_SOURCES = pmap.c lib/fileutils.c
|
pmap_SOURCES = pmap.c lib/fileutils.c
|
||||||
|
if BUILD_PWAIT
|
||||||
|
pwait_SOURCES = pgrep.c lib/fileutils.c lib/nsutils.c
|
||||||
|
endif
|
||||||
if !CYGWIN
|
if !CYGWIN
|
||||||
pwdx_SOURCES = pwdx.c lib/fileutils.c
|
pwdx_SOURCES = pwdx.c lib/fileutils.c
|
||||||
pwdx_LDADD= $(CYGWINFLAGS)
|
pwdx_LDADD= $(CYGWINFLAGS)
|
||||||
|
16
configure.ac
16
configure.ac
@ -10,6 +10,7 @@ AM_INIT_AUTOMAKE([foreign 1.11 subdir-objects -Wall -Wno-portability tar-pax no-
|
|||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
AC_CONFIG_SRCDIR([free.c])
|
AC_CONFIG_SRCDIR([free.c])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
AC_LANG([C])
|
||||||
|
|
||||||
# Checks for programs.
|
# Checks for programs.
|
||||||
AC_USE_SYSTEM_EXTENSIONS
|
AC_USE_SYSTEM_EXTENSIONS
|
||||||
@ -120,6 +121,21 @@ AC_TRY_COMPILE([#include <errno.h>],
|
|||||||
AC_MSG_RESULT(yes),
|
AC_MSG_RESULT(yes),
|
||||||
AC_MSG_RESULT(no))
|
AC_MSG_RESULT(no))
|
||||||
|
|
||||||
|
AC_CHECK_FUNC([pidfd_open], [enable_pwait=yes], [
|
||||||
|
AC_MSG_CHECKING([for __NR_pidfd_open])
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#ifndef __NR_pidfd_open
|
||||||
|
#error __NR_pidfd_open not defined
|
||||||
|
#endif
|
||||||
|
])], [enable_pwait=yes], [enable_pwait=no])
|
||||||
|
AC_MSG_RESULT([$enable_pwait])
|
||||||
|
])
|
||||||
|
if test "$enable_pwait" = yes; then
|
||||||
|
AC_DEFINE([ENABLE_PWAIT], [1], [Enable pwait])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL([BUILD_PWAIT], [test x$enable_pwait = xyes])
|
||||||
|
|
||||||
dnl watch8bit must be before the AC_ARG_WITH set as it sets up ncurses
|
dnl watch8bit must be before the AC_ARG_WITH set as it sets up ncurses
|
||||||
AC_SUBST([WITH_WATCH8BIT])
|
AC_SUBST([WITH_WATCH8BIT])
|
||||||
AC_ARG_ENABLE([watch8bit],
|
AC_ARG_ENABLE([watch8bit],
|
||||||
|
39
pgrep.1
39
pgrep.1
@ -9,13 +9,16 @@
|
|||||||
.\"
|
.\"
|
||||||
.TH PGREP "1" "2020-06-04" "procps-ng" "User Commands"
|
.TH PGREP "1" "2020-06-04" "procps-ng" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
pgrep, pkill \- look up or signal processes based on name and other attributes
|
pgrep, pkill, pwait \- look up, signal, or wait for processes based on name and other attributes
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B pgrep
|
.B pgrep
|
||||||
[options] pattern
|
[options] pattern
|
||||||
.br
|
.br
|
||||||
.B pkill
|
.B pkill
|
||||||
[options] pattern
|
[options] pattern
|
||||||
|
.br
|
||||||
|
.B pwait
|
||||||
|
[options] pattern
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B pgrep
|
.B pgrep
|
||||||
looks through the currently running processes and lists the process IDs which
|
looks through the currently running processes and lists the process IDs which
|
||||||
@ -41,6 +44,9 @@ OR
|
|||||||
will send the specified signal (by default
|
will send the specified signal (by default
|
||||||
.BR SIGTERM )
|
.BR SIGTERM )
|
||||||
to each process instead of listing them on stdout.
|
to each process instead of listing them on stdout.
|
||||||
|
.PP
|
||||||
|
.B pwait
|
||||||
|
will wait for each process instead of listing them on stdout.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
\fB\-\fR\fIsignal\fP
|
\fB\-\fR\fIsignal\fP
|
||||||
@ -54,7 +60,9 @@ only.)
|
|||||||
\fB\-c\fR, \fB\-\-count\fR
|
\fB\-c\fR, \fB\-\-count\fR
|
||||||
Suppress normal output; instead print a count of matching processes. When
|
Suppress normal output; instead print a count of matching processes. When
|
||||||
count does not match anything, e.g. returns zero, the command will return
|
count does not match anything, e.g. returns zero, the command will return
|
||||||
non-zero value.
|
non-zero value. Note that for pkill and pwait, the count is the number of
|
||||||
|
matching processes, not the processes that were successfully signaled or waited
|
||||||
|
for.
|
||||||
.TP
|
.TP
|
||||||
\fB\-d\fR, \fB\-\-delimiter\fR \fIdelimiter\fP
|
\fB\-d\fR, \fB\-\-delimiter\fR \fIdelimiter\fP
|
||||||
Sets the string used to delimit each process ID in the output (by default a
|
Sets the string used to delimit each process ID in the output (by default a
|
||||||
@ -77,9 +85,10 @@ is set, the full command line is used.
|
|||||||
\fB\-g\fR, \fB\-\-pgroup\fR \fIpgrp\fP,...
|
\fB\-g\fR, \fB\-\-pgroup\fR \fIpgrp\fP,...
|
||||||
Only match processes in the process group IDs listed. Process group 0 is
|
Only match processes in the process group IDs listed. Process group 0 is
|
||||||
translated into
|
translated into
|
||||||
.BR pgrep 's
|
.BR pgrep 's,
|
||||||
|
.BR pkill 's,
|
||||||
or
|
or
|
||||||
.BR pkill 's
|
.BR pwait 's
|
||||||
own process group.
|
own process group.
|
||||||
.TP
|
.TP
|
||||||
\fB\-G\fR, \fB\-\-group\fR \fIgid\fP,...
|
\fB\-G\fR, \fB\-\-group\fR \fIgid\fP,...
|
||||||
@ -114,9 +123,10 @@ Only match processes whose parent process ID is listed.
|
|||||||
\fB\-s\fR, \fB\-\-session\fR \fIsid\fP,...
|
\fB\-s\fR, \fB\-\-session\fR \fIsid\fP,...
|
||||||
Only match processes whose process session ID is listed. Session ID 0
|
Only match processes whose process session ID is listed. Session ID 0
|
||||||
is translated into
|
is translated into
|
||||||
.BR pgrep 's
|
.BR pgrep 's,
|
||||||
|
.BR pkill 's,
|
||||||
or
|
or
|
||||||
.BR pkill 's
|
.BR pwait 's
|
||||||
own session ID.
|
own session ID.
|
||||||
.TP
|
.TP
|
||||||
\fB\-t\fR, \fB\-\-terminal\fR \fIterm\fP,...
|
\fB\-t\fR, \fB\-\-terminal\fR \fIterm\fP,...
|
||||||
@ -134,6 +144,8 @@ symbolical value may be used.
|
|||||||
\fB\-v\fR, \fB\-\-inverse\fR\fR
|
\fB\-v\fR, \fB\-\-inverse\fR\fR
|
||||||
Negates the matching. This option is usually used in
|
Negates the matching. This option is usually used in
|
||||||
.BR pgrep 's
|
.BR pgrep 's
|
||||||
|
or
|
||||||
|
.BR pwait 's
|
||||||
context. In
|
context. In
|
||||||
.BR pkill 's
|
.BR pkill 's
|
||||||
context the short option is disabled to avoid accidental usage of the option.
|
context the short option is disabled to avoid accidental usage of the option.
|
||||||
@ -141,6 +153,8 @@ context the short option is disabled to avoid accidental usage of the option.
|
|||||||
\fB\-w\fR, \fB\-\-lightweight\fR\fR
|
\fB\-w\fR, \fB\-\-lightweight\fR\fR
|
||||||
Shows all thread ids instead of pids in
|
Shows all thread ids instead of pids in
|
||||||
.BR pgrep 's
|
.BR pgrep 's
|
||||||
|
or
|
||||||
|
.BR pwait 's
|
||||||
context. In
|
context. In
|
||||||
.BR pkill 's
|
.BR pkill 's
|
||||||
context this option is disabled.
|
context this option is disabled.
|
||||||
@ -152,8 +166,8 @@ match the
|
|||||||
.IR pattern .
|
.IR pattern .
|
||||||
.TP
|
.TP
|
||||||
\fB\-F\fR, \fB\-\-pidfile\fR \fIfile\fR
|
\fB\-F\fR, \fB\-\-pidfile\fR \fIfile\fR
|
||||||
Read \fIPID\fRs from \fIfile\fR. This option is perhaps more useful for
|
Read \fIPID\fRs from \fIfile\fR. This option is more useful for
|
||||||
.B pkill
|
.BR pkill or pwait
|
||||||
than
|
than
|
||||||
.BR pgrep .
|
.BR pgrep .
|
||||||
.TP
|
.TP
|
||||||
@ -223,8 +237,8 @@ $ renice +4 $(pgrep chrome)
|
|||||||
.PD 0
|
.PD 0
|
||||||
.TP
|
.TP
|
||||||
0
|
0
|
||||||
One or more processes matched the criteria. For pkill the process must also
|
One or more processes matched the criteria. For pkill and pwait, one or more
|
||||||
have been successfully signalled.
|
processes must also have been successfully signalled or waited for.
|
||||||
.TP
|
.TP
|
||||||
1
|
1
|
||||||
No processes matched or none of them could be signalled.
|
No processes matched or none of them could be signalled.
|
||||||
@ -242,9 +256,10 @@ complete command line, /proc/\fIpid\fP/cmdline. Threads may not have the
|
|||||||
same process name as the parent process but will have the same command line.
|
same process name as the parent process but will have the same command line.
|
||||||
.PP
|
.PP
|
||||||
The running
|
The running
|
||||||
.B pgrep
|
.BR pgrep ,
|
||||||
|
.BR pkill ,
|
||||||
or
|
or
|
||||||
.B pkill
|
.B pwait
|
||||||
process will never report itself as a
|
process will never report itself as a
|
||||||
match.
|
match.
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
|
112
pgrep.c
112
pgrep.c
@ -38,6 +38,11 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#if defined(ENABLE_PWAIT) && !defined(HAVE_PIDFD_OPEN)
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* EXIT_SUCCESS is 0 */
|
/* EXIT_SUCCESS is 0 */
|
||||||
/* EXIT_FAILURE is 1 */
|
/* EXIT_FAILURE is 1 */
|
||||||
#define EXIT_USAGE 2
|
#define EXIT_USAGE 2
|
||||||
@ -80,7 +85,13 @@ enum rel_items {
|
|||||||
(x) = (x) * 5 / 4 + 4; \
|
(x) = (x) * 5 / 4 + 4; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static int i_am_pkill = 0;
|
static enum {
|
||||||
|
PGREP = 0,
|
||||||
|
PKILL,
|
||||||
|
#ifdef ENABLE_PWAIT
|
||||||
|
PWAIT,
|
||||||
|
#endif
|
||||||
|
} prog_mode;
|
||||||
|
|
||||||
struct el {
|
struct el {
|
||||||
long num;
|
long num;
|
||||||
@ -132,17 +143,23 @@ static int __attribute__ ((__noreturn__)) usage(int opt)
|
|||||||
fputs(USAGE_HEADER, fp);
|
fputs(USAGE_HEADER, fp);
|
||||||
fprintf(fp, _(" %s [options] <pattern>\n"), program_invocation_short_name);
|
fprintf(fp, _(" %s [options] <pattern>\n"), program_invocation_short_name);
|
||||||
fputs(USAGE_OPTIONS, fp);
|
fputs(USAGE_OPTIONS, fp);
|
||||||
if (i_am_pkill == 0) {
|
switch (prog_mode) {
|
||||||
|
case PGREP:
|
||||||
fputs(_(" -d, --delimiter <string> specify output delimiter\n"),fp);
|
fputs(_(" -d, --delimiter <string> specify output delimiter\n"),fp);
|
||||||
fputs(_(" -l, --list-name list PID and process name\n"),fp);
|
fputs(_(" -l, --list-name list PID and process name\n"),fp);
|
||||||
fputs(_(" -a, --list-full list PID and full command line\n"),fp);
|
fputs(_(" -a, --list-full list PID and full command line\n"),fp);
|
||||||
fputs(_(" -v, --inverse negates the matching\n"),fp);
|
fputs(_(" -v, --inverse negates the matching\n"),fp);
|
||||||
fputs(_(" -w, --lightweight list all TID\n"), fp);
|
fputs(_(" -w, --lightweight list all TID\n"), fp);
|
||||||
}
|
break;
|
||||||
if (i_am_pkill == 1) {
|
case PKILL:
|
||||||
fputs(_(" -<sig>, --signal <sig> signal to send (either number or name)\n"), fp);
|
fputs(_(" -<sig>, --signal <sig> signal to send (either number or name)\n"), fp);
|
||||||
fputs(_(" -q, --queue <value> integer value to be sent with the signal\n"), fp);
|
fputs(_(" -q, --queue <value> integer value to be sent with the signal\n"), fp);
|
||||||
fputs(_(" -e, --echo display what is killed\n"), fp);
|
fputs(_(" -e, --echo display what is killed\n"), fp);
|
||||||
|
#ifdef ENABLE_PWAIT
|
||||||
|
case PWAIT:
|
||||||
|
fputs(_(" -e, --echo display PIDs before waiting\n"), fp);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
fputs(_(" -c, --count count of matching processes\n"), fp);
|
fputs(_(" -c, --count count of matching processes\n"), fp);
|
||||||
fputs(_(" -f, --full use full process name to match\n"), fp);
|
fputs(_(" -f, --full use full process name to match\n"), fp);
|
||||||
@ -676,6 +693,13 @@ static int signal_option(int *argc, char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(ENABLE_PWAIT) && !defined(HAVE_PIDFD_OPEN)
|
||||||
|
static int pidfd_open (pid_t pid, unsigned int flags)
|
||||||
|
{
|
||||||
|
return syscall(__NR_pidfd_open, pid, flags);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void parse_opts (int argc, char **argv)
|
static void parse_opts (int argc, char **argv)
|
||||||
{
|
{
|
||||||
char opts[64] = "";
|
char opts[64] = "";
|
||||||
@ -720,17 +744,22 @@ static void parse_opts (int argc, char **argv)
|
|||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (strstr (program_invocation_short_name, "pkill")) {
|
#ifdef ENABLE_PWAIT
|
||||||
|
if (strcmp (program_invocation_short_name, "pwait") == 0) {
|
||||||
|
prog_mode = PWAIT;
|
||||||
|
strcat (opts, "e");
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (strcmp (program_invocation_short_name, "pkill") == 0) {
|
||||||
int sig;
|
int sig;
|
||||||
i_am_pkill = 1;
|
prog_mode = PKILL;
|
||||||
sig = signal_option(&argc, argv);
|
sig = signal_option(&argc, argv);
|
||||||
if (-1 < sig)
|
if (-1 < sig)
|
||||||
opt_signal = sig;
|
opt_signal = sig;
|
||||||
/* These options are for pkill only */
|
|
||||||
strcat (opts, "eq:");
|
strcat (opts, "eq:");
|
||||||
} else {
|
} else {
|
||||||
/* These options are for pgrep only */
|
|
||||||
strcat (opts, "lad:vw");
|
strcat (opts, "lad:vw");
|
||||||
|
prog_mode = PGREP;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcat (opts, "LF:cfinoxP:O:g:s:u:U:G:t:r:?Vh");
|
strcat (opts, "LF:cfinoxP:O:g:s:u:U:G:t:r:?Vh");
|
||||||
@ -868,9 +897,6 @@ static void parse_opts (int argc, char **argv)
|
|||||||
case NS_OPTION:
|
case NS_OPTION:
|
||||||
opt_ns_pid = atoi(optarg);
|
opt_ns_pid = atoi(optarg);
|
||||||
if (opt_ns_pid == 0)
|
if (opt_ns_pid == 0)
|
||||||
usage ('?');
|
|
||||||
++criteria_count;
|
|
||||||
break;
|
|
||||||
case 'r': /* match by runstate */
|
case 'r': /* match by runstate */
|
||||||
opt_runstates = xstrdup (optarg);
|
opt_runstates = xstrdup (optarg);
|
||||||
++criteria_count;
|
++criteria_count;
|
||||||
@ -929,6 +955,14 @@ int main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
struct el *procs;
|
struct el *procs;
|
||||||
int num;
|
int num;
|
||||||
|
int i;
|
||||||
|
int kill_count = 0;
|
||||||
|
#ifdef ENABLE_PWAIT
|
||||||
|
int poll_count = 0;
|
||||||
|
int wait_count = 0;
|
||||||
|
int epollfd = epoll_create(1);
|
||||||
|
struct epoll_event ev, events[32];
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_PROGRAM_INVOCATION_NAME
|
#ifdef HAVE_PROGRAM_INVOCATION_NAME
|
||||||
program_invocation_name = program_invocation_short_name;
|
program_invocation_name = program_invocation_short_name;
|
||||||
@ -941,9 +975,18 @@ int main (int argc, char **argv)
|
|||||||
parse_opts (argc, argv);
|
parse_opts (argc, argv);
|
||||||
|
|
||||||
procs = select_procs (&num);
|
procs = select_procs (&num);
|
||||||
if (i_am_pkill) {
|
switch (prog_mode) {
|
||||||
int i;
|
case PGREP:
|
||||||
int kill_count = 0;
|
if (opt_count) {
|
||||||
|
fprintf(stdout, "%d\n", num);
|
||||||
|
} else {
|
||||||
|
if (opt_long || opt_longlong)
|
||||||
|
output_strlist (procs,num);
|
||||||
|
else
|
||||||
|
output_numlist (procs,num);
|
||||||
|
}
|
||||||
|
return !num;
|
||||||
|
case PKILL:
|
||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
if (execute_kill (procs[i].num, opt_signal) != -1) {
|
if (execute_kill (procs[i].num, opt_signal) != -1) {
|
||||||
if (opt_echo)
|
if (opt_echo)
|
||||||
@ -959,15 +1002,40 @@ int main (int argc, char **argv)
|
|||||||
if (opt_count)
|
if (opt_count)
|
||||||
fprintf(stdout, "%d\n", num);
|
fprintf(stdout, "%d\n", num);
|
||||||
return !kill_count;
|
return !kill_count;
|
||||||
} else {
|
#ifdef ENABLE_PWAIT
|
||||||
if (opt_count) {
|
case PWAIT:
|
||||||
|
if (opt_count)
|
||||||
fprintf(stdout, "%d\n", num);
|
fprintf(stdout, "%d\n", num);
|
||||||
} else {
|
|
||||||
if (opt_long || opt_longlong)
|
for (i = 0; i < num; i++) {
|
||||||
output_strlist (procs,num);
|
if (opt_echo)
|
||||||
else
|
printf(_("waiting for %s (pid %lu)\n"), procs[i].str, procs[i].num);
|
||||||
output_numlist (procs,num);
|
int pidfd = pidfd_open(procs[i].num, 0);
|
||||||
|
if (pidfd == -1) {
|
||||||
|
/* ignore ESRCH, same as pkill */
|
||||||
|
if (errno != ESRCH)
|
||||||
|
xwarn(_("opening pid %ld failed"), procs[i].num);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
ev.events = EPOLLIN | EPOLLET;
|
||||||
|
ev.data.fd = pidfd;
|
||||||
|
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pidfd, &ev) != -1)
|
||||||
|
poll_count++;
|
||||||
}
|
}
|
||||||
return !num; /* exit(EXIT_SUCCESS) if match, otherwise exit(EXIT_FAILURE) */
|
|
||||||
|
while (wait_count < poll_count) {
|
||||||
|
int ew = epoll_wait(epollfd, events, sizeof(events)/sizeof(events[0]), -1);
|
||||||
|
if (ew == -1) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
xwarn(_("epoll_wait failed"));
|
||||||
|
}
|
||||||
|
wait_count += ew;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !wait_count;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/* Not sure if it is possible to get here */
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user