#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "util-common.h"
char *hex_representation(const unsigned char *bytes, size_t size)
{
static const char *hex_digits = "0123456789abcdef";
char *str = malloc(2 * size + 1);
size_t i;
if(!str) {
return NULL;
}
for(i = 0; i < size; i++) {
str[2 * i] = hex_digits[bytes[i] >> 4];
str[2 * i + 1] = hex_digits[bytes[i] & 0x0f];
}
str[2 * size] = '\0';
return str;
}
const char *mbasename(const char *path)
{
const char *last = strrchr(path, '/');
if(last) {
return last + 1;
}
return path;
}
char *mdirname(const char *path)
{
char *ret, *last;
if(path == NULL || *path == '\0') {
return strdup(".");
}
if((ret = strdup(path)) == NULL) {
return NULL;
}
last = strrchr(ret, '/');
if(last != NULL) {
if(last == ret) {
last++;
}
*last = '\0';
return ret;
}
free(ret);
return strdup(".");
}
int llstat(char *path, struct stat *buf)
{
int ret;
char *c = NULL;
size_t len = strlen(path);
while(len > 1 && path[len - 1] == '/') {
--len;
c = path + len;
}
if(c) {
*c = '\0';
ret = lstat(path, buf);
*c = '/';
} else {
ret = lstat(path, buf);
}
return ret;
}
char *safe_fgets(char *s, int size, FILE *stream)
{
char *ret;
int errno_save = errno, ferror_save = ferror(stream);
while((ret = fgets(s, size, stream)) == NULL && !feof(stream)) {
if(errno == EINTR) {
errno = errno_save;
if(!ferror_save) {
clearerr(stream);
}
} else {
break;
}
}
return ret;
}
size_t strtrim(char *str)
{
char *end, *pch = str;
if(str == NULL || *str == '\0') {
return 0;
}
while(isspace((unsigned char)*pch)) {
pch++;
}
if(pch != str) {
size_t len = strlen(pch);
if(len == 0) {
*str = '\0';
return 0;
}
memmove(str, pch, len + 1);
pch = str;
}
end = (str + strlen(str) - 1);
while(isspace((unsigned char)*end)) {
end--;
}
*++end = '\0';
return end - pch;
}
#ifndef HAVE_STRNLEN
static size_t strnlen(const char *s, size_t max)
{
register const char *p;
for(p = s; *p && max--; ++p);
return (p - s);
}
#endif
#ifndef HAVE_STRNDUP
char *strndup(const char *s, size_t n)
{
size_t len = strnlen(s, n);
char *new = (char *) malloc(len + 1);
if(new == NULL) {
return NULL;
}
new[len] = '\0';
return (char *)memcpy(new, s, len);
}
#endif
void wordsplit_free(char **ws)
{
if(ws) {
char **c;
for(c = ws; *c; c++) {
free(*c);
}
free(ws);
}
}
char **wordsplit(const char *str)
{
const char *c = str, *end;
char **out = NULL, **outsave;
size_t count = 0;
if(str == NULL) {
errno = EINVAL;
return NULL;
}
for(c = str; isspace(*c); c++);
while(*c) {
size_t wordlen = 0;
outsave = out;
if((out = realloc(out, (count + 1) * sizeof(char*))) == NULL) {
out = outsave;
goto error;
}
for(end = c; *end && !isspace(*end); end++) {
if(*end == '\'' || *end == '"') {
char quote = *end;
while(*(++end) && *end != quote) {
if(*end == '\\' && *(end + 1) == quote) {
end++;
}
wordlen++;
}
if(*end != quote) {
errno = EINVAL;
goto error;
}
} else {
if(*end == '\\' && (end[1] == '\'' || end[1] == '"')) {
end++;
}
wordlen++;
}
}
if(wordlen == (size_t) (end - c)) {
if((out[count++] = strndup(c, wordlen)) == NULL) {
goto error;
}
} else {
char *dest = out[count++] = malloc(wordlen + 1);
if(dest == NULL) { goto error; }
while(c < end) {
if(*c == '\'' || *c == '"') {
char quote = *c;
for(c++; *c != quote; c++) {
if(*c == '\\' && *(c + 1) == quote) {
c++;
}
*(dest++) = *c;
}
c++;
} else {
if(*c == '\\' && (c[1] == '\'' || c[1] == '"')) {
c++;
}
*(dest++) = *(c++);
}
}
*dest = '\0';
}
if(*end == '\0') {
break;
} else {
for(c = end + 1; isspace(*c); c++);
}
}
outsave = out;
if((out = realloc(out, (count + 1) * sizeof(char*))) == NULL) {
out = outsave;
goto error;
}
out[count++] = NULL;
return out;
error:
while(count) {
free(out[--count]);
}
free(out);
return NULL;
}