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