void *xcalloc(size_t nmemb, size_t size) { void *result; result = calloc(nmemb, size); if (result == NULL) { errprintf("xcalloc: Out of memory!\n"); abort(); } #ifdef MEMORY_DEBUG add_to_memlist(result, nmemb*size); #endif return result; }
char *xstrdup(const char *s) { char *result; if (s == NULL) { errprintf("xstrdup: Cannot dup NULL string\n"); abort(); } result = strdup(s); if (result == NULL) { errprintf("xstrdup: Out of memory\n"); abort(); } #ifdef MEMORY_DEBUG add_to_memlist(result, strlen(result)+1); #endif return result; }
hobbitd_channel_t *setup_channel(enum msgchannels_t chnid, int role) { key_t key; struct stat st; struct sembuf s; hobbitd_channel_t *newch; unsigned int bufsz; int flags = ((role == CHAN_MASTER) ? (IPC_CREAT | 0600) : 0); char *bbh = xgetenv("BBHOME"); if ( (bbh == NULL) || (stat(bbh, &st) == -1) ) { errprintf("BBHOME not defined, or points to invalid directory - cannot continue.\n"); return NULL; } bufsz = 1024*shbufsz(chnid); dbgprintf("Setting up %s channel (id=%d)\n", channelnames[chnid], chnid); dbgprintf("calling ftok('%s',%d)\n", bbh, chnid); key = ftok(bbh, chnid); if (key == -1) { errprintf("Could not generate shmem key based on %s: %s\n", bbh, strerror(errno)); return NULL; } dbgprintf("ftok() returns: 0x%X\n", key); newch = (hobbitd_channel_t *)malloc(sizeof(hobbitd_channel_t)); newch->seq = 0; newch->channelid = chnid; newch->msgcount = 0; newch->shmid = shmget(key, bufsz, flags); if (newch->shmid == -1) { errprintf("Could not get shm of size %d: %s\n", bufsz, strerror(errno)); xfree(newch); return NULL; } dbgprintf("shmget() returns: 0x%X\n", newch->shmid); newch->channelbuf = (char *) shmat(newch->shmid, NULL, 0); if (newch->channelbuf == (char *)-1) { errprintf("Could not attach shm %s\n", strerror(errno)); if (role == CHAN_MASTER) shmctl(newch->shmid, IPC_RMID, NULL); xfree(newch); return NULL; } newch->semid = semget(key, 3, flags); if (newch->semid == -1) { errprintf("Could not get sem: %s\n", strerror(errno)); shmdt(newch->channelbuf); if (role == CHAN_MASTER) shmctl(newch->shmid, IPC_RMID, NULL); xfree(newch); return NULL; } if (role == CHAN_CLIENT) { /* * Clients must register their presence. * We use SEM_UNDO; so if the client crashes, it wont leave a stale count. */ s.sem_num = CLIENTCOUNT; s.sem_op = +1; s.sem_flg = SEM_UNDO; if (semop(newch->semid, &s, 1) == -1) { errprintf("Could not register presence: %s\n", strerror(errno)); shmdt(newch->channelbuf); xfree(newch); return NULL; } } else if (role == CHAN_MASTER) { int n; n = semctl(newch->semid, CLIENTCOUNT, GETVAL); if (n > 0) { errprintf("FATAL: hobbitd sees clientcount %d, should be 0\nCheck for hanging hobbitd_channel processes or stale semaphores\n", n); shmdt(newch->channelbuf); shmctl(newch->shmid, IPC_RMID, NULL); semctl(newch->semid, 0, IPC_RMID); xfree(newch); return NULL; } } #ifdef MEMORY_DEBUG add_to_memlist(newch->channelbuf, bufsz); #endif return newch; }