#include <ctype.h>
#include <curses.h>
#include <elf.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "hangman.h"
static int ksyms_elf_parse(void);
void
sym_getword(void)
{
uint tries;
off_t pos;
int buflen;
char symbuf[1 + BUFSIZ], *sym, *end;
size_t symlen;
for (tries = 0; tries < MAXBADWORDS; tries++) {
pos = arc4random_uniform(symsize);
if (lseek(symfd, pos + symoffs, SEEK_SET) == -1)
continue;
buflen = read(symfd, symbuf, BUFSIZ);
if (buflen == -1)
continue;
if (buflen + pos >= symsize)
buflen = symsize - pos;
*(end = symbuf + buflen) = '\0';
for (sym = symbuf; *sym != '\0'; sym++)
;
if (sym == end)
continue;
symlen = strlen(++sym);
if (symlen < MINLEN || symlen > MAXLEN)
continue;
if (strchr(sym, '.') != NULL || strchr(sym, '$') != NULL)
continue;
if (strncmp(sym, "__", 2) == 0)
continue;
break;
}
if (tries >= MAXBADWORDS) {
mvcur(0, COLS - 1, LINES -1, 0);
endwin();
errx(1, "can't seem a suitable symbol in %s",
Dict_name);
}
strlcpy(Word, sym, sizeof Word);
strlcpy(Known, sym, sizeof Known);
for (sym = Known; *sym != '\0'; sym++) {
if (*sym == '-')
*sym = '_';
if (isalnum((unsigned char)*sym))
*sym = '-';
}
}
int
sym_setup(void)
{
if ((symfd = open(Dict_name, O_RDONLY)) == -1)
return -1;
if (ksyms_elf_parse() == 0)
return 0;
close(symfd);
errno = ENOEXEC;
return -1;
}
int
ksyms_elf_parse(void)
{
Elf_Ehdr eh;
Elf_Shdr sh;
uint s;
if (lseek(symfd, 0, SEEK_SET) == -1)
return -1;
if (read(symfd, &eh, sizeof eh) != sizeof eh)
return -1;
if (!IS_ELF(eh))
return -1;
if (lseek(symfd, eh.e_shoff, SEEK_SET) == -1)
return -1;
symoffs = 0;
symsize = 0;
for (s = 0; s < eh.e_shnum; s++) {
if (read(symfd, &sh, sizeof sh) != sizeof sh)
return -1;
if (sh.sh_type == SHT_STRTAB) {
if (symsize > (off_t)sh.sh_size)
continue;
symoffs = (off_t)sh.sh_offset;
symsize = (off_t)sh.sh_size;
}
}
if (symsize == 0)
return -1;
return 0;
}