/*
* Copyright (c) 2004-2005, Stefan Walter
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the
* above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* * The names of contributors to this software may not be
* used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*
* CONTRIBUTORS
* Stef Walter <stef@memberwebs.com>
*
*
* PORTIONS FROM OPENBSD: -------------------------------------------------
*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "usuals.h"
#include "compat.h"
#include <ctype.h>
#include <stdlib.h>
#ifndef HAVE_REALLOCF
void* reallocf(void* ptr, size_t size)
{
void* ret = realloc(ptr, size);
if(!ret && size)
free(ptr);
return ret;
}
#endif
#ifndef HAVE_STRLWR
char* strlwr(char* s)
{
char* t = s;
while(*t)
{
*t = tolower(*t);
t++;
}
return s;
}
#endif
#ifndef HAVE_STRUPR
char* strupr(char* s)
{
char* t = s;
while(*t)
{
*t = toupper(*t);
t++;
}
return s;
}
#endif
#ifndef HAVE_STRLCPY
size_t strlcpy(char* dst, const char* src, size_t siz)
{
char* d = dst;
const char* s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if(n != 0 && --n != 0)
{
do
{
if((*d++ = *s++) == 0)
break;
}
while(--n != 0);
}
/* Not enough room in dst, add NUL and traverse rest of src */
if(n == 0)
{
if(siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return s - src - 1; /* count does not include NUL */
}
#endif
#ifndef HAVE_STRLCAT
size_t strlcat(char* dst, const char* src, size_t siz)
{
char* d = dst;
const char* s = src;
size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while(n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if(n == 0)
return dlen + strlen(s);
while(*s != '\0')
{
if(n != 1)
{
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return dlen + (s - src); /* count does not include NUL */
}
#endif
#ifndef HAVE_STRCASESTR
const char* strcasestr(const char *s, const char *find)
{
char c, sc;
size_t len;
if((c = *find++) != 0)
{
c = tolower((unsigned char)c);
len = strlen(find);
do
{
do
{
if((sc = *s++) == 0)
return (NULL);
}
while((char)tolower((unsigned char)sc) != c);
}
while (strncasecmp(s, find, len) != 0);
s--;
}
return((const char*)s);
}
#endif
#ifndef HAVE_SETENV
#include <stdio.h>
int setenv(const char* name, const char* value, int overwrite)
{
char* t;
int r;
if(getenv(name) && !overwrite)
return 0;
t = (char*)malloc((strlen(name) + strlen(value) + 2) * sizeof(char));
if(!t) return -1;
sprintf(t, "%s=%s", name, value);
r = putenv(t);
if(r != 0)
free(t);
return r;
}
#endif
#ifndef HAVE_DAEMON
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
int daemon(int nochdir, int noclose)
{
struct sigaction osa, sa;
int oerrno, fd, osa_ok;
pid_t newgrp;
/* A SIGHUP may be thrown when the parent exits below. */
sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
osa_ok = sigaction(SIGHUP, &sa, &osa);
switch(fork())
{
case -1:
return -1;
case 0:
break;
default:
_exit(0);
}
newgrp = setsid();
oerrno = errno;
if(osa_ok != -1)
sigaction(SIGHUP, &osa, NULL);
if(newgrp == -1)
{
errno = oerrno;
return -1;
}
if(!nochdir)
chdir("/");
if(!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1)
{
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
if(fd > 2)
close(fd);
}
return 0;
}
#endif
#ifndef HAVE_GETLINE
ssize_t getline(char** lineptr, size_t* n, FILE* stream)
{
return getdelim(lineptr, n, '\n', stream);
}
#endif
#ifndef HAVE_GETDELIM
ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* stream)
{
size_t written = 0;
int allocated, ch;
ssize_t ret = -1;
char* p;
if(!n || !lineptr || !stream)
{
errno = EINVAL;
return -1;
}
/* Track whether we allocated this or not */
allocated = !(*lineptr);
#ifdef HAVE_FLOCKFILE
/* Affects performance on Solaris. */
flockfile(stream);
#endif
for(;;)
{
if(!*lineptr)
*n = 0;
/* Reallocate if we need more space */
if(written == *n - 1)
{
*n = *n ? *n * 2 : 256;
if(!(p = (char*)realloc(*lineptr, *n)))
{
if(allocated && *lineptr)
free(*lineptr);
errno = ENOMEM;
ret = -1;
goto finally;
}
*lineptr = p;
}
while(written < *n - 1)
{
#ifdef HAVE_FLOCKFILE
ch = getc_unlocked(stream);
#else
ch = fgetc(stream);
#endif
if(ferror(stream))
{
if(allocated && *lineptr)
free(*lineptr);
ret = -1;
goto finally;
}
if(ch != EOF)
(*lineptr)[written++] = ch;
/* Done, null terminate, return */
if(ch == EOF || ch == delim)
{
(*lineptr)[written] = 0;
ret = written ? written : -1;
goto finally;
}
}
}
finally:
#ifdef HAVE_FLOCKFILE
funlockfile(stream);
#endif
return ret;
}
#endif
#ifndef HAVE_ERR_H
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
extern char** __argv;
static const char* calc_prog_name()
{
static char prognamebuf[256];
static int prepared = 0;
if(!prepared)
{
const char* beg = strrchr(__argv[0], '\\');
const char* temp = strrchr(__argv[0], '/');
beg = (beg > temp) ? beg : temp;
beg = (beg) ? beg + 1 : __argv[0];
temp = strrchr(__argv[0], '.');
temp = (temp > beg) ? temp : __argv[0] + strlen(__argv[0]);
if((temp - beg) > 255)
temp = beg + 255;
strncpy(prognamebuf, beg, temp - beg);
prognamebuf[temp - beg] = 0;
prepared = 1;
}
return prognamebuf;
}
static FILE* err_file; /* file to use for error output */
/*
* This is declared to take a `void *' so that the caller is not required
* to include <stdio.h> first. However, it is really a `FILE *', and the
* manual page documents it as such.
*/
void err_set_file(void *fp)
{
if (fp)
err_file = fp;
else
err_file = stderr;
}
void err(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verrc(eval, errno, fmt, ap);
va_end(ap);
}
void verr(int eval, const char *fmt, va_list ap)
{
verrc(eval, errno, fmt, ap);
}
void errc(int eval, int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verrc(eval, code, fmt, ap);
va_end(ap);
}
void verrc(int eval, int code, const char *fmt, va_list ap)
{
if (err_file == 0)
err_set_file((FILE *)0);
fprintf(err_file, "%s: ", calc_prog_name());
if (fmt != NULL) {
vfprintf(err_file, fmt, ap);
fprintf(err_file, ": ");
}
fprintf(err_file, "%s\n", strerror(code));
exit(eval);
}
void errx(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verrx(eval, fmt, ap);
va_end(ap);
}
void verrx(int eval, const char *fmt, va_list ap)
{
if (err_file == 0)
err_set_file((FILE *)0);
fprintf(err_file, "%s: ", calc_prog_name());
if (fmt != NULL)
vfprintf(err_file, fmt, ap);
fprintf(err_file, "\n");
exit(eval);
}
void warn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnc(errno, fmt, ap);
va_end(ap);
}
void vwarn(const char *fmt, va_list ap)
{
vwarnc(errno, fmt, ap);
}
void warnc(int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnc(code, fmt, ap);
va_end(ap);
}
void vwarnc(int code, const char *fmt, va_list ap)
{
if (err_file == 0)
err_set_file((FILE *)0);
fprintf(err_file, "%s: ", calc_prog_name());
if (fmt != NULL)
{
vfprintf(err_file, fmt, ap);
fprintf(err_file, ": ");
}
fprintf(err_file, "%s\n", strerror(code));
}
void warnx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnx(fmt, ap);
va_end(ap);
}
void vwarnx(const char *fmt, va_list ap)
{
if(err_file == 0)
err_set_file((FILE*)0);
fprintf(err_file, "%s: ", calc_prog_name());
if(fmt != NULL)
vfprintf(err_file, fmt, ap);
fprintf(err_file, "\n");
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1