Commit | Line | Data |
---|---|---|
24fd64ab DG |
1 | /* |
2 | * Simplified implementation of SYSV ipcs. | |
3 | */ | |
4 | ||
5 | #include <nlist.h> | |
6 | #include <stdio.h> | |
7 | #include <stdlib.h> | |
8 | #include <unistd.h> | |
9 | #include <paths.h> | |
10 | ||
11 | #include <sys/types.h> | |
12 | #include <sys/param.h> | |
13 | #include <sys/proc.h> | |
14 | #define KERNEL | |
15 | #include <sys/ipc.h> | |
16 | #include <sys/sem.h> | |
17 | #include <sys/shm.h> | |
18 | #include <sys/msg.h> | |
19 | ||
20 | static kmem_fd; | |
21 | ||
22 | getsymbol(struct nlist *symbols, char *symname, void *dptr, int len) | |
23 | { | |
24 | int i, rlen; | |
25 | ||
26 | for ( i = 0; symbols[i].n_name != NULL; i += 1 ) { | |
27 | if ( strcmp(symbols[i].n_name,symname) == 0 ) { | |
28 | break; | |
29 | } | |
30 | } | |
31 | ||
32 | if ( symbols[i].n_name == NULL ) { | |
33 | fprintf(stderr,"ipcs(getsymbol): symbol %s not in local symbols list\n", | |
34 | symname); | |
35 | exit(1); | |
36 | } | |
37 | ||
38 | if ( symbols[i].n_value == NULL ) { | |
39 | fprintf(stderr,"ipcs(getsymbol): symbol %s not in %s\n", | |
40 | symname,_PATH_UNIX); | |
41 | return(0); | |
42 | } | |
43 | ||
44 | if ( kmem_fd == 0 ) { | |
45 | kmem_fd = open("/dev/kmem",0); | |
46 | if ( kmem_fd < 0 ) { | |
47 | perror("ipcs(getsymbol(open /dev/kmem))"); | |
48 | exit(1); | |
49 | } | |
50 | } | |
51 | ||
52 | lseek(kmem_fd,symbols[i].n_value,SEEK_SET); | |
53 | if ( (rlen = read(kmem_fd,dptr,len)) != len ) { | |
54 | fprintf(stderr,"ipcs(getsymbol): can't fetch symbol %s from /dev/kmem\n",symname); | |
55 | exit(1); | |
56 | } | |
57 | return(1); | |
58 | } | |
59 | ||
60 | void | |
61 | getlocation(void *addr, void *dptr, int len) | |
62 | { | |
63 | int i, rlen; | |
64 | ||
65 | if ( kmem_fd == 0 ) { | |
66 | kmem_fd = open("/dev/kmem",0); | |
67 | if ( kmem_fd < 0 ) { | |
68 | perror("ipcs(getlocation(open /dev/kmem))"); | |
69 | exit(1); | |
70 | } | |
71 | } | |
72 | ||
73 | lseek(kmem_fd,(long)addr,SEEK_SET); | |
74 | if ( (rlen = read(kmem_fd,dptr,len)) != len ) { | |
75 | fprintf(stderr,"ipcs(getlocation): can't fetch location %08x from /dev/kmem\n",addr); | |
76 | exit(1); | |
77 | } | |
78 | } | |
79 | ||
80 | char * | |
81 | fmt_perm(ushort mode) | |
82 | { | |
83 | static char buffer[100]; | |
84 | ||
85 | buffer[0] = '-'; | |
86 | buffer[1] = '-'; | |
87 | buffer[2] = ((mode & 0400) ? 'r' : '-'); | |
88 | buffer[3] = ((mode & 0200) ? 'w' : '-'); | |
89 | buffer[4] = ((mode & 0100) ? 'a' : '-'); | |
90 | buffer[5] = ((mode & 0040) ? 'r' : '-'); | |
91 | buffer[6] = ((mode & 0020) ? 'w' : '-'); | |
92 | buffer[7] = ((mode & 0010) ? 'a' : '-'); | |
93 | buffer[8] = ((mode & 0004) ? 'r' : '-'); | |
94 | buffer[9] = ((mode & 0002) ? 'w' : '-'); | |
95 | buffer[10] = ((mode & 0001) ? 'a' : '-'); | |
96 | buffer[11] = '\0'; | |
97 | return(&buffer[0]); | |
98 | } | |
99 | ||
100 | void | |
101 | cvt_time(time_t t,char *buf) | |
102 | { | |
103 | struct tm tms; | |
104 | static char *months[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; | |
105 | if ( t == 0 ) { | |
106 | strcpy(buf,"<not set>"); | |
107 | } else { | |
108 | tms = *localtime(&t); | |
109 | if ( t > time(0) - 6 * 30 * 24 * 3600 ) { /* less than about 6 months ago? */ | |
110 | sprintf(buf,"%s %2d %2d:%2d", | |
111 | months[tms.tm_mon],tms.tm_mday,tms.tm_hour,tms.tm_min); | |
112 | } else { | |
113 | sprintf(buf,"%s %2d %5d", | |
114 | months[tms.tm_mon],tms.tm_mday,tms.tm_year+1900); | |
115 | } | |
116 | } | |
117 | } | |
118 | ||
119 | main() | |
120 | { | |
121 | static struct nlist symbols[] = { | |
122 | { "_sema" }, | |
123 | { "_seminfo" }, | |
124 | { "_semu" }, | |
125 | { "_msginfo" }, | |
126 | { "_msqids" }, | |
127 | { NULL } | |
128 | }; | |
129 | int i; | |
130 | int show_sem_values = 1; | |
131 | int show_undo_values = 1; | |
132 | ||
133 | switch ( nlist(_PATH_UNIX,&symbols[0]) ) { | |
134 | case 0: break; | |
135 | case -1: | |
136 | fprintf(stderr,"ipcs: can't open %s - bye!\n",_PATH_UNIX); | |
137 | exit(1); | |
138 | default: | |
139 | fprintf(stderr,"ipcs: nlist failed\n"); | |
140 | for ( i = 0; symbols[i].n_name != NULL; i += 1 ) { | |
141 | if ( symbols[i].n_value == 0 ) { | |
142 | fprintf(stderr,"\tsymbol %s not found\n",symbols[i].n_name); | |
143 | } | |
144 | } | |
145 | break; | |
146 | } | |
147 | ||
148 | /* | |
149 | for ( i = 0; symbols[i].n_name != NULL; i += 1 ) { | |
150 | fprintf(stderr,"\t%s : %08x\n",symbols[i].n_name,symbols[i].n_value); | |
151 | } | |
152 | */ | |
153 | ||
154 | if ( getsymbol(symbols,"_seminfo",&seminfo,sizeof(seminfo)) ) { | |
155 | struct semid_ds *xsema; | |
156 | ||
157 | printf("seminfo:\n"); | |
158 | printf("\tsemmap: %6d\t(# of entries in semaphore map)\n",seminfo.semmap); | |
159 | printf("\tsemmni: %6d\t(# of semaphore identifiers)\n",seminfo.semmni); | |
160 | printf("\tsemmns: %6d\t(# of semaphores in system)\n",seminfo.semmns); | |
161 | printf("\tsemmnu: %6d\t(# of undo structures in system)\n",seminfo.semmnu); | |
162 | printf("\tsemmsl: %6d\t(max # of semaphores per id)\n",seminfo.semmsl); | |
163 | printf("\tsemopm: %6d\t(max # of operations per semop call)\n",seminfo.semopm); | |
164 | printf("\tsemume: %6d\t(max # of undo entries per process)\n",seminfo.semume); | |
165 | printf("\tsemusz: %6d\t(size in bytes of undo structure)\n",seminfo.semusz); | |
166 | printf("\tsemvmx: %6d\t(semaphore maximum value)\n",seminfo.semvmx); | |
167 | printf("\tsemaem: %6d\t(adjust on exit max value)\n",seminfo.semaem); | |
168 | ||
169 | /* | |
170 | * Lock out other users of the semaphore facility | |
171 | */ | |
172 | ||
173 | if ( semconfig(SEM_CONFIG_FREEZE) != 0 ) { | |
174 | perror("semconfig"); | |
175 | fprintf(stderr,"Can't lock semaphore facility - winging it...\n"); | |
176 | } | |
177 | ||
178 | getsymbol(symbols,"_sema",&sema,sizeof(sema)); | |
179 | xsema = malloc(sizeof(struct semid_ds) * seminfo.semmni); | |
180 | getlocation(sema,xsema,sizeof(struct semid_ds) * seminfo.semmni); | |
181 | ||
182 | for ( i = 0; i < seminfo.semmni; i += 1 ) { | |
183 | if ( (xsema[i].sem_perm.mode & SEM_ALLOC) != 0 ) { | |
184 | char ctime_buf[100], otime_buf[100]; | |
185 | struct semid_ds *semaptr = &xsema[i]; | |
186 | cvt_time(semaptr->sem_ctime,ctime_buf); | |
187 | cvt_time(semaptr->sem_otime,otime_buf); | |
188 | ||
189 | printf("\nsema id: %d key: 0x%08x:\n", | |
190 | IXSEQ_TO_IPCID(i,semaptr->sem_perm), | |
191 | semaptr->sem_perm.key); | |
192 | ||
193 | printf(" cuid: %6d cgid: %6d ctime: %s\n", | |
194 | semaptr->sem_perm.cuid,semaptr->sem_perm.cgid,ctime_buf); | |
195 | ||
196 | printf(" uid: %6d gid: %6d otime: %s\n", | |
197 | semaptr->sem_perm.uid,semaptr->sem_perm.gid,otime_buf); | |
198 | ||
199 | printf(" nsems: %6d perm: %s\n", | |
200 | semaptr->sem_nsems,fmt_perm(semaptr->sem_perm.mode)); | |
201 | ||
202 | if ( show_sem_values ) { | |
203 | int j, value; | |
204 | union semun junk; | |
205 | for ( j = 0; j < semaptr->sem_nsems; j += 1 ) { | |
206 | if ( (value = semctl( IXSEQ_TO_IPCID(i,semaptr->sem_perm), j, GETVAL, junk )) < 0 ) { | |
207 | printf("can't get semaphore values\n"); | |
208 | break; | |
209 | } | |
210 | if ( j % 5 == 0 ) { | |
211 | if ( j == 0 ) { | |
212 | printf(" values: {"); | |
213 | } else { | |
214 | printf("\n"); | |
215 | printf(" "); | |
216 | } | |
217 | } | |
218 | printf(" %d",value); | |
219 | if ( j == semaptr->sem_nsems - 1 ) { | |
220 | printf(" }\n"); | |
221 | } else { | |
222 | printf(", "); | |
223 | } | |
224 | } | |
225 | } | |
226 | ||
227 | } | |
228 | ||
229 | } | |
230 | ||
231 | if ( show_undo_values ) { | |
232 | int j; | |
233 | int *ksemu, *semu; | |
234 | int semu_size; | |
235 | int got_one_undo = 0; | |
236 | ||
237 | semu = 0; | |
238 | semu_size = (int)SEMU(seminfo.semmnu); | |
239 | semu = (int *)malloc( semu_size ); | |
240 | getsymbol(symbols,"_semu",&ksemu,sizeof(ksemu)); | |
241 | getlocation(ksemu,semu,semu_size); | |
242 | ||
243 | printf("\nsem undos:\n"); | |
244 | for ( j = 0; j < seminfo.semmnu; j += 1 ) { | |
245 | struct sem_undo *suptr; | |
246 | int k; | |
247 | ||
248 | suptr = SEMU(j); | |
249 | if ( suptr->un_proc != NULL ) { | |
250 | struct proc proc; | |
251 | getlocation(suptr->un_proc,&proc,sizeof(proc)); | |
252 | got_one_undo = 1; | |
253 | printf(" pid %d: semid semnum adjval\n",proc.p_pid); | |
254 | for ( k = 0; k < suptr->un_cnt; k += 1 ) { | |
255 | printf(" %10d %5d %6d\n", | |
256 | IXSEQ_TO_IPCID(suptr->un_ent[k].un_id,xsema[suptr->un_ent[k].un_id].sem_perm), | |
257 | suptr->un_ent[k].un_num, | |
258 | suptr->un_ent[k].un_adjval); | |
259 | } | |
260 | } | |
261 | } | |
262 | if ( !got_one_undo ) { | |
263 | printf(" none allocated\n"); | |
264 | } | |
265 | } | |
266 | ||
267 | (void)semconfig(SEM_CONFIG_THAW); | |
268 | ||
269 | } else { | |
270 | fprintf(stderr,"SVID semaphores facility not configured in the system\n"); | |
271 | } | |
272 | ||
273 | if ( getsymbol(symbols,"_msginfo",&msginfo,sizeof(msginfo)) ) { | |
274 | struct msqid_ds *xmsqids; | |
275 | ||
276 | printf("\nmsginfo:\n"); | |
277 | printf("\tmsgmax: %6d\t(max characters in a message)\n",msginfo.msgmax); | |
278 | printf("\tmsgmni: %6d\t(# of message queues)\n",msginfo.msgmni); | |
279 | printf("\tmsgmnb: %6d\t(max characters in a message queue)\n",msginfo.msgmnb); | |
280 | printf("\tmsgtql: %6d\t(max # of messages in system)\n",msginfo.msgtql); | |
281 | printf("\tmsgssz: %6d\t(size of a message segment)\n",msginfo.msgssz); | |
282 | printf("\tmsgseg: %6d\t(# of message segments in system)\n",msginfo.msgseg); | |
283 | ||
284 | getsymbol(symbols,"_msqids",&msqids,sizeof(msqids)); | |
285 | xmsqids = malloc(sizeof(struct msqid_ds) * msginfo.msgmni); | |
286 | getlocation(msqids,xmsqids,sizeof(struct msqid_ds) * msginfo.msgmni); | |
287 | ||
288 | for ( i = 0; i < msginfo.msgmni; i += 1 ) { | |
289 | if ( xmsqids[i].msg_qbytes != 0 ) { | |
290 | char stime_buf[100], rtime_buf[100], ctime_buf[100]; | |
291 | struct msqid_ds *msqptr = &xmsqids[i]; | |
292 | ||
293 | cvt_time(msqptr->msg_stime,stime_buf); | |
294 | cvt_time(msqptr->msg_rtime,rtime_buf); | |
295 | cvt_time(msqptr->msg_ctime,ctime_buf); | |
296 | ||
297 | printf("\nmsgq id: %d key: 0x%08x\n", | |
298 | IXSEQ_TO_IPCID(i,msqptr->msg_perm), | |
299 | msqptr->msg_perm.key); | |
300 | ||
301 | printf(" cuid: %6d cgid: %6d ctime: %s\n", | |
302 | msqptr->msg_perm.cuid,msqptr->msg_perm.cgid,ctime_buf); | |
303 | ||
304 | printf(" uid: %6d gid: %6d\n", | |
305 | msqptr->msg_perm.uid,msqptr->msg_perm.gid); | |
306 | ||
307 | printf(" lspid: %6d stime: %s\n", | |
308 | msqptr->msg_lspid,stime_buf); | |
309 | ||
310 | printf(" lrpid: %6d qnum: %6d rtime: %s\n", | |
311 | msqptr->msg_lrpid,msqptr->msg_qnum,rtime_buf); | |
312 | ||
313 | printf(" cbytes:%6d qbytes:%6d perm: %s\n", | |
314 | msqptr->msg_cbytes,msqptr->msg_qbytes,fmt_perm(msqptr->msg_perm.mode)); | |
315 | ||
316 | } | |
317 | } | |
318 | ||
319 | } else { | |
320 | fprintf(stderr,"SVID messages facility not configured in the system\n"); | |
321 | } | |
322 | ||
323 | exit(0); | |
324 | } |