/* * misc.c - miscellaneous funcions module - implementation * * nc6 - an advanced netcat clone * Copyright (C) 2001-2006 Mauro Tortonesi * Copyright (C) 2002-2006 Chris Leishman * * 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 #include #include #include #include #include #ifdef HAVE_STRTOL #include #include #endif #include #ifdef HAVE_PATHS_H #include #endif #ifdef ENABLE_BLUEZ #ifdef HAVE_STDINT_H #include /* needed for uint8_t */ #endif #include #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