build-sys: Removal of contrib directory
There is nothing we have used here for over a decade Signed-off-by: Craig Small <csmall@dropbear.xyz>
This commit is contained in:
parent
86c7eeb70d
commit
5fcf104cba
@ -96,7 +96,6 @@ endif
|
||||
EXTRA_DIST = \
|
||||
.version \
|
||||
autogen.sh \
|
||||
contrib \
|
||||
COPYING.LIB \
|
||||
misc/git-version-gen \
|
||||
Documentation/CodingStyle.md \
|
||||
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* This is to test the compiler.
|
||||
* Copyright (C) Albert Cahalan
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
#include <curses.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Foul POS defines all sorts of stuff... */
|
||||
#include <term.h>
|
||||
#undef tab
|
||||
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <values.h>
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return 0;
|
||||
}
|
@ -1,677 +0,0 @@
|
||||
/*
|
||||
* Copyright 1998,2004 by Albert Cahalan
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* This is a minimal /bin/ps, designed to be smaller than the old ps
|
||||
* while still supporting some of the more important features of the
|
||||
* new ps. (for total size, note that this ps does not need libproc)
|
||||
* It is suitable for Linux-on-a-floppy systems only.
|
||||
*
|
||||
* Maintainers: do not compile or install for normal systems.
|
||||
* Anyone needing this will want to tweak their compiler anyway.
|
||||
*/
|
||||
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
|
||||
|
||||
#define DEV_ENCODE(M,m) ( \
|
||||
( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
#ifdef __sun__
|
||||
#include <sys/mkdev.h>
|
||||
#define _STRUCTURED_PROC 1
|
||||
#include <sys/procfs.h>
|
||||
#define NO_TTY_VALUE DEV_ENCODE(-1,-1)
|
||||
#define HZ 1 // only bother with seconds
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/user.h>
|
||||
#define NO_TTY_VALUE DEV_ENCODE(-1,-1)
|
||||
#define HZ 1 // only bother with seconds
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
#ifdef __linux__
|
||||
#include <asm/param.h> /* HZ */
|
||||
#include <asm/page.h> /* PAGE_SIZE */
|
||||
#define NO_TTY_VALUE DEV_ENCODE(0,0)
|
||||
#ifndef HZ
|
||||
#warning HZ not defined, assuming it is 100
|
||||
#define HZ 100
|
||||
#endif
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#warning PAGE_SIZE not defined, using sysconf() to determine correct value
|
||||
#define PAGE_SIZE (sysconf(_SC_PAGESIZE))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static char P_tty_text[16];
|
||||
static char P_cmd[16];
|
||||
static char P_state;
|
||||
static int P_euid;
|
||||
static int P_pid;
|
||||
static int P_ppid, P_pgrp, P_session, P_tty_num, P_tpgid;
|
||||
static unsigned long P_flags, P_min_flt, P_cmin_flt, P_maj_flt, P_cmaj_flt, P_utime, P_stime;
|
||||
static long P_cutime, P_cstime, P_priority, P_nice, P_timeout, P_alarm;
|
||||
static unsigned long P_start_time, P_vsize;
|
||||
static long P_rss;
|
||||
static unsigned long P_rss_rlim, P_start_code, P_end_code, P_start_stack, P_kstk_esp, P_kstk_eip;
|
||||
static unsigned P_signal, P_blocked, P_sigignore, P_sigcatch;
|
||||
static unsigned long P_wchan, P_nswap, P_cnswap;
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
static int screen_cols = 80;
|
||||
static int w_count;
|
||||
#endif
|
||||
|
||||
static int want_one_pid;
|
||||
static const char *want_one_command;
|
||||
static int select_notty;
|
||||
static int select_all;
|
||||
|
||||
static int ps_format;
|
||||
static int old_h_option;
|
||||
|
||||
/* we only pretend to support this */
|
||||
static int show_args; /* implicit with -f and all BSD options */
|
||||
static int bsd_c_option; /* this option overrides the above */
|
||||
|
||||
static int ps_argc; /* global argc */
|
||||
static char **ps_argv; /* global argv */
|
||||
static int thisarg; /* index into ps_argv */
|
||||
static char *flagptr; /* current location in ps_argv[thisarg] */
|
||||
|
||||
|
||||
|
||||
|
||||
static void usage(void){
|
||||
fprintf(stderr,
|
||||
"-C select by command name (minimal ps only accepts one)\n"
|
||||
"-p select by process ID (minimal ps only accepts one)\n"
|
||||
"-e all processes (same as ax)\n"
|
||||
"a all processes w/ tty, including other users\n"
|
||||
"x processes w/o controlling ttys\n"
|
||||
"-f full format\n"
|
||||
"-j,j job control format\n"
|
||||
"v virtual memory format\n"
|
||||
"-l,l long format\n"
|
||||
"u user-oriented format\n"
|
||||
"-o user-defined format (limited support, only \"ps -o pid=\")\n"
|
||||
"h no header\n"
|
||||
/*
|
||||
"-A all processes (same as ax)\n"
|
||||
"c true command name\n"
|
||||
"-w,w wide output\n"
|
||||
*/
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next argument, or call the usage function.
|
||||
* This handles both: -oFOO -o FOO
|
||||
*/
|
||||
static const char *get_opt_arg(void){
|
||||
const char *ret;
|
||||
ret = flagptr+1; /* assume argument is part of ps_argv[thisarg] */
|
||||
if(*ret) return ret;
|
||||
if(++thisarg >= ps_argc) usage(); /* there is nothing left */
|
||||
/* argument is the new ps_argv[thisarg] */
|
||||
ret = ps_argv[thisarg];
|
||||
if(!ret || !*ret) usage();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* return the PID, or 0 if nothing good */
|
||||
static void parse_pid(const char *str){
|
||||
char *endp;
|
||||
int num;
|
||||
if(!str) goto bad;
|
||||
num = strtol(str, &endp, 0);
|
||||
if(*endp != '\0') goto bad;
|
||||
if(num<1) goto bad;
|
||||
if(want_one_pid) goto bad;
|
||||
want_one_pid = num;
|
||||
return;
|
||||
bad:
|
||||
usage();
|
||||
}
|
||||
|
||||
/***************** parse SysV options, including Unix98 *****************/
|
||||
static void parse_sysv_option(void){
|
||||
do{
|
||||
switch(*flagptr){
|
||||
/**** selection ****/
|
||||
case 'C': /* end */
|
||||
if(want_one_command) usage();
|
||||
want_one_command = get_opt_arg();
|
||||
return; /* can't have any more options */
|
||||
case 'p': /* end */
|
||||
parse_pid(get_opt_arg());
|
||||
return; /* can't have any more options */
|
||||
case 'A':
|
||||
case 'e':
|
||||
select_all++;
|
||||
select_notty++;
|
||||
case 'w': /* here for now, since the real one is not used */
|
||||
break;
|
||||
/**** output format ****/
|
||||
case 'f':
|
||||
show_args = 1;
|
||||
/* FALL THROUGH */
|
||||
case 'j':
|
||||
case 'l':
|
||||
if(ps_format) usage();
|
||||
ps_format = *flagptr;
|
||||
break;
|
||||
case 'o': /* end */
|
||||
/* We only support a limited form: "ps -o pid=" (yes, just "pid=") */
|
||||
if(strcmp(get_opt_arg(),"pid=")) usage();
|
||||
if(ps_format) usage();
|
||||
ps_format = 'o';
|
||||
old_h_option++;
|
||||
return; /* can't have any more options */
|
||||
/**** other stuff ****/
|
||||
#if 0
|
||||
case 'w':
|
||||
w_count++;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
usage();
|
||||
} /* switch */
|
||||
}while(*++flagptr);
|
||||
}
|
||||
|
||||
/************************* parse BSD options **********************/
|
||||
static void parse_bsd_option(void){
|
||||
do{
|
||||
switch(*flagptr){
|
||||
/**** selection ****/
|
||||
case 'a':
|
||||
select_all++;
|
||||
break;
|
||||
case 'x':
|
||||
select_notty++;
|
||||
break;
|
||||
case 'p': /* end */
|
||||
parse_pid(get_opt_arg());
|
||||
return; /* can't have any more options */
|
||||
/**** output format ****/
|
||||
case 'j':
|
||||
case 'l':
|
||||
case 'u':
|
||||
case 'v':
|
||||
if(ps_format) usage();
|
||||
ps_format = 0x80 | *flagptr; /* use 0x80 to tell BSD from SysV */
|
||||
break;
|
||||
/**** other stuff ****/
|
||||
case 'c':
|
||||
bsd_c_option++;
|
||||
#if 0
|
||||
break;
|
||||
#endif
|
||||
case 'w':
|
||||
#if 0
|
||||
w_count++;
|
||||
#endif
|
||||
break;
|
||||
case 'h':
|
||||
old_h_option++;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
} /* switch */
|
||||
}while(*++flagptr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#include <termios.h>
|
||||
/* not used yet */
|
||||
static void choose_dimensions(void){
|
||||
struct winsize ws;
|
||||
char *columns;
|
||||
/* screen_cols is 80 by default */
|
||||
if(ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col>30) screen_cols = ws.ws_col;
|
||||
columns = getenv("COLUMNS");
|
||||
if(columns && *columns){
|
||||
long t;
|
||||
char *endptr;
|
||||
t = strtol(columns, &endptr, 0);
|
||||
if(!*endptr && (t>30) && (t<(long)999999999)) screen_cols = (int)t;
|
||||
}
|
||||
if(w_count && (screen_cols<132)) screen_cols=132;
|
||||
if(w_count>1) screen_cols=999999999;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void arg_parse(int argc, char *argv[]){
|
||||
int sel = 0; /* to verify option sanity */
|
||||
ps_argc = argc;
|
||||
ps_argv = argv;
|
||||
thisarg = 0;
|
||||
/**** iterate over the args ****/
|
||||
while(++thisarg < ps_argc){
|
||||
flagptr = ps_argv[thisarg];
|
||||
switch(*flagptr){
|
||||
case '0' ... '9':
|
||||
show_args = 1;
|
||||
parse_pid(flagptr);
|
||||
break;
|
||||
case '-':
|
||||
flagptr++;
|
||||
parse_sysv_option();
|
||||
break;
|
||||
default:
|
||||
show_args = 1;
|
||||
parse_bsd_option();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**** sanity check and clean-up ****/
|
||||
if(want_one_pid) sel++;
|
||||
if(want_one_command) sel++;
|
||||
if(select_notty || select_all) sel++;
|
||||
if(sel>1 || select_notty>1 || select_all>1 || bsd_c_option>1 || old_h_option>1) usage();
|
||||
if(bsd_c_option) show_args = 0;
|
||||
}
|
||||
|
||||
#ifdef __sun__
|
||||
/* return 1 if it works, or 0 for failure */
|
||||
static int stat2proc(int pid) {
|
||||
struct psinfo p; // /proc/*/psinfo, struct psinfo, psinfo_t
|
||||
char buf[32];
|
||||
int num;
|
||||
int fd;
|
||||
int tty_maj, tty_min;
|
||||
snprintf(buf, sizeof buf, "/proc/%d/psinfo", pid);
|
||||
if ( (fd = open(buf, O_RDONLY, 0) ) == -1 ) return 0;
|
||||
num = read(fd, &p, sizeof p);
|
||||
close(fd);
|
||||
if(num != sizeof p) return 0;
|
||||
|
||||
num = PRFNSZ;
|
||||
if (num >= sizeof P_cmd) num = sizeof P_cmd - 1;
|
||||
memcpy(P_cmd, p.pr_fname, num); // p.pr_fname or p.pr_lwp.pr_name
|
||||
P_cmd[num] = '\0';
|
||||
|
||||
P_pid = p.pr_pid;
|
||||
P_ppid = p.pr_ppid;
|
||||
P_pgrp = p.pr_pgid;
|
||||
P_session = p.pr_sid;
|
||||
P_euid = p.pr_euid;
|
||||
P_rss = p.pr_rssize;
|
||||
P_vsize = p.pr_size;
|
||||
P_start_time = p.pr_start.tv_sec;
|
||||
P_wchan = p.pr_lwp.pr_wchan;
|
||||
P_state = p.pr_lwp.pr_sname;
|
||||
P_nice = p.pr_lwp.pr_nice;
|
||||
P_priority = p.pr_lwp.pr_pri; // or pr_oldpri
|
||||
// P_ruid = p.pr_uid;
|
||||
// P_rgid = p.pr_gid;
|
||||
// P_egid = p.pr_egid;
|
||||
|
||||
#if 0
|
||||
// don't support these
|
||||
P_tpgid; P_flags,
|
||||
P_min_flt, P_cmin_flt, P_maj_flt, P_cmaj_flt, P_utime, P_stime;
|
||||
P_cutime, P_cstime, P_timeout, P_alarm;
|
||||
P_rss_rlim, P_start_code, P_end_code, P_start_stack, P_kstk_esp, P_kstk_eip;
|
||||
P_signal, P_blocked, P_sigignore, P_sigcatch;
|
||||
P_nswap, P_cnswap;
|
||||
#endif
|
||||
|
||||
// we like it Linux-encoded :-)
|
||||
tty_maj = major(p.pr_ttydev);
|
||||
tty_min = minor(p.pr_ttydev);
|
||||
P_tty_num = DEV_ENCODE(tty_maj,tty_min);
|
||||
|
||||
snprintf(P_tty_text, sizeof P_tty_text, "%3d,%-3d", tty_maj, tty_min);
|
||||
#if 1
|
||||
if (tty_maj == 24) snprintf(P_tty_text, sizeof P_tty_text, "pts/%-3u", tty_min);
|
||||
if (P_tty_num == NO_TTY_VALUE) memcpy(P_tty_text, " ? ", 8);
|
||||
if (P_tty_num == DEV_ENCODE(0,0)) memcpy(P_tty_text, "console", 8);
|
||||
#endif
|
||||
|
||||
if(P_pid != pid) return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/* return 1 if it works, or 0 for failure */
|
||||
static int stat2proc(int pid) {
|
||||
char buf[400];
|
||||
int num;
|
||||
int fd;
|
||||
char* tmp;
|
||||
int tty_maj, tty_min;
|
||||
snprintf(buf, 32, "/proc/%d/status", pid);
|
||||
if ( (fd = open(buf, O_RDONLY, 0) ) == -1 ) return 0;
|
||||
num = read(fd, buf, sizeof buf - 1);
|
||||
close(fd);
|
||||
if(num<43) return 0;
|
||||
buf[num] = '\0';
|
||||
|
||||
P_state = '-';
|
||||
|
||||
// FreeBSD /proc/*/status is seriously fucked. Unlike the Linux
|
||||
// files, we can't use strrchr to find the end of a command name.
|
||||
// Spaces in command names do not get escaped. To avoid spoofing,
|
||||
// one may skip 20 characters and then look _forward_ only to
|
||||
// find a pattern of entries that are {with,with,without} a comma.
|
||||
// The entry without a comma is wchan. Then count backwards!
|
||||
//
|
||||
// Don't bother for now. FreeBSD isn't worth the trouble.
|
||||
|
||||
tmp = strchr(buf,' ');
|
||||
num = tmp - buf;
|
||||
if (num >= sizeof P_cmd) num = sizeof P_cmd - 1;
|
||||
memcpy(P_cmd,buf,num);
|
||||
P_cmd[num] = '\0';
|
||||
|
||||
num = sscanf(tmp+1,
|
||||
"%d %d %d %d "
|
||||
"%d,%d "
|
||||
"%*s "
|
||||
"%ld,%*d "
|
||||
"%ld,%*d "
|
||||
"%ld,%*d "
|
||||
"%*s "
|
||||
"%d %d ",
|
||||
&P_pid, &P_ppid, &P_pgrp, &P_session,
|
||||
&tty_maj, &tty_min,
|
||||
/* SKIP funny flags thing */
|
||||
&P_start_time, /* SKIP microseconds */
|
||||
&P_utime, /* SKIP microseconds */
|
||||
&P_stime, /* SKIP microseconds */
|
||||
/* SKIP &P_wchan, for now -- it is a string */
|
||||
&P_euid, &P_euid // don't know which is which
|
||||
);
|
||||
/* fprintf(stderr, "stat2proc converted %d fields.\n",num); */
|
||||
|
||||
snprintf(P_tty_text, sizeof P_tty_text, "%3d,%-3d", tty_maj, tty_min);
|
||||
P_tty_num = DEV_ENCODE(tty_maj,tty_min);
|
||||
// tty decode is 224 to 256 bytes on i386
|
||||
#if 1
|
||||
tmp = NULL;
|
||||
if (tty_maj == 5) tmp = " ttyp%c ";
|
||||
if (tty_maj == 12) tmp = " ttyv%c ";
|
||||
if (tty_maj == 28) tmp = " ttyd%c ";
|
||||
if (P_tty_num == NO_TTY_VALUE) tmp = " ? ";
|
||||
if (P_tty_num == DEV_ENCODE(0,0)) tmp = "console";
|
||||
if (P_tty_num == DEV_ENCODE(12,255)) tmp = "consolectl";
|
||||
if (tmp) {
|
||||
snprintf(
|
||||
P_tty_text,
|
||||
sizeof P_tty_text,
|
||||
tmp,
|
||||
"0123456789abcdefghijklmnopqrstuvwxyz"[tty_min&31]
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(num < 9) return 0;
|
||||
if(P_pid != pid) return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
/* return 1 if it works, or 0 for failure */
|
||||
static int stat2proc(int pid) {
|
||||
char buf[800]; /* about 40 fields, 64-bit decimal is about 20 chars */
|
||||
int num;
|
||||
int fd;
|
||||
char* tmp;
|
||||
struct stat sb; /* stat() used to get EUID */
|
||||
snprintf(buf, 32, "/proc/%d/stat", pid);
|
||||
if ( (fd = open(buf, O_RDONLY, 0) ) == -1 ) return 0;
|
||||
num = read(fd, buf, sizeof buf - 1);
|
||||
fstat(fd, &sb);
|
||||
P_euid = sb.st_uid;
|
||||
close(fd);
|
||||
if(num<80) return 0;
|
||||
buf[num] = '\0';
|
||||
tmp = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */
|
||||
*tmp = '\0'; /* replace trailing ')' with NUL */
|
||||
/* parse these two strings separately, skipping the leading "(". */
|
||||
memset(P_cmd, 0, sizeof P_cmd); /* clear */
|
||||
sscanf(buf, "%d (%15c", &P_pid, P_cmd); /* comm[16] in kernel */
|
||||
num = sscanf(tmp + 2, /* skip space after ')' too */
|
||||
"%c "
|
||||
"%d %d %d %d %d "
|
||||
"%lu %lu %lu %lu %lu %lu %lu "
|
||||
"%ld %ld %ld %ld %ld %ld "
|
||||
"%lu %lu "
|
||||
"%ld "
|
||||
"%lu %lu %lu %lu %lu %lu "
|
||||
"%u %u %u %u " /* no use for RT signals */
|
||||
"%lu %lu %lu",
|
||||
&P_state,
|
||||
&P_ppid, &P_pgrp, &P_session, &P_tty_num, &P_tpgid,
|
||||
&P_flags, &P_min_flt, &P_cmin_flt, &P_maj_flt, &P_cmaj_flt, &P_utime, &P_stime,
|
||||
&P_cutime, &P_cstime, &P_priority, &P_nice, &P_timeout, &P_alarm,
|
||||
&P_start_time, &P_vsize,
|
||||
&P_rss,
|
||||
&P_rss_rlim, &P_start_code, &P_end_code, &P_start_stack, &P_kstk_esp, &P_kstk_eip,
|
||||
&P_signal, &P_blocked, &P_sigignore, &P_sigcatch,
|
||||
&P_wchan, &P_nswap, &P_cnswap
|
||||
);
|
||||
/* fprintf(stderr, "stat2proc converted %d fields.\n",num); */
|
||||
P_vsize /= 1024;
|
||||
P_rss *= (PAGE_SIZE/1024);
|
||||
|
||||
memcpy(P_tty_text, " ? ", 8);
|
||||
if (P_tty_num != NO_TTY_VALUE) {
|
||||
int tty_maj = (P_tty_num>>8)&0xfff;
|
||||
int tty_min = (P_tty_num&0xff) | ((P_tty_num>>12)&0xfff00);
|
||||
snprintf(P_tty_text, sizeof P_tty_text, "%3d,%-3d", tty_maj, tty_min);
|
||||
}
|
||||
|
||||
if(num < 30) return 0;
|
||||
if(P_pid != pid) return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char *do_time(unsigned long t){
|
||||
int hh,mm,ss;
|
||||
static char buf[32];
|
||||
int cnt = 0;
|
||||
t /= HZ;
|
||||
ss = t%60;
|
||||
t /= 60;
|
||||
mm = t%60;
|
||||
t /= 60;
|
||||
hh = t%24;
|
||||
t /= 24;
|
||||
if(t) cnt = snprintf(buf, sizeof buf, "%d-", (int)t);
|
||||
snprintf(cnt + buf, sizeof(buf)-cnt, "%02d:%02d:%02d", hh, mm, ss);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *do_user(void){
|
||||
static char buf[32];
|
||||
static struct passwd *p;
|
||||
static int lastuid = -1;
|
||||
if(P_euid != lastuid){
|
||||
p = getpwuid(P_euid);
|
||||
if(p) snprintf(buf, sizeof buf, "%-8.8s", p->pw_name);
|
||||
else snprintf(buf, sizeof buf, "%5d ", P_euid);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *do_cpu(int longform){
|
||||
static char buf[8];
|
||||
strcpy(buf," - ");
|
||||
if(!longform) buf[2] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *do_mem(int longform){
|
||||
static char buf[8];
|
||||
strcpy(buf," - ");
|
||||
if(!longform) buf[2] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *do_stime(void){
|
||||
static char buf[32];
|
||||
strcpy(buf," - ");
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void print_proc(void){
|
||||
switch(ps_format){
|
||||
case 0:
|
||||
printf("%5d %s %s", P_pid, P_tty_text, do_time(P_utime+P_stime));
|
||||
break;
|
||||
case 'o':
|
||||
printf("%d\n", P_pid);
|
||||
return; /* don't want the command */
|
||||
case 'l':
|
||||
printf(
|
||||
"0 %c %5d %5d %5d %s %3d %3d - "
|
||||
"%5ld %06x %s %s",
|
||||
P_state, P_euid, P_pid, P_ppid, do_cpu(0),
|
||||
(int)P_priority, (int)P_nice, P_vsize/(PAGE_SIZE/1024),
|
||||
(unsigned)(P_wchan&0xffffff), P_tty_text, do_time(P_utime+P_stime)
|
||||
);
|
||||
break;
|
||||
case 'f':
|
||||
printf(
|
||||
"%8s %5d %5d %s %s %s %s",
|
||||
do_user(), P_pid, P_ppid, do_cpu(0), do_stime(), P_tty_text, do_time(P_utime+P_stime)
|
||||
);
|
||||
break;
|
||||
case 'j':
|
||||
printf(
|
||||
"%5d %5d %5d %s %s",
|
||||
P_pid, P_pgrp, P_session, P_tty_text, do_time(P_utime+P_stime)
|
||||
);
|
||||
break;
|
||||
case 'u'|0x80:
|
||||
printf(
|
||||
"%8s %5d %s %s %5ld %4ld %s %c %s %s",
|
||||
do_user(), P_pid, do_cpu(1), do_mem(1), P_vsize, P_rss, P_tty_text, P_state,
|
||||
do_stime(), do_time(P_utime+P_stime)
|
||||
);
|
||||
break;
|
||||
case 'v'|0x80:
|
||||
printf(
|
||||
"%5d %s %c %s %6d - - %5d %s",
|
||||
P_pid, P_tty_text, P_state, do_time(P_utime+P_stime), (int)P_maj_flt,
|
||||
(int)P_rss, do_mem(1)
|
||||
);
|
||||
break;
|
||||
case 'j'|0x80:
|
||||
printf(
|
||||
"%5d %5d %5d %5d %s %5d %c %5d %s",
|
||||
P_ppid, P_pid, P_pgrp, P_session, P_tty_text, P_tpgid, P_state, P_euid, do_time(P_utime+P_stime)
|
||||
);
|
||||
break;
|
||||
case 'l'|0x80:
|
||||
printf(
|
||||
"0 %5d %5d %5d %3d %3d "
|
||||
"%5ld %4ld %06x %c %s %s",
|
||||
P_euid, P_pid, P_ppid, (int)P_priority, (int)P_nice,
|
||||
P_vsize, P_rss, (unsigned)(P_wchan&0xffffff), P_state, P_tty_text, do_time(P_utime+P_stime)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
if(show_args) printf(" [%s]\n", P_cmd);
|
||||
else printf(" %s\n", P_cmd);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
arg_parse(argc, argv);
|
||||
#if 0
|
||||
choose_dimensions();
|
||||
#endif
|
||||
if(!old_h_option){
|
||||
const char *head;
|
||||
switch(ps_format){
|
||||
default: /* can't happen */
|
||||
case 0: head = " PID TTY TIME CMD"; break;
|
||||
case 'l': head = "F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD"; break;
|
||||
case 'f': head = "USER PID PPID C STIME TTY TIME CMD"; break;
|
||||
case 'j': head = " PID PGID SID TTY TIME CMD"; break;
|
||||
case 'u'|0x80: head = "USER PID %CPU %MEM VSZ RSS TTY S START TIME COMMAND"; break;
|
||||
case 'v'|0x80: head = " PID TTY S TIME MAJFL TRS DRS RSS %MEM COMMAND"; break;
|
||||
case 'j'|0x80: head = " PPID PID PGID SID TTY TPGID S UID TIME COMMAND"; break;
|
||||
case 'l'|0x80: head = "F UID PID PPID PRI NI VSZ RSS WCHAN S TTY TIME COMMAND"; break;
|
||||
}
|
||||
printf("%s\n",head);
|
||||
}
|
||||
if(want_one_pid){
|
||||
if(stat2proc(want_one_pid)) print_proc();
|
||||
else exit(1);
|
||||
}else{
|
||||
struct dirent *ent; /* dirent handle */
|
||||
DIR *dir;
|
||||
int ouruid;
|
||||
int found_a_proc;
|
||||
found_a_proc = 0;
|
||||
ouruid = getuid();
|
||||
dir = opendir("/proc");
|
||||
while(( ent = readdir(dir) )){
|
||||
if(*ent->d_name<'0' || *ent->d_name>'9') continue;
|
||||
if(!stat2proc(atoi(ent->d_name))) continue;
|
||||
if(want_one_command){
|
||||
if(strcmp(want_one_command,P_cmd)) continue;
|
||||
}else{
|
||||
if(!select_notty && P_tty_num==NO_TTY_VALUE) continue;
|
||||
if(!select_all && P_euid!=ouruid) continue;
|
||||
}
|
||||
found_a_proc++;
|
||||
print_proc();
|
||||
}
|
||||
closedir(dir);
|
||||
exit(!found_a_proc);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,312 +0,0 @@
|
||||
See http://www.freelists.org/post/procps/Scan-results,5
|
||||
|
||||
|
||||
based on:
|
||||
filtered-with-patches.err
|
||||
|
||||
these are the categories i've assigned:
|
||||
defect_was_fixed
|
||||
EVALUATION_ORDER
|
||||
pmap
|
||||
TAINTED_STRING
|
||||
tload
|
||||
|
||||
possibly_filter_out_?
|
||||
MISSING_BREAK
|
||||
slabtop
|
||||
ps/output
|
||||
|
||||
avoidable_false_positive
|
||||
DEADCODE
|
||||
proc/readproc
|
||||
FORWARD_NULL
|
||||
top
|
||||
vmstat
|
||||
RESOURCE_LEAK
|
||||
ps/parser (3)
|
||||
STRING_NULL
|
||||
pwdx
|
||||
proc/readproc
|
||||
TAINTED_SCALAR
|
||||
pgrep
|
||||
slabtop
|
||||
top (3)
|
||||
TAINTED_STRING
|
||||
watch (2)
|
||||
TOCTOU
|
||||
sysctl (2)
|
||||
UNINIT
|
||||
ps/output (2)
|
||||
|
||||
unavoidable_false_positive_?
|
||||
UNREACHABLE
|
||||
ps/sortformat
|
||||
|
||||
unavoidable_false_positive_but_patched_anyway
|
||||
OVERRUN_STATIC
|
||||
top (no defect, but i yield)
|
||||
|
||||
|
||||
|
||||
pgrep ------------------------------------------------------------------------
|
||||
Error: TAINTED_SCALAR:
|
||||
agree that argv might be tainted
|
||||
but the (int)argv[1][1] index is being passed to isdigit() function (and glibc safely indexes into array sized at 384 bytes)
|
||||
my_category: avoidable_false_positive (out of step with current glibc implementation)
|
||||
pgrep.c:720: tainted_data: Passing tainted variable "argv" to a tainted sink.
|
||||
pgrep.c:558: data_index: Using tainted variable "(int)argv[1][1]" as an index to pointer "*__ctype_b_loc()".
|
||||
|
||||
|
||||
pmap -------------------------------------------------------------------------
|
||||
Error: EVALUATION_ORDER:
|
||||
agree that there is a problem.
|
||||
moreover, it deals with an undocumented command line argument (but sami has documentation addition pending)
|
||||
the logic was altered in line with intent, hopefully avoids this warning
|
||||
my_category: defect_was_fixed
|
||||
pmap.c:314: write_write_order: In "arg2 = (arg2 ? arg2++ : arg1)", "arg2" is written in "arg2" (the assignment left-hand side) and written in "arg2 ? arg2++ : arg1" but the order in which the side effects take place is undefined because there is no intervening sequence point.
|
||||
|
||||
|
||||
|
||||
pwdx -------------------------------------------------------------------------
|
||||
Error: STRING_NULL:
|
||||
static buffer is initialized to 0
|
||||
it is +1 larger than size passed to readlink
|
||||
was fixed in previous analysis
|
||||
my_category: avoidable_false_positive
|
||||
pwdx.c:86: string_null_argument: Function "readlink" does not terminate string "*buf".
|
||||
pwdx.c:73: var_assign_var: Assigning: "s" = "buf". Both now point to the same unterminated string.
|
||||
pwdx.c:73: var_assign_var: Assigning: "s" = "buf". Both now point to the same unterminated string.
|
||||
pwdx.c:73: var_assign_var: Assigning: "s" = "buf". Both now point to the same unterminated string.
|
||||
pwdx.c:92: string_null: Passing unterminated string "s" to "printf".
|
||||
|
||||
|
||||
|
||||
slabtop ----------------------------------------------------------------------
|
||||
Error: MISSING_BREAK:
|
||||
intentional fall through after setting return code
|
||||
no change made
|
||||
my_category: possibly_filter_out_?
|
||||
slabtop.c:314: unterminated_case: This case (value 104) is not terminated by a 'break' statement.
|
||||
slabtop.c:316: fallthrough: The above case falls through to this one.
|
||||
|
||||
Error: TAINTED_SCALAR:
|
||||
read limited to single byte signed 'char'
|
||||
ultimately passed to toupper() function (and glibc safely indexes into array sized at 384 bytes)
|
||||
my_category: avoidable_false_positive (out of step with current glibc implementation)
|
||||
slabtop.c:387: tainted_data_argument: Calling function "read" taints argument "c".
|
||||
slabtop.c:389: tainted_data: Passing tainted variable "c" to a tainted sink.
|
||||
slabtop.c:233: data_index: Using tainted variable "(int)c" as an index to pointer "*__ctype_toupper_loc()".
|
||||
|
||||
|
||||
|
||||
sysctl -----------------------------------------------------------------------
|
||||
Error: TOCTOU:
|
||||
the pathlength between these two events cannot be reduced further
|
||||
instead of assessing intervening lines of code, perhaps tool should assess 'if' statements (2)
|
||||
my_category: avoidable_false_positive
|
||||
sysctl.c:149: fs_check_call: Calling function "stat" to perform check on "tmpname".
|
||||
sysctl.c:168: toctou: Calling function "fopen" that uses "tmpname" after a check function. This can cause a time-of-check, time-of-use race condition.
|
||||
|
||||
Error: TOCTOU:
|
||||
the pathlength between these two events cannot be reduced further
|
||||
instead of assessing intervening lines of code, perhaps tool should assess 'if' statements (2)
|
||||
my_category: avoidable_false_positive
|
||||
sysctl.c:327: fs_check_call: Calling function "stat" to perform check on "tmpname".
|
||||
sysctl.c:345: toctou: Calling function "fopen" that uses "tmpname" after a check function. This can cause a time-of-check, time-of-use race condition.
|
||||
|
||||
|
||||
|
||||
tload ------------------------------------------------------------------------
|
||||
Error: TAINTED_STRING:
|
||||
altered perror call to provide an untainted string
|
||||
my_category: defect_was_fixed
|
||||
tload.c:89: tainted_string: Passing tainted string "argv[optind]" to a function that cannot accept tainted data.
|
||||
|
||||
|
||||
|
||||
top --------------------------------------------------------------------------
|
||||
Error: FORWARD_NULL:
|
||||
cpus cannot be NULL without fp also being NULL
|
||||
the very next 'if (!fp)' ensures cpus will be allocated
|
||||
my_category: avoidable_false_positive
|
||||
top.c:1790: assign_zero: Assigning: "cpus" = 0.
|
||||
top.c:1807: var_deref_op: Dereferencing null variable "cpus".
|
||||
|
||||
Error: OVERRUN_STATIC:
|
||||
This "error" is centered around the following code:
|
||||
f = w->pflgsall[i + w->begpflg];
|
||||
w->procflgs[i] = f;
|
||||
#ifndef USE_X_COLHDR
|
||||
if (P_MAXPFLGS < f) continue;
|
||||
#endif
|
||||
h = Fieldstab[f].head;
|
||||
|
||||
The enum P_MAXPFLGS is strictly a fencepost and can *never* appear in the arrays pflgsall or procflgs.
|
||||
Thus it (39th element) cannot be used in referencing Fieldstab.
|
||||
However, two enums of higher value (X_XON=40 and X_XOF=41) *can* appear in those arrays.
|
||||
But the test against the fencepost ensures that those two enums are *never* used in referencing Fieldstab.
|
||||
|
||||
When the analyzer sees the conditional using '<' and not '<=' it reports a false positive.
|
||||
|
||||
i'm tired of explaining this so the program was changed to accommodate the tool's deficiency
|
||||
my_category: unavoidable_false_positive_but_patched_anyway
|
||||
top.c:1417: overrun-local: Overrunning static array "Fieldstab", with 39 elements, at position 39 with index variable "f".
|
||||
|
||||
Error: TAINTED_SCALAR:
|
||||
the index is used subordinate to a case statement ensuring a value between '1' and '4'
|
||||
my_category: avoidable_false_positive
|
||||
top.c:2442: tainted_data_argument: Calling function "chin" taints argument "ch".
|
||||
top.c:848: tainted_data_argument: Calling function "read" taints parameter "*buf".
|
||||
top.c:2452: tainted_data: Using tainted variable "ch - 49" as an index into an array "Winstk".
|
||||
|
||||
Error: TAINTED_SCALAR:
|
||||
the index is used subordinate to as case statement ensuring a value between '1' and '4'
|
||||
my_category: avoidable_false_positive
|
||||
top.c:2719: tainted_data_argument: Calling function "chin" taints argument "ch".
|
||||
top.c:848: tainted_data_argument: Calling function "read" taints parameter "*buf".
|
||||
top.c:2720: tainted_data: Passing tainted variable "ch" to a tainted sink.
|
||||
top.c:2452: data_index: Using tainted variable "ch - 49" as an index to array "Winstk".
|
||||
|
||||
Error: TAINTED_SCALAR:
|
||||
buf tainted by chin is zero terminated
|
||||
single char is ultimately passed to isprintf() function (and glibc safely indexes into array sized at 384 bytes)
|
||||
my_category: avoidable_false_positive (out of step with current glibc implementation)
|
||||
top.c:972: tainted_data_return: Function "keyin" returns tainted data.
|
||||
top.c:912: tainted_data_argument: Function "chin" taints argument "buf".
|
||||
top.c:848: tainted_data_argument: Calling function "read" taints parameter "*buf".
|
||||
top.c:926: return_tainted_data: Returning tainted variable "buf[0]".
|
||||
top.c:972: var_assign: Assigning: "key" = "keyin", which taints "key".
|
||||
top.c:1001: tainted_data: Using tainted variable "(int)key" as an index to pointer "*__ctype_b_loc()".
|
||||
|
||||
|
||||
|
||||
vmstat -----------------------------------------------------------------------
|
||||
Error: FORWARD_NULL:
|
||||
partition made non-null with optarg for -p where statMode |= PARTITIONSTAT
|
||||
if no optarg then program exits with usage
|
||||
thus call to diskpartition_format will be with non-null pointer
|
||||
my_category: avoidable_false_positive
|
||||
vmstat.c:593: assign_zero: Assigning: "partition" = 0.
|
||||
vmstat.c:669: var_deref_model: Passing null variable "partition" to function "diskpartition_format", which dereferences it.
|
||||
vmstat.c:301: deref_parm_in_call: Function "strcmp" dereferences parameter "partition_name". (The dereference is assumed on the basis of the 'nonnull' parameter attribute.)
|
||||
|
||||
|
||||
|
||||
watch ------------------------------------------------------------------------
|
||||
Error: TAINTED_STRING:
|
||||
even though the environment variable COLUMNS might begin tainted, from my analysis, the tool is totally mistaken
|
||||
strtol actually untaints data in the form of 't' and 'endptr' then the environment variable COLUMNS is potentially purified with -1
|
||||
my_category: avoidable_false_positive
|
||||
watch.c:95: tainted_string_return_content: "getenv" returns tainted string content.
|
||||
watch.c:95: var_assign: Assigning: "s" = "getenv("COLUMNS")", which taints "s".
|
||||
watch.c:100: tainted_data_transitive: Call to function "strtol" with tainted argument "s" returns tainted data.
|
||||
watch.c:100: var_assign: Assigning: "t" = "strtol(s, &endptr, 0)", which taints "t".
|
||||
watch.c:101: var_assign_var: Assigning: "incoming_cols" = "(int)t". Both are now tainted.
|
||||
watch.c:102: var_assign_var: Assigning: "width" = "incoming_cols". Both are now tainted.
|
||||
watch.c:103: vararg_transitive: Call to "snprintf" with tainted argument "width" taints "env_col_buf".
|
||||
watch.c:104: tainted_string: Passing tainted string "env_col_buf" to a function that cannot accept tainted data.
|
||||
|
||||
Error: TAINTED_STRING:
|
||||
even though the environment variable LINES might begin tainted, from my analysis, the tool is totally mistaken
|
||||
strtol actually untaints data in the form of 't' and 'endptr' then the environment variable LINES is potentially purified with -1
|
||||
my_category: avoidable_false_positive
|
||||
watch.c:108: tainted_string_return_content: "getenv" returns tainted string content.
|
||||
watch.c:108: var_assign: Assigning: "s" = "getenv("LINES")", which taints "s".
|
||||
watch.c:113: tainted_data_transitive: Call to function "strtol" with tainted argument "s" returns tainted data.
|
||||
watch.c:113: var_assign: Assigning: "t" = "strtol(s, &endptr, 0)", which taints "t".
|
||||
watch.c:114: var_assign_var: Assigning: "incoming_rows" = "(int)t". Both are now tainted.
|
||||
watch.c:115: var_assign_var: Assigning: "height" = "incoming_rows". Both are now tainted.
|
||||
watch.c:116: vararg_transitive: Call to "snprintf" with tainted argument "height" taints "env_row_buf".
|
||||
watch.c:117: tainted_string: Passing tainted string "env_row_buf" to a function that cannot accept tainted data.
|
||||
|
||||
|
||||
|
||||
proc/readproc ----------------------------------------------------------------
|
||||
Error: DEADCODE:
|
||||
the tool does not understand gperf and the pseudo case labels preceded by goto
|
||||
the following code snippets illustrate the deficiency:
|
||||
goto *(&&base + entry.offset);
|
||||
...
|
||||
case_Threads:
|
||||
Threads = strtol(S,&S,10);
|
||||
continue;
|
||||
my_category: avoidable_false_positive
|
||||
proc/readproc.c:387: dead_error_condition: On this path, the condition "Threads" cannot be true.
|
||||
proc/readproc.c:115: const: After this line, the value of "Threads" is equal to 0.
|
||||
proc/readproc.c:115: assignment: Assigning: "Threads" = "0L".
|
||||
proc/readproc.c:388: dead_error_begin: Execution cannot reach this statement "P->nlwp = Threads;".
|
||||
|
||||
Error: STRING_NULL:
|
||||
read is asked to retrieve -1 bytes than passed capacity: num_read = read(fd, ret, cap - 1);
|
||||
file2str does indeed null terminate sbuf: ret[num_read] = '\0';
|
||||
my_category: avoidable_false_positive
|
||||
proc/readproc.c:1193: string_null_argument: Function "file2str" does not terminate string "*sbuf".
|
||||
proc/readproc.c:514: string_null_argument: Function "read" fills array "*ret" with a non-terminated string.
|
||||
proc/readproc.c:1197: string_null: Passing unterminated string "sbuf" to a function expecting a null-terminated string.
|
||||
proc/readproc.c:447: string_null_sink_parm_call: Passing parameter "S" to "strchr" which expects a null-terminated string.
|
||||
|
||||
|
||||
|
||||
ps/output --------------------------------------------------------------------
|
||||
Error: MISSING_BREAK:
|
||||
intentional fall through
|
||||
my_category: possibly_filter_out_?
|
||||
ps/output.c:1983: unterminated_default: The default case is not terminated by a 'break' statement.
|
||||
ps/output.c:1984: fallthrough: The above case falls through to this one.
|
||||
|
||||
Error: UNINIT:
|
||||
the first member is initialized in the very next statement, sufficient for bsearch callback
|
||||
key.spec = findme;
|
||||
my_category: avoidable_false_positive
|
||||
ps/output.c:1737: var_decl: Declaring variable "key" without initializer.
|
||||
ps/output.c:1739: uninit_use_in_call: Using uninitialized value "key": field "key".flags is uninitialized when calling "bsearch".
|
||||
|
||||
Error: UNINIT:
|
||||
the first member is initialized in the very next statement, sufficient for bsearch callback
|
||||
key.spec = findme;
|
||||
my_category: avoidable_false_positive
|
||||
ps/output.c:1745: var_decl: Declaring variable "key" without initializer.
|
||||
ps/output.c:1747: uninit_use_in_call: Using uninitialized value "key": field "key".head is uninitialized when calling "bsearch".
|
||||
|
||||
|
||||
|
||||
ps/parser --------------------------------------------------------------------
|
||||
Error: RESOURCE_LEAK:
|
||||
intentional omission
|
||||
abexit shortly
|
||||
my_category: avoidable_false_positive
|
||||
ps/parser.c:1021: alloc_fn: Calling allocation function "malloc".
|
||||
ps/parser.c:1021: var_assign: Assigning: "pidnode" = storage returned from "malloc(sizeof (selection_node) /*24*/)".
|
||||
ps/parser.c:1041: leaked_storage: Variable "pidnode" going out of scope leaks the storage it points to.
|
||||
ps/parser.c:1062: leaked_storage: Variable "pidnode" going out of scope leaks the storage it points to.
|
||||
|
||||
Error: RESOURCE_LEAK:
|
||||
intentional omission
|
||||
abexit shortly
|
||||
my_category: avoidable_false_positive
|
||||
ps/parser.c:1025: alloc_fn: Calling allocation function "malloc".
|
||||
ps/parser.c:1025: var_assign: Assigning: "grpnode" = storage returned from "malloc(sizeof (selection_node) /*24*/)".
|
||||
ps/parser.c:1041: leaked_storage: Variable "grpnode" going out of scope leaks the storage it points to.
|
||||
ps/parser.c:1062: leaked_storage: Variable "grpnode" going out of scope leaks the storage it points to.
|
||||
|
||||
Error: RESOURCE_LEAK:
|
||||
intentional omission
|
||||
abexit shortly
|
||||
my_category: avoidable_false_positive
|
||||
ps/parser.c:1029: alloc_fn: Calling allocation function "malloc".
|
||||
ps/parser.c:1029: var_assign: Assigning: "sidnode" = storage returned from "malloc(sizeof (selection_node) /*24*/)".
|
||||
ps/parser.c:1041: leaked_storage: Variable "sidnode" going out of scope leaks the storage it points to.
|
||||
ps/parser.c:1062: leaked_storage: Variable "sidnode" going out of scope leaks the storage it points to.
|
||||
|
||||
|
||||
|
||||
ps/sortformat ----------------------------------------------------------------
|
||||
Error: UNREACHABLE:
|
||||
the tool does not understand the following 'label' usage (nor do i - perhaps some obscure compiler/platform warning/quirk)
|
||||
goto unknown;
|
||||
...
|
||||
if(0) unknown: err=errbuf;
|
||||
my_category: unavoidable_false_positive_?
|
||||
ps/sortformat.c:312: unreachable: This code cannot be reached: "if (0){
|
||||
unknown:
|
||||
err = ...".
|
@ -1,745 +0,0 @@
|
||||
/*
|
||||
* w.c - show logged users and what they are doing
|
||||
*
|
||||
* Copyright (c) Dec 1993, Oct 1994 Steve "Mr. Bassman" Bryant
|
||||
* bassman@hpbbi30.bbn.hp.com (Old address)
|
||||
* bassman@muttley.soc.staffs.ac.uk
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* An alternative "w" program for Linux.
|
||||
* Shows users and their processes.
|
||||
*
|
||||
* Info:
|
||||
* I starting writing as an improvement of the w program included
|
||||
* with linux. The idea was to add in some extra functionality to the
|
||||
* program, and see if I could fix a couple of bugs which seemed to
|
||||
* occur.
|
||||
* Mr. Bassman, 10/94
|
||||
*
|
||||
* Acknowledgments:
|
||||
*
|
||||
* The original version of w:
|
||||
* Copyright (c) 1993 Larry Greenfield (greenfie@gauss.rutgers.edu)
|
||||
*
|
||||
* Uptime routine and w mods:
|
||||
* Michael K. Johnson (johnsonm@stolaf.edu)
|
||||
*
|
||||
*
|
||||
* Distribution:
|
||||
* This program is freely distributable under the terms of copyleft.
|
||||
* No warranty, no support, use at your own risk etc.
|
||||
*
|
||||
* Compilation:
|
||||
* gcc -O -o w sysinfo.c whattime.c w.c
|
||||
*
|
||||
* Usage:
|
||||
* w [-hfusd] [user]
|
||||
*
|
||||
*
|
||||
* $Log: tmp-junk.c,v $
|
||||
* Revision 1.1 2002/02/01 22:46:37 csmall
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.5 1994/10/26 17:57:35 bassman
|
||||
* Loads of stuff - see comments.
|
||||
*
|
||||
* Revision 1.4 1994/01/01 12:57:21 johnsonm
|
||||
* Added RCS, and some other fixes.
|
||||
*
|
||||
* Revision history:
|
||||
* Jan 01, 1994 (mkj): Eliminated GCC warnings, took out unnecessary
|
||||
* dead variables in fscanf, replacing them with
|
||||
* *'d format qualifiers. Also added RCS stuff.
|
||||
* Oct 26, 1994 (bass): Tidied up the code, fixed bug involving corrupt
|
||||
* utmp records. Added switch for From field;
|
||||
* default is compile-time set. Added -d option
|
||||
* as a remnant from BSD 'w'. Fixed bug so it now
|
||||
* behaves if the first process on a tty isn't owned
|
||||
* by the person first logged in on that tty, and
|
||||
* also detects su'd users. Changed the tty format
|
||||
* to the short one.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <time.h>
|
||||
#include <utmp.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include "proc/whattime.h"
|
||||
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
/*
|
||||
* Default setting for whether to have a From field. The -f switch
|
||||
* toggles this - if the default is to have it, using -f will turn
|
||||
* it off; if the default is not to have it, the -f switch will put
|
||||
* it in. Possible values are TRUE (to have the field by default),
|
||||
* and FALSE.
|
||||
*/
|
||||
#define DEFAULT_FROM TRUE
|
||||
#define ZOMBIE "<zombie>"
|
||||
|
||||
|
||||
void put_syntax();
|
||||
char *idletime();
|
||||
char *logintime();
|
||||
|
||||
static char rcsid[]="$Id: tmp-junk.c,v 1.1 2002/02/01 22:46:37 csmall Exp $";
|
||||
|
||||
|
||||
void main (argc, argv)
|
||||
|
||||
int argc;
|
||||
char *argv[];
|
||||
|
||||
{
|
||||
int header=TRUE, long_format=TRUE, ignore_user=TRUE,
|
||||
from_switch=DEFAULT_FROM, show_pid=FALSE, line_length;
|
||||
int i, j;
|
||||
struct utmp *utmp_rec;
|
||||
struct stat stat_rec;
|
||||
struct passwd *passwd_entry;
|
||||
uid_t uid;
|
||||
char username[9], tty[13], rhost[17], login_time[27];
|
||||
char idle_time[7], what[1024], pid[10];
|
||||
char out_line[1024], file_name[256];
|
||||
char search_name[9];
|
||||
int jcpu, pcpu, tpgid, curr_pid, utime, stime, cutime, cstime;
|
||||
char /*ch,*/ state, comm[1024], *columns_ptr;
|
||||
FILE *fp;
|
||||
|
||||
|
||||
search_name[0] = '\0';
|
||||
|
||||
|
||||
/*
|
||||
* Process the command line
|
||||
*/
|
||||
if (argc > 1)
|
||||
{
|
||||
/*
|
||||
* Args that start with '-'
|
||||
*/
|
||||
for (i = 1; ((i < argc) && (argv[i][0] == '-')); i ++)
|
||||
{
|
||||
for (j = 1; argv[i][j] != '\0'; j++)
|
||||
{
|
||||
switch (argv[i][j])
|
||||
{
|
||||
case 'h':
|
||||
header = FALSE;
|
||||
break;
|
||||
case 's':
|
||||
long_format = FALSE;
|
||||
break;
|
||||
case 'u':
|
||||
ignore_user = FALSE;
|
||||
break;
|
||||
case 'd':
|
||||
show_pid = TRUE;
|
||||
break;
|
||||
case 'f':
|
||||
if (DEFAULT_FROM == TRUE)
|
||||
from_switch = FALSE;
|
||||
else
|
||||
from_switch = TRUE;
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "w: unknown option: '%c'\n",
|
||||
argv[i][j]);
|
||||
put_syntax ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for arg not starting with '-' (ie: username)
|
||||
*/
|
||||
if (argc > i)
|
||||
{
|
||||
strncpy (search_name, argv[i], 8);
|
||||
search_name[8] = '\0';
|
||||
i ++;
|
||||
|
||||
if (argc > i)
|
||||
{
|
||||
fprintf (stderr, "w: syntax error\n");
|
||||
put_syntax ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Check that /proc is actually there, or else we can't
|
||||
* get all the information.
|
||||
*/
|
||||
if (chdir ("/proc"))
|
||||
{
|
||||
fprintf (stderr, "w: fatal error: cannot access /proc\n");
|
||||
perror (strerror(errno));
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Find out our screen width from $COLUMNS
|
||||
*/
|
||||
columns_ptr = getenv ("COLUMNS");
|
||||
if (columns_ptr == NULL)
|
||||
{
|
||||
struct winsize window;
|
||||
|
||||
/*
|
||||
* Try getting it directly
|
||||
*/
|
||||
if ((ioctl (1, TIOCGWINSZ, &window) != 1) && (window.ws_col > 0))
|
||||
line_length = window.ws_col;
|
||||
else
|
||||
line_length = 80; /* Default length assumed */
|
||||
}
|
||||
else
|
||||
line_length = atoi (columns_ptr);
|
||||
|
||||
/*
|
||||
* Maybe we should check whether there is enough space on
|
||||
* the lines for the options selected...
|
||||
*/
|
||||
if (line_length < 60)
|
||||
long_format = FALSE;
|
||||
|
||||
line_length --;
|
||||
|
||||
|
||||
/*
|
||||
* Print whatever headers
|
||||
*/
|
||||
if (header == TRUE)
|
||||
{
|
||||
/*
|
||||
* uptime: from MKJ's uptime routine,
|
||||
* found in whattime.c
|
||||
*/
|
||||
print_uptime();
|
||||
|
||||
|
||||
/*
|
||||
* Print relevant header bits
|
||||
*/
|
||||
printf ("User tty ");
|
||||
|
||||
if (long_format == TRUE)
|
||||
{
|
||||
if (from_switch == TRUE)
|
||||
printf ("From ");
|
||||
|
||||
printf (" login@ idle JCPU PCPU ");
|
||||
|
||||
if (show_pid == TRUE)
|
||||
printf (" PID ");
|
||||
|
||||
printf ("what\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf (" idle ");
|
||||
|
||||
if (show_pid == TRUE)
|
||||
printf (" PID ");
|
||||
|
||||
printf ("what\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Process user information.
|
||||
*/
|
||||
while ((utmp_rec = getutent()))
|
||||
{
|
||||
/*
|
||||
* Check we actually want to see this record.
|
||||
* It must be a valid active user process,
|
||||
* and match a specified search name.
|
||||
*/
|
||||
if ( (utmp_rec->ut_type == USER_PROCESS)
|
||||
&& (strcmp(utmp_rec->ut_user, ""))
|
||||
&& ( (search_name[0] == '\0')
|
||||
|| ( (search_name[0] != '\0')
|
||||
&& !strncmp(search_name, utmp_rec->ut_user, 8) ) ) )
|
||||
{
|
||||
/*
|
||||
* Get the username
|
||||
*/
|
||||
strncpy (username, utmp_rec->ut_user, 8);
|
||||
username[8] = '\0'; /* Set end terminator */
|
||||
|
||||
|
||||
/*
|
||||
* Find out the uid of that user (from their
|
||||
* passwd entry)
|
||||
*/
|
||||
uid = -1;
|
||||
if ((passwd_entry = getpwnam (username)) != NULL)
|
||||
{
|
||||
uid = passwd_entry->pw_uid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get (and clean up) the tty line
|
||||
*/
|
||||
for (i = 0; (utmp_rec->ut_line[i] > 32) && (i < 6); i ++)
|
||||
tty[i] = utmp_rec->ut_line[i];
|
||||
|
||||
utmp_rec->ut_line[i] = '\0';
|
||||
tty[i] = '\0';
|
||||
|
||||
|
||||
/*
|
||||
* Don't bother getting info if it's not asked for
|
||||
*/
|
||||
if (long_format == TRUE)
|
||||
{
|
||||
|
||||
/*
|
||||
* Get the remote hostname; this can be up to 16 chars,
|
||||
* but if any chars are invalid (ie: [^a-zA-Z0-9\.])
|
||||
* then the char is changed to a string terminator.
|
||||
*/
|
||||
if (from_switch == TRUE)
|
||||
{
|
||||
strncpy (rhost, utmp_rec->ut_host, 16);
|
||||
rhost[16] = '\0';
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the login time
|
||||
* (Calculated by LG's routine, below)
|
||||
*/
|
||||
strcpy (login_time, logintime(utmp_rec->ut_time));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Get the idle time.
|
||||
* (Calculated by LG's routine, below)
|
||||
*/
|
||||
strcpy (idle_time, idletime (tty));
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* That's all the info out of /etc/utmp.
|
||||
* The rest is more difficult. We use the pid from
|
||||
* utmp_rec->ut_pid to look in /proc for the info.
|
||||
* NOTE: This is not necessarily the active pid, so we chase
|
||||
* down the path of parent -> child pids until we find it,
|
||||
* according to the information given in /proc/<pid>/stat.
|
||||
*/
|
||||
|
||||
sprintf (pid, "%d", utmp_rec->ut_pid);
|
||||
|
||||
what[0] = '\0';
|
||||
strcpy (file_name, pid);
|
||||
strcat (file_name, "/stat");
|
||||
jcpu = 0;
|
||||
pcpu = 0;
|
||||
|
||||
if ((fp = fopen(file_name, "r")))
|
||||
{
|
||||
while (what[0] == '\0')
|
||||
{
|
||||
/*
|
||||
* Check /proc/<pid>/stat to see if the process
|
||||
* controlling the tty is the current one
|
||||
*/
|
||||
fscanf (fp, "%d %s %c %*d %*d %*d %*d %d "
|
||||
"%*u %*u %*u %*u %*u %d %d %d %d",
|
||||
&curr_pid, comm, &state, &tpgid,
|
||||
&utime, &stime, &cutime, &cstime);
|
||||
|
||||
fclose (fp);
|
||||
|
||||
if (comm[0] == '\0')
|
||||
strcpy (comm, "-");
|
||||
|
||||
/*
|
||||
* Calculate jcpu and pcpu.
|
||||
* JCPU is the time used by all processes and their
|
||||
* children, attached to the tty.
|
||||
* PCPU is the time used by the current process
|
||||
* (calculated once after the loop, using last
|
||||
* obtained values).
|
||||
*/
|
||||
if (!jcpu)
|
||||
jcpu = cutime + cstime;
|
||||
|
||||
/*
|
||||
* Check for a zombie first...
|
||||
*/
|
||||
if (state == 'Z')
|
||||
strcpy (what, ZOMBIE);
|
||||
else if (curr_pid == tpgid)
|
||||
{
|
||||
/*
|
||||
* If it is the current process, read cmdline
|
||||
* If that's empty, then the process is swapped out,
|
||||
* or is a zombie, so we use the command given in stat
|
||||
* which is in normal round brackets, ie: "()".
|
||||
*/
|
||||
strcpy (file_name, pid);
|
||||
strcat (file_name, "/cmdline");
|
||||
if ((fp = fopen(file_name, "r")))
|
||||
{
|
||||
i = 0;
|
||||
j = fgetc (fp);
|
||||
while ((j != EOF) && (i < 256))
|
||||
{
|
||||
if (j == '\0')
|
||||
j = ' ';
|
||||
|
||||
what[i] = j;
|
||||
i++;
|
||||
j = fgetc (fp);
|
||||
}
|
||||
what[i] = '\0';
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
if (what[0] == '\0')
|
||||
strcpy (what, comm);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Check out the next process
|
||||
* If we can't open it, use info from this process,
|
||||
* so we have to check out cmdline first.
|
||||
*
|
||||
* If we're not using "-u" then should we just
|
||||
* say "-" (or "-su") instead of a command line ?
|
||||
* If so, we should strpcy(what, "-"); when we
|
||||
* fclose() in the if after the stat() below.
|
||||
*/
|
||||
strcpy (file_name, pid);
|
||||
strcat (file_name, "/cmdline");
|
||||
|
||||
if ((fp = fopen (file_name, "r")))
|
||||
{
|
||||
i = 0;
|
||||
j = fgetc (fp);
|
||||
while ((j != EOF) && (i < 256))
|
||||
{
|
||||
if (j == '\0')
|
||||
j = ' ';
|
||||
|
||||
what[i] = j;
|
||||
i++;
|
||||
j = fgetc (fp);
|
||||
}
|
||||
what[i] = '\0';
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
if (what[0] == '\0')
|
||||
strcpy (what, comm);
|
||||
|
||||
/*
|
||||
* Now we have something in the what variable,
|
||||
* in case we can't open the next process.
|
||||
*/
|
||||
sprintf (pid, "%d", tpgid);
|
||||
strcpy (file_name, pid);
|
||||
strcat (file_name, "/stat");
|
||||
|
||||
fp = fopen (file_name, "r");
|
||||
|
||||
if (fp && (ignore_user == FALSE))
|
||||
{
|
||||
/*
|
||||
* We don't necessarily go onto the next process,
|
||||
* unless we are either ignoring who the effective
|
||||
* user is, or it's the same uid
|
||||
*/
|
||||
stat (file_name, &stat_rec);
|
||||
|
||||
/*
|
||||
* If the next process is not owned by this
|
||||
* user finish the loop.
|
||||
*/
|
||||
if (stat_rec.st_uid != uid)
|
||||
{
|
||||
fclose (fp);
|
||||
|
||||
strcpy (what, "-su");
|
||||
/*
|
||||
* See comment above somewhere; I've used
|
||||
* "-su" here, as the next process is owned
|
||||
* by someone else; this is generally
|
||||
* because the user has done an "su" which
|
||||
* then exec'd something else.
|
||||
*/
|
||||
}
|
||||
else
|
||||
what[0] = '\0';
|
||||
}
|
||||
else if (fp) /* else we are ignoring uid's */
|
||||
what[0] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Could not open first process for user */
|
||||
strcpy (what, "?");
|
||||
|
||||
|
||||
/*
|
||||
* There is a bug somewhere in my version of linux
|
||||
* which means that utmp records are not cleaned
|
||||
* up properly when users log out. However, we
|
||||
* can detect this, by the users first process
|
||||
* not being there when we look in /proc.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Don't output a line for "dead" users.
|
||||
* This gets round a bug which doesn't update utmp/wtmp
|
||||
* when users log out.
|
||||
*/
|
||||
if (what[0] != '?')
|
||||
{
|
||||
#ifdef 0
|
||||
/* This makes unix98 pty's not line up, so has been disabled - JEH. */
|
||||
/*
|
||||
* Remove the letters 'tty' from the tty id
|
||||
*/
|
||||
if (!strncmp (tty, "tty", 3))
|
||||
{
|
||||
for (i = 3; tty[i - 1] != '\0'; i ++)
|
||||
tty[i - 3] = tty[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Common fields
|
||||
*/
|
||||
sprintf (out_line, "%-9.8s%-6.7s ", username, tty);
|
||||
|
||||
|
||||
/*
|
||||
* Format the line for output
|
||||
*/
|
||||
if (long_format == TRUE)
|
||||
{
|
||||
/*
|
||||
* Calculate CPU usage
|
||||
*/
|
||||
pcpu = utime + stime;
|
||||
jcpu /= 100;
|
||||
pcpu /= 100;
|
||||
|
||||
if (from_switch == TRUE)
|
||||
sprintf (out_line, "%s %-16.15s", out_line, rhost);
|
||||
|
||||
sprintf (out_line, "%s%8.8s ", out_line, login_time);
|
||||
|
||||
}
|
||||
|
||||
sprintf (out_line, "%s%6s", out_line, idle_time);
|
||||
|
||||
|
||||
if (long_format == TRUE)
|
||||
{
|
||||
if (!jcpu)
|
||||
strcat (out_line, " ");
|
||||
else if (jcpu/60)
|
||||
sprintf (out_line, "%s%3d:%02d", out_line,
|
||||
jcpu/60, jcpu%60);
|
||||
else
|
||||
sprintf (out_line, "%s %2d", out_line, jcpu);
|
||||
|
||||
if (!pcpu)
|
||||
strcat (out_line, " ");
|
||||
else if (pcpu/60)
|
||||
sprintf (out_line, "%s%3d:%02d", out_line,
|
||||
pcpu/60, pcpu%60);
|
||||
else
|
||||
sprintf (out_line, "%s %2d", out_line, pcpu);
|
||||
}
|
||||
|
||||
if (show_pid == TRUE)
|
||||
sprintf (out_line, "%s %5.5s", out_line, pid);
|
||||
|
||||
|
||||
strcat (out_line, " ");
|
||||
strcat (out_line, what);
|
||||
|
||||
|
||||
/*
|
||||
* Try not to exceed the line length
|
||||
*/
|
||||
out_line[line_length] = '\0';
|
||||
|
||||
printf ("%s\n", out_line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* put_syntax()
|
||||
*
|
||||
* Routine to print the correct syntax to call this program,
|
||||
* and then exit out appropriately
|
||||
*/
|
||||
void put_syntax ()
|
||||
{
|
||||
fprintf (stderr, "usage: w [-hfsud] [user]\n");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* idletime()
|
||||
*
|
||||
* Routine which returns a string containing
|
||||
* the idle time of a given user.
|
||||
*
|
||||
* This routine was lifted from the original w program
|
||||
* by Larry Greenfield (greenfie@gauss.rutgers.edu)
|
||||
* Copyright (c) 1993 Larry Greenfield
|
||||
*
|
||||
*/
|
||||
char *idletime (tty)
|
||||
|
||||
char *tty;
|
||||
|
||||
{
|
||||
struct stat terminfo;
|
||||
unsigned long idle;
|
||||
char ttytmp[40];
|
||||
static char give[20];
|
||||
time_t curtime;
|
||||
|
||||
curtime = time (NULL);
|
||||
|
||||
sprintf (ttytmp, "/dev/%s", tty);
|
||||
stat (ttytmp, &terminfo);
|
||||
idle = (unsigned long) curtime - (unsigned long) terminfo.st_atime;
|
||||
|
||||
if (idle >= (60 * 60)) /* more than an hour */
|
||||
{
|
||||
if (idle >= (60 * 60 * 48)) /* more than two days */
|
||||
sprintf (give, "%2ludays", idle / (60 * 60 * 24));
|
||||
else
|
||||
sprintf (give, " %2lu:%02u", idle / (60 * 60),
|
||||
(unsigned) ((idle / 60) % 60));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (idle / 60)
|
||||
sprintf (give, "%6lu", idle / 60);
|
||||
else
|
||||
give[0]=0;
|
||||
}
|
||||
|
||||
return give;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* logintime()
|
||||
*
|
||||
* Returns the time given in a suitable format
|
||||
*
|
||||
* This routine was lifted from the original w program
|
||||
* by Larry Greenfield (greenfie@gauss.rutgers.edu)
|
||||
* Copyright (c) 1993 Larry Greenfield
|
||||
*
|
||||
*/
|
||||
|
||||
#undef ut_time
|
||||
|
||||
char *logintime(ut_time)
|
||||
|
||||
time_t ut_time;
|
||||
|
||||
{
|
||||
time_t curtime;
|
||||
struct tm *logintime, *curtm;
|
||||
int hour, am, curday, logday;
|
||||
static char give[20];
|
||||
static char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
|
||||
"Sat" };
|
||||
static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
|
||||
"Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
|
||||
curtime = time(NULL);
|
||||
curtm = localtime(&curtime);
|
||||
curday = curtm->tm_yday;
|
||||
logintime = localtime(&ut_time);
|
||||
hour = logintime->tm_hour;
|
||||
logday = logintime->tm_yday;
|
||||
am = (hour < 12);
|
||||
|
||||
if (!am)
|
||||
hour -= 12;
|
||||
|
||||
if (hour == 0)
|
||||
hour = 12;
|
||||
|
||||
/*
|
||||
* This is a newer behavior: it waits 12 hours and the next day, and then
|
||||
* goes to the 2nd time format. This should reduce confusion.
|
||||
* It then waits only 6 days (not till the last moment) to go the last
|
||||
* time format.
|
||||
*/
|
||||
if ((curtime > (ut_time + (60 * 60 * 12))) && (logday != curday))
|
||||
{
|
||||
if (curtime > (ut_time + (60 * 60 * 24 * 6)))
|
||||
sprintf(give, "%2d%3s%2d", logintime->tm_mday,
|
||||
month[logintime->tm_mon], (logintime->tm_year % 100));
|
||||
else
|
||||
sprintf(give, "%*s%2d%s", 3, weekday[logintime->tm_wday],
|
||||
hour, am ? "am" : "pm");
|
||||
}
|
||||
else
|
||||
sprintf(give, "%2d:%02d%s", hour, logintime->tm_min, am ? "am" : "pm");
|
||||
|
||||
return give;
|
||||
}
|
||||
|
197
contrib/utmp.c
197
contrib/utmp.c
@ -1,197 +0,0 @@
|
||||
/*
|
||||
* utmp.c - utmp printing command
|
||||
* Copyright (C) Albert Cahalan
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <time.h>
|
||||
#include <utmp.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* examine and fix utmp entries. Note that the code for fixing entries
|
||||
is not complete, and indeed does nothing at all at this time. No bug
|
||||
reports, please, as I am still actively working on this. It is not
|
||||
here for general use, but only so that I can ferret out any bugs that
|
||||
exist on other peoples systems without having to log in to their systems
|
||||
myself ;-) */
|
||||
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
|
||||
FILE *ut; /* /var/run/utmp */
|
||||
struct utmp uts; /* utmp record */
|
||||
char user[UT_NAMESIZE + 1];
|
||||
char host[17];
|
||||
char ch;
|
||||
int print_all = 0, list = 0, fix = 0;
|
||||
|
||||
/* get options */
|
||||
while ((ch = getopt(argc, argv, "laf")) != EOF)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
print_all = 1;
|
||||
break;
|
||||
case 'l':
|
||||
list = 1;
|
||||
break;
|
||||
case 'f':
|
||||
fix = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* check argument options */
|
||||
if ( (!list && !print_all && !fix)) {
|
||||
fprintf(stderr, "You must specify a command line option:\n\tl = list\n\
|
||||
\tf = fix\n\ta = all (requires l or f)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (list) {
|
||||
ut = fopen(UTMP_FILE, "r");
|
||||
while (fread(&uts, sizeof(uts), 1, ut))
|
||||
if (((uts.ut_type == USER_PROCESS) && (uts.ut_name[0] != '\000'))
|
||||
|| print_all) {
|
||||
strncpy(user, uts.ut_user, UT_NAMESIZE);
|
||||
user[UT_NAMESIZE]=0;
|
||||
strncpy(host, uts.ut_host, 16);
|
||||
host[16]=0;
|
||||
printf("ut_type: %d\n", uts.ut_type);
|
||||
printf("ut_pid: %d\n", uts.ut_pid);
|
||||
printf("ut_line: %s\n", uts.ut_line);
|
||||
printf("ut_id: %2s\n", uts.ut_id);
|
||||
printf("ut_time: %d\n", uts.ut_time);
|
||||
printf("ut_user: %s\n", user);
|
||||
printf("ut_host: %s\n", host);
|
||||
printf("ut_addr: %d\n\n", uts.ut_addr);
|
||||
}
|
||||
fclose(ut);
|
||||
}
|
||||
|
||||
|
||||
if (fix) {
|
||||
ut = fopen(UTMP_FILE, "r");
|
||||
while (fread(&uts, sizeof(uts), 1, ut))
|
||||
if (((uts.ut_type == USER_PROCESS) && (uts.ut_name[0] != '\000'))
|
||||
|| print_all) {
|
||||
/* Display entry in utmp */
|
||||
strncpy(user, uts.ut_user, UT_NAMESIZE);
|
||||
user[UT_NAMESIZE]=0;
|
||||
strncpy(host, uts.ut_host, 16);
|
||||
host[16]=0;
|
||||
printf("ut_type: %d\n", uts.ut_type);
|
||||
printf("ut_pid: %d\n", uts.ut_pid);
|
||||
printf("ut_line: %s\n", uts.ut_line);
|
||||
printf("ut_id: %s2\n", uts.ut_id);
|
||||
printf("ut_time: %d\n", uts.ut_time);
|
||||
printf("ut_user: %s\n", user);
|
||||
printf("ut_host: %s\n", host);
|
||||
printf("ut_addr: %d\n\n", uts.ut_addr);
|
||||
|
||||
printf("Modify this record? (y/N): "); fflush(stdout);
|
||||
/* Ask if to delete or no */
|
||||
if ((ch = getchar()) == 'y' || ch == 'Y') {
|
||||
while (getchar() != '\n');
|
||||
printf("Change ut_type? "); fflush(stdout);
|
||||
if ((ch = getchar()) == 'y' || ch == 'Y') {
|
||||
while (getchar() != '\n');
|
||||
printf("INIT, LOGIN, USER, or DEAD_PROCESS? (I/L/U/D): ");
|
||||
fflush(stdout);
|
||||
ch = getchar();
|
||||
switch (ch) {
|
||||
case 'i':
|
||||
case 'I':
|
||||
uts.ut_type = INIT_PROCESS;
|
||||
break;
|
||||
case 'l':
|
||||
case 'L':
|
||||
uts.ut_type = LOGIN_PROCESS;
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
uts.ut_type = USER_PROCESS;
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
uts.ut_type = DEAD_PROCESS;
|
||||
break;
|
||||
default:
|
||||
printf("Invalid choice: %c\n", ch);
|
||||
}
|
||||
if (ch != '\n') while ((ch = getchar()) != '\n');
|
||||
}
|
||||
if (ch != '\n') while ((ch = getchar()) != '\n');
|
||||
printf("Change ut_id field? (y/N): "); fflush(stdout);
|
||||
if ((ch = getchar()) == 'y' || ch == 'Y') {
|
||||
while (getchar() != '\n');
|
||||
printf("Please enter the two characters for ut_id: ");
|
||||
fflush(stdout);
|
||||
uts.ut_id[0] = getchar();
|
||||
uts.ut_id[1] = getchar();
|
||||
while ((ch = getchar()) != '\n');
|
||||
}
|
||||
if (ch != '\n') while ((ch = getchar()) != '\n');
|
||||
printf("Change the ut_user field? (y/N): "); fflush(stdout);
|
||||
if ((ch = getchar()) == 'y' || ch == 'Y') {
|
||||
int i;
|
||||
while (getchar() != '\n');
|
||||
printf("Please enter the new ut_name, up to %c characters: ",
|
||||
UT_NAMESIZE);
|
||||
fflush(stdout);
|
||||
for (i=0; i<UT_NAMESIZE; i++) {
|
||||
ch = getchar();
|
||||
uts.ut_user[i] = (ch != '\n') ? ch : i = UT_NAMESIZE, (char) 0;
|
||||
}
|
||||
}
|
||||
if (ch != '\n') while ((ch = getchar()) != '\n');
|
||||
printf("Change the ut_host field? (y/N): "); fflush(stdout);
|
||||
if ((ch = getchar()) == 'y' || ch == 'Y') {
|
||||
int i;
|
||||
while (getchar() != '\n');
|
||||
printf("Please enter the new ut_host, up to 16 characters: ");
|
||||
fflush(stdout);
|
||||
for (i=0; i<16; i++) {
|
||||
ch = getchar();
|
||||
uts.ut_user[i] = (ch != '\n') ? ch : i = 16, (char) 0;
|
||||
}
|
||||
if (ch != '\n') while ((ch = getchar()) != '\n');
|
||||
}
|
||||
|
||||
/* Here go the changes...*/
|
||||
/* utmpname(UTMP_FILE);
|
||||
setutent();
|
||||
pututline(&uts);
|
||||
endutent(); */
|
||||
/* But they don't work... */
|
||||
|
||||
}
|
||||
if (ch != '\n') while ((ch = getchar()) != '\n');
|
||||
/* here we should write the utmp entry */
|
||||
}
|
||||
fclose(ut);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user