Voici un .c et un .h que j'utilise assez frequemment dans mes codes. Il s'agit de quelques fonctions passe-partout, essentiellement de manipulation de chaines de caractère. Le .h regroupe une liste de #defines correspondant à des fonctions classiques mais encadrées de tests.

tools.h

L'inévitable license, ici une license BSD

/*
 * Copyright (c) 2005
 *      iMil <imil@gcu.info>.  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. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by iMil.
 * 4. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY iMil 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 iMil OR THE VOICES IN HIS HEAD
 * 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.
 *
 * $Id: tools.h,v 1.6 2005/03/12 09:54:44 imil Exp $ 
 */

On verifie que ce header n'a pas déjà été inclu

#ifndef _TOOLS_H
#define _TOOLS_H

Et on inclut quelques headers nécessaires

#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include <limits.h>
#include <sys/queue.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>

#include <string.h>
#include <err.h>

On place quelques constantes

#define MAXLEN LINE_MAX
#define MIDLEN 256
#define SMLLEN 32
#define D_WARN 5
#define D_INFO 10
#define T_FALSE 0
#define T_TRUE 1

Et nous déclarons nos fonctions “helper”.

Ces deux premiers #defines sont des conteneurs des fonctions read(2) et close(2) dans un contexte threadé qui sortent du thread courant si l'operation d'I/O echoue

#define R_READ(fd, buf, len)                                            \
        if (read(fd, buf, len) < 0) {                                   \
                warn("read()");                                         \
                pthread_exit(NULL);                                     \
        }

#define R_CLOSE(fd)                                                     \
        do {                                                            \
                close(fd);                                              \
                pthread_exit(NULL);                                     \
        } while (/* CONSTCOND */ 0)

Voici une serie de conteneurs de fonctions d'allocation mémoire et copie chaines de caractères, avec dans tous les cas :

  • verification de l'allocation
  • verification de la non nullité des membres
#define XMALLOC(elm, size)                                              \
        do {                                                            \
                elm = malloc(size);                                     \
                if (elm == NULL)                                        \
                        err(1, "can't allocate memory\n");              \
                memset(elm, 0, size);                                   \
        } while (/* CONSTCOND */ 0)

#define XSTRDUP(dest, src)                                              \
        do {                                                            \
                if (src == NULL)                                        \
                        dest = NULL;                                    \
                else {                                                  \
                        dest = strdup(src);                             \
                        if (dest == NULL)                               \
                                err(1, "can't strdup %s\n", src);       \
                }                                                       \
        } while (/* CONSTCOND */ 0)

#define XREALLOC(elm, size)                                             \
        do {                                                            \
                void *telm;                                             \
                if (elm == NULL)                                        \
                        XMALLOC(elm, size);                             \
                else {                                                  \
                        telm = realloc(elm, size);                      \
                        if (telm == NULL)                               \
                                err(1, "can't allocate memory\n");      \
                        elm = telm;                                     \
                }                                                       \
        } while (/* CONSTCOND */ 0)

#define DSTSRC_CHK(dst, src)                                            \
                if (dst == NULL) {                                      \
                        warn("NULL destination");                       \
                        break;                                          \
                }                                                       \
                if (src == NULL) {                                      \
                        warn("NULL source");                            \
                        break;                                          \
                }


#define XSTRCPY(dst, src)                                               \
        do {                                                            \
                DSTSRC_CHK(dst, src);                                   \
                strcpy(dst, src);                                       \
        } while (/* CONSTCOND */ 0)

#define XSTRCAT(dst, src)                                               \
        do {                                                            \
                DSTSRC_CHK(dst, src);                                   \
                strcat(dst, src);                                       \
        } while (/* CONSTCOND */ 0)

#define XFREE(elm)                                                      \
        do {                                                            \
                if (elm != NULL) {                                      \
                        free(elm);                                      \
                        elm = NULL;                                     \
                }                                                       \
        } while (/* CONSTCOND */ 0)

Un petit typedef créant un type “booléen”

typedef uint8_t T_Bool;

Et la liste des fonctions disponibles dans tools.c

/* "nettoie" une chaine de caractères de \n et \r */
extern int trimcr(char *);
/* 
 * divise une chaine de caractères en une liste de pointeurs vers des chaines 
 * fonction d'un délimiteur et renvoie cette liste
 * ATTENTION: cette liste et ses membres sont alloués
 */
extern char **splitstr(char *, const char *);
/* libère une liste créée avec splistr (ou de type similaire) */
extern void free_list(char ***);
/* 
 * revoie une chaine dans laquelle la le premier const char * est remplacé par le 
 * second 
 */
extern char *strreplace(char *, const char *, const char *);
/*
 * "coupe" une chaine à l'indice passé en second paramètre et finit la chaine par 
 * "..."
*/
extern void cut_str(char *, int);
/* extention de printf orientée debugging, fonction du premier paramètre */
extern void d_printf(uint8_t, char *, ...);
/* renvoie la laveur minimale des deux parametres */
extern int min(int, int);
/* renvoie la valeur maximale des deux paramètres */
extern int max(int, int);
/*
 * "remplit" la chaine de caractères avec le second parametre, jusqu'à l'indice passé 
 * dans le 3eme parametre
 */
extern void line_padding(char *, char, int);
/* renvoie la taille d'une liste */
extern int listlen(const char **);
/*
 * renvoie une liste de chaines correspondant à la sortie de la commande passée en 
 * 1er parametre. Le second parametre, s'il n'est pas NULL, permet de ne renvoyer que
 * les sorties contenant la chaine passée 
 */
extern char **exec_list(const char *, const char *);
/* verification de la présence du second parametre dans la liste passée en 1er param */
extern T_Bool is_listed(const char **, const char *);
/* client TCP minimal: 1er parametre: host, second parametre: port */
extern int tcpclient(char *, int);

#endif

tools.c

/*
 * Copyright (c) 2005
 *      iMil <imil@gcu.info>.  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. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by iMil.
 * 4. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY iMil 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 iMil OR THE VOICES IN HIS HEAD
 * 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.
 *
 * $Id: tools.c,v 1.3 2005/03/12 09:54:44 imil Exp $ 
 */

#include "tools.h"

__inline int
trimcr(char *str)
{
        uint16_t len;
        
        if (str == NULL)
                return (-1);
        
        len = strlen(str);
        
        while (len--)
                if ((str[len] == '\r') || (str[len] == '\n'))
                        str[len] = '\0';
        
        return (0);
}

char **
splitstr(char *str, const char *sep)
{
        int i, size;
        char *p, *tmp, **split;
        
        for (i = 0, size = 0; str[i] != '\0'; i++)
                if (str[i] == *sep)
                        size++;

        /* size = number of separators + 1 member + NULL */
        size += 2;
        XMALLOC(split, size * sizeof(char *));

        i = 0;
        for (p = str; p != NULL;)
                while ((tmp = strsep(&p, sep)) != NULL) {
                        if (*tmp != '\0') {
                                while (*tmp == ' ' || *tmp == '\t')
                                        tmp++;
                                XSTRDUP(split[i], tmp);
                                i++;
                        }
                }

        split[i] = NULL;

        return(split);
}

void
free_list(char ***list)
{
        int i;
        char **plist;

        if (*list != NULL) {
                plist = *list;
                for (i = 0; plist[i] != NULL; i++)
                        XFREE(plist[i]);
                XFREE(*list);
        }
}

void
cut_str(char *str, int maxlen)
{
        int len, i, j;

        if (str == NULL)
                return;

        len = strlen(str);

        if (len > maxlen) {
                j = 0;
                /* step back */
                for (i = maxlen - j; j < 3; j++)
                        str[i + j] = '.';
                str[i + j] = '\0';
        }
}

int verbose = 10;

/* debug printf, show info if global verbose >= verbosity */
void
d_printf(uint8_t verbosity, char *fmt, ...) {
        char buffer[MAXLEN];
        
        if (verbose >= verbosity ) {
                va_list args;
                va_start(args, fmt);
                vsnprintf(buffer, MAXLEN, fmt, args);
                fprintf(stderr, "%s", buffer);
                va_end(args);
        }
}

__inline int
max(int a, int b)
{
        return (a > b ? a : b);
}
__inline int
min(int a, int b)
{
        return (a < b ? a : b);
}

int
tcpclient(char *host, int port) {
        int s;
        struct sockaddr_in sa;
        struct hostent *he;

        if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
                warn("socket");
                return (-1);
        }
  
        bzero(&sa, sizeof sa);

        sa.sin_family = AF_INET;
        sa.sin_port = htons(port);

        if ((he = gethostbyname(host)) == NULL) {
                herror(host);
                return (-1);
        }
  
        bcopy(he->h_addr_list[0],&sa.sin_addr, he->h_length);

        if (connect(s, (struct sockaddr *)&sa, sizeof sa) < 0) {
                warn("connect");
                close(s);
                return (-1);
        }

        return (s);
}

/* CAUTION, this function assume you know how long your line is ! */
void
line_padding(char *line, char fill, int len)
{
        int i;
        char *p;

        if (line == NULL || fill == 0 || len == 0)
                return;

        i = strlen(line);
        p = &line[i];
        for (; i < len; i++)
                p[i] = fill;

        p[i] = '\0';
}

char *
strreplace(char *str, const char *from, const char *to)
{
        int fromlen, tolen, i;
        char *p, *ret, buf[MAXLEN];

        memset(buf, 0, MAXLEN);

        fromlen = strlen(from);
        /* keep space for \0's strcat */
        tolen = strlen(to) + 1;

        for (i = 0, p = str; *p != 0;) {
                if (strncmp(p, from, fromlen) == 0) {
                        strncat(buf, to, tolen);
                        p += fromlen;
                        i += tolen;
                } else {
                        buf[i] = *p;
                        p++;
                        i++;
                }
        }
        buf[i] = '\0';

        XSTRDUP(ret, buf);
        return(ret);
}

int
listlen(const char **list)
{
        int i;

        for (i = 0; list[i] != NULL; i++);
        return(i);
}

/* execute a command and receive result on a char ** */
char **
exec_list(const char *cmd, const char *match)
{
        FILE *fp;
        int size;
        char **res, *rawlist, buf[MAXLEN];

        if ((fp = popen(cmd, "r")) == NULL)
                return(NULL);

        rawlist = NULL;
        size = 0;

        while (fgets(buf, MAXLEN, fp) != NULL) {
                if (match == NULL || strstr(buf, match) != NULL) {
                        size += (strlen(buf) + 1) * sizeof(char);
                        
                        XREALLOC(rawlist,  size);
                        strcat(rawlist, buf);
                }
        }
        pclose(fp);

        if (rawlist == NULL)
                return(NULL);

        res = splitstr(rawlist, "\n");
        XFREE(rawlist);

        return(res);
}

T_Bool
is_listed(const char **list, const char *item)
{
        for (; *list != NULL; list++)
                if (strcmp(item, *list) == 0)
                        return(T_TRUE);

        return(T_FALSE);
}
c/imil_s_tools.txt · Last modified: 2010/01/12 13:29 (external edit)
www.chimeric.de Creative Commons License Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0