yaft/util.h
2017-01-13 16:50:38 +09:00

396 lines
7.4 KiB
C

/* See LICENSE for licence details. */
/* error functions */
enum loglevel_t {
DEBUG = 0,
WARN,
ERROR,
FATAL,
};
void logging(enum loglevel_t loglevel, char *format, ...)
{
va_list arg;
static const char *loglevel2str[] = {
[DEBUG] = "DEBUG",
[WARN] = "WARN",
[ERROR] = "ERROR",
[FATAL] = "FATAL",
};
/* debug message is available on verbose mode */
if ((loglevel == DEBUG) && (VERBOSE == false))
return;
fprintf(stderr, ">>%s<<\t", loglevel2str[loglevel]);
va_start(arg, format);
vfprintf(stderr, format, arg);
va_end(arg);
}
/* wrapper of C functions */
int eopen(const char *path, int flag)
{
int fd;
errno = 0;
if ((fd = open(path, flag)) < 0) {
logging(ERROR, "couldn't open \"%s\"\n", path);
logging(ERROR, "open: %s\n", strerror(errno));
}
return fd;
}
int eclose(int fd)
{
int ret;
errno = 0;
if ((ret = close(fd)) < 0)
logging(ERROR, "close: %s\n", strerror(errno));
return ret;
}
FILE *efopen(const char *path, char *mode)
{
FILE *fp;
errno = 0;
if ((fp = fopen(path, mode)) == NULL) {
logging(ERROR, "couldn't open \"%s\"\n", path);
logging(ERROR, "fopen: %s\n", strerror(errno));
}
return fp;
}
int efclose(FILE *fp)
{
int ret;
errno = 0;
if ((ret = fclose(fp)) < 0)
logging(ERROR, "fclose: %s\n", strerror(errno));
return ret;
}
void *emmap(void *addr, size_t len, int prot, int flag, int fd, off_t offset)
{
void *fp;
errno = 0;
if ((fp = mmap(addr, len, prot, flag, fd, offset)) == MAP_FAILED)
logging(ERROR, "mmap: %s\n", strerror(errno));
return fp;
}
int emunmap(void *ptr, size_t len)
{
int ret;
errno = 0;
if ((ret = munmap(ptr, len)) < 0)
logging(ERROR, "munmap: %s\n", strerror(errno));
return ret;
}
void *ecalloc(size_t nmemb, size_t size)
{
void *ptr;
errno = 0;
if ((ptr = calloc(nmemb, size)) == NULL)
logging(ERROR, "calloc: %s\n", strerror(errno));
return ptr;
}
void *erealloc(void *ptr, size_t size)
{
void *new;
errno = 0;
if ((new = realloc(ptr, size)) == NULL)
logging(ERROR, "realloc: %s\n", strerror(errno));
return new;
}
int eselect(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *tv)
{
int ret;
errno = 0;
if ((ret = select(maxfd, readfds, writefds, errorfds, tv)) < 0) {
if (errno == EINTR)
return eselect(maxfd, readfds, writefds, errorfds, tv);
else
logging(ERROR, "select: %s\n", strerror(errno));
}
return ret;
}
ssize_t ewrite(int fd, const void *buf, size_t size)
{
ssize_t ret;
errno = 0;
if ((ret = write(fd, buf, size)) < 0) {
if (errno == EINTR) {
logging(ERROR, "write: EINTR occurred\n");
return ewrite(fd, buf, size);
} else if (errno == EAGAIN || errno == EWOULDBLOCK) {
logging(ERROR, "write: EAGAIN or EWOULDBLOCK occurred, sleep %d usec\n", SLEEP_TIME);
usleep(SLEEP_TIME);
return ewrite(fd, buf, size);
} else {
logging(ERROR, "write: %s\n", strerror(errno));
return ret;
}
} else if (ret < (ssize_t) size) {
logging(ERROR, "data size:%zu write size:%zd\n", size, ret);
return ewrite(fd, (char *) buf + ret, size - ret);
}
return ret;
}
int esigaction(int signo, struct sigaction *act, struct sigaction *oact)
{
int ret;
errno = 0;
if ((ret = sigaction(signo, act, oact)) < 0)
logging(ERROR, "sigaction: %s\n", strerror(errno));
return ret;
}
int etcgetattr(int fd, struct termios *tm)
{
int ret;
errno = 0;
if ((ret = tcgetattr(fd, tm)) < 0)
logging(ERROR, "tcgetattr: %s\n", strerror(errno));
return ret;
}
int etcsetattr(int fd, int action, const struct termios *tm)
{
int ret;
errno = 0;
if ((ret = tcsetattr(fd, action, tm)) < 0)
logging(ERROR, "tcgetattr: %s\n", strerror(errno));
return ret;
}
int eopenpty(int *amaster, int *aslave, char *aname,
const struct termios *termp, const struct winsize *winsize)
{
int master;
char *name = NULL;
errno = 0;
if ((master = posix_openpt(O_RDWR | O_NOCTTY)) < 0
|| grantpt(master) < 0
|| unlockpt(master) < 0
|| (name = ptsname(master)) == NULL) {
logging(ERROR, "openpty: %s\n", strerror(errno));
return -1;
}
*amaster = master;
*aslave = eopen(name, O_RDWR | O_NOCTTY);
if (aname)
/* XXX: we don't use the slave's name, do nothing */
(void) aname;
//strncpy(aname, name, _POSIX_TTY_NAME_MAX - 1);
//snprintf(aname, _POSIX_TTY_NAME_MAX, "%s", name);
if (termp)
etcsetattr(*aslave, TCSAFLUSH, termp);
if (winsize)
ioctl(*aslave, TIOCSWINSZ, winsize);
return 0;
}
pid_t eforkpty(int *amaster, char *name,
const struct termios *termp, const struct winsize *winsize)
{
int master, slave;
pid_t pid;
if (eopenpty(&master, &slave, name, termp, winsize) < 0)
return -1;
errno = 0;
pid = fork();
if (pid < 0) {
logging(ERROR, "fork: %s\n", strerror(errno));
return pid;
} else if (pid == 0) { /* child */
close(master);
setsid();
dup2(slave, STDIN_FILENO);
dup2(slave, STDOUT_FILENO);
dup2(slave, STDERR_FILENO);
/* XXX: this ioctl may fail in Mac OS X
ref http://www.opensource.apple.com/source/Libc/Libc-825.25/util/pty.c?txt */
if (ioctl(slave, TIOCSCTTY, NULL))
logging(WARN, "ioctl: TIOCSCTTY faild\n");
close(slave);
return 0;
}
/* parent */
close(slave);
*amaster = master;
return pid;
}
int esetenv(const char *name, const char *value, int overwrite)
{
int ret;
errno = 0;
if ((ret = setenv(name, value, overwrite)) < 0)
logging(ERROR, "setenv: %s\n", strerror(errno));
return ret;
}
int eexecvp(const char *file, const char *argv[])
{
int ret;
errno = 0;
if ((ret = execvp(file, (char * const *) argv)) < 0)
logging(ERROR, "execvp: %s\n", strerror(errno));
return ret;
}
int eexecl(const char *path)
{
int ret;
errno = 0;
/* XXX: assume only one argument is given */
if ((ret = execl(path, path, NULL)) < 0)
logging(ERROR, "execl: %s\n", strerror(errno));
return ret;
}
long estrtol(const char *nptr, char **endptr, int base)
{
long int ret;
errno = 0;
ret = strtol(nptr, endptr, base);
if (ret == LONG_MIN || ret == LONG_MAX) {
logging(ERROR, "strtol: %s\n", strerror(errno));
return 0;
}
return ret;
}
/* parse_arg functions */
void reset_parm(struct parm_t *pt)
{
pt->argc = 0;
for (int i = 0; i < MAX_ARGS; i++)
pt->argv[i] = NULL;
}
void add_parm(struct parm_t *pt, char *cp)
{
if (pt->argc >= MAX_ARGS)
return;
logging(DEBUG, "argv[%d]: %s\n", pt->argc, (cp == NULL) ? "NULL": cp);
pt->argv[pt->argc] = cp;
pt->argc++;
}
void parse_arg(char *buf, struct parm_t *pt, int delim, int (is_valid)(int c))
{
/*
v..........v d v.....v d v.....v ... d
(valid char) (delimiter)
argv[0] argv[1] argv[2] ... argv[argc - 1]
*/
size_t length;
char *cp, *vp;
if (buf == NULL)
return;
length = strlen(buf);
logging(DEBUG, "parse_arg() length:%u\n", (unsigned) length);
vp = NULL;
for (size_t i = 0; i < length; i++) {
cp = buf + i;
if (vp == NULL && is_valid(*cp))
vp = cp;
if (*cp == delim) {
*cp = '\0';
add_parm(pt, vp);
vp = NULL;
}
if (i == (length - 1) && (vp != NULL || *cp == '\0'))
add_parm(pt, vp);
}
logging(DEBUG, "argc:%d\n", pt->argc);
}
/* other functions */
int my_ceil(int val, int div)
{
if (div == 0)
return 0;
else
return (val + div - 1) / div;
}
int dec2num(char *str)
{
if (str == NULL)
return 0;
return estrtol(str, NULL, 10);
}
int hex2num(char *str)
{
if (str == NULL)
return 0;
return estrtol(str, NULL, 16);
}
int sum(struct parm_t *parm)
{
int sum = 0;
for (int i = 0; i < parm->argc; i++)
sum += dec2num(parm->argv[i]);
return sum;
}