#define LENGTH_PCTCPU 10  /* Maximum percent cpu sufficient to hold 100000.00 or up to 1000 cpus  */
/* Proc::ProcessTable functions */
void ppt_warn(const char*, ...);
void bless_into_proc(char* , char**, ...);

/* it also gets used by init_static_vars at the way top of the file,
 * I wanted init_static_vars to be at the way top close to the global vars */
static char *read_file(const char *path, const char *extra_path, off_t *len,
	struct obstack *mem_pool);

struct procstat
{
	/* user/group id of the user running it */
	int				uid;
	int				gid;
	/* values scraped from /proc/{$pid}/stat */
	pid_t				pid;
	char				comm[16];					/* limit in kernel, likewise in procps */
	char				state_c;
	int					ppid;
	int					pgrp;
	int					sid;
	int					tty;
	unsigned 			flags;
	unsigned long		minflt, cminflt, majflt, cmajflt;
	unsigned long long	utime, stime;
	long long			cutime, cstime;
	long				priority;
	unsigned long long 	start_time;
	unsigned long		vsize;
	long 				rss;
	unsigned long		wchan;
	/* these are derived from above time values */
	unsigned long long	time, ctime;
	/* from above state_c but fixed up elsewhere */
	const char		*state;
	/* values scraped from /proc/{$pid}/status */
	int				euid, suid, fuid;
	int				egid, sgid, fgid;
	/* cwd, cmdline & exec files; values allocated at the end of obstacks */
	char			*cwd;
	char			*cmndline;
	char			*exec;
	/* other values */
	char			pctcpu[LENGTH_PCTCPU];	/* precent cpu, without '%' char */
	char			pctmem[sizeof("100.00")];	/* precent memory, without '%' char */
};


enum state
{
	SLEEP,
	WAIT,
	RUN,
	IDLE,
	DEFUNCT,
	STOP,
	UWAIT,
    DEAD,
    WAKEKILL,
    TRACINGSTOP
};


/* strings, to make sure they get placed in read only memory,
 * ditto for pointers to them and so we avoid relocations */
static const char strings[] =
{
/* process state */
	"sleep\0" 
    "wait\0" 
    "run\0" 
    "idle\0" 
    "defunct\0" 
    "stop\0"
    "uwait\0"
    "dead\0"
    "wakekill\0"
    "tracingstop\0"
/* error messages */
	"/proc unavailable\0"
	"intilization failed\0"
/* fields */
	"uid\0"
	"gid\0"
	"pid\0"
	"fname\0"
	"ppid\0"
	"pgrp\0"
	"sess\0"
	"ttynum\0"
	"flags\0"
	"minflt\0"
	"cminflt\0"
	"majflt\0"
	"cmajflt\0"
	"utime\0"
	"stime\0"
	"cutime\0"
	"cstime\0"
	"priority\0"
	"start\0"
	"size\0"
	"rss\0"
	"wchan\0"
	"time\0"
	"ctime\0"
	"state\0"
	"euid\0"
	"suid\0"
	"fuid\0"
	"egid\0"
	"sgid\0"
	"fgid\0"
	"pctcpu\0"
	"pctmem\0"
	"cmndline\0"
	"exec\0"
	"cwd\0"
/* format string */
	"IIISIIIILLLLLJJJJIJPLLJJSIIIIIISSSSS\0"
};


static const size_t strings_index[] =
{
/* I generated this array with a perl script processing the above char array,
 * and then performed cross string optimization (by hand) for: 
 *		pid,	time,	uid,	gid,	minflt,		majflt,
 */
/* process status strings */
     0,
     6,
     11,
     15,
     20,
     28,
     33,
     39,
     44,
     53,
/* error messages */
     65,
     83,
/* fields */
     103,
     107,
     111,
     115,
     121,
     126,
     131,
     136,
     143,
     149,
     156,
     164,
     171,
     179,
     185,
     191,
     198,
     205,
     214,
     220,
     225,
     229,
     235,
     240,
     246,
     252,
     257,
     262,
     267,
     272,
     277,
     282,
     289,
     296,
     305,
     310,
/* default format string (pre lower casing) */
     314,
};


enum string_name {
	/* NOTE: we start this enum at 10, so we can use still keep using the
  	 * state enum, and have those correspond to the static strings */
/* error messages */
	STR_ERR_PROC_STATFS = 10,
	STR_ERR_INIT,
/* fields */
	STR_FIELD_UID,
	STR_FIELD_GID,
	STR_FIELD_PID,
	STR_FIELD_FNAME,
	STR_FIELD_PPID,
	STR_FIELD_PGRP,
	STR_FIELD_SESS,
	STR_FIELD_TTYNUM,
	STR_FIELD_FLAGS,
	STR_FIELD_MINFLT,
	STR_FIELD_CMINFLT,
	STR_FIELD_MAJFLT,
	STR_FIELD_CMAJFLT,
	STR_FIELD_UTIME,
	STR_FIELD_STIME,
	STR_FIELD_CUTIME,
	STR_FIELD_CSTIME,
	STR_FIELD_PRIORITY,
	STR_FIELD_START,
	STR_FIELD_SIZE,
	STR_FIELD_RSS,
	STR_FIELD_WCHAN,
	STR_FIELD_TIME,
	STR_FIELD_CTIME,
	STR_FIELD_STATE,
	STR_FIELD_EUID,
	STR_FIELD_SUID,
	STR_FIELD_FUID,
	STR_FIELD_EGID,
	STR_FIELD_SGID,
	STR_FIELD_FGID,
	STR_FIELD_PCTCPU,
	STR_FIELD_PCTMEM,
	STR_FIELD_CMNDLINE,
	STR_FIELD_EXEC,
	STR_FIELD_CWD,
/* format string */
	STR_DEFAULT_FORMAT
};


enum field
{
	F_UID,
	F_GID,
	F_PID,
	F_FNAME,
	F_PPID,
	F_PGRP,
	F_SESS,
	F_TTYNUM,
	F_FLAGS,
	F_MINFLT,
	F_CMINFLT,
	F_MAJFLT,
	F_CMAJFLT,
	F_UTIME,
	F_STIME,
	F_CUTIME,
	F_CSTIME,
	F_PRIORITY,
	F_START,
	F_SIZE,
	F_RSS,
	F_WCHAN,
	F_TIME,
	F_CTIME,
	F_STATE,
	F_EUID,
	F_SUID,
	F_FUID,
	F_EGID,
	F_SGID,
	F_FGID,
	F_PCTCPU,
	F_PCTMEM,
	F_CMNDLINE,
	F_EXEC,
	F_CWD
};



static const char* const field_names[] =
{
     strings + 103,
     strings + 107,
     strings + 111,
     strings + 115,
     strings + 121,
     strings + 126,
     strings + 131,
     strings + 136,
     strings + 143,
     strings + 149,
     strings + 156,
     strings + 164,
     strings + 171,
     strings + 179,
     strings + 185,
     strings + 191,
     strings + 198,
     strings + 205,
     strings + 214,
     strings + 220,
     strings + 225,
     strings + 229,
     strings + 235,
     strings + 240,
     strings + 246,
     strings + 252,
     strings + 257,
     strings + 262,
     strings + 267,
     strings + 272,
     strings + 277,
     strings + 282,
     strings + 289,
     strings + 296,
     strings + 305,
     strings + 310,
};