📄 pgrep.c
字号:
/* emacs settings: -*- c-basic-offset: 8 tab-width: 8 -*- * * pgrep/pkill -- utilities to filter the process table * * Copyright 2000 Kjetil Torgrim Homme <kjetilho@ifi.uio.no> * * May be distributed under the conditions of the * GNU General Public License; a copy is in COPYING * * Changes by Albert Cahalan, 2002,2006. * */#include <stdio.h>#include <stdlib.h>#include <limits.h>#include <unistd.h>#include <ctype.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <signal.h>#include <pwd.h>#include <grp.h>#include <regex.h>#include <errno.h>#include "proc/readproc.h"#include "proc/sig.h"#include "proc/devname.h"#include "proc/sysinfo.h"#include "proc/version.h" /* procps_version */// EXIT_SUCCESS is 0// EXIT_FAILURE is 1#define EXIT_USAGE 2#define EXIT_FATAL 3static int i_am_pkill = 0;static const char *progname = "pgrep";union el { long num; char * str;};/* User supplied arguments */static int opt_full = 0;static int opt_long = 0;static int opt_oldest = 0;static int opt_newest = 0;static int opt_negate = 0;static int opt_exact = 0;static int opt_signal = SIGTERM;static int opt_lock = 0;static int opt_case = 0;static const char *opt_delim = "\n";static union el *opt_pgrp = NULL;static union el *opt_rgid = NULL;static union el *opt_pid = NULL;static union el *opt_ppid = NULL;static union el *opt_sid = NULL;static union el *opt_term = NULL;static union el *opt_euid = NULL;static union el *opt_ruid = NULL;static char *opt_pattern = NULL;static char *opt_pidfile = NULL;static int usage (int opt) NORETURN;static int usage (int opt){ if (i_am_pkill) fprintf (stderr, "Usage: pkill [-SIGNAL] [-fvx] "); else fprintf (stderr, "Usage: pgrep [-flvx] [-d DELIM] "); fprintf (stderr, "[-n|-o] [-P PPIDLIST] [-g PGRPLIST] [-s SIDLIST]\n" "\t[-u EUIDLIST] [-U UIDLIST] [-G GIDLIST] [-t TERMLIST] " "[PATTERN]\n"); exit (opt == '?' ? EXIT_SUCCESS : EXIT_USAGE);}static union el *split_list (const char *restrict str, int (*convert)(const char *, union el *)){ char *copy = strdup (str); char *ptr = copy; char *sep_pos; int i = 0; int size = 0; union el *list = NULL; do { if (i == size) { size = size * 5 / 4 + 4; // add 1 because slot zero is a count list = realloc (list, 1 + size * sizeof *list); if (list == NULL) exit (EXIT_FATAL); } sep_pos = strchr (ptr, ','); if (sep_pos) *sep_pos = 0; // Use ++i instead of i++ because slot zero is a count if (!convert (ptr, &list[++i])) exit (EXIT_USAGE); if (sep_pos) ptr = sep_pos + 1; } while (sep_pos); free (copy); if (!i) { free (list); list = NULL; } else { list[0].num = i; } return list;}// strict_atol returns a Boolean: TRUE if the input string// contains a plain number, FALSE if there are any non-digits.static int strict_atol (const char *restrict str, long *restrict value){ int res = 0; int sign = 1; if (*str == '+') ++str; else if (*str == '-') { ++str; sign = -1; } for ( ; *str; ++str) { if (! isdigit (*str)) return (0); res *= 10; res += *str - '0'; } *value = sign * res; return 1;}#include <sys/file.h>// Seen non-BSD code do this:////if (fcntl_lock(pid_fd, F_SETLK, F_WRLCK, SEEK_SET, 0, 0) == -1)// return -1;int fcntl_lock(int fd, int cmd, int type, int whence, int start, int len){ struct flock lock[1]; lock->l_type = type; lock->l_whence = whence; lock->l_start = start; lock->l_len = len; return fcntl(fd, cmd, lock);} // We try a read lock. The daemon should have a write lock.// Seen using flock: FreeBSD codestatic int has_flock(int fd){ return flock(fd, LOCK_SH|LOCK_NB)==-1 && errno==EWOULDBLOCK;}// We try a read lock. The daemon should have a write lock.// Seen using fcntl: libslackstatic int has_fcntl(int fd){ struct flock f; // seriously, struct flock is for a fnctl lock! f.l_type = F_RDLCK; f.l_whence = SEEK_SET; f.l_start = 0; f.l_len = 0; return fcntl(fd,F_SETLK,&f)==-1 && (errno==EACCES || errno==EAGAIN);}static union el *read_pidfile(void){ char buf[12]; int fd; struct stat sbuf; char *endp; int pid; union el *list = NULL; fd = open(opt_pidfile, O_RDONLY|O_NOCTTY|O_NONBLOCK); if(fd<0) goto out; if(fstat(fd,&sbuf) || !S_ISREG(sbuf.st_mode) || sbuf.st_size<1) goto out; // type of lock, if any, is not standardized on Linux if(opt_lock && !has_flock(fd) && !has_fcntl(fd)) goto out; memset(buf,'\0',sizeof buf); buf[read(fd,buf+1,sizeof buf-2)] = '\0'; pid = strtoul(buf+1,&endp,10); if(endp<=buf+1 || pid<1 || pid>0x7fffffff) goto out; if(*endp && !isspace(*endp)) goto out; list = malloc(2 * sizeof *list); list[0].num = 1; list[1].num = pid;out: close(fd); return list;}static int conv_uid (const char *restrict name, union el *restrict e){ struct passwd *pwd; if (strict_atol (name, &e->num)) return (1); pwd = getpwnam (name); if (pwd == NULL) { fprintf (stderr, "%s: invalid user name: %s\n", progname, name); return 0; } e->num = pwd->pw_uid; return 1;}static int conv_gid (const char *restrict name, union el *restrict e){ struct group *grp; if (strict_atol (name, &e->num)) return 1; grp = getgrnam (name); if (grp == NULL) { fprintf (stderr, "%s: invalid group name: %s\n", progname, name); return 0; } e->num = grp->gr_gid; return 1;}static int conv_pgrp (const char *restrict name, union el *restrict e){ if (! strict_atol (name, &e->num)) { fprintf (stderr, "%s: invalid process group: %s\n", progname, name); return 0; } if (e->num == 0) e->num = getpgrp (); return 1;}static int conv_sid (const char *restrict name, union el *restrict e){ if (! strict_atol (name, &e->num)) { fprintf (stderr, "%s: invalid session id: %s\n", progname, name); return 0; } if (e->num == 0) e->num = getsid (0); return 1;}static int conv_num (const char *restrict name, union el *restrict e){ if (! strict_atol (name, &e->num)) { fprintf (stderr, "%s: not a number: %s\n", progname, name); return 0; } return 1;}static int conv_str (const char *restrict name, union el *restrict e){ e->str = strdup (name); return 1;}static int match_numlist (long value, const union el *restrict list){ int found = 0; if (list == NULL) found = 0; else { int i; for (i = list[0].num; i > 0; i--) { if (list[i].num == value) found = 1; } } return found;}static int match_strlist (const char *restrict value, const union el *restrict list){ int found = 0; if (list == NULL) found = 0; else { int i; for (i = list[0].num; i > 0; i--) { if (! strcmp (list[i].str, value)) found = 1; } } return found;}static void output_numlist (const union el *restrict list, int num){ int i; const char *delim = opt_delim; for (i = 0; i < num; i++) { if(i+1==num) delim = "\n"; printf ("%ld%s", list[i].num, delim); }}static void output_strlist (const union el *restrict list, int num){// FIXME: escape codes int i; const char *delim = opt_delim; for (i = 0; i < num; i++) { if(i+1==num) delim = "\n"; printf ("%s%s", list[i].str, delim); }}static PROCTAB *do_openproc (void){ PROCTAB *ptp; int flags = 0; if (opt_pattern || opt_full) flags |= PROC_FILLCOM; if (opt_ruid || opt_rgid) flags |= PROC_FILLSTATUS; if (opt_oldest || opt_newest || opt_pgrp || opt_sid || opt_term) flags |= PROC_FILLSTAT; if (!(flags & PROC_FILLSTAT)) flags |= PROC_FILLSTATUS; // FIXME: need one, and PROC_FILLANY broken if (opt_euid && !opt_negate) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -