X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Futils%2Fos.c;h=e975f96e743b6510102426d6450dbe9270690e1c;hp=e3f1fe2d42bb61d072940949a7ddee345836d4f6;hb=1d4f883090c6e081041d8909256a393727a2ecf1;hpb=a9ae0d1a4c9e2992d932489c96cd63b2ce2a0c56 diff --git a/src/utils/os.c b/src/utils/os.c index e3f1fe2..e975f96 100644 --- a/src/utils/os.c +++ b/src/utils/os.c @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -45,12 +46,44 @@ #include #include +#include #include /* * public API */ +char * +sdb_get_homedir(void) +{ + char *username = sdb_get_current_user(); + + struct passwd pw_entry; + struct passwd *result = NULL; + + char buf[4096]; + + int status; + + if (username) { + memset(&pw_entry, 0, sizeof(pw_entry)); + status = getpwnam_r(username, &pw_entry, buf, sizeof(buf), &result); + } + else + status = -1; + + if (status || (! result)) { + char errbuf[1024]; + sdb_log(SDB_LOG_WARNING, "os: Failed to determine home directory " + "for user %s: %s", username, + sdb_strerror(errno, errbuf, sizeof(errbuf))); + free(username); + return NULL; + } + free(username); + return strdup(result->pw_dir); +} /* sdb_get_homedir */ + int sdb_mkdir_all(const char *pathname, mode_t mode) { @@ -150,7 +183,7 @@ sdb_get_current_user(void) uid_t uid; - char buf[1024]; + char buf[4096]; int status; uid = geteuid(); @@ -166,5 +199,145 @@ sdb_get_current_user(void) return strdup(result->pw_name); } /* sdb_get_current_user */ +int +sdb_select(int fd, int type) +{ + fd_set fds; + fd_set *readfds = NULL; + fd_set *writefds = NULL; + fd_set *exceptfds = NULL; + + if (fd < 0) { + errno = EBADF; + return -1; + } + + FD_ZERO(&fds); + + switch (type) { + case SDB_SELECTIN: + readfds = &fds; + break; + case SDB_SELECTOUT: + writefds = &fds; + break; + case SDB_SELECTERR: + exceptfds = &fds; + break; + default: + errno = EINVAL; + return -1; + } + + FD_SET(fd, &fds); + + while (42) { + int n; + errno = 0; + n = select(fd + 1, readfds, writefds, exceptfds, NULL); + + if ((n < 0) && (errno != EINTR)) + return n; + if (n > 0) + break; + } + return 0; +} /* sdb_select */ + +ssize_t +sdb_write(int fd, size_t msg_len, const void *msg) +{ + const char *buf; + size_t len; + + if ((fd < 0) || (msg_len && (! msg))) + return -1; + if (! msg_len) + return 0; + + buf = msg; + len = msg_len; + while (len > 0) { + ssize_t status; + + if (sdb_select(fd, SDB_SELECTOUT)) + return -1; + + errno = 0; + status = write(fd, buf, len); + if (status < 0) { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + continue; + if (errno == EINTR) + continue; + + return status; + } + + len -= (size_t)status; + buf += status; + } + + return (ssize_t)msg_len; +} /* sdb_write */ + +int +sdb_resolve(int network, const char *address, struct addrinfo **res) +{ + struct addrinfo ai_hints; + const char *host; + char *port; + int status; + + if (! res) { + errno = EINVAL; + return EAI_SYSTEM; + } + + if (address) { + host = address; + port = strchr(host, ':'); + if (port) { + *port = '\0'; + ++port; + } + if (! *host) + host = NULL; + } + else { + host = NULL; + port = NULL; + } + + memset(&ai_hints, 0, sizeof(ai_hints)); + ai_hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + if (network & SDB_NET_V4) + ai_hints.ai_family = AF_INET; + else if (network & SDB_NET_V6) + ai_hints.ai_family = AF_INET6; + else + ai_hints.ai_family = AF_UNSPEC; + + if ((network & SDB_NET_IP) == SDB_NET_IP) { + ai_hints.ai_socktype = 0; + ai_hints.ai_protocol = 0; + } + else if (network & SDB_NET_TCP) { + ai_hints.ai_socktype = SOCK_STREAM; + ai_hints.ai_protocol = IPPROTO_TCP; + } + else if (network & SDB_NET_UDP) { + ai_hints.ai_socktype = SOCK_DGRAM; + ai_hints.ai_protocol = IPPROTO_UDP; + } + + status = getaddrinfo(host, port, &ai_hints, res); + if (port) { + --port; + *port = ':'; + } + return status; +} /* sdb_resolve */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */