Logo Search packages:      
Sourcecode: sbrsh version File versions  Download package

common.c

/*
 * Copyright (c) 2003, 2004 Nokia
 * Author: tsavola@movial.fi
 *
 * This program is licensed under GPL (see COPYING for details)
 */

#include "types.h"
#include "common.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
#include <sys/socket.h>

const char *oom = "Out of memory";

void oom_error(void)
{
      errno = 0;
      error(oom);
}

/**
 * Sets a file descriptor (non-)blocking.
 * @param fd the behaviour of this file descriptor will be changed
 * @param nonblock if TRUE, fd is set nonblocking; if FALSE, fd is set blocking
 */
int set_nonblocking(int fd, bool_t nonblock)
{
      int val;

      val = fcntl(fd, F_GETFL, 0);
      if (val < 0)
            return -1;

      if (nonblock) {
            if (val & O_NONBLOCK)
                  return 0;

            val |= O_NONBLOCK;
      } else {
            if (!(val & O_NONBLOCK))
                  return 0;

            val &= ~O_NONBLOCK;
      }

      return fcntl(fd, F_SETFL, val);
}

/**
 * Sets a file descriptor to close-on-exec.
 */
int set_closeonexec(int fd)
{
      int val;

      val = fcntl(fd, F_GETFD, 0);
      if (val < 0)
            return -1;

      if (val & FD_CLOEXEC)
            return 0;

      return fcntl(fd, F_SETFD, val | FD_CLOEXEC);
}

int setsockopt_bool(int s, int level, int sockopt, bool_t value)
{
      return setsockopt(s, level, sockopt, &value, sizeof (value));
}

/**
 * Gets a neat progname.
 */
char *get_progname(char *name)
{
      char *p;

      p = strrchr(name, '/');
      if (p && strlen(p) >= 2)
            return &p[1];
      else
            return name;
}

uint32_t resolve(const char *hostname)
{
      struct hostent *host;
      uint32_t addr;

      host = gethostbyname(hostname);
      if (!host)
            goto _err;

      addr = *(uint32_t *) host->h_addr;
      if (!addr)
            goto _err;

      return ntohl(addr);

_err:
      error("Can't resolve host: %s", hostname);
      return 0;
}

/**
 * Frees all components of a null-terminated vector with a given function and
 * the vector itself. If the function is NULL, free(3) will be used. If vec is
 * NULL, nothing happens.
 * @param vec tor
 * @param func tion
 */
void free_vec(void **vec, free_func_t *func)
{
      void **p;

      if (!vec)
            return;

      if (!func)
            func = (free_func_t *) free;

      for (p = vec; *p; ++p)
            func(*p);

      free(vec);
}

size_t calc_vec_len(void **vec)
{
      size_t len = 0;

      if (vec)
            while (*vec++)
                  ++len;

      return len;
}

static ssize_t do_read_line(FILE *file, char *buf, size_t size,
                            char comment_char, bool_t *blankp)
{
      bool_t blank = TRUE;
      bool_t comm = FALSE;
      size_t i = 0;
      int c;

      if (feof(file))
            return -1;

      while (1) {
            c = fgetc(file);
            if (c == EOF || c == '\n')
                  break;

            if (!isspace(c))
                  blank = FALSE;

            if (c == comment_char)
                  comm = TRUE;

            if (!comm && i < size - 1) {
                  *buf++ = c;
                  i++;
            }
      }
      *buf = '\0';

      if (blankp)
            *blankp = blank;

      return i;
}

ssize_t read_line(FILE *file, char *buf, size_t size)
{
      return do_read_line(file, buf, size, '#', NULL);
}

ssize_t read_line_blank(FILE *file, char *buf, size_t size, bool_t *blankp)
{
      return do_read_line(file, buf, size, '#', blankp);
}

/**
 * Reads a line, not stopping on comments.
 */
ssize_t read_line_nocomments(FILE *file, char *buf, size_t size)
{
      return do_read_line(file, buf, size, '\0', NULL);
}

char *skip_spaces(const char *buf)
{
      while (*buf && isspace(*buf))
            ++buf;

      return (char *) buf;
}

char *find_space(const char *buf)
{
      while (*buf && !isspace(*buf))
            ++buf;

      return (char *) buf;
}

char *find_line(char *buf)
{
      while (*buf && *buf++ != '\n')
            ;

      return buf;
}

char *trim_string(char *buf)
{
      char *next;

      buf = skip_spaces(buf);

      for (next = buf; 1; ) {
            char *end = find_space(next);

            if (*end == '\0')
                  break;

            next = skip_spaces(end);
            if (*next == '\0') {
                  *end = '\0';
                  break;
            }
      }

      return buf;
}

int split_string(char *line, ...)
{
      va_list arg;
      char **strp, *str;
      int n = 0;

      va_start(arg, line);

      while (1) {
            strp = va_arg(arg, char **);
            if (!strp)
                  break;

            if (strlen(line) == 0) {
                  *strp = NULL;
                  continue;
            }

            str = line;

            line = find_space(line);
            if (*line) {
                  *line++ = '\0';
                  line = skip_spaces(line);
            }

            if (strlen(str) > 0) {
                  *strp = str;
                  n++;
            } else {
                  *strp = NULL;
            }
      }

      va_end(arg);

      return n;
}

size_t string_cat(char *buf, size_t bufsize, const char *piece, ...)
{
      char *str;
      ssize_t avail;
      va_list arg;

      va_start(arg, piece);

      str = buf;
      *str = '\0';

      while (piece) {
            size_t len;

            avail = (bufsize - 1) - strlen(str);
            if (avail <= 0) {
                  break;
            }

            len = strlen(piece);
            if (len > avail) {
                  strncat(str, piece, avail);
                  break;
            }

            strcat(str, piece);

            piece = va_arg(arg, char *);
      }

      va_end(arg);

      return strlen(buf);
}

Generated by  Doxygen 1.6.0   Back to index