dockapps/wmmenu/utils.c
Doug Torrance 2167b4c354 wmmenu: Fix -Wsign-compare compiler warning.
Use size_t instead of int since comparing with sizeof.
2015-01-24 18:40:48 +00:00

184 lines
3.5 KiB
C

#define _POSIX_SOURCE
#define _POSIX_C_SOURCE 199309L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
/* POSIX */
#include <unistd.h>
#include "utils.h"
#include "error.h"
#include "types.h"
static char * ReadAll (FILE * f, int offset)
{
char buf [10*1024] ;
size_t iRead, nRead ;
char * ret ;
clearerr (f) ;
iRead = 0 ;
nRead = 0 ;
while (iRead < sizeof buf)
{
nRead = fread (buf+iRead, 1, (sizeof buf)-iRead, f) ;
if (nRead <= 0) break ;
iRead += nRead ;
}
if (nRead > 0)
{
assert (iRead == sizeof buf) ;
ret = ReadAll (f, offset+iRead) ;
}
else
if (ferror (f) != 0)
{
error ("read file: %s", strerror (errno)) ;
ret = NULL ;
}
else
{
ret = malloc (offset+iRead+1) ;
if (ret == NULL) error ("failed to allocate memory") ;
ret[offset+iRead] = EOS ;
}
memcpy (ret+offset, buf, iRead) ;
return ret ;
}
extern char * File_ReadAll (FILE * f)
{
assert (f != NULL) ;
return ReadAll (f, 0) ;
}
static const char * getHome (void)
{
static char homeDir [80] = "" ;
static int initialized = 0 ;
if (! initialized)
{
const char * env ;
env = getenv ("HOME") ;
if (env != NULL && env[0] != EOS)
{
sprintf (homeDir, "%.*s", (int)(sizeof homeDir)-1, env) ;
}
initialized = 1 ;
}
return homeDir[0] != EOS ? homeDir : NULL ;
}
extern bool File_FindInPath (char * out, int outSz,
const char * path, const char * basename)
{
char name [FILENAME_MAX] ;
int len ;
assert (path != NULL) ;
assert (basename != NULL) ;
assert (out != NULL) ;
/* regular path */
if (access (basename, F_OK) == 0)
{
sprintf (out, "%.*s", outSz-1, basename) ;
return true ;
}
else
/* relative to home directory */
if (strncmp (basename, "~/", 2) == 0 && getHome () != NULL)
{
sprintf (name, "%s%s", getHome (), basename+1) ;
if (access (name, F_OK) == 0)
{
sprintf (out, "%.*s", outSz-1, name) ;
return true ;
}
else
{
return false ;
}
}
else
/* forbid relative to PATH just like shell */
/* NB: absolute non-existent files also drop here */
if (strchr (basename, '/') != NULL)
{
return false ;
}
else
{
while (*path != EOS)
{
len = strcspn (path, ":") ;
if (strncmp (path, "~/", 2) == 0)
{
sprintf (name, "%s%.*s/%s",
getHome (), len-1, path+1, basename) ;
}
else
{
sprintf (name, "%.*s/%s", len, path, basename) ;
}
if (access (name, F_OK) == 0)
{
sprintf (out, "%.*s", outSz-1, name) ;
return true ;
}
path += len ;
while (*path == ':') path++ ;
}
return false ;
}
}
extern char * File_ReadOutputFromCommand (const char * cmd)
{
FILE * out ;
char * ret ;
if ((out = popen (cmd, "r")) == NULL)
{
error ("when calling command: %s, error: ",
cmd, strerror (errno)) ;
ret = NULL ;
}
else
{
ret = File_ReadAll (out) ;
pclose (out) ;
/* if return value is correct, remove trailing whitespace */
if (ret != NULL)
{
char *lastNotWhite, *cursor ;
char c ;
cursor = lastNotWhite = ret ;
while ((c = *cursor++) != EOS)
{
if (strchr (" \t\n", c) == NULL)
{
lastNotWhite = cursor ;
}
}
*lastNotWhite = EOS ;
}
}
return ret ;
}