Merge branch 'master' of gitorious.org:procps/procps
This commit is contained in:
commit
8a2113bcf2
@ -52,6 +52,14 @@ EXTRA_DIST = \
|
|||||||
Documentation/TODO \
|
Documentation/TODO \
|
||||||
sysctl.conf
|
sysctl.conf
|
||||||
|
|
||||||
|
if BUILD_PIDOF
|
||||||
|
usrbin_exec_PROGRAMS += pidof
|
||||||
|
dist_man_MANS += pidof.1
|
||||||
|
pidof_SOURCES = pidof.c $(top_srcdir)/lib/fileutils.c
|
||||||
|
else
|
||||||
|
EXTRA_DIST += pidof.1
|
||||||
|
endif
|
||||||
|
|
||||||
if BUILD_KILL
|
if BUILD_KILL
|
||||||
bin_PROGRAMS = kill
|
bin_PROGRAMS = kill
|
||||||
dist_man_MANS += kill.1
|
dist_man_MANS += kill.1
|
||||||
|
@ -168,6 +168,12 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# AC_ARG_ENABLEs
|
# AC_ARG_ENABLEs
|
||||||
|
AC_ARG_ENABLE([pidof],
|
||||||
|
AS_HELP_STRING([--disable-pidof], [do not build pidof]),
|
||||||
|
[], [enable_pidof=yes]
|
||||||
|
)
|
||||||
|
AM_CONDITIONAL(BUILD_PIDOF, test "x$enable_pidof" = xyes)
|
||||||
|
|
||||||
AC_ARG_ENABLE([kill],
|
AC_ARG_ENABLE([kill],
|
||||||
AS_HELP_STRING([--disable-kill], [do not build kill]),
|
AS_HELP_STRING([--disable-kill], [do not build kill]),
|
||||||
[], [enable_kill=yes]
|
[], [enable_kill=yes]
|
||||||
|
60
pidof.1
Normal file
60
pidof.1
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
'\" -*- coding: UTF-8 -*-
|
||||||
|
.\" Copyright (C) 1998 Miquel van Smoorenburg.
|
||||||
|
.\"
|
||||||
|
.\" 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, write to the Free Software
|
||||||
|
.\" Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
.\"
|
||||||
|
.TH PIDOF 1 "24 Jul 2013" "" "User Commands"
|
||||||
|
.SH NAME
|
||||||
|
pidof -- find the process ID of a running program.
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B pidof
|
||||||
|
.RB [ \-s ]
|
||||||
|
.RB [ \-c ]
|
||||||
|
.RB [ \-x ]
|
||||||
|
.RB [ \-o
|
||||||
|
.IR omitpid[,omitpid..] ]
|
||||||
|
.RB [ \-o
|
||||||
|
.IR omitpid[,omitpid..].. ]
|
||||||
|
.B program
|
||||||
|
.RB [ program.. ]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B Pidof
|
||||||
|
finds the process id's (pids) of the named programs. It prints those
|
||||||
|
id's on the standard output.
|
||||||
|
.SH OPTIONS
|
||||||
|
.IP \-s
|
||||||
|
Single shot - this instructs the program to only return one \fIpid\fP.
|
||||||
|
.IP \-c
|
||||||
|
Only return process ids that are running with the same root directory.
|
||||||
|
This option is ignored for non-root users, as they will be unable to check
|
||||||
|
the current root directory of processes they do not own.
|
||||||
|
.IP \-x
|
||||||
|
Scripts too - this causes the program to also return process id's of
|
||||||
|
shells running the named scripts.
|
||||||
|
.IP "-o \fIomitpid\fP"
|
||||||
|
Tells \fIpidof\fP to omit processes with that process id.
|
||||||
|
.SH "EXIT STATUS"
|
||||||
|
.TP
|
||||||
|
.B 0
|
||||||
|
At least one program was found with the requested name.
|
||||||
|
.TP
|
||||||
|
.B 1
|
||||||
|
No program was found with the requested name.
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR pgrep (1),
|
||||||
|
.BR pkill (1)
|
||||||
|
.SH AUTHOR
|
||||||
|
Jaromir Capik <jcapik@redhat.com>
|
369
pidof.c
Normal file
369
pidof.c
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
/*
|
||||||
|
* pidof.c - Utility for listing pids of running processes
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Jaromir Capik <jcapik@redhat.com>
|
||||||
|
*
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include "c.h"
|
||||||
|
#include "fileutils.h"
|
||||||
|
#include "nls.h"
|
||||||
|
#include "xalloc.h"
|
||||||
|
#include "proc/readproc.h"
|
||||||
|
#include "proc/version.h" /* procps_version */
|
||||||
|
|
||||||
|
|
||||||
|
#define grow_size(x) (x = x * 5 / 4 + 1024)
|
||||||
|
#define safe_free(x) if (x) { free(x); x=NULL; }
|
||||||
|
|
||||||
|
|
||||||
|
struct el {
|
||||||
|
pid_t pid;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct el *procs = NULL;
|
||||||
|
static int proc_count = 0;
|
||||||
|
|
||||||
|
struct el *omitted_procs = NULL;
|
||||||
|
static int omit_count = 0;
|
||||||
|
|
||||||
|
static char *program = NULL;
|
||||||
|
|
||||||
|
/* switch flags */
|
||||||
|
static int opt_single_shot = 0; /* -s */
|
||||||
|
static int opt_scripts_too = 0; /* -x */
|
||||||
|
static int opt_rootdir_check = 0; /* -c */
|
||||||
|
|
||||||
|
static char *pidof_root = NULL;
|
||||||
|
|
||||||
|
static int __attribute__ ((__noreturn__)) usage(int opt)
|
||||||
|
{
|
||||||
|
int err = (opt == '?');
|
||||||
|
FILE *fp = err ? stderr : stdout;
|
||||||
|
|
||||||
|
fputs(USAGE_HEADER, fp);
|
||||||
|
fprintf(fp, _(" %s [options] [program [...]]\n"), program_invocation_short_name);
|
||||||
|
fputs(USAGE_OPTIONS, fp);
|
||||||
|
fputs(_(" -s, --single-shot return one PID only\n"
|
||||||
|
" -c, --check-root omit processes with different root\n"
|
||||||
|
" -x scripts too\n"
|
||||||
|
" -o, --omit-pid <PID,...> omit processes with PID\n"), fp);
|
||||||
|
fputs(USAGE_SEPARATOR, fp);
|
||||||
|
fputs(USAGE_HELP, fp);
|
||||||
|
fputs(USAGE_VERSION, fp);
|
||||||
|
fprintf(fp, USAGE_MAN_TAIL("pidof(1)"));
|
||||||
|
|
||||||
|
exit(fp == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int is_omitted (pid_t pid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < omit_count; i++) {
|
||||||
|
if (pid == omitted_procs[i].pid) return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *get_basename (char *filename)
|
||||||
|
{
|
||||||
|
char *pos;
|
||||||
|
char *result;
|
||||||
|
|
||||||
|
pos = result = filename;
|
||||||
|
while (*pos != '\0') {
|
||||||
|
if (*(pos++) == '/') result = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *pid_link (pid_t pid, const char *base_name)
|
||||||
|
{
|
||||||
|
char link [PROCPATHLEN];
|
||||||
|
char *result;
|
||||||
|
int path_alloc_size;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
snprintf(link, sizeof(link), "/proc/%d/%s", pid, base_name);
|
||||||
|
|
||||||
|
len = path_alloc_size = 0;
|
||||||
|
result = NULL;
|
||||||
|
do {
|
||||||
|
if (len == path_alloc_size) {
|
||||||
|
grow_size (path_alloc_size);
|
||||||
|
result = (char *) xrealloc (result, path_alloc_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((len = readlink(link, result, path_alloc_size - 1)) < 0) {
|
||||||
|
len = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (len == path_alloc_size);
|
||||||
|
|
||||||
|
result[len] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void select_procs (void)
|
||||||
|
{
|
||||||
|
PROCTAB *ptp;
|
||||||
|
proc_t task;
|
||||||
|
int match, root_check_ok;
|
||||||
|
static int size = 0;
|
||||||
|
char *cmd_arg0, *cmd_arg0base;
|
||||||
|
char *cmd_arg1, *cmd_arg1base;
|
||||||
|
char *pos;
|
||||||
|
char *program_base;
|
||||||
|
char *root_link;
|
||||||
|
char *exe_link;
|
||||||
|
char *exe_link_base;
|
||||||
|
|
||||||
|
/* get the input base name */
|
||||||
|
program_base = get_basename(program);
|
||||||
|
|
||||||
|
ptp = openproc (PROC_FILLCOM | PROC_FILLSTAT);
|
||||||
|
|
||||||
|
exe_link = root_link = NULL;
|
||||||
|
memset(&task, 0, sizeof (task));
|
||||||
|
while(readproc(ptp, &task)) {
|
||||||
|
|
||||||
|
if (opt_rootdir_check) {
|
||||||
|
/* get the /proc/<pid>/root symlink value */
|
||||||
|
root_link = pid_link(task.XXXID, "root");
|
||||||
|
match = !strcmp(pidof_root, root_link);
|
||||||
|
safe_free(root_link);
|
||||||
|
|
||||||
|
if (!match) { /* root check failed */
|
||||||
|
memset (&task, 0, sizeof (task));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_omitted(task.XXXID) && task.cmdline) {
|
||||||
|
|
||||||
|
cmd_arg0 = *task.cmdline;
|
||||||
|
|
||||||
|
/* processes starting with '-' are login shells */
|
||||||
|
if (*cmd_arg0 == '-') {
|
||||||
|
cmd_arg0++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the argv0 base name */
|
||||||
|
cmd_arg0base = get_basename(cmd_arg0);
|
||||||
|
|
||||||
|
/* get the /proc/<pid>/exe symlink value */
|
||||||
|
exe_link = pid_link(task.XXXID, "exe");
|
||||||
|
|
||||||
|
/* get the exe_link base name */
|
||||||
|
exe_link_base = get_basename(exe_link);
|
||||||
|
|
||||||
|
match = 0;
|
||||||
|
|
||||||
|
if (!strcmp(program, cmd_arg0base) ||
|
||||||
|
!strcmp(program_base, cmd_arg0) ||
|
||||||
|
!strcmp(program, cmd_arg0) ||
|
||||||
|
|
||||||
|
!strcmp(program, exe_link_base) ||
|
||||||
|
!strcmp(program, exe_link))
|
||||||
|
{
|
||||||
|
match = 1;
|
||||||
|
|
||||||
|
} else if (opt_scripts_too && *(task.cmdline+1)) {
|
||||||
|
|
||||||
|
pos = cmd_arg1base = cmd_arg1 = *(task.cmdline+1);
|
||||||
|
|
||||||
|
/* get the arg1 base name */
|
||||||
|
while (*pos != '\0') {
|
||||||
|
if (*(pos++) == '/') cmd_arg1base = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if script, then task.cmd = argv1, otherwise task.cmd = argv0 */
|
||||||
|
if (task.cmd &&
|
||||||
|
!strncmp(task.cmd, cmd_arg1base, strlen(task.cmd)) &&
|
||||||
|
(!strcmp(program, cmd_arg1base) ||
|
||||||
|
!strcmp(program_base, cmd_arg1) ||
|
||||||
|
!strcmp(program, cmd_arg1)))
|
||||||
|
{
|
||||||
|
match = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
safe_free(exe_link);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
if (proc_count == size) {
|
||||||
|
grow_size(size);
|
||||||
|
procs = xrealloc(procs, size * (sizeof *procs));
|
||||||
|
}
|
||||||
|
if (procs) {
|
||||||
|
procs[proc_count++].pid = task.XXXID;
|
||||||
|
} else {
|
||||||
|
xerrx(EXIT_FAILURE, _("internal error"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (&task, 0, sizeof (task));
|
||||||
|
}
|
||||||
|
|
||||||
|
closeproc (ptp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void add_to_omit_list (char *input_arg)
|
||||||
|
{
|
||||||
|
static int omit_size = 0;
|
||||||
|
|
||||||
|
char *omit_str;
|
||||||
|
char *endptr;
|
||||||
|
|
||||||
|
pid_t omit_pid;
|
||||||
|
|
||||||
|
omit_str = NULL;
|
||||||
|
omit_str = strtok(input_arg, ",");
|
||||||
|
while (omit_str) {
|
||||||
|
|
||||||
|
omit_pid = strtoul(omit_str, &endptr, 10);
|
||||||
|
|
||||||
|
if (*endptr == '\0') {
|
||||||
|
if (omit_count == omit_size) {
|
||||||
|
grow_size(omit_size);
|
||||||
|
omitted_procs = xrealloc(omitted_procs, omit_size * sizeof(*omitted_procs));
|
||||||
|
}
|
||||||
|
if (omitted_procs) {
|
||||||
|
omitted_procs[omit_count++].pid = omit_pid;
|
||||||
|
} else {
|
||||||
|
xerrx(EXIT_FAILURE, _("internal error"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
xwarnx(_("illegal omit pid value (%s)!\n"), omit_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
omit_str = strtok(NULL, ",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int opt;
|
||||||
|
signed int i;
|
||||||
|
int found = 0;
|
||||||
|
int first_pid = 1;
|
||||||
|
|
||||||
|
const char *opts = "scnxmo:?Vh";
|
||||||
|
|
||||||
|
static const struct option longopts[] = {
|
||||||
|
{"check-root", no_argument, NULL, 'c'},
|
||||||
|
{"single-shot", no_argument, NULL, 's'},
|
||||||
|
{"omit-pid", required_argument, NULL, 'o'},
|
||||||
|
{"help", no_argument, NULL, 'h'},
|
||||||
|
{"version", no_argument, NULL, 'V'},
|
||||||
|
{NULL, 0, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_PROGRAM_INVOCATION_NAME
|
||||||
|
program_invocation_name = program_invocation_short_name;
|
||||||
|
#endif
|
||||||
|
setlocale (LC_ALL, "");
|
||||||
|
bindtextdomain (PACKAGE, LOCALEDIR);
|
||||||
|
textdomain (PACKAGE);
|
||||||
|
atexit (close_stdout);
|
||||||
|
|
||||||
|
/* process command-line options */
|
||||||
|
while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 's':
|
||||||
|
opt_single_shot = 1;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
add_to_omit_list (optarg);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
opt_scripts_too = 1;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
if (geteuid() == 0) {
|
||||||
|
opt_rootdir_check = 1;
|
||||||
|
pidof_root = pid_link(getpid(), "root");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
printf (PROCPS_NG_VERSION);
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
case 'h':
|
||||||
|
case '?':
|
||||||
|
usage (opt);
|
||||||
|
break;
|
||||||
|
/* compatibility-only switches */
|
||||||
|
case 'n': /* avoiding stat(2) on NFS volumes doesn't make any sense anymore ... */
|
||||||
|
/* ... as this reworked solution does not use stat(2) at all */
|
||||||
|
case 'm': /* omitting relatives with argv[0] & argv[1] matching the argv[0] & argv[1] ...*/
|
||||||
|
/* ... of explicitly omitted PIDs is too 'expensive' and as we don't know */
|
||||||
|
/* ... wheter it is still needed, we won't re-implement it unless ... */
|
||||||
|
/* ... somebody gives us a good reason to do so :) */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* main loop */
|
||||||
|
while (argc - optind) { /* for each program */
|
||||||
|
|
||||||
|
program = argv[optind++];
|
||||||
|
|
||||||
|
select_procs(); /* get the list of matching processes */
|
||||||
|
|
||||||
|
if (proc_count) {
|
||||||
|
|
||||||
|
found = 1;
|
||||||
|
for (i = proc_count - 1; i >= 0; i--) { /* and display their PIDs */
|
||||||
|
if (first_pid) {
|
||||||
|
first_pid = 0;
|
||||||
|
printf ("%ld", procs[i].pid);
|
||||||
|
} else {
|
||||||
|
printf (" %ld", procs[i].pid);
|
||||||
|
}
|
||||||
|
if (opt_single_shot) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* final line feed */
|
||||||
|
if (found) printf("\n");
|
||||||
|
|
||||||
|
/* some cleaning */
|
||||||
|
safe_free(procs);
|
||||||
|
safe_free(omitted_procs);
|
||||||
|
safe_free(pidof_root);
|
||||||
|
|
||||||
|
return !found;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user