/*
* misc.c - miscellaneous funcions module - implementation
*
* nc6 - an advanced netcat clone
* Copyright (C) 2001-2006 Mauro Tortonesi <mauro _at_ deepspace6.net>
* Copyright (C) 2002-2006 Chris Leishman <chris _at_ leishman.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "system.h"
#include "misc.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#ifdef HAVE_STRTOL
#include <errno.h>
#include <limits.h>
#endif
#include <unistd.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#ifdef ENABLE_BLUEZ
#ifdef HAVE_STDINT_H
#include <stdint.h> /* needed for uint8_t */
#endif
#include <bluetooth/bluetooth.h>
#endif
RCSID("@(#) $Header: /ds6/cvs/nc6/src/misc.c,v 1.29 2006/01/19 22:46:23 chris Exp $");
/* abort with an internal error message */
void fatal_internal(const char *template, ...)
{
va_list ap;
assert(template != NULL);
fprintf(stderr, "%s: internal error: ", get_program_name());
va_start(ap, template);
vfprintf(stderr, template, ap);
va_end(ap);
fprintf(stderr, " (please report this error to nc6 authors)\n");
abort();
}
/* exit the program with an error message */
void fatal(const char *template, ...)
{
va_list ap;
assert(template != NULL);
fprintf(stderr, "%s: ", get_program_name());
va_start(ap, template);
vfprintf(stderr, template, ap);
va_end(ap);
fprintf(stderr, "\n");
exit(EXIT_FAILURE);
}
void warning(const char *template, ...)
{
va_list ap;
assert(template != NULL);
fprintf(stderr, "%s: ", get_program_name());
va_start(ap, template);
vfprintf(stderr, template, ap);
va_end(ap);
fprintf(stderr, "\n");
}
/* same as `malloc' but report error if no memory available */
void *xmalloc(size_t size)
{
register void *value = malloc(size);
if (value == NULL) fatal(_("virtual memory exhausted"));
return value;
}
char *xstrdup(const char *str)
{
register char *nstr = (char *)xmalloc(strlen(str));
/* we should use srtlcpy here instead of strcpy */
strcpy(nstr, str);
return nstr;
}
void nonblock(int fd)
{
int arg;
if ((arg = fcntl(fd, F_GETFL, 0)) < 0)
fatal("error reading file descriptor flags: %s",
strerror(errno));
arg |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, arg) < 0)
fatal("error setting flag O_NONBLOCK on file descriptor",
strerror(errno));
}
int open3(const char *cmd, int *in, int *out, int *err)
{
int inpipe[2];
int outpipe[2];
int errpipe[2];
int pid;
if (in != NULL) {
if (pipe(inpipe) < 0)
return -1;
} else {
inpipe[0] = open(_PATH_DEVNULL, O_RDONLY);
if (inpipe[0] < 0)
return -1;
}
if (out != NULL) {
if (pipe(outpipe) < 0)
return -1;
} else {
outpipe[1] = open(_PATH_DEVNULL, O_WRONLY);
if (outpipe[1] < 0)
return -1;
}
if (err != NULL) {
if (pipe(errpipe) < 0)
return -1;
} else {
errpipe[1] = open(_PATH_DEVNULL, O_WRONLY);
if (errpipe[1] < 0)
return -1;
}
/* fork the process */
pid = fork();
if (pid < 0) {
return -1;
} else if (pid == 0) {
char *argv[4];
/* child */
/* close parents descriptors */
close(inpipe[1]);
close(outpipe[0]);
close(errpipe[0]);
argv[0] = "sh";
argv[1] = "-c";
argv[2] = xstrdup(cmd); /* have to strdup to remove const */
argv[3] = NULL;
/* replace stdin, stdout and stderr */
close(STDIN_FILENO);
if (dup2(inpipe[0], STDIN_FILENO) < 0)
fatal("dup2 failed: %s", strerror(errno));
close(inpipe[0]);
close(STDOUT_FILENO);
if (dup2(outpipe[1], STDOUT_FILENO) < 0)
fatal("dup2 failed: %s", strerror(errno));
close(outpipe[1]);
close(STDERR_FILENO);
if (dup2(errpipe[1], STDERR_FILENO) < 0)
fatal("dup2 failed: %s", strerror(errno));
close(errpipe[1]);
/* exec the required command */
execv(_PATH_BSHELL, argv);
fatal("execv failed: %s", strerror(errno));
}
/* parent */
/* close childs descriptors */
close(inpipe[0]);
close(outpipe[1]);
close(errpipe[1]);
if (in != NULL) *in = inpipe[1];
if (out != NULL) *out = outpipe[0];
if (err != NULL) *err = errpipe[0];
return pid;
}
int safe_atoi(const char *str, int *result)
{
long int lresult;
char *endptr;
assert(str != NULL);
assert(result != NULL);
#ifdef HAVE_STRTOL
errno = 0;
lresult = strtol(str, &endptr, 10);
if (*endptr != '\0') {
errno = EINVAL;
return -1;
}
if (errno == ERANGE || lresult > INT_MAX || lresult < INT_MIN) {
errno = ERANGE;
return -1;
}
#else
for (endptr = str; *endptr != '\0'; ++endptr) {
if (!isdigit(*endptr)) {
errno = EINVAL;
return -1;
}
}
lresult = atoi(str);
#endif
*result = lresult;
return 0;
}
#ifdef ENABLE_BLUEZ
int safe_ba2str(const bdaddr_t *ba, char *str, size_t strlen)
{
uint8_t b[6];
baswap((bdaddr_t *)b, ba);
return snprintf(str, strlen, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
b[0], b[1], b[2], b[3], b[4], b[5]);
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1