* pidof/killall5 - make omit pid list a dynamic one.
* pidof - provide '-n' to skip stat(2) syscall on network based FS.
This commit is contained in:
@@ -11,6 +11,8 @@
|
|||||||
* Flush block devices on halt/reboot if not done by the kernel.
|
* Flush block devices on halt/reboot if not done by the kernel.
|
||||||
* Set SHELL to /bin/sh in the environmant of shutdown.
|
* Set SHELL to /bin/sh in the environmant of shutdown.
|
||||||
* Retry to write out shutdown messages if interrupted.
|
* Retry to write out shutdown messages if interrupted.
|
||||||
|
* pidof/killall5 - make omit pid list a dynamic one.
|
||||||
|
* pidof - provide '-n' to skip stat(2) syscall on network based FS.
|
||||||
|
|
||||||
sysvinit (2.88dsf) UNRELEASED; urgency=low
|
sysvinit (2.88dsf) UNRELEASED; urgency=low
|
||||||
|
|
||||||
|
@@ -22,9 +22,9 @@ killall5 -- send a signal to all processes.
|
|||||||
.B killall5
|
.B killall5
|
||||||
.RB -signalnumber
|
.RB -signalnumber
|
||||||
.RB [ \-o
|
.RB [ \-o
|
||||||
.IR omitpid ]
|
.IR omitpid[,omitpid..]]
|
||||||
.RB [ \-o
|
.RB [ \-o
|
||||||
.IR omitpid.. ]
|
.IR omitpid[,omitpid..].. ]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B killall5
|
.B killall5
|
||||||
is the SystemV killall command. It sends a signal to all processes except
|
is the SystemV killall command. It sends a signal to all processes except
|
||||||
|
20
man/pidof.8
20
man/pidof.8
@@ -22,11 +22,12 @@ pidof -- find the process ID of a running program.
|
|||||||
.B pidof
|
.B pidof
|
||||||
.RB [ \-s ]
|
.RB [ \-s ]
|
||||||
.RB [ \-c ]
|
.RB [ \-c ]
|
||||||
|
.RB [ \-n ]
|
||||||
.RB [ \-x ]
|
.RB [ \-x ]
|
||||||
.RB [ \-o
|
.RB [ \-o
|
||||||
.IR omitpid ]
|
.IR omitpid[,omitpid..] ]
|
||||||
.RB [ \-o
|
.RB [ \-o
|
||||||
.IR omitpid.. ]
|
.IR omitpid[,omitpid..].. ]
|
||||||
.B program
|
.B program
|
||||||
.RB [ program.. ]
|
.RB [ program.. ]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
@@ -40,13 +41,22 @@ a
|
|||||||
.B start-stop-daemon
|
.B start-stop-daemon
|
||||||
(8) program that should be used instead.
|
(8) program that should be used instead.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.IP -s
|
.IP \-s
|
||||||
Single shot - this instructs the program to only return one \fIpid\fP.
|
Single shot - this instructs the program to only return one \fIpid\fP.
|
||||||
.IP -c
|
.IP \-c
|
||||||
Only return process ids that are running with the same root directory.
|
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
|
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.
|
the current root directory of processes they do not own.
|
||||||
.IP -x
|
.IP \-n
|
||||||
|
Avoid
|
||||||
|
.BR stat (2)
|
||||||
|
system function call on all binaries which are located on network
|
||||||
|
based file systems like
|
||||||
|
.BR NFS .
|
||||||
|
Instead of using this option the the variable
|
||||||
|
.B PIDOF_NETFS
|
||||||
|
may be set and exported.
|
||||||
|
.IP \-x
|
||||||
Scripts too - this causes the program to also return process id's of
|
Scripts too - this causes the program to also return process id's of
|
||||||
shells running the named scripts.
|
shells running the named scripts.
|
||||||
.IP "-o \fIomitpid\fP"
|
.IP "-o \fIomitpid\fP"
|
||||||
|
518
src/killall5.c
518
src/killall5.c
@@ -19,6 +19,10 @@
|
|||||||
* - syslog() only if not a connected to controlling terminal
|
* - syslog() only if not a connected to controlling terminal
|
||||||
* - swapped out programs pids are caught now
|
* - swapped out programs pids are caught now
|
||||||
*
|
*
|
||||||
|
* Werner Fink
|
||||||
|
* - make omit dynamic
|
||||||
|
* - provide '-n' to skip stat(2) syscall on network based FS
|
||||||
|
*
|
||||||
* This file is part of the sysvinit suite,
|
* This file is part of the sysvinit suite,
|
||||||
* Copyright (C) 1991-2004 Miquel van Smoorenburg.
|
* Copyright (C) 1991-2004 Miquel van Smoorenburg.
|
||||||
*
|
*
|
||||||
@@ -36,24 +40,27 @@
|
|||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <syslog.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <mntent.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl";
|
char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl";
|
||||||
|
|
||||||
#define STATNAMELEN 15
|
#define STATNAMELEN 15
|
||||||
|
#define DO_NETFS 2
|
||||||
#define DO_STAT 1
|
#define DO_STAT 1
|
||||||
#define NO_STAT 0
|
#define NO_STAT 0
|
||||||
|
|
||||||
@@ -67,8 +74,9 @@ typedef struct proc {
|
|||||||
ino_t ino; /* Inode number */
|
ino_t ino; /* Inode number */
|
||||||
dev_t dev; /* Device it is on */
|
dev_t dev; /* Device it is on */
|
||||||
pid_t pid; /* Process ID. */
|
pid_t pid; /* Process ID. */
|
||||||
int sid; /* Session ID. */
|
pid_t sid; /* Session ID. */
|
||||||
int kernel; /* Kernel thread or zombie. */
|
char kernel; /* Kernel thread or zombie. */
|
||||||
|
char nfs; /* Name found on network FS. */
|
||||||
struct proc *next; /* Pointer to next struct. */
|
struct proc *next; /* Pointer to next struct. */
|
||||||
} PROC;
|
} PROC;
|
||||||
|
|
||||||
@@ -85,9 +93,38 @@ typedef struct {
|
|||||||
PIDQ *next;
|
PIDQ *next;
|
||||||
} PIDQ_HEAD;
|
} PIDQ_HEAD;
|
||||||
|
|
||||||
|
typedef struct _s_omit {
|
||||||
|
struct _s_omit *next;
|
||||||
|
struct _s_omit *prev;
|
||||||
|
pid_t pid;
|
||||||
|
} OMIT;
|
||||||
|
|
||||||
|
typedef struct _s_shadow
|
||||||
|
{
|
||||||
|
struct _s_shadow *next;
|
||||||
|
struct _s_shadow *prev;
|
||||||
|
size_t nlen;
|
||||||
|
char * name;
|
||||||
|
} SHADOW;
|
||||||
|
|
||||||
|
typedef struct _s_nfs
|
||||||
|
{
|
||||||
|
struct _s_nfs *next; /* Pointer to next struct. */
|
||||||
|
struct _s_nfs *prev; /* Pointer to previous st. */
|
||||||
|
SHADOW *shadow; /* Pointer to shadows */
|
||||||
|
char * name;
|
||||||
|
size_t nlen;
|
||||||
|
} NFS;
|
||||||
|
|
||||||
/* List of processes. */
|
/* List of processes. */
|
||||||
PROC *plist;
|
PROC *plist;
|
||||||
|
|
||||||
|
/* List of processes to omit. */
|
||||||
|
OMIT *omit;
|
||||||
|
|
||||||
|
/* List of NFS mountes partitions. */
|
||||||
|
NFS *nlist;
|
||||||
|
|
||||||
/* Did we stop all processes ? */
|
/* Did we stop all processes ? */
|
||||||
int sent_sigstop;
|
int sent_sigstop;
|
||||||
|
|
||||||
@@ -99,10 +136,23 @@ __attribute__ ((format (printf, 2, 3)))
|
|||||||
#endif
|
#endif
|
||||||
void nsyslog(int pri, char *fmt, ...);
|
void nsyslog(int pri, char *fmt, ...);
|
||||||
|
|
||||||
|
#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
|
||||||
|
# ifndef inline
|
||||||
|
# define inline __inline__
|
||||||
|
# endif
|
||||||
|
# ifndef restrict
|
||||||
|
# define restrict __restrict__
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#define alignof(type) ((sizeof(type)+(sizeof(void*)-1)) & ~(sizeof(void*)-1))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Malloc space, barf if out of memory.
|
* Malloc space, barf if out of memory.
|
||||||
*/
|
*/
|
||||||
void *xmalloc(int bytes)
|
#ifdef __GNUC__
|
||||||
|
static void *xmalloc(size_t) __attribute__ ((__malloc__));
|
||||||
|
#endif
|
||||||
|
static void *xmalloc(size_t bytes)
|
||||||
{
|
{
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
@@ -114,6 +164,18 @@ void *xmalloc(int bytes)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
static inline void xmemalign(void **, size_t, size_t) __attribute__ ((__nonnull__ (1)));
|
||||||
|
#endif
|
||||||
|
static inline void xmemalign(void **memptr, size_t alignment, size_t size)
|
||||||
|
{
|
||||||
|
if ((posix_memalign(memptr, alignment, size)) < 0) {
|
||||||
|
if (sent_sigstop) kill(-1, SIGCONT);
|
||||||
|
nsyslog(LOG_ERR, "out of memory");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if the proc filesystem is there. Mount if needed.
|
* See if the proc filesystem is there. Mount if needed.
|
||||||
*/
|
*/
|
||||||
@@ -164,6 +226,212 @@ int mount_proc(void)
|
|||||||
return did_mount;
|
return did_mount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int isnetfs(const char * type)
|
||||||
|
{
|
||||||
|
static const char* netfs[] = {"nfs", "nfs4", "smbfs", "cifs", "afs", "ncpfs", (char*)0};
|
||||||
|
int n;
|
||||||
|
for (n = 0; netfs[n]; n++) {
|
||||||
|
if (!strcasecmp(netfs[n], type))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remember all NFS typed partitions.
|
||||||
|
*/
|
||||||
|
void init_nfs(void)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
struct mntent * ent;
|
||||||
|
FILE * mnt;
|
||||||
|
|
||||||
|
nlist = (NFS*)0;
|
||||||
|
|
||||||
|
if (stat("/proc/version", &st) < 0)
|
||||||
|
return;
|
||||||
|
if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while ((ent = getmntent(mnt))) {
|
||||||
|
if (isnetfs(ent->mnt_type)) {
|
||||||
|
size_t nlen = strlen(ent->mnt_dir);
|
||||||
|
NFS *restrict p;
|
||||||
|
xmemalign((void*)&p, sizeof(void*), alignof(NFS)+(nlen+1));
|
||||||
|
p->name = ((char*)p)+alignof(NFS);
|
||||||
|
p->nlen = nlen;
|
||||||
|
p->shadow = (SHADOW*)0;
|
||||||
|
|
||||||
|
strcpy(p->name, ent->mnt_dir);
|
||||||
|
if (nlist)
|
||||||
|
nlist->prev = p;
|
||||||
|
p->next = nlist;
|
||||||
|
p->prev = (NFS*)0;
|
||||||
|
nlist = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endmntent(mnt);
|
||||||
|
|
||||||
|
if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while ((ent = getmntent(mnt))) {
|
||||||
|
NFS *p;
|
||||||
|
|
||||||
|
for (p = nlist; p; p = p->next) {
|
||||||
|
SHADOW * restrict s;
|
||||||
|
size_t nlen;
|
||||||
|
|
||||||
|
if (strcmp(ent->mnt_dir, p->name) == 0)
|
||||||
|
continue;
|
||||||
|
if (strncmp(ent->mnt_dir, p->name, p->nlen) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nlen = strlen(ent->mnt_dir);
|
||||||
|
xmemalign((void*)&s, sizeof(void*), alignof(SHADOW)+(nlen+1));
|
||||||
|
s->name = ((char*)s)+alignof(SHADOW);
|
||||||
|
s->nlen = nlen;
|
||||||
|
|
||||||
|
strcpy(s->name, ent->mnt_dir);
|
||||||
|
if (p->shadow)
|
||||||
|
p->shadow->prev = s;
|
||||||
|
s->next = p->shadow;
|
||||||
|
s->prev = (SHADOW*)0;
|
||||||
|
p->shadow = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endmntent(mnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_shadow(SHADOW *restrict shadow)
|
||||||
|
{
|
||||||
|
SHADOW *s, *n, *l;
|
||||||
|
|
||||||
|
n = shadow;
|
||||||
|
l = (SHADOW*)0;
|
||||||
|
for (s = shadow; n; s = n) {
|
||||||
|
l = s->prev;
|
||||||
|
n = s->next;
|
||||||
|
if (s == shadow) {
|
||||||
|
if (n) n->prev = (SHADOW*)0;
|
||||||
|
shadow = n;
|
||||||
|
} else if (l) {
|
||||||
|
if (n) n->prev = l;
|
||||||
|
l->next = n;
|
||||||
|
}
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_mnt(void)
|
||||||
|
{
|
||||||
|
NFS *p, *n, *l;
|
||||||
|
|
||||||
|
n = nlist;
|
||||||
|
l = (NFS*)0;
|
||||||
|
for (p = nlist; n; p = n) {
|
||||||
|
l = p->prev;
|
||||||
|
n = p->next;
|
||||||
|
if (p == nlist) {
|
||||||
|
if (n) n->prev = (NFS*)0;
|
||||||
|
nlist = n;
|
||||||
|
} else if (l) {
|
||||||
|
if (n) n->prev = l;
|
||||||
|
l->next = n;
|
||||||
|
}
|
||||||
|
if (p->shadow)
|
||||||
|
clear_shadow(p->shadow);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if path is ia shadow off a NFS partition.
|
||||||
|
*/
|
||||||
|
static int shadow(SHADOW *restrict this, const char *restrict name, const size_t nlen)
|
||||||
|
{
|
||||||
|
SHADOW *s;
|
||||||
|
|
||||||
|
if (!this)
|
||||||
|
goto out;
|
||||||
|
for (s = this; s; s = s->next) {
|
||||||
|
if (nlen < s->nlen)
|
||||||
|
continue;
|
||||||
|
if (name[s->nlen] != '\0' && name[s->nlen] != '/')
|
||||||
|
continue;
|
||||||
|
if (strncmp(name, s->name, s->nlen) == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check path is located on a network based partition.
|
||||||
|
*/
|
||||||
|
int check4nfs(const char * path, char * real)
|
||||||
|
{
|
||||||
|
char buf[PATH_MAX+1];
|
||||||
|
const char *curr;
|
||||||
|
int deep = MAXSYMLINKS;
|
||||||
|
|
||||||
|
if (!nlist) return 0;
|
||||||
|
|
||||||
|
curr = path;
|
||||||
|
do {
|
||||||
|
const char *prev;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if ((prev = strdupa(curr)) == NULL) {
|
||||||
|
nsyslog(LOG_ERR, "strdupa(): %s\n", strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if ((len = readlink(curr, buf, PATH_MAX)) < 0)
|
||||||
|
break;
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
if (buf[0] != '/') {
|
||||||
|
const char *slash;
|
||||||
|
|
||||||
|
if ((slash = strrchr(prev, '/'))) {
|
||||||
|
size_t off = slash - prev + 1;
|
||||||
|
|
||||||
|
if (off + len > PATH_MAX)
|
||||||
|
len = PATH_MAX - off;
|
||||||
|
|
||||||
|
memmove(&buf[off], &buf[0], len + 1);
|
||||||
|
memcpy(&buf[0], prev, off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
curr = &buf[0];
|
||||||
|
|
||||||
|
if (deep-- <= 0) return 0;
|
||||||
|
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
if (real) strcpy(real, curr);
|
||||||
|
|
||||||
|
if (errno == EINVAL) {
|
||||||
|
const size_t nlen = strlen(curr);
|
||||||
|
NFS *p;
|
||||||
|
for (p = nlist; p; p = p->next) {
|
||||||
|
if (nlen < p->nlen)
|
||||||
|
continue;
|
||||||
|
if (curr[p->nlen] != '\0' && curr[p->nlen] != '/')
|
||||||
|
continue;
|
||||||
|
if (!strncmp(curr, p->name, p->nlen)) {
|
||||||
|
if (shadow(p->shadow, curr, nlen))
|
||||||
|
continue;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int readarg(FILE *fp, char *buf, int sz)
|
int readarg(FILE *fp, char *buf, int sz)
|
||||||
{
|
{
|
||||||
int c = 0, f = 0;
|
int c = 0, f = 0;
|
||||||
@@ -208,6 +476,7 @@ int readproc(int do_stat)
|
|||||||
n = p->next;
|
n = p->next;
|
||||||
if (p->argv0) free(p->argv0);
|
if (p->argv0) free(p->argv0);
|
||||||
if (p->argv1) free(p->argv1);
|
if (p->argv1) free(p->argv1);
|
||||||
|
if (p->statname) free(p->statname);
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
plist = NULL;
|
plist = NULL;
|
||||||
@@ -242,6 +511,9 @@ int readproc(int do_stat)
|
|||||||
nsyslog(LOG_ERR,
|
nsyslog(LOG_ERR,
|
||||||
"can't get program name from /proc/%s\n",
|
"can't get program name from /proc/%s\n",
|
||||||
path);
|
path);
|
||||||
|
if (p->argv0) free(p->argv0);
|
||||||
|
if (p->argv1) free(p->argv1);
|
||||||
|
if (p->statname) free(p->statname);
|
||||||
free(p);
|
free(p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -265,6 +537,9 @@ int readproc(int do_stat)
|
|||||||
p->sid = 0;
|
p->sid = 0;
|
||||||
nsyslog(LOG_ERR, "can't read sid from %s\n",
|
nsyslog(LOG_ERR, "can't read sid from %s\n",
|
||||||
path);
|
path);
|
||||||
|
if (p->argv0) free(p->argv0);
|
||||||
|
if (p->argv1) free(p->argv1);
|
||||||
|
if (p->statname) free(p->statname);
|
||||||
free(p);
|
free(p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -273,6 +548,9 @@ int readproc(int do_stat)
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
} else {
|
} else {
|
||||||
/* Process disappeared.. */
|
/* Process disappeared.. */
|
||||||
|
if (p->argv0) free(p->argv0);
|
||||||
|
if (p->argv1) free(p->argv1);
|
||||||
|
if (p->statname) free(p->statname);
|
||||||
free(p);
|
free(p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -317,15 +595,29 @@ int readproc(int do_stat)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Process disappeared.. */
|
/* Process disappeared.. */
|
||||||
|
if (p->argv0) free(p->argv0);
|
||||||
|
if (p->argv1) free(p->argv1);
|
||||||
|
if (p->statname) free(p->statname);
|
||||||
free(p);
|
free(p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to stat the executable. */
|
/* Try to stat the executable. */
|
||||||
snprintf(path, sizeof(path), "/proc/%s/exe", d->d_name);
|
snprintf(path, sizeof(path), "/proc/%s/exe", d->d_name);
|
||||||
if (do_stat && stat(path, &st) == 0) {
|
|
||||||
|
p->nfs = 0;
|
||||||
|
|
||||||
|
switch (do_stat) {
|
||||||
|
case DO_NETFS:
|
||||||
|
if ((p->nfs = check4nfs(path, buf)))
|
||||||
|
break;
|
||||||
|
case DO_STAT:
|
||||||
|
if (stat(path, &st) != 0)
|
||||||
|
break;
|
||||||
p->dev = st.st_dev;
|
p->dev = st.st_dev;
|
||||||
p->ino = st.st_ino;
|
p->ino = st.st_ino;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Link it into the list. */
|
/* Link it into the list. */
|
||||||
@@ -391,13 +683,29 @@ PIDQ_HEAD *pidof(char *prog)
|
|||||||
PIDQ_HEAD *q;
|
PIDQ_HEAD *q;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *s;
|
char *s;
|
||||||
|
int nfs = 0;
|
||||||
int dostat = 0;
|
int dostat = 0;
|
||||||
int foundone = 0;
|
int foundone = 0;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
|
char real[PATH_MAX+1];
|
||||||
|
|
||||||
if (! prog)
|
if (! prog)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* Try to stat the executable. */
|
||||||
|
if (prog[0] == '/') {
|
||||||
|
memset(&real[0], 0, sizeof(real));
|
||||||
|
|
||||||
|
if (check4nfs(prog, real))
|
||||||
|
nfs++;
|
||||||
|
|
||||||
|
if (real[0] != '\0')
|
||||||
|
prog = &real[0]; /* Binary located on network FS. */
|
||||||
|
|
||||||
|
if ((nfs == 0) && (stat(prog, &st) == 0))
|
||||||
|
dostat++; /* Binary located on a local FS. */
|
||||||
|
}
|
||||||
|
|
||||||
/* Get basename of program. */
|
/* Get basename of program. */
|
||||||
if ((s = strrchr(prog, '/')) == NULL)
|
if ((s = strrchr(prog, '/')) == NULL)
|
||||||
s = prog;
|
s = prog;
|
||||||
@@ -410,13 +718,11 @@ PIDQ_HEAD *pidof(char *prog)
|
|||||||
q = (PIDQ_HEAD *)xmalloc(sizeof(PIDQ_HEAD));
|
q = (PIDQ_HEAD *)xmalloc(sizeof(PIDQ_HEAD));
|
||||||
q = init_pid_q(q);
|
q = init_pid_q(q);
|
||||||
|
|
||||||
/* Try to stat the executable. */
|
|
||||||
if (prog[0] == '/' && stat(prog, &st) == 0)
|
|
||||||
dostat++;
|
|
||||||
|
|
||||||
/* First try to find a match based on dev/ino pair. */
|
/* First try to find a match based on dev/ino pair. */
|
||||||
if (dostat) {
|
if (dostat && !nfs) {
|
||||||
for (p = plist; p; p = p->next) {
|
for (p = plist; p; p = p->next) {
|
||||||
|
if (p->nfs)
|
||||||
|
continue;
|
||||||
if (p->dev == st.st_dev && p->ino == st.st_ino) {
|
if (p->dev == st.st_dev && p->ino == st.st_ino) {
|
||||||
add_pid_to_q(q, p);
|
add_pid_to_q(q, p);
|
||||||
foundone++;
|
foundone++;
|
||||||
@@ -424,6 +730,25 @@ PIDQ_HEAD *pidof(char *prog)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Second try to find a match based on full path name on
|
||||||
|
* network FS located binaries */
|
||||||
|
if (!foundone && nfs) {
|
||||||
|
for (p = plist; p; p = p->next) {
|
||||||
|
char exe [PATH_MAX+1];
|
||||||
|
char path[PATH_MAX+1];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
snprintf(exe, sizeof(exe), "/proc/%d/exe", p->pid);
|
||||||
|
if ((len = readlink(exe, path, PATH_MAX)) < 0)
|
||||||
|
continue;
|
||||||
|
path[len] = '\0';
|
||||||
|
if (strcmp(prog, path) != 0)
|
||||||
|
continue;
|
||||||
|
add_pid_to_q(q, p);
|
||||||
|
foundone++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* If we didn't find a match based on dev/ino, try the name. */
|
/* If we didn't find a match based on dev/ino, try the name. */
|
||||||
if (!foundone) for (p = plist; p; p = p->next) {
|
if (!foundone) for (p = plist; p; p = p->next) {
|
||||||
ok = 0;
|
ok = 0;
|
||||||
@@ -469,10 +794,22 @@ PIDQ_HEAD *pidof(char *prog)
|
|||||||
strchr(p->argv0, ' '))) {
|
strchr(p->argv0, ' '))) {
|
||||||
ok |= (strcmp(p->statname, s) == 0);
|
ok |= (strcmp(p->statname, s) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we have a `-' as the first character, process
|
||||||
|
* probably used as a login shell
|
||||||
|
*/
|
||||||
|
if (strlen(s) <= STATNAMELEN &&
|
||||||
|
p->argv1 == NULL &&
|
||||||
|
(p->argv0 != NULL &&
|
||||||
|
p->argv0[0] == '-')) {
|
||||||
|
ok |= (strcmp(p->statname, s) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (ok) add_pid_to_q(q, p);
|
if (ok) add_pid_to_q(q, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Give usage message and exit. */
|
/* Give usage message and exit. */
|
||||||
@@ -506,8 +843,7 @@ void nsyslog(int pri, char *fmt, ...)
|
|||||||
|
|
||||||
#define PIDOF_SINGLE 0x01
|
#define PIDOF_SINGLE 0x01
|
||||||
#define PIDOF_OMIT 0x02
|
#define PIDOF_OMIT 0x02
|
||||||
|
#define PIDOF_NETFS 0x04
|
||||||
#define PIDOF_OMITSZ 5
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pidof functionality.
|
* Pidof functionality.
|
||||||
@@ -516,19 +852,22 @@ int main_pidof(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
PIDQ_HEAD *q;
|
PIDQ_HEAD *q;
|
||||||
PROC *p;
|
PROC *p;
|
||||||
pid_t opid[PIDOF_OMITSZ], spid;
|
char *token, *here;
|
||||||
int f;
|
int f;
|
||||||
int first = 1;
|
int first = 1;
|
||||||
int i, oind, opt, flags = 0;
|
int opt, flags = 0;
|
||||||
int chroot_check = 0;
|
int chroot_check = 0;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char tmp[512];
|
char tmp[512];
|
||||||
|
|
||||||
for (oind = PIDOF_OMITSZ-1; oind > 0; oind--)
|
omit = (OMIT*)0;
|
||||||
opid[oind] = 0;
|
nlist = (NFS*)0;
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
|
|
||||||
while ((opt = getopt(argc,argv,"hco:sx")) != EOF) switch (opt) {
|
if ((token = getenv("PIDOF_NETFS")) && (strcmp(token,"no") != 0))
|
||||||
|
flags |= PIDOF_NETFS;
|
||||||
|
|
||||||
|
while ((opt = getopt(argc,argv,"hco:sxn")) != EOF) switch (opt) {
|
||||||
case '?':
|
case '?':
|
||||||
nsyslog(LOG_ERR,"invalid options on command line!\n");
|
nsyslog(LOG_ERR,"invalid options on command line!\n");
|
||||||
closelog();
|
closelog();
|
||||||
@@ -537,22 +876,28 @@ int main_pidof(int argc, char **argv)
|
|||||||
if (geteuid() == 0) chroot_check = 1;
|
if (geteuid() == 0) chroot_check = 1;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
if (oind >= PIDOF_OMITSZ -1) {
|
here = optarg;
|
||||||
nsyslog(LOG_ERR,"omit pid buffer size %d "
|
while ((token = strsep(&here, ",;:"))) {
|
||||||
"exceeded!\n", PIDOF_OMITSZ);
|
OMIT *restrict optr;
|
||||||
closelog();
|
pid_t opid;
|
||||||
exit(1);
|
|
||||||
|
if (strcmp("%PPID", token) == 0)
|
||||||
|
opid = getppid();
|
||||||
|
else
|
||||||
|
opid = (pid_t)atoi(token);
|
||||||
|
|
||||||
|
if (opid < 1) {
|
||||||
|
nsyslog(LOG_ERR,
|
||||||
|
"illegal omit pid value "
|
||||||
|
"(%s)!\n", token);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
xmemalign((void*)&optr, sizeof(void*), alignof(OMIT));
|
||||||
|
optr->next = omit;
|
||||||
|
optr->prev = (OMIT*)0;
|
||||||
|
optr->pid = opid;
|
||||||
|
omit = optr;
|
||||||
}
|
}
|
||||||
if (strcmp("%PPID",optarg) == 0)
|
|
||||||
opid[oind] = getppid();
|
|
||||||
else if ((opid[oind] = atoi(optarg)) < 1) {
|
|
||||||
nsyslog(LOG_ERR,
|
|
||||||
"illegal omit pid value (%s)!\n",
|
|
||||||
optarg);
|
|
||||||
closelog();
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
oind++;
|
|
||||||
flags |= PIDOF_OMIT;
|
flags |= PIDOF_OMIT;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
@@ -561,6 +906,9 @@ int main_pidof(int argc, char **argv)
|
|||||||
case 'x':
|
case 'x':
|
||||||
scripts_too++;
|
scripts_too++;
|
||||||
break;
|
break;
|
||||||
|
case 'n':
|
||||||
|
flags |= PIDOF_NETFS;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* Nothing */
|
/* Nothing */
|
||||||
break;
|
break;
|
||||||
@@ -578,21 +926,28 @@ int main_pidof(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & PIDOF_NETFS)
|
||||||
|
init_nfs(); /* Which network based FS are online? */
|
||||||
|
|
||||||
/* Print out process-ID's one by one. */
|
/* Print out process-ID's one by one. */
|
||||||
readproc(DO_STAT);
|
readproc((flags & PIDOF_NETFS) ? DO_NETFS : DO_STAT);
|
||||||
|
|
||||||
for(f = 0; f < argc; f++) {
|
for(f = 0; f < argc; f++) {
|
||||||
if ((q = pidof(argv[f])) != NULL) {
|
if ((q = pidof(argv[f])) != NULL) {
|
||||||
spid = 0;
|
pid_t spid = 0;
|
||||||
while ((p = get_next_from_pid_q(q))) {
|
while ((p = get_next_from_pid_q(q))) {
|
||||||
if (flags & PIDOF_OMIT) {
|
if ((flags & PIDOF_OMIT) && omit) {
|
||||||
for (i = 0; i < oind; i++)
|
OMIT * optr;
|
||||||
if (opid[i] == p->pid)
|
for (optr = omit; optr; optr = optr->next) {
|
||||||
|
if (optr->pid == p->pid)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On a match, continue with
|
* On a match, continue with
|
||||||
* the for loop above.
|
* the for loop above.
|
||||||
*/
|
*/
|
||||||
if (i < oind)
|
if (optr)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (flags & PIDOF_SINGLE) {
|
if (flags & PIDOF_SINGLE) {
|
||||||
@@ -620,22 +975,20 @@ int main_pidof(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (!first)
|
if (!first)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
clear_mnt();
|
||||||
|
|
||||||
closelog();
|
closelog();
|
||||||
return(first ? 1 : 0);
|
return(first ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define KILLALL_OMITSZ 16
|
|
||||||
|
|
||||||
/* Main for either killall or pidof. */
|
/* Main for either killall or pidof. */
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
PROC *p;
|
PROC *p;
|
||||||
int pid, sid = -1;
|
int pid, sid = -1;
|
||||||
pid_t opid[KILLALL_OMITSZ];
|
|
||||||
int i, oind, omit = 0;
|
|
||||||
int sig = SIGKILL;
|
int sig = SIGKILL;
|
||||||
|
int c;
|
||||||
|
|
||||||
/* return non-zero if no process was killed */
|
/* return non-zero if no process was killed */
|
||||||
int retval = 2;
|
int retval = 2;
|
||||||
@@ -654,30 +1007,34 @@ int main(int argc, char **argv)
|
|||||||
return main_pidof(argc, argv);
|
return main_pidof(argc, argv);
|
||||||
|
|
||||||
/* Right, so we are "killall". */
|
/* Right, so we are "killall". */
|
||||||
for (oind = KILLALL_OMITSZ-1; oind > 0; oind--)
|
omit = (OMIT*)0;
|
||||||
opid[oind] = 0;
|
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
for (i = 1; i < argc; i++) {
|
for (c = 1; c < argc; c++) {
|
||||||
if (argv[i][0] == '-') (argv[i])++;
|
if (argv[c][0] == '-') (argv[c])++;
|
||||||
if (argv[i][0] == 'o') {
|
if (argv[c][0] == 'o') {
|
||||||
if (++i >= argc) usage();
|
char * token, * here;
|
||||||
if (oind >= KILLALL_OMITSZ -1) {
|
|
||||||
nsyslog(LOG_ERR,"omit pid buffer size "
|
if (++c >= argc)
|
||||||
"%d exceeded!\n",
|
usage();
|
||||||
KILLALL_OMITSZ);
|
|
||||||
closelog();
|
here = argv[c];
|
||||||
exit(1);
|
while ((token = strsep(&here, ",;:"))) {
|
||||||
|
OMIT *restrict optr;
|
||||||
|
pid_t opid = (pid_t)atoi(token);
|
||||||
|
|
||||||
|
if (opid < 1) {
|
||||||
|
nsyslog(LOG_ERR,
|
||||||
|
"illegal omit pid value "
|
||||||
|
"(%s)!\n", token);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
xmemalign((void*)&optr, sizeof(void*), alignof(OMIT));
|
||||||
|
optr->next = omit;
|
||||||
|
optr->prev = (OMIT*)0;
|
||||||
|
optr->pid = opid;
|
||||||
|
omit = optr;
|
||||||
}
|
}
|
||||||
if ((opid[oind] = atoi(argv[i])) < 1) {
|
|
||||||
nsyslog(LOG_ERR,
|
|
||||||
"illegal omit pid value "
|
|
||||||
"(%s)!\n", argv[i]);
|
|
||||||
closelog();
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
oind++;
|
|
||||||
omit = 1;
|
|
||||||
}
|
}
|
||||||
else if ((sig = atoi(argv[1])) <= 0 || sig > 31)
|
else if ((sig = atoi(argv[1])) <= 0 || sig > 31)
|
||||||
usage();
|
usage();
|
||||||
@@ -716,14 +1073,19 @@ int main(int argc, char **argv)
|
|||||||
for (p = plist; p; p = p->next) {
|
for (p = plist; p; p = p->next) {
|
||||||
if (p->pid == 1 || p->pid == pid || p->sid == sid || p->kernel)
|
if (p->pid == 1 || p->pid == pid || p->sid == sid || p->kernel)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (omit) {
|
if (omit) {
|
||||||
for (i = 0; i < oind; i++)
|
OMIT * optr;
|
||||||
if (opid[i] == p->pid)
|
for (optr = omit; optr; optr = optr->next) {
|
||||||
|
if (optr->pid == p->pid)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* On a match, continue with the for loop above. */
|
/* On a match, continue with the for loop above. */
|
||||||
if (i < oind)
|
if (optr)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
kill(p->pid, sig);
|
kill(p->pid, sig);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user