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:
Craig Small 2022-08-29 17:46:03 +10:00
parent 86c7eeb70d
commit 5fcf104cba
6 changed files with 0 additions and 1980 deletions

View File

@ -96,7 +96,6 @@ endif
EXTRA_DIST = \ EXTRA_DIST = \
.version \ .version \
autogen.sh \ autogen.sh \
contrib \
COPYING.LIB \ COPYING.LIB \
misc/git-version-gen \ misc/git-version-gen \
Documentation/CodingStyle.md \ Documentation/CodingStyle.md \

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 = ...".

View File

@ -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;
}

View File

@ -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;
}