[procps-ng] - Introducing pidof (#987064)

Jaromír Cápík jcapik at fedoraproject.org
Thu Oct 17 15:55:19 UTC 2013


commit 2a194a1eb17559a1bf2f0dc09fd3f402a8add817
Author: Jaromir Capik <jcapik at redhat.com>
Date:   Thu Oct 17 17:55:10 2013 +0200

    - Introducing pidof (#987064)

 pidof                       |    5 +
 procps-ng-3.3.8-pidof.patch |  552 +++++++++++++++++++++++++++++++++++++++++++
 procps-ng.spec              |   19 ++-
 3 files changed, 574 insertions(+), 2 deletions(-)
---
diff --git a/pidof b/pidof
new file mode 100755
index 0000000..5bf33ee
--- /dev/null
+++ b/pidof
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+[ $0 = /sbin/pidof ] && echo -e "WARNING: pidof has been moved from /sbin to /usr/bin.\n         Please, change/remove the hardcoded path." 1>&2
+
+/usr/bin/pidof "$@"
diff --git a/procps-ng-3.3.8-pidof.patch b/procps-ng-3.3.8-pidof.patch
new file mode 100644
index 0000000..7c1b1a4
--- /dev/null
+++ b/procps-ng-3.3.8-pidof.patch
@@ -0,0 +1,552 @@
+diff --git a/Makefile.am b/Makefile.am
+index 3d66d60..7075e67 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -52,6 +52,14 @@ EXTRA_DIST = \
+ 	Documentation/TODO \
+ 	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
+ bin_PROGRAMS = kill
+ dist_man_MANS += kill.1
+diff --git a/pidof.1 b/pidof.1
+new file mode 100644
+index 0000000..f2544c8
+--- /dev/null
++++ b/pidof.1
+@@ -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 at redhat.com>
+diff --git a/pidof.c b/pidof.c
+new file mode 100644
+index 0000000..6cce24c
+--- /dev/null
++++ b/pidof.c
+@@ -0,0 +1,371 @@
++/*
++ * pidof.c - Utility for listing pids of running processes
++ *
++ * Copyright (C) 2013  Jaromir Capik <jcapik at 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/sig.h"
++#include "proc/devname.h"
++#include "proc/sysinfo.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[] = {
++		{"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;
++}
+-- 
+1.8.3.1
+
+diff --git a/pidof.c b/pidof.c
+index 6cce24c..a39a4c0 100644
+--- a/pidof.c
++++ b/pidof.c
+@@ -26,9 +26,6 @@
+ #include "nls.h"
+ #include "xalloc.h"
+ #include "proc/readproc.h"
+-#include "proc/sig.h"
+-#include "proc/devname.h"
+-#include "proc/sysinfo.h"
+ #include "proc/version.h" /* procps_version */
+ 
+ 
+@@ -284,6 +281,7 @@ int main (int argc, char **argv)
+ 	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'},
+-- 
+1.8.3.1
+
+diff --git a/pidof.1 b/pidof.1
+index f2544c8..f49cd23 100644
+--- a/pidof.1
++++ b/pidof.1
+@@ -44,7 +44,9 @@ the current root directory of processes they do not own.
+ 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.
++Tells \fIpidof\fP to omit processes with that process id. The special
++pid \fB%PPID\fP can be used to name the parent process of the \fIpidof\fP
++program, in other words the calling shell or shell script.
+ .SH "EXIT STATUS"
+ .TP
+ .B 0
+diff --git a/pidof.c b/pidof.c
+index a39a4c0..72344e7 100644
+--- a/pidof.c
++++ b/pidof.c
+@@ -246,10 +246,15 @@ static void add_to_omit_list (char *input_arg)
+ 	pid_t omit_pid;
+ 
+ 	omit_str = NULL;
+-	omit_str = strtok(input_arg, ",");
++	omit_str = strtok(input_arg, ",;:");
+ 	while (omit_str) {
+ 
+-		omit_pid = strtoul(omit_str, &endptr, 10);
++		if (!strcmp(omit_str,"%PPID")) {  /* keeping this %PPID garbage for backward compatibility only */
++			omit_pid = getppid();     /* ... as it can be replaced with $$ in common shells */
++			endptr = omit_str + sizeof("%PPID") - 1;
++		} else {
++			omit_pid = strtoul(omit_str, &endptr, 10);
++		}
+ 
+ 		if (*endptr == '\0') {
+ 			if (omit_count == omit_size) {
+@@ -265,7 +270,7 @@ static void add_to_omit_list (char *input_arg)
+ 			xwarnx(_("illegal omit pid value (%s)!\n"), omit_str);
+ 		}
+ 
+-		omit_str = strtok(NULL, ",");
++		omit_str = strtok(NULL, ",;:");
+ 	}
+ }
+ 
+diff -Naur procps-ng-3.3.8.orig/configure.ac procps-ng-3.3.8/configure.ac
+--- procps-ng-3.3.8.orig/configure.ac	2013-10-16 19:45:54.000000000 +0200
++++ procps-ng-3.3.8/configure.ac	2013-10-16 19:46:56.057000000 +0200
+@@ -168,6 +168,12 @@
+ fi
+ 
+ # 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],
+   AS_HELP_STRING([--disable-kill], [do not build kill]),
+   [], enable_kill=yes
diff --git a/procps-ng.spec b/procps-ng.spec
index 133305b..b2b960c 100644
--- a/procps-ng.spec
+++ b/procps-ng.spec
@@ -4,12 +4,13 @@
 Summary: System and process monitoring utilities
 Name: procps-ng
 Version: 3.3.8
-Release: 15%{?dist}
+Release: 16%{?dist}
 License: GPL+ and GPLv2 and GPLv2+ and GPLv3+ and LGPLv2+
 Group: Applications/System
 URL: https://sourceforge.net/projects/procps-ng/
 
-Source: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.xz
+Source0: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.xz
+Source1: pidof
 
 Patch0: 0001-top-add-the-major-version-to-dlopen-of-libnuma-sonam.patch
 Patch1: 0002-library-for-atexit-support-fix-fileutils-for-EPIPE.patch
@@ -24,6 +25,7 @@ Patch9: procps-add_support_for_linux_namespaces.patch
 Patch10: pgrep-introduce_support_for_namespaces.patch
 Patch11: skill-support_namespaces.patch
 Patch12: procps-fix_the_fatal_make_dist_error_for_nsutils.patch
+Patch13: procps-ng-3.3.8-pidof.patch
 
 Requires(post): /sbin/ldconfig
 Requires(postun): /sbin/ldconfig
@@ -48,6 +50,12 @@ Obsoletes: procps < 3.2.9-1
 Provides: /sbin/sysctl
 Provides: /bin/ps
 
+# sysvinit removal in Fedora 21
+Conflicts: sysvinit-tools < 0:2.88-14
+Obsoletes: sysvinit-tools > 0:2.88-14
+Provides: /sbin/pidof
+
+
 %description
 The procps package contains a set of system utilities that provide
 system information. Procps includes ps, free, skill, pkill, pgrep,
@@ -95,6 +103,8 @@ System and process monitoring utilities development headers
 %patch10 -p1
 %patch11 -p1
 %patch12 -p1
+%patch13 -p1
+
 
 %build
 # The following stuff is needed for git archives only
@@ -135,6 +145,8 @@ make DESTDIR=%{buildroot} install
 
 mkdir -p %{buildroot}%{_sysconfdir}/sysctl.d
 
+install -pm755 %{SOURCE1} %{buildroot}%{_sbindir}
+
 %post -p /sbin/ldconfig
 
 %postun -p /sbin/ldconfig
@@ -161,6 +173,9 @@ mkdir -p %{buildroot}%{_sysconfdir}/sysctl.d
 %{_includedir}/proc
 
 %changelog
+* Wed Oct 16 2013 Jaromir Capik <jcapik at redhat.com> - 3.3.8-16
+- Introducing pidof (#987064)
+
 * Tue Sep 17 2013 Aristeu Rozanski <aris at redhat.com> - 3.3.8-15
 - Introduce namespaces support (#1016242)
 


More information about the scm-commits mailing list