1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1989-2011 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <glenn.s.fowler@gmail.com> * 18 * * 19 ***********************************************************************/ 20 #pragma prototyped 21 /* 22 * Glenn Fowler 23 * AT&T Research 24 * 25 * process status stream PSS_METHOD_info implementation 26 */ 27 28 #include "psslib.h" 29 30 #if PSS_METHOD != PSS_METHOD_info 31 32 NoN(pss_info) 33 34 #else 35 36 #include <info.h> 37 #include <sys/../proc.h> /* clash with ast <proc.h> */ 38 #include <sys/inode.h> 39 40 typedef struct State_s 41 { 42 int mem; 43 struct pentry* pr; 44 struct pentry* pp; 45 struct pentry* pe; 46 struct pentry ps[1]; 47 } State_t; 48 49 static int 50 info_init(Pss_t* pss) 51 { 52 register State_t* state; 53 char* mem; 54 int fd; 55 unsigned long n; 56 unsigned long a; 57 58 mem = "/dev/mem"; 59 if ((fd = open(mem, O_RDONLY)) < 0) 60 { 61 if (pss->disc->errorf) 62 (*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "%s: cannot read", mem); 63 return -1; 64 } 65 n = info(_I_NPROCTAB); 66 a = info(_I_PROCTAB); 67 if (!(state = vmnewof(pss->vm, 0, State_t, 1, (n - 1) * sizeof(struct pentry)))) 68 { 69 if (pss->disc->errorf) 70 (*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "out of space"); 71 goto bad; 72 } 73 if (lseek(fd, a, SEEK_SET) != a) 74 { 75 if (pss->disc->errorf) 76 (*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "%s: %lu: seek error", mem, a); 77 goto bad; 78 } 79 if (read(fd, state->ps, n * sizeof(state->ps[0])) != n * sizeof(state->ps[0])) 80 { 81 if (pss->disc->errorf) 82 (*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "%s: %lu entry read error", mem, n); 83 goto bad; 84 } 85 state->mem = fd; 86 state->pp = state->ps; 87 state->pe = state->ps + n; 88 pss->data = state; 89 return 1; 90 bad: 91 close(fd); 92 free(state); 93 return -1; 94 } 95 96 static int 97 info_read(Pss_t* pss, Pss_id_t pid) 98 { 99 register State_t* state = (State_t*)pss->data; 100 int count; 101 102 if (pid) 103 { 104 for (state->pp = state->ps; state->pp < state->pe; state->pp++) 105 if (state->pp->pstate != PRFREE && state->pp->pid == pid) 106 break; 107 } 108 else 109 while (state->pp < state->pe && state->pp->pstate == PRFREE) 110 state->pp++; 111 if (state->pp >= state->pe) 112 return 0; 113 state->pr = state->pp++; 114 pss->pid = state->pr->pid; 115 return 1; 116 } 117 118 static int 119 info_part(register Pss_t* pss, register Pssent_t* pe) 120 { 121 State_t* state = (State_t*)pss->data; 122 register struct pentry* pr = state->pr; 123 124 pe->pid = pr->pid; 125 pe->pgrp = pr->pgroup; 126 pe->tty = pr->cdevnum == -1 ? PSS_NODEV : pr->cdevnum; 127 pe->uid = pr->uid; 128 switch ((int)(pr->pstate & 0xf)) 129 { 130 case PRREADY: pe->state = 'I'; break; 131 case PRCURR: pe->state = pr->pid == getpid() ? 'R' : 'S'; break; 132 case PRWAIT: pe->state = 'W'; break; 133 case SUSPVAL: pe->state = 'S'; break; 134 case PRSTOP: pe->state = 'T'; break; 135 case ZOMBIEVAL: pe->state = 'Z'; break; 136 default: pe->state = 'O'; break; 137 } 138 return 1; 139 } 140 141 static int 142 info_full(register Pss_t* pss, register Pssent_t* pe) 143 { 144 register State_t* state = (State_t*)pss->data; 145 register struct pentry* pr = state->pr; 146 unsigned long fields = pss->disc->fields & pss->meth->fields; 147 char* s; 148 int i; 149 struct pssentry px; 150 struct st_entry st; 151 152 if (pe->state != PSS_ZOMBIE) 153 { 154 if ((fields & (PSS_sid|PSS_size|PSS_time)) && 155 lseek(state->mem, (unsigned long)pr->pss, SEEK_SET) == (unsigned long)pr->pss && 156 read(state->mem, &px, sizeof(px)) == sizeof(px)) 157 { 158 pe->sid = px.sid; 159 pe->size = (pr->stack_total + (px.brk - px.data_start)) / 1024; 160 pe->time = (px.pss_utime + px.stime) / 5; 161 } 162 if ((fields & (PSS_pri)) && 163 lseek(state->mem, (unsigned long)pr->i, SEEK_SET) == (unsigned long)pr->i && 164 read(state->mem, &st, sizeof(st)) == sizeof(st)) 165 { 166 pe->pri = st.pprio; 167 pe->nice = st.rprio; 168 } 169 if (fields & PSS_command) 170 pe->command = ((s = strrchr(pr->pname, '/')) && *++s) ? s : pr->pname; 171 pe->args = pr->pname; 172 } 173 pe->flags = pr->pflag; 174 pe->ppid = pr->ppid; 175 pe->gid = pr->gid; 176 return 1; 177 } 178 179 static int 180 info_done(register Pss_t* pss) 181 { 182 register State_t* state = (State_t*)pss->data; 183 184 close(state->mem); 185 free(state); 186 return 0; 187 } 188 189 static Pssmeth_t info_method = 190 { 191 "info", 192 "[-version?@(#)$Id: pss info (AT&T Research) 2005-02-11 $\n]" 193 "[-author?Glenn Fowler <gsf@research.att.com>]", 194 PSS_args|PSS_command|PSS_flags|PSS_gid|PSS_nice|PSS_pgrp|PSS_pid|PSS_ppid|PSS_pri|PSS_sid|PSS_size|PSS_state|PSS_time|PSS_tty|PSS_uid, 195 info_init, 196 info_read, 197 info_part, 198 info_full, 199 0, 200 0, 201 0, 202 info_done 203 }; 204 205 Pssmeth_t* _pss_method = &info_method; 206 207 #endif 208