procps 010114
This commit is contained in:
422
ps/global.c
Normal file
422
ps/global.c
Normal file
@ -0,0 +1,422 @@
|
||||
/*
|
||||
* Copyright 1998 by Albert Cahalan; all rights resered.
|
||||
* 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.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <string.h>
|
||||
|
||||
/*#undef __GLIBC_MINOR__
|
||||
#define __GLIBC_MINOR__ 1 */
|
||||
#include "common.h"
|
||||
/*#undef __GLIBC_MINOR__
|
||||
#define __GLIBC_MINOR__ 0 */
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
#include "../proc/version.h"
|
||||
#include "../proc/sysinfo.h"
|
||||
|
||||
|
||||
#ifndef __GNU_LIBRARY__
|
||||
#define __GNU_LIBRARY__ -1
|
||||
#endif
|
||||
#ifndef __GLIBC__
|
||||
#define __GLIBC__ -1
|
||||
#endif
|
||||
#ifndef __GLIBC_MINOR__
|
||||
#define __GLIBC_MINOR__ -1
|
||||
#endif
|
||||
|
||||
|
||||
static char *saved_personality_text = "You found a bug!";
|
||||
|
||||
int all_processes = -1;
|
||||
char *bsd_j_format = (char *)0xdeadbeef;
|
||||
char *bsd_l_format = (char *)0xdeadbeef;
|
||||
char *bsd_s_format = (char *)0xdeadbeef;
|
||||
char *bsd_u_format = (char *)0xdeadbeef;
|
||||
char *bsd_v_format = (char *)0xdeadbeef;
|
||||
int bsd_c_option = -1;
|
||||
int bsd_e_option = -1;
|
||||
uid_t cached_euid = -1;
|
||||
dev_t cached_tty = -1;
|
||||
char forest_prefix[4 * 32*1024 + 100];
|
||||
int forest_type = -1;
|
||||
unsigned format_flags = 0xffffffff; /* -l -f l u s -j... */
|
||||
format_node *format_list = (format_node *)0xdeadbeef; /* digested formatting options */
|
||||
unsigned format_modifiers = 0xffffffff; /* -c -j -y -P -L... */
|
||||
int header_gap = -1;
|
||||
int header_type = -1;
|
||||
int include_dead_children = -1;
|
||||
int lines_to_next_header = -1;
|
||||
const char *namelist_file = (const char *)0xdeadbeef;
|
||||
int negate_selection = -1;
|
||||
int running_only = -1;
|
||||
unsigned personality = 0xffffffff;
|
||||
int prefer_bsd_defaults = -1;
|
||||
int screen_cols = -1;
|
||||
int screen_rows = -1;
|
||||
unsigned long seconds_since_boot = -1;
|
||||
selection_node *selection_list = (selection_node *)0xdeadbeef;
|
||||
unsigned simple_select = 0xffffffff;
|
||||
sort_node *sort_list = (sort_node *)0xdeadbeef; /* ready-to-use sort list */
|
||||
char *sysv_f_format = (char *)0xdeadbeef;
|
||||
char *sysv_fl_format = (char *)0xdeadbeef;
|
||||
char *sysv_j_format = (char *)0xdeadbeef;
|
||||
char *sysv_l_format = (char *)0xdeadbeef;
|
||||
int unix_f_option = -1;
|
||||
int user_is_number = -1;
|
||||
int wchan_is_number = -1;
|
||||
|
||||
|
||||
static void reset_selection_list(void){
|
||||
selection_node *old;
|
||||
selection_node *walk = selection_list;
|
||||
if(selection_list == (selection_node *)0xdeadbeef){
|
||||
selection_list = NULL;
|
||||
return;
|
||||
}
|
||||
while(walk){
|
||||
old = walk;
|
||||
walk = old->next;
|
||||
free(old->u);
|
||||
free(old);
|
||||
}
|
||||
selection_list = NULL;
|
||||
}
|
||||
|
||||
/* The rules:
|
||||
* 1. Defaults are implementation-specific. (ioctl,termcap,guess)
|
||||
* 2. COLUMNS and LINES override the defaults. (standards compliance)
|
||||
* 3. Command line options override everything else.
|
||||
* 4. Actual output may be more if the above is too narrow.
|
||||
*/
|
||||
static void set_screen_size(void){
|
||||
struct winsize ws;
|
||||
char *columns; /* Unix98 environment variable */
|
||||
char *lines; /* Unix98 environment variable */
|
||||
if(ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col>0 && ws.ws_row>0){
|
||||
screen_cols = ws.ws_col;
|
||||
screen_rows = ws.ws_row;
|
||||
}else{ /* TODO: ought to do tgetnum("co") and tgetnum("li") now */
|
||||
screen_cols = 80;
|
||||
screen_rows = 24;
|
||||
}
|
||||
if(!isatty(STDOUT_FILENO)) screen_cols = OUTBUF_SIZE;
|
||||
columns = getenv("COLUMNS");
|
||||
if(columns && *columns){
|
||||
long t;
|
||||
char *endptr;
|
||||
t = strtol(columns, &endptr, 0);
|
||||
if(!*endptr && (t>0) && (t<(long)OUTBUF_SIZE)) screen_cols = (int)t;
|
||||
}
|
||||
lines = getenv("LINES");
|
||||
if(lines && *lines){
|
||||
long t;
|
||||
char *endptr;
|
||||
t = strtol(lines, &endptr, 0);
|
||||
if(!*endptr && (t>0) && (t<(long)OUTBUF_SIZE)) screen_rows = (int)t;
|
||||
}
|
||||
if((screen_cols<9) || (screen_rows<2))
|
||||
fprintf(stderr,"Your %dx%d screen size is bogus. Expect trouble.\n",
|
||||
screen_cols, screen_rows
|
||||
);
|
||||
}
|
||||
|
||||
/**************** personality control **************/
|
||||
|
||||
typedef struct personality_table_struct {
|
||||
const char *name; /* personality name */
|
||||
const void *jump; /* See gcc extension info. :-) */
|
||||
} personality_table_struct;
|
||||
|
||||
static int compare_personality_table_structs(const void *a, const void *b){
|
||||
return strcasecmp(((personality_table_struct*)a)->name,((personality_table_struct*)b)->name);
|
||||
}
|
||||
|
||||
static const char *set_personality(void){
|
||||
char *s;
|
||||
size_t sl;
|
||||
char buf[16];
|
||||
personality_table_struct findme = { buf, NULL};
|
||||
personality_table_struct *found;
|
||||
static const personality_table_struct personality_table[] = {
|
||||
{"390", &&case_390},
|
||||
{"aix", &&case_aix},
|
||||
{"bsd", &&case_bsd},
|
||||
{"compaq", &&case_compaq},
|
||||
{"debian", &&case_debian},
|
||||
{"default", &&case_default},
|
||||
{"digital", &&case_digital},
|
||||
{"gnu", &&case_gnu},
|
||||
{"hp", &&case_hp},
|
||||
{"hpux", &&case_hpux},
|
||||
{"irix", &&case_irix},
|
||||
{"linux", &&case_linux},
|
||||
{"old", &&case_old},
|
||||
{"os390", &&case_os390},
|
||||
{"posix", &&case_posix},
|
||||
{"s390", &&case_s390},
|
||||
{"sco", &&case_sco},
|
||||
{"sgi", &&case_sgi},
|
||||
{"solaris2", &&case_solaris2},
|
||||
{"sunos4", &&case_sunos4},
|
||||
{"sysv", &&case_sysv},
|
||||
{"tru64", &&case_tru64},
|
||||
{"unix", &&case_unix},
|
||||
{"unix95", &&case_unix95},
|
||||
{"unix98", &&case_unix98},
|
||||
{"unknown", &&case_unknown}
|
||||
};
|
||||
const int personality_table_count = sizeof(personality_table)/sizeof(personality_table_struct);
|
||||
|
||||
personality = 0;
|
||||
prefer_bsd_defaults = 0;
|
||||
|
||||
bsd_j_format = "OL_j";
|
||||
bsd_l_format = "OL_l";
|
||||
bsd_s_format = "OL_s";
|
||||
bsd_u_format = "OL_u";
|
||||
bsd_v_format = "OL_v";
|
||||
|
||||
/* When these are NULL, the code does SysV output modifier logic */
|
||||
sysv_f_format = NULL;
|
||||
sysv_fl_format = NULL;
|
||||
sysv_j_format = NULL;
|
||||
sysv_l_format = NULL;
|
||||
|
||||
s = getenv("PS_PERSONALITY");
|
||||
if(!s || !*s) s = getenv("CMD_ENV");
|
||||
if(!s || !*s) s="unknown"; /* "Do The Right Thing[tm]" */
|
||||
if(getenv("I_WANT_A_BROKEN_PS")) s="old";
|
||||
sl = strlen(s);
|
||||
if(sl > 15) return "Environment specified an unknown personality.";
|
||||
strncpy(buf, s, sl);
|
||||
buf[sl] = '\0';
|
||||
saved_personality_text = strdup(buf);
|
||||
|
||||
found = bsearch(&findme, personality_table, personality_table_count,
|
||||
sizeof(personality_table_struct), compare_personality_table_structs
|
||||
);
|
||||
|
||||
if(!found) return "Environment specified an unknown personality.";
|
||||
|
||||
goto *(found->jump); /* See gcc extension info. :-) */
|
||||
|
||||
case_bsd:
|
||||
personality = PER_FORCE_BSD | PER_BSD_h | PER_BSD_m;
|
||||
prefer_bsd_defaults = 1;
|
||||
bsd_j_format = "FB_j";
|
||||
bsd_l_format = "FB_l";
|
||||
/* bsd_s_format not used */
|
||||
bsd_u_format = "FB_u";
|
||||
bsd_v_format = "FB_v";
|
||||
return NULL;
|
||||
|
||||
case_old:
|
||||
personality = PER_FORCE_BSD | PER_OLD_m;
|
||||
prefer_bsd_defaults = 1;
|
||||
return NULL;
|
||||
|
||||
case_debian: /* Toss this? They don't seem to care much. */
|
||||
case_gnu:
|
||||
personality = PER_GOOD_o | PER_CUMUL_MARKED | PER_OLD_m;
|
||||
prefer_bsd_defaults = 1;
|
||||
sysv_f_format = "RD_f";
|
||||
/* sysv_fl_format = "RD_fl"; */ /* Debian can't do this! */
|
||||
sysv_j_format = "RD_j";
|
||||
sysv_l_format = "RD_l";
|
||||
return NULL;
|
||||
|
||||
case_linux:
|
||||
personality = PER_GOOD_o | PER_ZAP_ADDR | PER_SANE_USER;
|
||||
return NULL;
|
||||
|
||||
case_default: /* use defaults for ps, ignoring other environment variables */
|
||||
return NULL;
|
||||
|
||||
case_unknown: /* defaults, but also check inferior environment variables */
|
||||
if(
|
||||
getenv("UNIX95") /* Irix */
|
||||
|| getenv("POSIXLY_CORRECT") /* most gnu stuff */
|
||||
|| (getenv("POSIX2") && !strcmp(getenv("POSIX2"), "on")) /* Unixware 7 */
|
||||
) personality = PER_BROKEN_o;
|
||||
return NULL;
|
||||
|
||||
case_aix:
|
||||
bsd_j_format = "FB_j";
|
||||
bsd_l_format = "FB_l";
|
||||
/* bsd_s_format not used */
|
||||
bsd_u_format = "FB_u";
|
||||
bsd_v_format = "FB_v";
|
||||
return NULL;
|
||||
|
||||
case_tru64:
|
||||
case_compaq:
|
||||
case_digital:
|
||||
personality = PER_GOOD_o | PER_BSD_h;
|
||||
prefer_bsd_defaults = 1;
|
||||
sysv_f_format = "F5FMT";
|
||||
sysv_fl_format = "FL5FMT";
|
||||
sysv_j_format = "JFMT";
|
||||
sysv_l_format = "L5FMT";
|
||||
bsd_j_format = "JFMT";
|
||||
bsd_l_format = "LFMT";
|
||||
bsd_s_format = "SFMT";
|
||||
bsd_u_format = "UFMT";
|
||||
bsd_v_format = "VFMT";
|
||||
return NULL;
|
||||
|
||||
case_sunos4:
|
||||
personality = PER_NO_DEFAULT_g;
|
||||
prefer_bsd_defaults = 1;
|
||||
bsd_j_format = "FB_j";
|
||||
bsd_l_format = "FB_l";
|
||||
/* bsd_s_format not used */
|
||||
bsd_u_format = "FB_u";
|
||||
bsd_v_format = "FB_v";
|
||||
return NULL;
|
||||
|
||||
case_irix:
|
||||
case_sgi:
|
||||
s = getenv("_XPG");
|
||||
if(s && s[0]>'0' && s[0]<='9') personality = PER_BROKEN_o;
|
||||
else personality = PER_IRIX_l;
|
||||
return NULL;
|
||||
|
||||
case_os390: /* IBM's OS/390 OpenEdition on the S/390 mainframe */
|
||||
case_s390:
|
||||
case_390:
|
||||
sysv_j_format = "J390"; /* don't know what -jl and -jf do */
|
||||
return NULL;
|
||||
|
||||
case_hp:
|
||||
case_hpux:
|
||||
case_posix:
|
||||
case_sco:
|
||||
case_solaris2:
|
||||
case_sysv:
|
||||
case_unix95:
|
||||
case_unix98:
|
||||
case_unix:
|
||||
personality = PER_BROKEN_o;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/************ Call this to reinitialize everything ***************/
|
||||
void reset_global(void){
|
||||
static proc_t p;
|
||||
reset_selection_list();
|
||||
look_up_our_self(&p);
|
||||
set_screen_size();
|
||||
set_personality();
|
||||
|
||||
all_processes = 0;
|
||||
bsd_c_option = 0;
|
||||
bsd_e_option = 0;
|
||||
cached_euid = geteuid();
|
||||
cached_tty = p.tty;
|
||||
/* forest_prefix must be all zero because of POSIX */
|
||||
forest_type = 0;
|
||||
format_flags = 0; /* -l -f l u s -j... */
|
||||
format_list = NULL; /* digested formatting options */
|
||||
format_modifiers = 0; /* -c -j -y -P -L... */
|
||||
header_gap = -1; /* send lines_to_next_header to -infinity */
|
||||
header_type = HEAD_SINGLE;
|
||||
include_dead_children = 0;
|
||||
lines_to_next_header = 1;
|
||||
namelist_file = NULL;
|
||||
negate_selection = 0;
|
||||
running_only = 0;
|
||||
seconds_since_boot = uptime(0,0);
|
||||
selection_list = NULL;
|
||||
simple_select = 0;
|
||||
sort_list = NULL;
|
||||
unix_f_option = 0;
|
||||
user_is_number = 0;
|
||||
wchan_is_number = 0;
|
||||
}
|
||||
|
||||
/*********** spew variables ***********/
|
||||
void self_info(void){
|
||||
#ifndef EMULATE_FPUTS
|
||||
int count;
|
||||
#endif
|
||||
fprintf(stderr,
|
||||
"BSD j %s\n"
|
||||
"BSD l %s\n"
|
||||
"BSD s %s\n"
|
||||
"BSD u %s\n"
|
||||
"BSD v %s\n"
|
||||
"SysV -f %s\n"
|
||||
"SysV -fl %s\n"
|
||||
"SysV -j %s\n"
|
||||
"SysV -l %s\n"
|
||||
"\n",
|
||||
bsd_j_format ? bsd_j_format : "(none)",
|
||||
bsd_l_format ? bsd_l_format : "(none)",
|
||||
bsd_s_format ? bsd_s_format : "(none)",
|
||||
bsd_u_format ? bsd_u_format : "(none)",
|
||||
bsd_v_format ? bsd_v_format : "(none)",
|
||||
sysv_f_format ? sysv_f_format : "(none)",
|
||||
sysv_fl_format ? sysv_fl_format : "(none)",
|
||||
sysv_j_format ? sysv_j_format : "(none)",
|
||||
sysv_l_format ? sysv_l_format : "(none)"
|
||||
);
|
||||
|
||||
display_version();
|
||||
fprintf(stderr, "Linux version %d.%d.%d\n",
|
||||
LINUX_VERSION_MAJOR(linux_version_code),
|
||||
LINUX_VERSION_MINOR(linux_version_code),
|
||||
LINUX_VERSION_PATCH(linux_version_code)
|
||||
);
|
||||
/* __libc_print_version(); */ /* how can we get the run-time version? */
|
||||
fprintf(stderr, "Compiled with: libc %d, internal version %d.%d\n\n",
|
||||
__GNU_LIBRARY__, __GLIBC__, __GLIBC_MINOR__
|
||||
);
|
||||
|
||||
#ifdef EMULATE_FPUTS
|
||||
fprintf(stderr, "libc assumed lame, using fprintf to emulate fputs.\n\n");
|
||||
#else
|
||||
fprintf(stderr, "fputs(\"");
|
||||
count = fputs("123456789", stderr);
|
||||
fprintf(stderr, "\", stderr) gives %d, which is %s.\n",
|
||||
count, count==9?"good":"BAD!\nAdjust ps/common.h or libc, then recompile"
|
||||
);
|
||||
if(count!=9){
|
||||
fprintf(stderr, "(procps includes a libc patch called glibc.patch)\n");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
|
||||
fprintf(stderr,
|
||||
"header_gap=%d lines_to_next_header=%d\n"
|
||||
"screen_cols=%d screen_rows=%d\n"
|
||||
"\n",
|
||||
header_gap, lines_to_next_header,
|
||||
screen_cols, screen_rows
|
||||
);
|
||||
|
||||
/* open_psdb(namelist_file); */
|
||||
fprintf(stderr,
|
||||
"personality=0x%08x (from \"%s\")\n"
|
||||
"EUID=%d TTY=%d,%d Hertz=%ld\n"
|
||||
/* "namelist_file=\"%s\"\n" */
|
||||
,
|
||||
personality, saved_personality_text,
|
||||
cached_euid, (int)major(cached_tty), (int)minor(cached_tty), Hertz /* ,
|
||||
namelist_file?namelist_file:"<no System.map file>" */
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user