build-sys: add contrib directory

Move files that are not compiled to <build-root>/contrib
directory. The files consist two unmaintained commands,
alternative ps & w, and and broken utmp examination / printing
utility. The dummy.c became unnecessary at the point when
autotools where re-introduced.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
Sami Kerola
2011-06-05 12:17:14 +02:00
parent 71d10d3a49
commit a425a65d46
6 changed files with 5 additions and 3 deletions

31
contrib/dummy.c Normal file
View File

@@ -0,0 +1,31 @@
// This is to test the compiler.
#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;
}

670
contrib/minimal.c Normal file
View File

@@ -0,0 +1,670 @@
/*
* Copyright 1998,2004 by Albert Cahalan; all rights reserved.
* This file may be used subject to the terms and conditions of the
* GNU Library General Public License Version 2, or any later version
* at your option, as published by the Free Software Foundation.
* This program 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 Library General Public License for more details.
*/
/* 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, assuming it is 4096
#define PAGE_SIZE 4096
#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;
}

730
contrib/tmp-junk.c Normal file
View File

@@ -0,0 +1,730 @@
/*
* w.c v1.4
*
* An alternative "w" program for Linux.
* Shows users and their processes.
*
* Copyright (c) Dec 1993, Oct 1994 Steve "Mr. Bassman" Bryant
* bassman@hpbbi30.bbn.hp.com (Old address)
* bassman@muttley.soc.staffs.ac.uk
*
* 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;
}

178
contrib/utmp.c Normal file
View File

@@ -0,0 +1,178 @@
#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;
}