diff --git a/Makefile.am b/Makefile.am index c555ac06..db5f932b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -96,7 +96,6 @@ endif EXTRA_DIST = \ .version \ autogen.sh \ - contrib \ COPYING.LIB \ misc/git-version-gen \ Documentation/CodingStyle.md \ diff --git a/contrib/dummy.c b/contrib/dummy.c deleted file mode 100644 index dffc7075..00000000 --- a/contrib/dummy.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Foul POS defines all sorts of stuff... */ -#include -#undef tab - -#include -#include -#include -#include - -int main(int argc, char *argv[]){ - (void)argc; - (void)argv; - return 0; -} diff --git a/contrib/minimal.c b/contrib/minimal.c deleted file mode 100644 index cda14239..00000000 --- a/contrib/minimal.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DEV_ENCODE(M,m) ( \ - ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \ -) - -/////////////////////////////////////////////////////// -#ifdef __sun__ -#include -#define _STRUCTURED_PROC 1 -#include -#define NO_TTY_VALUE DEV_ENCODE(-1,-1) -#define HZ 1 // only bother with seconds -#endif - -/////////////////////////////////////////////////////// -#ifdef __FreeBSD__ -#include -#include -#include -#include -#include -#define NO_TTY_VALUE DEV_ENCODE(-1,-1) -#define HZ 1 // only bother with seconds -#endif - -/////////////////////////////////////////////////////// -#ifdef __linux__ -#include /* HZ */ -#include /* 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 -/* 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 "" */ - *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; -} diff --git a/contrib/response.filtered-with-patches.err b/contrib/response.filtered-with-patches.err deleted file mode 100644 index 687a20b6..00000000 --- a/contrib/response.filtered-with-patches.err +++ /dev/null @@ -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 = ...". diff --git a/contrib/tmp-junk.c b/contrib/tmp-junk.c deleted file mode 100644 index 21885b49..00000000 --- a/contrib/tmp-junk.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 "" - - -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//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//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; -} - diff --git a/contrib/utmp.c b/contrib/utmp.c deleted file mode 100644 index 00ebc55d..00000000 --- a/contrib/utmp.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include - -/* 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