guowenxue
2020-08-21 02f4d9518378031c63df7a36c49d8b2eabdaab90
add program folder
114 files added
157518 ■■■■■ changed files
program/converterd/cp_comport.c 600 ●●●●● patch | view | raw | blame | history
program/converterd/cp_comport.h 67 ●●●●● patch | view | raw | blame | history
program/converterd/cp_dictionary.c 398 ●●●●● patch | view | raw | blame | history
program/converterd/cp_dictionary.h 165 ●●●●● patch | view | raw | blame | history
program/converterd/cp_iniparser.c 807 ●●●●● patch | view | raw | blame | history
program/converterd/cp_iniparser.h 308 ●●●●● patch | view | raw | blame | history
program/converterd/cp_logger.c 433 ●●●●● patch | view | raw | blame | history
program/converterd/cp_logger.h 111 ●●●●● patch | view | raw | blame | history
program/converterd/cp_proc.c 341 ●●●●● patch | view | raw | blame | history
program/converterd/cp_proc.h 42 ●●●●● patch | view | raw | blame | history
program/converterd/cp_socket.c 252 ●●●●● patch | view | raw | blame | history
program/converterd/cp_socket.h 40 ●●●●● patch | view | raw | blame | history
program/converterd/cvd_conf.c 121 ●●●●● patch | view | raw | blame | history
program/converterd/cvd_conf.h 31 ●●●●● patch | view | raw | blame | history
program/converterd/cvd_main.c 309 ●●●●● patch | view | raw | blame | history
program/converterd/cvd_main.h 40 ●●●●● patch | view | raw | blame | history
program/converterd/makefile 114 ●●●●● patch | view | raw | blame | history
program/cp_library/at91_ioctl.h 91 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_array.c 168 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_array.h 41 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_atcmd.c 668 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_atcmd.h 68 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_common.h 68 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_comport.c 600 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_comport.h 67 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_dictionary.c 398 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_dictionary.h 165 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_fds.c 633 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_fds.h 114 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_gprs.c 705 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_gprs.h 126 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_gsmmux.c 75 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_gsmmux.h 44 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_hal.c 257 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_hal.h 56 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_iniparser.c 807 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_iniparser.h 308 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_klist.h 723 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_logger.c 420 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_logger.h 110 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_network.c 358 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_network.h 37 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_ppp.c 552 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_ppp.h 138 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_proc.c 341 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_proc.h 42 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_queue.c 155 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_queue.h 49 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_ringbuf.c 103 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_ringbuf.h 57 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_sock.c 854 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_sock.h 184 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_string.c 673 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_string.h 86 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_time.h 123 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_vector.c 96 ●●●●● patch | view | raw | blame | history
program/cp_library/cp_vector.h 40 ●●●●● patch | view | raw | blame | history
program/cp_library/cscope.in.out patch | view | raw | blame | history
program/cp_library/cscope.out 132502 ●●●●● patch | view | raw | blame | history
program/cp_library/cscope.po.out patch | view | raw | blame | history
program/cp_library/makefile 107 ●●●●● patch | view | raw | blame | history
program/cp_library/tags 1322 ●●●●● patch | view | raw | blame | history
program/cp_library/test/comport.c 238 ●●●●● patch | view | raw | blame | history
program/cp_library/test/makefile 121 ●●●●● patch | view | raw | blame | history
program/cp_library/test/sample.ini 11 ●●●●● patch | view | raw | blame | history
program/cp_library/test/swe_tpdud.c 360 ●●●●● patch | view | raw | blame | history
program/cp_library/test/swe_tpdud.h 42 ●●●●● patch | view | raw | blame | history
program/cp_library/test/test_array.c 82 ●●●●● patch | view | raw | blame | history
program/cp_library/test/test_hal.c 210 ●●●●● patch | view | raw | blame | history
program/cp_library/test/test_hh.c 85 ●●●●● patch | view | raw | blame | history
program/cp_library/test/test_ini.c 48 ●●●●● patch | view | raw | blame | history
program/cp_library/test/test_klist.c 79 ●●●●● patch | view | raw | blame | history
program/cp_library/test/test_logger.c 58 ●●●●● patch | view | raw | blame | history
program/cp_library/test/test_queue.c 84 ●●●●● patch | view | raw | blame | history
program/cp_library/test/test_sock_client.c 110 ●●●●● patch | view | raw | blame | history
program/cp_library/test/test_sock_server.c 98 ●●●●● patch | view | raw | blame | history
program/cp_library/test/test_string.c 77 ●●●●● patch | view | raw | blame | history
program/cp_library/test/test_vector.c 67 ●●●●● patch | view | raw | blame | history
program/fwed/etc/default_apn.conf 741 ●●●●● patch | view | raw | blame | history
program/fwed/fwe_entry.c 96 ●●●●● patch | view | raw | blame | history
program/fwed/fwe_entry.h 39 ●●●●● patch | view | raw | blame | history
program/fwed/gpsd/gpsd.c 211 ●●●●● patch | view | raw | blame | history
program/fwed/gpsd/gpsd.h 52 ●●●●● patch | view | raw | blame | history
program/fwed/gpsd/makefile 95 ●●●●● patch | view | raw | blame | history
program/fwed/gpsd/nmea_info.c 195 ●●●●● patch | view | raw | blame | history
program/fwed/gpsd/nmea_info.h 234 ●●●●● patch | view | raw | blame | history
program/fwed/gpsd/nmea_parse.c 681 ●●●●● patch | view | raw | blame | history
program/fwed/gpsd/nmea_parse.h 65 ●●●●● patch | view | raw | blame | history
program/fwed/gsmd/gsmd.c 153 ●●●●● patch | view | raw | blame | history
program/fwed/gsmd/gsmd.h 43 ●●●●● patch | view | raw | blame | history
program/fwed/gsmd/makefile 95 ●●●●● patch | view | raw | blame | history
program/fwed/makefile 201 ●●●●● patch | view | raw | blame | history
program/fwed/zigd/makefile 95 ●●●●● patch | view | raw | blame | history
program/fwed/zigd/zigd.c 152 ●●●●● patch | view | raw | blame | history
program/fwed/zigd/zigd.h 51 ●●●●● patch | view | raw | blame | history
program/serial2socket/thread_mode/cp_comport.c 600 ●●●●● patch | view | raw | blame | history
program/serial2socket/thread_mode/cp_comport.h 67 ●●●●● patch | view | raw | blame | history
program/serial2socket/thread_mode/cp_logger.c 433 ●●●●● patch | view | raw | blame | history
program/serial2socket/thread_mode/cp_logger.h 111 ●●●●● patch | view | raw | blame | history
program/serial2socket/thread_mode/cp_proc.c 342 ●●●●● patch | view | raw | blame | history
program/serial2socket/thread_mode/cp_proc.h 42 ●●●●● patch | view | raw | blame | history
program/serial2socket/thread_mode/cp_socket.c 357 ●●●●● patch | view | raw | blame | history
program/serial2socket/thread_mode/cp_socket.h 65 ●●●●● patch | view | raw | blame | history
program/serial2socket/thread_mode/makefile 70 ●●●●● patch | view | raw | blame | history
program/serial2socket/thread_mode/sp2sck.c 319 ●●●●● patch | view | raw | blame | history
program/serial2socket/thread_mode/sp2sck.h 31 ●●●●● patch | view | raw | blame | history
program/sqlite/build.sh 124 ●●●●● patch | view | raw | blame | history
program/sqlite/makefile 123 ●●●●● patch | view | raw | blame | history
program/sqlite/test_sqlite.c 150 ●●●●● patch | view | raw | blame | history
program/unp/makefile 79 ●●●●● patch | view | raw | blame | history
program/unp/socket_client.c 209 ●●●●● patch | view | raw | blame | history
program/unp/socket_server_select.c 435 ●●●●● patch | view | raw | blame | history
program/unp/socket_server_thread.c 272 ●●●●● patch | view | raw | blame | history
program/unp/test.sh 10 ●●●●● patch | view | raw | blame | history
program/converterd/cp_comport.c
New file
@@ -0,0 +1,600 @@
/*  ********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_comport.c
 *    Description:  It's the comport operate library.
 *
 *        Version:  1.0.0(10/17/2011~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/17/2011 03:33:25 PM"
 *
 ********************************************************************************/
#include    "cp_comport.h"
/**************************************************************************************
 *  Description: Set the comport structure
 *   Input Args: dev_name:  The comport device name path, such as '/dev/ttyS3'
 *               baudrate:  The baudrate, such as 115200
 *               settings:  The databit,parity,stopbit,flowctrl settings, such as '8N1N'
 *  Output Args: NONE
 * Return Value: The COM_PORT structure pointer.
 *************************************************************************************/
COM_PORT *comport_init(const char *dev_name, int baudrate, const char *settings)
{
    COM_PORT *comport = NULL;
    if (NULL == (comport = (COM_PORT *) malloc(sizeof(COM_PORT))))
    {
        return NULL;
    }
    memset(comport, 0, sizeof(COM_PORT));
    comport->is_connted = 0;
    comport->frag_size = 128;
    strncpy(comport->dev_name, dev_name, DEVNAME_LEN);
    comport->baudrate = baudrate;
    set_settings(comport, settings);
#ifdef  COM_DEBUG
    disp_settings(comport);
#endif
    return comport;
}
#ifdef  COM_DEBUG
void disp_settings(COM_PORT * comport)
{
    COM_PRINT("Device:\t\t\t\"%s\"\n", comport->dev_name);
    COM_PRINT("Baudrate:\t\t%ld\n", comport->baudrate);
    COM_PRINT("DataBit:\t\t\'%d\'\n", comport->databit);
    switch (comport->parity)
    {
      case 0:
          COM_PRINT("Parity:\t\t\t\'N\'\n");
          break;
      case 1:
          COM_PRINT("Parity:\t\t\t\'O\'\n");
          break;
      case 2:
          COM_PRINT("Parity:\t\t\t\'E\'\n");
          break;
      case 3:
          COM_PRINT("Parity:\t\t\t\'S\'\n");
          break;
    }
    COM_PRINT("StopBit:\t\t\'%ld\'\n", (long int)comport->stopbit);
    switch (comport->flowctrl)
    {
      case 0:
          COM_PRINT("FlowCtrl:\t\t\'N\'\n");
          break;
      case 1:
          COM_PRINT("FlowCtrl:\t\t\'S\'\n");
          break;
      case 2:
          COM_PRINT("FlowCtrl:\t\t\'H\'\n");
          break;
      case 3:
          COM_PRINT("FlowCtrl:\t\t\'B\'\n");
          break;
    }
    COM_PRINT("\n");
    return;
}
#endif
/**************************************************************************************
 *  Description: Set the comport databit,parity,stopbit,flowctrl
 *   Input Args: comport: the COM_PORT pointer
 *               settings: The databit/parity/stopbit/flowctrl settings as like "8N1N"
 *  Output Args: NONE
 * Return Value: NONE
 *************************************************************************************/
void set_settings(COM_PORT * comport, const char *settings)
{
    if(NULL==settings || NULL==comport)
        return ;
    switch (settings[0])        /* data bit */
    {
      case '7':
          comport->databit = 7;
          break;
      case '8':
      default:
          comport->databit = 8;
          break;
    }
    switch (settings[1])        /* parity */
    {
      case 'O':
      case 'o':
          comport->parity = 1;
          break;
      case 'E':
      case 'e':
          comport->parity = 2;
          break;
      case 'S':
      case 's':
          comport->parity = 3;
          break;
      case 'N':
      case 'n':
      default:
          comport->parity = 0;
          break;
    }
    switch (settings[2])        /* stop bit */
    {
      case '0':
          comport->stopbit = 0;
          break;
      case '1':
      default:
          comport->stopbit = 1;
          break;
    }
    switch (settings[3])        /* flow control */
    {
      case 'S':
      case 's':
          comport->flowctrl = 1;
          break;
      case 'H':
      case 'h':
          comport->flowctrl = 2;
          break;
      case 'B':
      case 'b':
          comport->flowctrl = 3;
          break;
      case 'N':
      case 'n':
      default:
          comport->flowctrl = 0;
          break;
    }
}
void comport_close(COM_PORT * comport)
{
    if (0 != comport->fd)
    {
        COM_PRINT("Close device \"%s\"\n", comport->dev_name);
        close(comport->fd);
    }
    comport->is_connted = 0x00;
    comport->fd = -1;
}
void comport_term(COM_PORT * comport)
{
    if(NULL == comport)
        return;
    if (0 != comport->fd)
    {
        comport_close(comport);
    }
    memset(comport, 0x00, sizeof(COM_PORT));
    free(comport);
    comport = NULL;
    return;
}
int comport_open(COM_PORT * comport)
{
    int retval = -1;
    struct termios old_cfg, new_cfg;
    int old_flags;
    long tmp;
    if(NULL==comport)
        return -1;
    comport_close(comport);
    /* Not a TTY device */
    if( !strstr(comport->dev_name, "tty"))
    {
        COM_PRINT("Open Not tty device \"%s\"\n", comport->dev_name);
        comport->fd = open(comport->dev_name, O_RDWR);
        retval = comport->fd<0 ? -2 : comport->fd;
        goto CleanUp;
    }
    comport->fd = open(comport->dev_name, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (comport->fd < 0)
    {
        retval = -3;
        goto CleanUp;
    }
    COM_PRINT("Open device \"%s\"\n", comport->dev_name);
    if ((-1 != (old_flags = fcntl(comport->fd, F_GETFL, 0)))
        && (-1 != fcntl(comport->fd, F_SETFL, old_flags & ~O_NONBLOCK)))
    {
        // Flush input and output
        if (-1 == tcflush(comport->fd, TCIOFLUSH))
        {
            retval = -4;
            goto CleanUp;
        }
    }
    else                        // Failure
    {
        retval = -5;
        goto CleanUp;
    }
    if (0 != tcgetattr(comport->fd, &old_cfg))
    {
        retval = -6;          // Failed to get Com settings
        goto CleanUp;
    }
    memset(&new_cfg, 0, sizeof(new_cfg));
    /*=====================================*/
    /*       Configure comport         */
    /*=====================================*/
    new_cfg.c_cflag &= ~CSIZE;
    new_cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    new_cfg.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
    new_cfg.c_oflag &= ~(OPOST);
    /* Set the data bit */
    switch (comport->databit)
    {
      case 0x07:
          new_cfg.c_cflag |= CS7;
          break;
      case 0x06:
          new_cfg.c_cflag |= CS6;
          break;
      case 0x05:
          new_cfg.c_cflag |= CS5;
          break;
      default:
          new_cfg.c_cflag |= CS8;
          break;
    }
    /* Set the parity */
    switch (comport->parity)
    {
      case 0x01:               // Odd
          new_cfg.c_cflag |= (PARENB | PARODD);
          new_cfg.c_cflag |= (INPCK | ISTRIP);
          break;
      case 0x02:               // Even
          new_cfg.c_cflag |= PARENB;
          new_cfg.c_cflag &= ~PARODD;;
          new_cfg.c_cflag |= (INPCK | ISTRIP);
          break;
      case 0x03:
          new_cfg.c_cflag &= ~PARENB;
          new_cfg.c_cflag &= ~CSTOPB;
          break;
      default:
          new_cfg.c_cflag &= ~PARENB;
    }
    /* Set Stop bit */
    if (0x01 != comport->stopbit)
    {
        new_cfg.c_cflag |= CSTOPB;
    }
    else
    {
        new_cfg.c_cflag &= ~CSTOPB;
    }
    /* Set flow control */
    switch (comport->flowctrl)
    {
      case 1:                  // Software control
      case 3:
          new_cfg.c_cflag &= ~(CRTSCTS);
          new_cfg.c_iflag |= (IXON | IXOFF);
          break;
      case 2:                  // Hardware control
          new_cfg.c_cflag |= CRTSCTS;   // Also called CRTSCTS
          new_cfg.c_iflag &= ~(IXON | IXOFF);
          break;
      default:                 // NONE
          new_cfg.c_cflag &= ~(CRTSCTS);
          new_cfg.c_iflag &= ~(IXON | IXOFF);
          break;
    }
    /* Set baudrate */
    switch (comport->baudrate)
    {
      case 115200:
          tmp = B115200;
          break;
      case 57600:
          tmp = B57600;
          break;
      case 38400:
          tmp = B38400;
          break;
      case 19200:
          tmp = B19200;
          break;
      case 9600:
          tmp = B9600;
          break;
      case 4800:
          tmp = B4800;
          break;
      case 2400:
          tmp = B2400;
          break;
      case 1800:
          tmp = B1800;
          break;
      case 1200:
          tmp = B1200;
          break;
      case 600:
          tmp = B600;
          break;
      case 300:
          tmp = B300;
          break;
      case 200:
          tmp = B200;
          break;
      case 150:
          tmp = B150;
          break;
      case 134:
          tmp = B134;
          break;
      case 110:
          tmp = B110;
          break;
      case 75:
          tmp = B75;
          break;
      case 50:
          tmp = B50;
          break;
      default:
          tmp = B115200;
    }
    cfsetispeed(&new_cfg, tmp);
    cfsetispeed(&new_cfg, tmp);
    /* Set the Com port timeout settings */
    new_cfg.c_cc[VMIN] = 0;
    new_cfg.c_cc[VTIME] = 0;
    tcflush(comport->fd, TCIFLUSH);
    if (0 != tcsetattr(comport->fd, TCSANOW, &new_cfg))
    {
        retval = -7;          // Failed to set device com port settings
        goto CleanUp;
    }
    COM_PRINT("Connected device \"%s\".\n", comport->dev_name);
    comport->is_connted = 0x01;
    retval = comport->fd;
CleanUp:
    COM_PRINT("Open device \"%s\" %s.\n", comport->dev_name, retval>0 ? "successfully" : "failure");
    return retval;
}
void nonblock()
{
    struct termios ttystate;
    //get the terminal state
    tcgetattr(STDIN_FILENO, &ttystate);
    //turn off canonical mode
    ttystate.c_lflag &= ~ICANON;
    //minimum of number input read.
    ttystate.c_cc[VMIN] = 1;
    //set the terminal attributes.
    tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
}
int kbhit()
{
    struct timeval tv;
    fd_set fds;
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
    select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
    return FD_ISSET(STDIN_FILENO, &fds);
}
int comport_recv(COM_PORT * comport, char *buf, int buf_size, unsigned long timeout)
{
    int retval = 0;             // Function return value
    int iRet;
    fd_set stReadFds, stExcpFds;
    struct timeval stTime;
    if (NULL == buf || 0 >= buf_size)
    {
        COM_PRINT("%s() usage error.\n", __FUNCTION__);
        retval = -1;
        goto CleanUp;
    }
    if (0x01 != comport->is_connted)
    {
        COM_PRINT("%s() comport not connected.\n", __FUNCTION__);
        retval = -2;
        goto CleanUp;
    }
    //printf("bufsize=%d timeout=%lu\n", buf_size, timeout);
    FD_ZERO(&stReadFds);
    FD_ZERO(&stExcpFds);
    FD_SET(comport->fd, &stReadFds);
    FD_SET(comport->fd, &stExcpFds);
    if (0xFFFFFFFF != timeout)
    {
        stTime.tv_sec = (time_t) (timeout / 1000);
        stTime.tv_usec = (long)(1000 * (timeout % 1000));
        iRet = select(comport->fd + 1, &stReadFds, 0, &stExcpFds, &stTime);
        if (0 == iRet)
        {
            retval = 0;         // No data in Com port buffer
            goto CleanUp;
        }
        else if (0 < iRet)
        {
            if (0 != FD_ISSET(comport->fd, &stExcpFds))
            {
                retval = -6;  // Error during checking recv status
                COM_PRINT("Error checking recv status.\n");
                goto CleanUp;
            }
            if (0 == FD_ISSET(comport->fd, &stReadFds))
            {
                retval = 0;  // No incoming data
                COM_PRINT("No incoming data.\n");
                goto CleanUp;
            }
        }
        else
        {
            if (EINTR == errno)
            {
                COM_PRINT("catch interrupt signal.\n");
                retval = 0;  // Interrupted signal catched
            }
            else
            {
                COM_PRINT("Check recv status failure.\n");
                retval = -7;  // Error during checking recv status
            }
            goto CleanUp;
        }
    }
    usleep(10000); /* sleep for 10ms for data incoming */
    // Get data from Com port
    iRet = read(comport->fd, buf, buf_size);
    if (0 > iRet)
    {
        if (EINTR == errno)
            retval = 0;      // Interrupted signal catched
        else
            retval = -3;      // Failed to read Com port
        goto CleanUp;
    }
#if 0
    {
        int   i=0;
        printf("Receive %d bytes data: \n", iRet);
        for(i=0; i<iRet; i++)
        {
            printf("0x%02x ", buf[i]);
        }
        printf("\n");
    }
#endif
    retval = iRet;
  CleanUp:
    return retval;
}
int comport_send(COM_PORT * comport, char *buf, int send_bytes)
{
    char *ptr, *end;
    int retval = 0;
    int send = 0;
    if (NULL == buf || 0 >= send_bytes)
    {
        COM_PRINT("%s() Usage error.\n", __FUNCTION__);
        retval = -1;
        goto CleanUp;
    }
    if (0x01 != comport->is_connted)    // Comport not opened ?
    {
        retval = -3;
        COM_PRINT("Serail not connected.\n");
        goto CleanUp;
    }
    //printf("Send %s with %d bytes.\n", buf, send_bytes);
    // Large data, then slice them and send
    if (comport->frag_size < send_bytes)
    {
        ptr = buf;
        end = buf + send_bytes;
        do
        {
            // Large than frag_size
            if (comport->frag_size < (end - ptr))
            {
                send = write(comport->fd, ptr, comport->frag_size);
                if (0 >= send || comport->frag_size != send)
                {
                    retval = -4;
                    goto CleanUp;
                }
                ptr += comport->frag_size;
            }
            else                // Less than frag_size, maybe last fragmention.
            {
                send = write(comport->fd, ptr, (end - ptr));
                if (0 >= send || (end - ptr) != send)
                {
                    retval = -4;
                    goto CleanUp;
                }
                ptr += (end - ptr);
            }
        }
        while (ptr < end);
    }
    else                        // The send data is not large than a fragmention.
    {
        send = write(comport->fd, buf, send_bytes);
        if (0 >= send || send_bytes != send)
        {
            retval = -5;
            goto CleanUp;
        }
    }
  CleanUp:
    return retval;
}
program/converterd/cp_comport.h
New file
@@ -0,0 +1,67 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_comport.h
 *    Description:  This head file is for the common TTY/Serial port operator library
 *
 *        Version:  1.0.0(10/17/2011~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/17/2011 03:33:25 PM"
 *
 ********************************************************************************/
#ifndef  _CP_COMPORT_H
#define  _CP_COMPORT_H
#include  <stdio.h>
#include  <stdlib.h>
#include  <unistd.h>
#include  <string.h>
#include  <getopt.h>
#include  <fcntl.h>
#include  <errno.h>
#include  <termios.h>
#include  <sys/stat.h>
#include  <sys/wait.h>
#include  <sys/types.h>
#include  <sys/stat.h>
#include  <sys/select.h>
#define BUF_64  64
#ifndef DEVNAME_LEN
#define DEVNAME_LEN          64
#endif
//#define COM_DEBUG
#ifdef  COM_DEBUG
#define COM_PRINT(format,args...) printf(format, ##args)
#else
#define COM_PRINT(format,args...) do{} while(0);
#endif
//#define msleep(m)               {struct timespec cSleep; cSleep.tv_sec = 0; cSleep.tv_nsec = m * 1000; nanosleep(&cSleep, 0);}
typedef struct __COM_PORT
{
    unsigned char databit, parity, stopbit, flowctrl, is_connted;
    char dev_name[DEVNAME_LEN];
    unsigned char  used;     /* This comport used or not now */
    int fd;
    int frag_size;
    long baudrate;
} COM_PORT;
COM_PORT *comport_init(const char *dev_name, int baudrate, const char *settings);
void comport_close(COM_PORT * comport);
int comport_open(COM_PORT * comport);
void comport_term(COM_PORT * comport);
int comport_recv(COM_PORT * comport, char *buf, int buf_size, unsigned long timeout);
int comport_send(COM_PORT * comport, char *buf, int send_bytes);
void set_settings(COM_PORT * comport, const char *settings);
void disp_settings(COM_PORT * comport);
void nonblock();
int kbhit();
#endif
program/converterd/cp_dictionary.c
New file
@@ -0,0 +1,398 @@
/*-------------------------------------------------------------------------*/
/**
   @file    cp_dictionary.c
   @author  N. Devillard
   @brief   Implements a dictionary for string variables.
   This module implements a simple dictionary object, i.e. a list
   of string/string associations. This object is useful to store e.g.
   informations retrieved from a configuration file (ini files).
*/
/*--------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
                                Includes
 ---------------------------------------------------------------------------*/
#include "cp_dictionary.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/** Maximum value size for integers and doubles. */
#define MAXVALSZ    1024
/** Minimal allocated number of entries in a dictionary */
#define DICTMINSZ   128
/** Invalid key token */
#define DICT_INVALID_KEY    ((char*)-1)
/*---------------------------------------------------------------------------
                            Private functions
 ---------------------------------------------------------------------------*/
/* Doubles the allocated size associated to a pointer */
/* 'size' is the current allocated size. */
static void * mem_double(void * ptr, int size)
{
    void * newptr ;
    newptr = calloc(2*size, 1);
    if (newptr==NULL) {
        return NULL ;
    }
    memcpy(newptr, ptr, size);
    free(ptr);
    return newptr ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Duplicate a string
  @param    s String to duplicate
  @return   Pointer to a newly allocated string, to be freed with free()
  This is a replacement for strdup(). This implementation is provided
  for systems that do not have it.
 */
/*--------------------------------------------------------------------------*/
static char * xstrdup(const char * s)
{
    char * t ;
    if (!s)
        return NULL ;
    t = (char*)malloc(strlen(s)+1) ;
    if (t) {
        strcpy(t,s);
    }
    return t ;
}
/*---------------------------------------------------------------------------
                            Function codes
 ---------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/**
  @brief    Compute the hash key for a string.
  @param    key     Character string to use for key.
  @return   1 unsigned int on at least 32 bits.
  This hash function has been taken from an Article in Dr Dobbs Journal.
  This is normally a collision-free function, distributing keys evenly.
  The key is stored anyway in the struct so that collision can be avoided
  by comparing the key itself in last resort.
 */
/*--------------------------------------------------------------------------*/
unsigned dictionary_hash(const char * key)
{
    int         len ;
    unsigned    hash ;
    int         i ;
    len = strlen(key);
    for (hash=0, i=0 ; i<len ; i++) {
        hash += (unsigned)key[i] ;
        hash += (hash<<10);
        hash ^= (hash>>6) ;
    }
    hash += (hash <<3);
    hash ^= (hash >>11);
    hash += (hash <<15);
    return hash ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Create a new dictionary object.
  @param    size    Optional initial size of the dictionary.
  @return   1 newly allocated dictionary objet.
  This function allocates a new dictionary object of given size and returns
  it. If you do not know in advance (roughly) the number of entries in the
  dictionary, give size=0.
 */
/*--------------------------------------------------------------------------*/
dictionary * dictionary_new(int size)
{
    dictionary  *   d ;
    /* If no size was specified, allocate space for DICTMINSZ */
    if (size<DICTMINSZ) size=DICTMINSZ ;
    if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) {
        return NULL;
    }
    d->size = size ;
    d->val  = (char **)calloc(size, sizeof(char*));
    d->key  = (char **)calloc(size, sizeof(char*));
    d->hash = (unsigned int *)calloc(size, sizeof(unsigned));
    return d ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Delete a dictionary object
  @param    d   dictionary object to deallocate.
  @return   void
  Deallocate a dictionary object and all memory associated to it.
 */
/*--------------------------------------------------------------------------*/
void dictionary_del(dictionary * d)
{
    int     i ;
    if (d==NULL) return ;
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]!=NULL)
            free(d->key[i]);
        if (d->val[i]!=NULL)
            free(d->val[i]);
    }
    free(d->val);
    free(d->key);
    free(d->hash);
    free(d);
    return ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get a value from a dictionary.
  @param    d       dictionary object to search.
  @param    key     Key to look for in the dictionary.
  @param    def     Default value to return if key not found.
  @return   1 pointer to internally allocated character string.
  This function locates a key in a dictionary and returns a pointer to its
  value, or the passed 'def' pointer if no such key can be found in
  dictionary. The returned character pointer points to data internal to the
  dictionary object, you should not try to free it or modify it.
 */
/*--------------------------------------------------------------------------*/
char * dictionary_get(dictionary * d, const char * key, char * def)
{
    unsigned    hash ;
    int         i ;
    hash = dictionary_hash(key);
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]==NULL)
            continue ;
        /* Compare hash */
        if (hash==d->hash[i]) {
            /* Compare string, to avoid hash collisions */
            if (!strcmp(key, d->key[i])) {
                return d->val[i] ;
            }
        }
    }
    return def ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Set a value in a dictionary.
  @param    d       dictionary object to modify.
  @param    key     Key to modify or add.
  @param    val     Value to add.
  @return   int     0 if Ok, anything else otherwise
  If the given key is found in the dictionary, the associated value is
  replaced by the provided one. If the key cannot be found in the
  dictionary, it is added to it.
  It is Ok to provide a NULL value for val, but NULL values for the dictionary
  or the key are considered as errors: the function will return immediately
  in such a case.
  Notice that if you dictionary_set a variable to NULL, a call to
  dictionary_get will return a NULL value: the variable will be found, and
  its value (NULL) is returned. In other words, setting the variable
  content to NULL is equivalent to deleting the variable from the
  dictionary. It is not possible (in this implementation) to have a key in
  the dictionary without value.
  This function returns non-zero in case of failure.
 */
/*--------------------------------------------------------------------------*/
int dictionary_set(dictionary * d, const char * key, const char * val)
{
    int         i ;
    unsigned    hash ;
    if (d==NULL || key==NULL) return -1 ;
    /* Compute hash for this key */
    hash = dictionary_hash(key) ;
    /* Find if value is already in dictionary */
    if (d->n>0) {
        for (i=0 ; i<d->size ; i++) {
            if (d->key[i]==NULL)
                continue ;
            if (hash==d->hash[i]) { /* Same hash value */
                if (!strcmp(key, d->key[i])) {   /* Same key */
                    /* Found a value: modify and return */
                    if (d->val[i]!=NULL)
                        free(d->val[i]);
                    d->val[i] = val ? xstrdup(val) : NULL ;
                    /* Value has been modified: return */
                    return 0 ;
                }
            }
        }
    }
    /* Add a new value */
    /* See if dictionary needs to grow */
    if (d->n==d->size) {
        /* Reached maximum size: reallocate dictionary */
        d->val  = (char **)mem_double(d->val,  d->size * sizeof(char*)) ;
        d->key  = (char **)mem_double(d->key,  d->size * sizeof(char*)) ;
        d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ;
        if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) {
            /* Cannot grow dictionary */
            return -1 ;
        }
        /* Double size */
        d->size *= 2 ;
    }
    /* Insert key in the first empty slot. Start at d->n and wrap at
       d->size. Because d->n < d->size this will necessarily
       terminate. */
    for (i=d->n ; d->key[i] ; ) {
        if(++i == d->size) i = 0;
    }
    /* Copy key */
    d->key[i]  = xstrdup(key);
    d->val[i]  = val ? xstrdup(val) : NULL ;
    d->hash[i] = hash;
    d->n ++ ;
    return 0 ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Delete a key in a dictionary
  @param    d       dictionary object to modify.
  @param    key     Key to remove.
  @return   void
  This function deletes a key in a dictionary. Nothing is done if the
  key cannot be found.
 */
/*--------------------------------------------------------------------------*/
void dictionary_unset(dictionary * d, const char * key)
{
    unsigned    hash ;
    int         i ;
    if (key == NULL) {
        return;
    }
    hash = dictionary_hash(key);
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]==NULL)
            continue ;
        /* Compare hash */
        if (hash==d->hash[i]) {
            /* Compare string, to avoid hash collisions */
            if (!strcmp(key, d->key[i])) {
                /* Found key */
                break ;
            }
        }
    }
    if (i>=d->size)
        /* Key not found */
        return ;
    free(d->key[i]);
    d->key[i] = NULL ;
    if (d->val[i]!=NULL) {
        free(d->val[i]);
        d->val[i] = NULL ;
    }
    d->hash[i] = 0 ;
    d->n -- ;
    return ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Dump a dictionary to an opened file pointer.
  @param    d   Dictionary to dump
  @param    f   Opened file pointer.
  @return   void
  Dumps a dictionary onto an opened file pointer. Key pairs are printed out
  as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
  output file pointers.
 */
/*--------------------------------------------------------------------------*/
void dictionary_dump(dictionary * d, FILE * out)
{
    int     i ;
    if (d==NULL || out==NULL) return ;
    if (d->n<1) {
        fprintf(out, "empty dictionary\n");
        return ;
    }
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]) {
            fprintf(out, "%20s\t[%s]\n",
                    d->key[i],
                    d->val[i] ? d->val[i] : "UNDEF");
        }
    }
    return ;
}
/* Test code */
#ifdef TESTDIC
#define NVALS 20000
int main(int argc, char *argv[])
{
    dictionary  *   d ;
    char    *   val ;
    int         i ;
    char        cval[90] ;
    /* Allocate dictionary */
    printf("allocating...\n");
    d = dictionary_new(0);
    /* Set values in dictionary */
    printf("setting %d values...\n", NVALS);
    for (i=0 ; i<NVALS ; i++) {
        sprintf(cval, "%04d", i);
        dictionary_set(d, cval, "salut");
    }
    printf("getting %d values...\n", NVALS);
    for (i=0 ; i<NVALS ; i++) {
        sprintf(cval, "%04d", i);
        val = dictionary_get(d, cval, DICT_INVALID_KEY);
        if (val==DICT_INVALID_KEY) {
            printf("cannot get value for key [%s]\n", cval);
        }
    }
    printf("unsetting %d values...\n", NVALS);
    for (i=0 ; i<NVALS ; i++) {
        sprintf(cval, "%04d", i);
        dictionary_unset(d, cval);
    }
    if (d->n != 0) {
        printf("error deleting values\n");
    }
    printf("deallocating...\n");
    dictionary_del(d);
    return 0 ;
}
#endif
/* vim: set ts=4 et sw=4 tw=75 */
program/converterd/cp_dictionary.h
New file
@@ -0,0 +1,165 @@
/*-------------------------------------------------------------------------*/
/**
   @file    cp_dictionary.h
   @author  N. Devillard
   @brief   Implements a dictionary for string variables.
   This module implements a simple dictionary object, i.e. a list
   of string/string associations. This object is useful to store e.g.
   informations retrieved from a configuration file (ini files).
*/
/*--------------------------------------------------------------------------*/
#ifndef _CP_DICTIONARY_H_
#define _CP_DICTIONARY_H_
/*---------------------------------------------------------------------------
                                Includes
 ---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/*---------------------------------------------------------------------------
                                New types
 ---------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/**
  @brief    Dictionary object
  This object contains a list of string/string associations. Each
  association is identified by a unique string key. Looking up values
  in the dictionary is speeded up by the use of a (hopefully collision-free)
  hash function.
 */
/*-------------------------------------------------------------------------*/
typedef struct _dictionary_ {
    int             n ;     /** Number of entries in dictionary */
    int             size ;  /** Storage size */
    char        **  val ;   /** List of string values */
    char        **  key ;   /** List of string keys */
    unsigned     *  hash ;  /** List of hash values for keys */
} dictionary ;
/*---------------------------------------------------------------------------
                            Function prototypes
 ---------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/**
  @brief    Compute the hash key for a string.
  @param    key     Character string to use for key.
  @return   1 unsigned int on at least 32 bits.
  This hash function has been taken from an Article in Dr Dobbs Journal.
  This is normally a collision-free function, distributing keys evenly.
  The key is stored anyway in the struct so that collision can be avoided
  by comparing the key itself in last resort.
 */
/*--------------------------------------------------------------------------*/
unsigned dictionary_hash(const char * key);
/*-------------------------------------------------------------------------*/
/**
  @brief    Create a new dictionary object.
  @param    size    Optional initial size of the dictionary.
  @return   1 newly allocated dictionary objet.
  This function allocates a new dictionary object of given size and returns
  it. If you do not know in advance (roughly) the number of entries in the
  dictionary, give size=0.
 */
/*--------------------------------------------------------------------------*/
dictionary * dictionary_new(int size);
/*-------------------------------------------------------------------------*/
/**
  @brief    Delete a dictionary object
  @param    d   dictionary object to deallocate.
  @return   void
  Deallocate a dictionary object and all memory associated to it.
 */
/*--------------------------------------------------------------------------*/
void dictionary_del(dictionary * vd);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get a value from a dictionary.
  @param    d       dictionary object to search.
  @param    key     Key to look for in the dictionary.
  @param    def     Default value to return if key not found.
  @return   1 pointer to internally allocated character string.
  This function locates a key in a dictionary and returns a pointer to its
  value, or the passed 'def' pointer if no such key can be found in
  dictionary. The returned character pointer points to data internal to the
  dictionary object, you should not try to free it or modify it.
 */
/*--------------------------------------------------------------------------*/
char * dictionary_get(dictionary * d, const char * key, char * def);
/*-------------------------------------------------------------------------*/
/**
  @brief    Set a value in a dictionary.
  @param    d       dictionary object to modify.
  @param    key     Key to modify or add.
  @param    val     Value to add.
  @return   int     0 if Ok, anything else otherwise
  If the given key is found in the dictionary, the associated value is
  replaced by the provided one. If the key cannot be found in the
  dictionary, it is added to it.
  It is Ok to provide a NULL value for val, but NULL values for the dictionary
  or the key are considered as errors: the function will return immediately
  in such a case.
  Notice that if you dictionary_set a variable to NULL, a call to
  dictionary_get will return a NULL value: the variable will be found, and
  its value (NULL) is returned. In other words, setting the variable
  content to NULL is equivalent to deleting the variable from the
  dictionary. It is not possible (in this implementation) to have a key in
  the dictionary without value.
  This function returns non-zero in case of failure.
 */
/*--------------------------------------------------------------------------*/
int dictionary_set(dictionary * vd, const char * key, const char * val);
/*-------------------------------------------------------------------------*/
/**
  @brief    Delete a key in a dictionary
  @param    d       dictionary object to modify.
  @param    key     Key to remove.
  @return   void
  This function deletes a key in a dictionary. Nothing is done if the
  key cannot be found.
 */
/*--------------------------------------------------------------------------*/
void dictionary_unset(dictionary * d, const char * key);
/*-------------------------------------------------------------------------*/
/**
  @brief    Dump a dictionary to an opened file pointer.
  @param    d   Dictionary to dump
  @param    f   Opened file pointer.
  @return   void
  Dumps a dictionary onto an opened file pointer. Key pairs are printed out
  as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
  output file pointers.
 */
/*--------------------------------------------------------------------------*/
void dictionary_dump(dictionary * d, FILE * out);
#endif
program/converterd/cp_iniparser.c
New file
@@ -0,0 +1,807 @@
/*-------------------------------------------------------------------------*/
/**
   @file    cp_iniparser.c
   @author  N. Devillard
   @brief   Parser for ini files.
*/
/*--------------------------------------------------------------------------*/
/*---------------------------- Includes ------------------------------------*/
#include <ctype.h>
#include "cp_iniparser.h"
/*---------------------------- Defines -------------------------------------*/
#define ASCIILINESZ         (1024)
#define INI_INVALID_KEY     ((char*)-1)
/*---------------------------------------------------------------------------
                        Private to this module
 ---------------------------------------------------------------------------*/
/**
 * This enum stores the status for each parsed line (internal use only).
 */
typedef enum _line_status_ {
    LINE_UNPROCESSED,
    LINE_ERROR,
    LINE_EMPTY,
    LINE_COMMENT,
    LINE_SECTION,
    LINE_VALUE
} line_status ;
/*-------------------------------------------------------------------------*/
/**
  @brief    Convert a string to lowercase.
  @param    s   String to convert.
  @return   ptr to statically allocated string.
  This function returns a pointer to a statically allocated string
  containing a lowercased version of the input string. Do not free
  or modify the returned string! Since the returned string is statically
  allocated, it will be modified at each function call (not re-entrant).
 */
/*--------------------------------------------------------------------------*/
static char * strlwc(const char * s)
{
    static char l[ASCIILINESZ+1];
    int i ;
    if (s==NULL) return NULL ;
    memset(l, 0, ASCIILINESZ+1);
    i=0 ;
    while (s[i] && i<ASCIILINESZ) {
        l[i] = (char)tolower((int)s[i]);
        i++ ;
    }
    l[ASCIILINESZ]=(char)0;
    return l ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Remove blanks at the beginning and the end of a string.
  @param    s   String to parse.
  @return   ptr to statically allocated string.
  This function returns a pointer to a statically allocated string,
  which is identical to the input string, except that all blank
  characters at the end and the beg. of the string have been removed.
  Do not free or modify the returned string! Since the returned string
  is statically allocated, it will be modified at each function call
  (not re-entrant).
 */
/*--------------------------------------------------------------------------*/
static char * strstrip(const char * s)
{
    static char l[ASCIILINESZ+1];
    char * last ;
    if (s==NULL) return NULL ;
    while (isspace((int)*s) && *s) s++;
    memset(l, 0, ASCIILINESZ+1);
    strcpy(l, s);
    last = l + strlen(l);
    while (last > l) {
        if (!isspace((int)*(last-1)))
            break ;
        last -- ;
    }
    *last = (char)0;
    return (char*)l ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get number of sections in a dictionary
  @param    d   Dictionary to examine
  @return   int Number of sections found in dictionary
  This function returns the number of sections found in a dictionary.
  The test to recognize sections is done on the string stored in the
  dictionary: a section name is given as "section" whereas a key is
  stored as "section:key", thus the test looks for entries that do not
  contain a colon.
  This clearly fails in the case a section name contains a colon, but
  this should simply be avoided.
  This function returns -1 in case of error.
 */
/*--------------------------------------------------------------------------*/
int iniparser_getnsec(dictionary * d)
{
    int i ;
    int nsec ;
    if (d==NULL) return -1 ;
    nsec=0 ;
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]==NULL)
            continue ;
        if (strchr(d->key[i], ':')==NULL) {
            nsec ++ ;
        }
    }
    return nsec ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get name for section n in a dictionary.
  @param    d   Dictionary to examine
  @param    n   Section number (from 0 to nsec-1).
  @return   Pointer to char string
  This function locates the n-th section in a dictionary and returns
  its name as a pointer to a string statically allocated inside the
  dictionary. Do not free or modify the returned string!
  This function returns NULL in case of error.
 */
/*--------------------------------------------------------------------------*/
char * iniparser_getsecname(dictionary * d, int n)
{
    int i ;
    int foundsec ;
    if (d==NULL || n<0) return NULL ;
    foundsec=0 ;
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]==NULL)
            continue ;
        if (strchr(d->key[i], ':')==NULL) {
            foundsec++ ;
            if (foundsec>n)
                break ;
        }
    }
    if (foundsec<=n) {
        return NULL ;
    }
    return d->key[i] ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Dump a dictionary to an opened file pointer.
  @param    d   Dictionary to dump.
  @param    f   Opened file pointer to dump to.
  @return   void
  This function prints out the contents of a dictionary, one element by
  line, onto the provided file pointer. It is OK to specify @c stderr
  or @c stdout as output files. This function is meant for debugging
  purposes mostly.
 */
/*--------------------------------------------------------------------------*/
void iniparser_dump(dictionary * d, FILE * f)
{
    int     i ;
    if (d==NULL || f==NULL) return ;
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]==NULL)
            continue ;
        if (d->val[i]!=NULL) {
            fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
        } else {
            fprintf(f, "[%s]=UNDEF\n", d->key[i]);
        }
    }
    return ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Save a dictionary to a loadable ini file
  @param    d   Dictionary to dump
  @param    f   Opened file pointer to dump to
  @return   void
  This function dumps a given dictionary into a loadable ini file.
  It is Ok to specify @c stderr or @c stdout as output files.
 */
/*--------------------------------------------------------------------------*/
void iniparser_dump_ini(dictionary * d, FILE * f)
{
    int     i ;
    int     nsec ;
    char *  secname ;
    if (d==NULL || f==NULL) return ;
    nsec = iniparser_getnsec(d);
    if (nsec<1) {
        /* No section in file: dump all keys as they are */
        for (i=0 ; i<d->size ; i++) {
            if (d->key[i]==NULL)
                continue ;
            fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
        }
        return ;
    }
    for (i=0 ; i<nsec ; i++) {
        secname = iniparser_getsecname(d, i) ;
        iniparser_dumpsection_ini(d, secname, f) ;
    }
    fprintf(f, "\n");
    return ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Save a dictionary section to a loadable ini file
  @param    d   Dictionary to dump
  @param    s   Section name of dictionary to dump
  @param    f   Opened file pointer to dump to
  @return   void
  This function dumps a given section of a given dictionary into a loadable ini
  file.  It is Ok to specify @c stderr or @c stdout as output files.
 */
/*--------------------------------------------------------------------------*/
void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f)
{
    int     j ;
    char    keym[ASCIILINESZ+1];
    int     seclen ;
    if (d==NULL || f==NULL) return ;
    if (! iniparser_find_entry(d, s)) return ;
    seclen  = (int)strlen(s);
    fprintf(f, "\n[%s]\n", s);
    sprintf(keym, "%s:", s);
    for (j=0 ; j<d->size ; j++) {
        if (d->key[j]==NULL)
            continue ;
        if (!strncmp(d->key[j], keym, seclen+1)) {
            fprintf(f,
                    "%-30s = %s\n",
                    d->key[j]+seclen+1,
                    d->val[j] ? d->val[j] : "");
        }
    }
    fprintf(f, "\n");
    return ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the number of keys in a section of a dictionary.
  @param    d   Dictionary to examine
  @param    s   Section name of dictionary to examine
  @return   Number of keys in section
 */
/*--------------------------------------------------------------------------*/
int iniparser_getsecnkeys(dictionary * d, char * s)
{
    int     seclen, nkeys ;
    char    keym[ASCIILINESZ+1];
    int j ;
    nkeys = 0;
    if (d==NULL) return nkeys;
    if (! iniparser_find_entry(d, s)) return nkeys;
    seclen  = (int)strlen(s);
    sprintf(keym, "%s:", s);
    for (j=0 ; j<d->size ; j++) {
        if (d->key[j]==NULL)
            continue ;
        if (!strncmp(d->key[j], keym, seclen+1))
            nkeys++;
    }
    return nkeys;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the number of keys in a section of a dictionary.
  @param    d   Dictionary to examine
  @param    s   Section name of dictionary to examine
  @return   pointer to statically allocated character strings
  This function queries a dictionary and finds all keys in a given section.
  Each pointer in the returned char pointer-to-pointer is pointing to
  a string allocated in the dictionary; do not free or modify them.
  This function returns NULL in case of error.
 */
/*--------------------------------------------------------------------------*/
char ** iniparser_getseckeys(dictionary * d, char * s)
{
    char **keys;
    int i, j ;
    char    keym[ASCIILINESZ+1];
    int     seclen, nkeys ;
    keys = NULL;
    if (d==NULL) return keys;
    if (! iniparser_find_entry(d, s)) return keys;
    nkeys = iniparser_getsecnkeys(d, s);
    keys = (char**) malloc(nkeys*sizeof(char*));
    seclen  = (int)strlen(s);
    sprintf(keym, "%s:", s);
    i = 0;
    for (j=0 ; j<d->size ; j++) {
        if (d->key[j]==NULL)
            continue ;
        if (!strncmp(d->key[j], keym, seclen+1)) {
            keys[i] = d->key[j];
            i++;
        }
    }
    return keys;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key
  @param    d       Dictionary to search
  @param    key     Key string to look for
  @param    def     Default value to return if key not found.
  @return   pointer to statically allocated character string
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the pointer passed as 'def' is returned.
  The returned char pointer is pointing to a string allocated in
  the dictionary, do not free or modify it.
 */
/*--------------------------------------------------------------------------*/
char * iniparser_getstring(dictionary * d, const char * key, char * def)
{
    char * lc_key ;
    char * sval ;
    if (d==NULL || key==NULL)
        return def ;
    lc_key = strlwc(key);
    sval = dictionary_get(d, lc_key, def);
    return sval ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key, convert to an int
  @param    d Dictionary to search
  @param    key Key string to look for
  @param    notfound Value to return in case of error
  @return   integer
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the notfound value is returned.
  Supported values for integers include the usual C notation
  so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
  are supported. Examples:
  "42"      ->  42
  "042"     ->  34 (octal -> decimal)
  "0x42"    ->  66 (hexa  -> decimal)
  Warning: the conversion may overflow in various ways. Conversion is
  totally outsourced to strtol(), see the associated man page for overflow
  handling.
  Credits: Thanks to A. Becker for suggesting strtol()
 */
/*--------------------------------------------------------------------------*/
int iniparser_getint(dictionary * d, const char * key, int notfound)
{
    char    *   str ;
    str = iniparser_getstring(d, key, INI_INVALID_KEY);
    if (str==INI_INVALID_KEY) return notfound ;
    return (int)strtol(str, NULL, 0);
}
int iniparser_getlong(dictionary * d, const char * key, int notfound)
{
    char    *   str ;
    str = iniparser_getstring(d, key, INI_INVALID_KEY);
    if (str==INI_INVALID_KEY) return notfound ;
    return strtol(str, NULL, 0);
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key, convert to a double
  @param    d Dictionary to search
  @param    key Key string to look for
  @param    notfound Value to return in case of error
  @return   double
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the notfound value is returned.
 */
/*--------------------------------------------------------------------------*/
double iniparser_getdouble(dictionary * d, const char * key, double notfound)
{
    char    *   str ;
    str = iniparser_getstring(d, key, INI_INVALID_KEY);
    if (str==INI_INVALID_KEY) return notfound ;
    return atof(str);
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key, convert to a boolean
  @param    d Dictionary to search
  @param    key Key string to look for
  @param    notfound Value to return in case of error
  @return   integer
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the notfound value is returned.
  A true boolean is found if one of the following is matched:
  - A string starting with 'y'
  - A string starting with 'Y'
  - A string starting with 't'
  - A string starting with 'T'
  - A string starting with '1'
  A false boolean is found if one of the following is matched:
  - A string starting with 'n'
  - A string starting with 'N'
  - A string starting with 'f'
  - A string starting with 'F'
  - A string starting with '0'
  The notfound value returned if no boolean is identified, does not
  necessarily have to be 0 or 1.
 */
/*--------------------------------------------------------------------------*/
int iniparser_getboolean(dictionary * d, const char * key, int notfound)
{
    char    *   c ;
    int         ret ;
    c = iniparser_getstring(d, key, INI_INVALID_KEY);
    if (c==INI_INVALID_KEY) return notfound ;
    if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
        ret = 1 ;
    } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
        ret = 0 ;
    } else {
        ret = notfound ;
    }
    return ret;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Finds out if a given entry exists in a dictionary
  @param    ini     Dictionary to search
  @param    entry   Name of the entry to look for
  @return   integer 1 if entry exists, 0 otherwise
  Finds out if a given entry exists in the dictionary. Since sections
  are stored as keys with NULL associated values, this is the only way
  of querying for the presence of sections in a dictionary.
 */
/*--------------------------------------------------------------------------*/
int iniparser_find_entry(
    dictionary  *   ini,
    const char  *   entry
)
{
    int found=0 ;
    if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
        found = 1 ;
    }
    return found ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Set an entry in a dictionary.
  @param    ini     Dictionary to modify.
  @param    entry   Entry to modify (entry name)
  @param    val     New value to associate to the entry.
  @return   int 0 if Ok, -1 otherwise.
  If the given entry can be found in the dictionary, it is modified to
  contain the provided value. If it cannot be found, -1 is returned.
  It is Ok to set val to NULL.
 */
/*--------------------------------------------------------------------------*/
int iniparser_set(dictionary * ini, const char * entry, const char * val)
{
    return dictionary_set(ini, strlwc(entry), val) ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Delete an entry in a dictionary
  @param    ini     Dictionary to modify
  @param    entry   Entry to delete (entry name)
  @return   void
  If the given entry can be found, it is deleted from the dictionary.
 */
/*--------------------------------------------------------------------------*/
void iniparser_unset(dictionary * ini, const char * entry)
{
    dictionary_unset(ini, strlwc(entry));
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Load a single line from an INI file
  @param    input_line  Input line, may be concatenated multi-line input
  @param    section     Output space to store section
  @param    key         Output space to store key
  @param    value       Output space to store value
  @return   line_status value
 */
/*--------------------------------------------------------------------------*/
static line_status iniparser_line(
    char * input_line,
    char * section,
    char * key,
    char * value)
{
    line_status sta ;
    char        line[ASCIILINESZ+1];
    static char left_line[ASCIILINESZ+1];
    int         len, offset ;
    strcpy(line, strstrip(input_line));
    len = (int)strlen(line);
    sta = LINE_UNPROCESSED ;
    if (len<1) {
        /* Empty line */
        sta = LINE_EMPTY ;
        memset(input_line, 0, len);
    } else if (line[0]=='#' || line[0]==';') {
        /* Comment line */
        sta = LINE_COMMENT ;
        memset(input_line, 0, len);
    } else if (line[0]=='[') {
        /* Section name */
        sscanf(line, "[%[^]]", section);
        strcpy(section, strstrip(section));
        strcpy(section, strlwc(section));
        /* Left configure will go to next time to parser */
        offset = strlen(section) + 2;
        strcpy( left_line, strstrip(&(line[offset])) );
        strcpy( left_line, strstrip(left_line));
        if( strlen(left_line) > 0)
        {
            strcpy(input_line, left_line);
            strcat(input_line, "\n");
        }
        else
        {
            memset(input_line, 0, len);
        }
        sta = LINE_SECTION ;
    } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
           ||  sscanf (line, "%[^=] = '%[^\']'",   key, value) == 2
           ||  sscanf (line, "%[^=] = %[^;#]",     key, value) == 2) {
        char      *ptr = NULL;
        /* Usual key=value, with or without comments */
        strcpy(key, strstrip(key));
        strcpy(key, strlwc(key));
        strcpy(value, strstrip(value));
        /*
         * sscanf cannot handle '' or "" as empty values
         * this is done here
         */
        if (!strncmp(value, "\"\"", 2) || (!strncmp(value, "''", 2)) ) {
            value[0]=0 ;
        }
        ptr = strchr(line, '=');
        if('\''==*(ptr+1) || '\"'==*(ptr+1))
        {
            offset = strlen(key)+strlen(value) + 1 + 2; /* Skip $key='$val' */
        }
        else
        {
            offset = strlen(key)+strlen(value) + 1; /* Skip $key=$val */
        }
        strcpy( left_line, strstrip(&(line[offset])) );
        if( strlen(left_line) > 0)
        {
            strcpy(input_line, left_line);
            strcat(input_line, "\n");
        }
        else
        {
            memset(input_line, 0, len);
        }
        sta = LINE_VALUE ;
    } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2
           ||  sscanf(line, "%[^=] %[=]", key, value) == 2) {
        /*
         * Special cases:
         * key=
         * key=;
         * key=#
         */
        strcpy(key, strstrip(key));
        strcpy(key, strlwc(key));
        value[0]=0 ;
        sta = LINE_VALUE ;
    } else {
        /* Generate syntax error */
        sta = LINE_ERROR ;
        memset(input_line, 0, len);
    }
    return sta ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Parse an ini file and return an allocated dictionary object
  @param    ininame Name of the ini file to read.
  @return   Pointer to newly allocated dictionary
  This is the parser for ini files. This function is called, providing
  the name of the file to be read. It returns a dictionary object that
  should not be accessed directly, but through accessor functions
  instead.
  The returned dictionary must be freed using iniparser_freedict().
 */
/*--------------------------------------------------------------------------*/
dictionary * iniparser_load(const char * ininame)
{
    FILE * in ;
    char line    [ASCIILINESZ+1] ;
    char section [ASCIILINESZ+1] ;
    char key     [ASCIILINESZ+1] ;
    char tmp     [ASCIILINESZ+1] ;
    char val     [ASCIILINESZ+1] ;
    int  last=0 ;
    int  len ;
    int  lineno=0 ;
    int  errs=0;
    dictionary * dict ;
    if ((in=fopen(ininame, "r"))==NULL) {
        fprintf(stderr, "iniparser: cannot open %s\n", ininame);
        return NULL ;
    }
    dict = dictionary_new(0) ;
    if (!dict) {
        fclose(in);
        return NULL ;
    }
    memset(line,    0, ASCIILINESZ);
    memset(section, 0, ASCIILINESZ);
    memset(key,     0, ASCIILINESZ);
    memset(val,     0, ASCIILINESZ);
    last=0 ;
    while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
        lineno++ ;
CONTINUE_PARSER:
        len = (int)strlen(line)-1;
        if (len==0)
            continue;
        /* Safety check against buffer overflows */
        if (line[len]!='\n') {
            fprintf(stderr,
                    "iniparser: input line too long in %s (%d)\n",
                    ininame,
                    lineno);
            dictionary_del(dict);
            fclose(in);
            return NULL ;
        }
        /* Get rid of \n and spaces at end of line */
        while ((len>=0) &&
                ((line[len]=='\n') || (isspace(line[len])))) {
            line[len]=0 ;
            len-- ;
        }
        /* Detect multi-line */
        if (line[len]=='\\') {
            /* Multi-line value */
            last=len ;
            continue ;
        } else {
            last=0 ;
        }
        switch ( iniparser_line(line, section, key, val) ) {
            case LINE_EMPTY:
            case LINE_COMMENT:
            break ;
            case LINE_SECTION:
            errs = dictionary_set(dict, section, NULL);
            break ;
            case LINE_VALUE:
            sprintf(tmp, "%s:%s", section, key);
            errs = dictionary_set(dict, tmp, val) ;
            break ;
            case LINE_ERROR:
            fprintf(stderr, "iniparser: syntax error in %s (%d):\n",
                    ininame,
                    lineno);
            fprintf(stderr, "-> %s\n", line);
            errs++ ;
            break;
            default:
            break ;
        }
        if( strlen(line) > 0)
        {
            goto CONTINUE_PARSER;
        }
        memset(line, 0, ASCIILINESZ);
        last=0;
        if (errs<0) {
            fprintf(stderr, "iniparser: memory allocation failure\n");
            break ;
        }
    }
    if (errs) {
        dictionary_del(dict);
        dict = NULL ;
    }
    fclose(in);
    return dict ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Free all memory associated to an ini dictionary
  @param    d Dictionary to free
  @return   void
  Free all memory associated to an ini dictionary.
  It is mandatory to call this function before the dictionary object
  gets out of the current context.
 */
/*--------------------------------------------------------------------------*/
void iniparser_freedict(dictionary * d)
{
    dictionary_del(d);
}
/* vim: set ts=4 et sw=4 tw=75 */
program/converterd/cp_iniparser.h
New file
@@ -0,0 +1,308 @@
/*-------------------------------------------------------------------------*/
/**
   @file    cp_iniparser.h
   @author  N. Devillard
   @brief   Parser for ini files.
*/
/*--------------------------------------------------------------------------*/
#ifndef _CP_INIPARSER_H_
#define _CP_INIPARSER_H_
/*---------------------------------------------------------------------------
                                Includes
 ---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
 * The following #include is necessary on many Unixes but not Linux.
 * It is not needed for Windows platforms.
 * Uncomment it if needed.
 */
/* #include <unistd.h> */
#include "cp_dictionary.h"
/*-------------------------------------------------------------------------*/
/**
  @brief    Get number of sections in a dictionary
  @param    d   Dictionary to examine
  @return   int Number of sections found in dictionary
  This function returns the number of sections found in a dictionary.
  The test to recognize sections is done on the string stored in the
  dictionary: a section name is given as "section" whereas a key is
  stored as "section:key", thus the test looks for entries that do not
  contain a colon.
  This clearly fails in the case a section name contains a colon, but
  this should simply be avoided.
  This function returns -1 in case of error.
 */
/*--------------------------------------------------------------------------*/
int iniparser_getnsec(dictionary * d);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get name for section n in a dictionary.
  @param    d   Dictionary to examine
  @param    n   Section number (from 0 to nsec-1).
  @return   Pointer to char string
  This function locates the n-th section in a dictionary and returns
  its name as a pointer to a string statically allocated inside the
  dictionary. Do not free or modify the returned string!
  This function returns NULL in case of error.
 */
/*--------------------------------------------------------------------------*/
char * iniparser_getsecname(dictionary * d, int n);
/*-------------------------------------------------------------------------*/
/**
  @brief    Save a dictionary to a loadable ini file
  @param    d   Dictionary to dump
  @param    f   Opened file pointer to dump to
  @return   void
  This function dumps a given dictionary into a loadable ini file.
  It is Ok to specify @c stderr or @c stdout as output files.
 */
/*--------------------------------------------------------------------------*/
void iniparser_dump_ini(dictionary * d, FILE * f);
/*-------------------------------------------------------------------------*/
/**
  @brief    Save a dictionary section to a loadable ini file
  @param    d   Dictionary to dump
  @param    s   Section name of dictionary to dump
  @param    f   Opened file pointer to dump to
  @return   void
  This function dumps a given section of a given dictionary into a loadable ini
  file.  It is Ok to specify @c stderr or @c stdout as output files.
 */
/*--------------------------------------------------------------------------*/
void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f);
/*-------------------------------------------------------------------------*/
/**
  @brief    Dump a dictionary to an opened file pointer.
  @param    d   Dictionary to dump.
  @param    f   Opened file pointer to dump to.
  @return   void
  This function prints out the contents of a dictionary, one element by
  line, onto the provided file pointer. It is OK to specify @c stderr
  or @c stdout as output files. This function is meant for debugging
  purposes mostly.
 */
/*--------------------------------------------------------------------------*/
void iniparser_dump(dictionary * d, FILE * f);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the number of keys in a section of a dictionary.
  @param    d   Dictionary to examine
  @param    s   Section name of dictionary to examine
  @return   Number of keys in section
 */
/*--------------------------------------------------------------------------*/
int iniparser_getsecnkeys(dictionary * d, char * s);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the number of keys in a section of a dictionary.
  @param    d   Dictionary to examine
  @param    s   Section name of dictionary to examine
  @return   pointer to statically allocated character strings
  This function queries a dictionary and finds all keys in a given section.
  Each pointer in the returned char pointer-to-pointer is pointing to
  a string allocated in the dictionary; do not free or modify them.
  This function returns NULL in case of error.
 */
/*--------------------------------------------------------------------------*/
char ** iniparser_getseckeys(dictionary * d, char * s);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key
  @param    d       Dictionary to search
  @param    key     Key string to look for
  @param    def     Default value to return if key not found.
  @return   pointer to statically allocated character string
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the pointer passed as 'def' is returned.
  The returned char pointer is pointing to a string allocated in
  the dictionary, do not free or modify it.
 */
/*--------------------------------------------------------------------------*/
char * iniparser_getstring(dictionary * d, const char * key, char * def);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key, convert to an int
  @param    d Dictionary to search
  @param    key Key string to look for
  @param    notfound Value to return in case of error
  @return   integer
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the notfound value is returned.
  Supported values for integers include the usual C notation
  so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
  are supported. Examples:
  - "42"      ->  42
  - "042"     ->  34 (octal -> decimal)
  - "0x42"    ->  66 (hexa  -> decimal)
  Warning: the conversion may overflow in various ways. Conversion is
  totally outsourced to strtol(), see the associated man page for overflow
  handling.
  Credits: Thanks to A. Becker for suggesting strtol()
 */
/*--------------------------------------------------------------------------*/
int iniparser_getint(dictionary * d, const char * key, int notfound);
int iniparser_getlong(dictionary * d, const char * key, int notfound);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key, convert to a double
  @param    d Dictionary to search
  @param    key Key string to look for
  @param    notfound Value to return in case of error
  @return   double
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the notfound value is returned.
 */
/*--------------------------------------------------------------------------*/
double iniparser_getdouble(dictionary * d, const char * key, double notfound);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key, convert to a boolean
  @param    d Dictionary to search
  @param    key Key string to look for
  @param    notfound Value to return in case of error
  @return   integer
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the notfound value is returned.
  A true boolean is found if one of the following is matched:
  - A string starting with 'y'
  - A string starting with 'Y'
  - A string starting with 't'
  - A string starting with 'T'
  - A string starting with '1'
  A false boolean is found if one of the following is matched:
  - A string starting with 'n'
  - A string starting with 'N'
  - A string starting with 'f'
  - A string starting with 'F'
  - A string starting with '0'
  The notfound value returned if no boolean is identified, does not
  necessarily have to be 0 or 1.
 */
/*--------------------------------------------------------------------------*/
int iniparser_getboolean(dictionary * d, const char * key, int notfound);
/*-------------------------------------------------------------------------*/
/**
  @brief    Set an entry in a dictionary.
  @param    ini     Dictionary to modify.
  @param    entry   Entry to modify (entry name)
  @param    val     New value to associate to the entry.
  @return   int 0 if Ok, -1 otherwise.
  If the given entry can be found in the dictionary, it is modified to
  contain the provided value. If it cannot be found, -1 is returned.
  It is Ok to set val to NULL.
 */
/*--------------------------------------------------------------------------*/
int iniparser_set(dictionary * ini, const char * entry, const char * val);
/*-------------------------------------------------------------------------*/
/**
  @brief    Delete an entry in a dictionary
  @param    ini     Dictionary to modify
  @param    entry   Entry to delete (entry name)
  @return   void
  If the given entry can be found, it is deleted from the dictionary.
 */
/*--------------------------------------------------------------------------*/
void iniparser_unset(dictionary * ini, const char * entry);
/*-------------------------------------------------------------------------*/
/**
  @brief    Finds out if a given entry exists in a dictionary
  @param    ini     Dictionary to search
  @param    entry   Name of the entry to look for
  @return   integer 1 if entry exists, 0 otherwise
  Finds out if a given entry exists in the dictionary. Since sections
  are stored as keys with NULL associated values, this is the only way
  of querying for the presence of sections in a dictionary.
 */
/*--------------------------------------------------------------------------*/
int iniparser_find_entry(dictionary * ini, const char * entry) ;
/*-------------------------------------------------------------------------*/
/**
  @brief    Parse an ini file and return an allocated dictionary object
  @param    ininame Name of the ini file to read.
  @return   Pointer to newly allocated dictionary
  This is the parser for ini files. This function is called, providing
  the name of the file to be read. It returns a dictionary object that
  should not be accessed directly, but through accessor functions
  instead.
  The returned dictionary must be freed using iniparser_freedict().
 */
/*--------------------------------------------------------------------------*/
dictionary * iniparser_load(const char * ininame);
/*-------------------------------------------------------------------------*/
/**
  @brief    Free all memory associated to an ini dictionary
  @param    d Dictionary to free
  @return   void
  Free all memory associated to an ini dictionary.
  It is mandatory to call this function before the dictionary object
  gets out of the current context.
 */
/*--------------------------------------------------------------------------*/
void iniparser_freedict(dictionary * d);
#endif
program/converterd/cp_logger.c
New file
@@ -0,0 +1,433 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_log.c
 *    Description:  This file is the linux infrastructural logger system library
 *
 *        Version:  1.0.0(08/08/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "08/08/2012 04:24:01 PM"
 *
 ********************************************************************************/
#include "cp_logger.h"
//#include "cp_common.h"
#define PRECISE_TIME_FACTOR 1000
static unsigned long log_rollback_size = LOG_ROLLBACK_NONE;
static cp_logger *logger = NULL;
char *log_str[LOG_LEVEL_MAX + 1] = { "", "F", "E", "W", "N", "D", "I", "T", "M" };
static char *cp_time_format = DEFAULT_TIME_FORMAT;
void cp_log_set_time_format(char *time_format)
{
    cp_time_format = time_format;
}
static void cp_log_default_signal_handler(int sig)
{
    if(!logger)
        return ;
    if (sig == SIGHUP)
    {
        signal(SIGHUP, cp_log_default_signal_handler);
        log_fatal("SIGHUP received - reopenning log file [%s]", logger->file);
        cp_log_reopen();
    }
}
static void log_banner(char *prefix)
{
    if(!logger)
        return ;
    fprintf(logger->fp, "%s log \"%s\" on level [%s] size [%lu] KiB, log system version %s\n",
            prefix, logger->file, log_str[logger->level], log_rollback_size / 1024, LOG_VERSION_STR);
#ifdef LOG_FILE_LINE
    fprintf(logger->fp, " [Date]    [Time]   [Level] [PID/TID] [File/Line]  [Content]\n");
#else
    fprintf(logger->fp, " [Date]    [Time]   [Level] [PID/TID] [Content]\n");
#endif
    fprintf(logger->fp, "-------------------------------------------------------------\n");
}
static void check_and_rollback(void)
{
    if(!logger)
        return ;
    if (log_rollback_size != LOG_ROLLBACK_NONE)
    {
        long _curOffset = ftell(logger->fp);
        if ((_curOffset != -1) && (_curOffset >= log_rollback_size))
        {
            char cmd[512];
            snprintf(cmd, sizeof(cmd), "cp -f %s %s.roll", logger->file, logger->file);
            system(cmd);
            if (-1 == fseek(logger->fp, 0L, SEEK_SET))
                fprintf(logger->fp, "log rollback fseek failed \n");
            rewind(logger->fp);
            truncate(logger->file, 0);
            log_banner("Already rollback");
        }
    }
}
cp_logger *cp_log_init(cp_logger *log, char *filename, int level, int log_size)
{
    if(NULL == log)
    {
        logger = malloc(sizeof(cp_logger));
        memset(logger, 0, sizeof(cp_logger));
        logger->flag |= CP_LOGGER_MALLOC;
    }
    else
    {
        logger = log;
        logger->flag |= CP_LOGGER_ARGUMENT;
    }
    if(NULL == logger)
    {
        return NULL;
    }
    strncpy(logger->file, filename, FILENAME_LEN);
    logger->level = level;
    logger->size = log_size;
    return logger;
}
int cp_log_open(void)
{
    struct sigaction act;
    char *filemode;
    if(!logger)
    {
        return -1;
    }
    log_rollback_size = logger->size <= 0 ? LOG_ROLLBACK_NONE : logger->size*1024;    /* Unit KiB */
    if ('\0' == logger->file)
        return -1;
    if (!strcmp(logger->file, DBG_LOG_FILE))
    {
        logger->fp = stderr;
        log_rollback_size = LOG_ROLLBACK_NONE;
        logger->flag |= CP_LOGGER_CONSOLE;
        goto OUT;
    }
    filemode = (log_rollback_size==LOG_ROLLBACK_NONE) ? "a+" : "w+";
    logger->fp = fopen(logger->file, filemode);
    if (NULL == logger->fp)
    {
        fprintf(stderr, "Open log file \"%s\" in %s failure\n", logger->file, filemode);
        return -2;
    }
    act.sa_handler = cp_log_default_signal_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGHUP, &act, NULL);
  OUT:
    log_banner("Initialize");
    return 0;
}
void cp_log_close(void)
{
    if (!logger || !logger->fp )
        return;
    log_banner("\nTerminate");
    cp_log_raw("\n\n\n\n");
    fflush(logger->fp);
    fclose(logger->fp);
    logger->fp = NULL;
    return ;
}
int cp_log_reopen(void)
{
    int rc = 0;
    char *filemode;
    if( !logger )
        return -1;
    log_rollback_size = logger->size <= 0 ? LOG_ROLLBACK_NONE : logger->size*1024;    /* Unit KiB */
    if (logger->flag & CP_LOGGER_CONSOLE )
    {
        fflush(logger->fp);
        logger->fp = stderr;
        return 0;
    }
    if (logger->fp)
    {
        cp_log_close();
        filemode = log_rollback_size==LOG_ROLLBACK_NONE ? "a+" : "w+";
        logger->fp = fopen(logger->file, filemode);
        if (logger->fp == NULL)
            rc = -2;
    }
    else
    {
        rc = -3;
    }
    if (!rc)
    {
        log_banner("\nReopen");
    }
    return rc;
}
void cp_log_term(void)
{
    if(!logger)
        return ;
    cp_log_close();
    if (logger->flag & CP_LOGGER_MALLOC )
    {
        free(logger);
    }
    logger = NULL;
}
void cp_log_raw(const char *fmt, ...)
{
    va_list argp;
    if (!logger || !logger->fp)
        return;
    check_and_rollback();
    va_start(argp, fmt);
    vfprintf(logger->fp, fmt, argp);
    va_end(argp);
}
static void cp_printout(char *level, char *fmt, va_list argp)
{
    char buf[MAX_LOG_MESSAGE_LEN];
    struct tm *local;
    struct timeval now;
    char timestr[256];
    if(!logger)
        return ;
    pthread_t tid;
    check_and_rollback();
#ifdef MULTHREADS
    tid = pthread_self();
#else
    tid = getpid();
#endif
    gettimeofday(&now, NULL);
    local = localtime(&now.tv_sec);
    strftime(timestr, 256, cp_time_format, local);
    vsnprintf(buf, MAX_LOG_MESSAGE_LEN, fmt, argp);
#ifdef DUMPLICATE_OUTPUT
    printf("%s.%03ld [%s] [%06lu]: %s",
           timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, buf);
#endif
    if (logger->fp)
        fprintf(logger->fp, "%s.%03ld [%s] [%06lu]: %s", timestr, now.tv_usec / PRECISE_TIME_FACTOR,
                level, tid, buf);
    if (logger->fp)
        fflush(logger->fp);
}
static void cp_printout_line(char *level, char *fmt, char *file, int line, va_list argp)
{
    char buf[MAX_LOG_MESSAGE_LEN];
    struct tm *local;
    struct timeval now;
    char timestr[256];
    if(!logger)
        return ;
    pthread_t tid;
    check_and_rollback();
#ifdef MULTHREADS
    tid = pthread_self();
#else
    tid = getpid();
#endif
    gettimeofday(&now, NULL);
    local = localtime(&now.tv_sec);
    strftime(timestr, 256, cp_time_format, local);
    vsnprintf(buf, MAX_LOG_MESSAGE_LEN, fmt, argp);
#ifdef DUMPLICATE_OUTPUT
    printf("%s.%03ld [%s] [%06lu] (%s [%04d]) : %s",
           timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, file, line, buf);
#endif
    if (logger->fp)
        fprintf(logger->fp, "%s.%03ld [%s] [%06lu] (%s [%04d]) : %s",
                timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, file, line, buf);
    if (logger->fp)
        fflush(logger->fp);
}
void cp_log_str(int level, const char *msg)
{
    if (!logger || level>logger->level)
        return;
    check_and_rollback();
    if (logger->fp)
        fwrite(msg, 1, strlen(msg), logger->fp);
    if(logger->fp)
        fflush(logger->fp);
}
void cp_log(int level, char *fmt, ...)
{
    va_list argp;
    if (!logger || level>logger->level)
        return;
    va_start(argp, fmt);
    cp_printout(log_str[level], fmt, argp);
    va_end(argp);
}
void cp_log_line(int level, char *file, int line, char *fmt, ...)
{
    va_list argp;
    if (!logger || level>logger->level)
        return;
    va_start(argp, fmt);
    cp_printout_line(log_str[level], fmt, file, line, argp);
    va_end(argp);
}
#define LINELEN 81
#define CHARS_PER_LINE 16
static char *print_char =
    "                "
    "                "
    " !\"#$%&'()*+,-./"
    "0123456789:;<=>?"
    "@ABCDEFGHIJKLMNO"
    "PQRSTUVWXYZ[\\]^_"
    "`abcdefghijklmno"
    "pqrstuvwxyz{|}~ "
    "                "
    "                "
    " ???????????????"
    "????????????????"
    "????????????????"
    "????????????????"
    "????????????????"
    "????????????????";
void cp_log_dump(int level, char *buf, int len)
{
    int rc;
    int idx;
    char prn[LINELEN];
    char lit[CHARS_PER_LINE + 2];
    char hc[4];
    short line_done = 1;
    if (!logger || level>logger->level)
        return;
    rc = len;
    idx = 0;
    lit[CHARS_PER_LINE] = '\0';
    while (rc > 0)
    {
        if (line_done)
            snprintf(prn, LINELEN, "%08X: ", idx);
        do
        {
            unsigned char c = buf[idx];
            snprintf(hc, 4, "%02X ", c);
            strncat(prn, hc, LINELEN);
            lit[idx % CHARS_PER_LINE] = print_char[c];
        }
        while (--rc > 0 && (++idx % CHARS_PER_LINE != 0));
        line_done = (idx % CHARS_PER_LINE) == 0;
        if (line_done)
        {
#ifdef DUMPLICATE_OUTPUT
            printf("%s  %s\n", prn, lit);
#endif
            if (logger->fp)
                fprintf(logger->fp, "%s  %s\n", prn, lit);
        }
    }
    if (!line_done)
    {
        int ldx = idx % CHARS_PER_LINE;
        lit[ldx++] = print_char[(int)buf[idx]];
        lit[ldx] = '\0';
        while ((++idx % CHARS_PER_LINE) != 0)
            strncat(prn, "   ", LINELEN);
#ifdef DUMPLICATE_OUTPUT
        printf("%s  %s\n", prn, lit);
#endif
        if (logger->fp)
            fprintf(logger->fp, "%s  %s\n", prn, lit);
    }
}
program/converterd/cp_logger.h
New file
@@ -0,0 +1,111 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_logger.h
 *    Description:  This file is the linux infrastructural logger system library
 *
 *        Version:  1.0.0(08/08/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "08/08/2012 05:16:56 PM"
 *
 ********************************************************************************/
#ifndef __CP_LOG_H
#define __CP_LOG_H
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/time.h>
#define LOG_VERSION_STR             "1.0.0"
#ifndef FILENAME_LEN
#define FILENAME_LEN                64
#endif
#define DEFAULT_LOGFILE             "cp_logger.log"
#define DBG_LOG_FILE                "console"  /*  Debug mode log file is console */
#define LOG_ROLLBACK_SIZE           512    /* Default rollback log size  */
#define LOG_ROLLBACK_NONE           0      /* Set rollback size to 0 will not rollback  */
#define DEFAULT_TIME_FORMAT         "%Y-%m-%d %H:%M:%S"
#define MAX_LOG_MESSAGE_LEN         0x1000
//#define DUMPLICATE_OUTPUT  /* Log to file and printf on console  */
#define LOG_FILE_LINE      /* Log the file and line */
enum
{
    LOG_LEVEL_DISB = 0,               /*  Disable "Debug" */
    LOG_LEVEL_FATAL,                  /*  Debug Level "Fatal" */
    LOG_LEVEL_ERROR,                  /*  Debug Level "ERROR" */
    LOG_LEVEL_WARN,                   /*  Debug Level "warnning" */
    LOG_LEVEL_NRML,                   /*  Debug Level "Normal" */
    LOG_LEVEL_DEBUG,                  /*  Debug Level "Debug" */
    LOG_LEVEL_INFO,                   /*  Debug Level "Information" */
    LOG_LEVEL_TRACE,                  /*  Debug Level "Trace" */
    LOG_LEVEL_MAX,
};
#define CP_LOGGER_MALLOC              1<<0
#define CP_LOGGER_ARGUMENT            0<<0
#define CP_LOGGER_CONSOLE             1<<1
#define CP_LOGGER_FILE                0<<1
#define CP_LOGGER_LEVEL_OPT           1<<2 /*  The log level is sepcified by the command option */
typedef struct _cp_logger
{
    unsigned char      flag;  /* This logger pointer is malloc() or passed by argument */
    char               file[FILENAME_LEN];
    int                level;
    int                size;
    FILE               *fp;
} cp_logger;
extern char *log_str[];
extern cp_logger *cp_log_init(cp_logger *log, char *filename, int level, int log_size);
extern int  cp_log_open(void);
extern void cp_log_set_time_format(char *time_format);
extern int  cp_log_reopen(void);
extern void cp_log_term(void);
extern void cp_log_raw(const char *fmt, ...);
extern void cp_log(int level, char *fmt, ...);
extern void cp_log_line(int level, char *file, int line, char *fmt, ...);
extern void cp_log_str(int level, const char *msg);
extern void cp_log_dump(int level, char *buf, int len);
#ifdef LOG_FILE_LINE
#define log_trace(fmt, ...) cp_log_line(LOG_LEVEL_TRACE, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define log_info(fmt, ...)  cp_log_line(LOG_LEVEL_INFO,  __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define log_dbg(fmt, ...)   cp_log_line(LOG_LEVEL_DEBUG, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define log_nrml(fmt, ...)  cp_log_line(LOG_LEVEL_NRML,  __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define log_warn(fmt, ...)  cp_log_line(LOG_LEVEL_WARN,  __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define log_err(fmt, ...)   cp_log_line(LOG_LEVEL_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define log_fatal(fmt, ...) cp_log_line(LOG_LEVEL_FATAL, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#else
#define log_trace(fmt, ...) cp_log(LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__)
#define log_info(fmt, ...) cp_log(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
#define log_dbg(fmt, ...) cp_log(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
#define log_nrml(fmt, ...) cp_log(LOG_LEVEL_NRML, fmt, ##__VA_ARGS__)
#define log_warn(fmt, ...) cp_log(LOG_LEVEL_WARN, fmt, ##__VA_ARGS__)
#define log_err(fmt, ...) cp_log(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define log_fatal(fmt, ...) cp_log(LOG_LEVEL_FATAL, fmt, ##__VA_ARGS__)
#endif
#endif /* __CP_LOG_H  */
program/converterd/cp_proc.c
New file
@@ -0,0 +1,341 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_proc.c
 *    Description:  This file is the process API
 *
 *        Version:  1.0.0(11/06/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/06/2012 09:19:02 PM"
 *
 ********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libgen.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include "cp_proc.h"
#include "cp_logger.h"
CP_PROC_SIG     g_cp_signal={0};
void cp_proc_sighandler(int sig)
{
    switch(sig)
    {
        case SIGINT:
            log_warn("SIGINT - stopping\n");
            g_cp_signal.stop = 1;
            break;
        case SIGTERM:
            log_warn("SIGTERM - stopping\n");
            g_cp_signal.stop = 1;
            break;
        case SIGSEGV:
            log_warn("SIGSEGV - stopping\n");
#if 0
            if(g_cp_signal.stop)
                exit(0);
            g_cp_signal.stop = 1;
#endif
            break;
        case SIGPIPE:
            log_warn("SIGPIPE - warnning\n");
            break;
        default:
            break;
    }
}
void cp_install_proc_signal(void)
{
    struct sigaction sigact, sigign;
    log_nrml("Install default signal handler.\n");
    /*  Initialize the catch signal structure. */
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigact.sa_handler = cp_proc_sighandler;
    /*  Setup the ignore signal. */
    sigemptyset(&sigign.sa_mask);
    sigign.sa_flags = 0;
    sigign.sa_handler = SIG_IGN;
    sigaction(SIGTERM, &sigact, 0); /*  catch terminate signal "kill" command */
    sigaction(SIGINT,  &sigact, 0); /*  catch interrupt signal CTRL+C */
    //sigaction(SIGSEGV, &sigact, 0); /*  catch segmentation faults  */
    sigaction(SIGPIPE, &sigact, 0); /*  catch broken pipe */
#if 0
    sigaction(SIGCHLD, &sigact, 0); /*  catch child process return */
    sigaction(SIGUSR2, &sigact, 0); /*  catch USER signal */
#endif
}
/* ****************************************************************************
 * FunctionName: daemonize
 * Description : Set the programe runs as daemon in background
 * Inputs      : nodir: DON'T change the work directory to / :  1:NoChange 0:Change
 *               noclose: close the opened file descrtipion or not 1:Noclose 0:Close
 * Output      : NONE
 * Return      : NONE
 * *****************************************************************************/
void daemonize(int nochdir, int noclose)
{
    int retval, fd;
    int i;
    /*  already a daemon */
    if (1 == getppid())
        return;
    /*  fork error */
    retval = fork();
    if (retval < 0) exit(1);
    /*  parent process exit */
    if (retval > 0)
        exit(0);
    /*  obtain a new process session group */
    setsid();
    if (!noclose)
    {
        /*  close all descriptors */
        for (i = getdtablesize(); i >= 0; --i)
        {
            //if (i != g_logPtr->fd)
                close(i);
        }
        /*  Redirect Standard input [0] to /dev/null */
        fd = open("/dev/null", O_RDWR);
        /* Redirect Standard output [1] to /dev/null */
        dup(fd);
        /* Redirect Standard error [2] to /dev/null */
        dup(fd);
    }
    umask(0);
    if (!nochdir)
        chdir("/");
    return;
}
/* ****************************************************************************
 * FunctionName: record_daemon_pid
 * Description : Record the running daemon program PID to the file "pid_file"
 * Inputs      : pid_file:The record PID file path
 * Output      : NONE
 * Return      : 0: Record successfully  Else: Failure
 * *****************************************************************************/
int record_daemon_pid(const char *pid_file)
{
    struct stat fStatBuf;
    int fd = -1;
    int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;
    char ipc_dir[64] = { 0 };
    strncpy(ipc_dir, pid_file, 64);
    /* dirname() will modify ipc_dir and save the result */
    dirname(ipc_dir);
    /* If folder pid_file PATH doesnot exist, then we will create it" */
    if (stat(ipc_dir, &fStatBuf) < 0)
    {
        if (mkdir(ipc_dir, mode) < 0)
        {
            log_fatal("cannot create %s: %s\n", ipc_dir, strerror(errno));
            return -1;
        }
        (void)chmod(ipc_dir, mode);
    }
    /*  Create the process running PID file */
    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    if ((fd = open(pid_file, O_RDWR | O_CREAT | O_TRUNC, mode)) >= 0)
    {
        char pid[PID_ASCII_SIZE];
        snprintf(pid, sizeof(pid), "%u\n", (unsigned)getpid());
        write(fd, pid, strlen(pid));
        close(fd);
        log_dbg("Record PID<%u> to file %s.\n", getpid(), pid_file);
    }
    else
    {
        log_fatal("cannot create %s: %s\n", pid_file, strerror(errno));
        return -1;
    }
    return 0;
}
/* ****************************************************************************
 * FunctionName: get_daemon_pid
 * Description : Get the daemon process PID from the PID record file "pid_file"
 * Inputs      : pid_file: the PID record file
 * Output      : NONE
 * Return      : pid_t: The daemon process PID number
 * *****************************************************************************/
pid_t get_daemon_pid(const char *pid_file)
{
    FILE *f;
    pid_t pid;
    if ((f = fopen(pid_file, "rb")) != NULL)
    {
        char pid_ascii[PID_ASCII_SIZE];
        (void)fgets(pid_ascii, PID_ASCII_SIZE, f);
        (void)fclose(f);
        pid = atoi(pid_ascii);
    }
    else
    {
        log_fatal("Can't open PID record file %s: %s\n", pid_file, strerror(errno));
        return -1;
    }
    return pid;
}
/* ****************************************************************************
 * FunctionName: check_daemon_running
 * Description : Check the daemon program already running or not
 * Inputs      : pid_file: The record running daemon program PID
 * Output      : NONE
 * Return      : 1: The daemon program alread running   0: Not running
 * *****************************************************************************/
int check_daemon_running(const char *pid_file)
{
    int retVal = -1;
    struct stat fStatBuf;
    retVal = stat(pid_file, &fStatBuf);
    if (0 == retVal)
    {
        pid_t pid = -1;
        printf("PID record file \"%s\" exist.\n", pid_file);
        pid = get_daemon_pid(pid_file);
        if (pid > 0)  /*  Process pid exist */
        {
            if ((retVal = kill(pid, 0)) == 0)
            {
                printf("Program with PID[%d] seems running.\n", pid);
                return 1;
            }
            else   /* Send signal to the old process get no reply. */
            {
                printf("Program with PID[%d] seems exit.\n", pid);
                remove(pid_file);
                return 0;
            }
        }
        else if (0 == pid)
        {
            printf("Can not read program PID form record file.\n");
            remove(pid_file);
            return 0;
        }
        else  /* Read pid from file "pid_file" failure */
        {
            printf("Read record file \"%s\" failure, maybe program still running.\n", pid_file);
            return 1;
        }
    }
    return 0;
}
/* ****************************************************************************
 * FunctionName: set_daemon_running
 * Description : Set the programe running as daemon if it's not running and record
 *               its PID to the pid_file.
 * Inputs      : pid_file: The record running daemon program PID
 * Output      : NONE
 * Return      : 0: Successfully. 1: Failure
 * *****************************************************************************/
int set_daemon_running(const char *pid_file)
{
    daemonize(0, 1);
    log_nrml("Program running as daemon [PID:%d].\n", getpid());
    if (record_daemon_pid(pid_file) < 0)
    {
        log_fatal("Record PID to file \"%s\" failure.\n", pid_file);
        return -2;
    }
    return 0;
}
int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg)
{
    int        retval = 0;
    pthread_attr_t thread_attr;
    /* Initialize the thread  attribute */
    retval = pthread_attr_init(&thread_attr);
    if(retval)
        return -1;
    /* Set the stack size of the thread */
    retval = pthread_attr_setstacksize(&thread_attr, 120 * 1024);
    if(retval)
        goto CleanUp;
    /* Set thread to detached state:Don`t need pthread_join */
    retval = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
    if(retval)
        goto CleanUp;
    /* Create the thread */
    retval = pthread_create(thread_id, &thread_attr, thread_workbody, thread_arg);
    if(retval)
        goto CleanUp;
CleanUp:
    /* Destroy the  attributes  of  thread */
    pthread_attr_destroy(&thread_attr);
    return retval;
}
void exec_system_cmd(const char *format, ...)
{
    char                cmd[256];
    va_list             args;
    int                 done;
    memset(cmd, 0, sizeof(cmd));
    va_start(args, format);
    done = vsnprintf(cmd, sizeof(cmd), format, args);
    va_end(args);
    system(cmd);
}
program/converterd/cp_proc.h
New file
@@ -0,0 +1,42 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_proc.h
 *    Description:  This head file is for Linux process API
 *
 *        Version:  1.0.0(11/06/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/06/2012 09:21:33 PM"
 *
 ********************************************************************************/
#ifndef __CP_PROC_H
#define __CP_PROC_H
#include <signal.h>
#define PID_ASCII_SIZE  11
typedef struct __CP_PROC_SIG
{
    int       signal;
    unsigned  stop;     /* 0: Not term  1: Stop  */
}  CP_PROC_SIG;
typedef void *(THREAD_BODY) (void *thread_arg);
extern CP_PROC_SIG     g_cp_signal;
extern void cp_install_proc_signal(void);
extern void daemonize(int nochdir, int noclose);
extern int record_daemon_pid(const char *pid_file);
extern pid_t get_daemon_pid(const char *pid_file);
extern int check_daemon_running(const char *pid_file);
extern int set_daemon_running(const char *pid_file);
extern void exec_system_cmd(const char *format, ...);
extern int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg);
#endif
program/converterd/cp_socket.c
New file
@@ -0,0 +1,252 @@
/*********************************************************************************
 *      Copyright:  (C) 2014 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_socket.c
 *    Description:  This file
 *
 *        Version:  1.0.0(11/18/2014)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/18/2014 11:15:04 PM"
 *
 ********************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/un.h>
#include <sys/types.h>
#include <linux/sockios.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "cp_logger.h"
#include "cp_socket.h"
int cp_sock_set_nonblock(int sockfd)
{
    int opts;
    /*
     * fcntl may set:
     *
     * EACCES, EAGAIN: Operation is prohibited by locks held by other
     *          processes. Or, operation is prohibited because the file has
     *          been memory-mapped by another process.
     * EBADF:   fd is not an open file descriptor, or the command was F_SETLK
     *          or F_SETLKW and the file descriptor open mode doesn't match
     *          with the type of lock requested.
     * EDEADLK: It was detected that the specified F_SETLKW command would
     *          cause a deadlock.
     * EFAULT:  lock is outside your accessible address space.
     * EINTR:   For F_SETLKW, the command was interrupted by a signal. For
     *          F_GETLK and F_SETLK, the command was interrupted by a signal
     *          before the lock was checked or acquired. Most likely when
     *          locking a remote file (e.g. locking over NFS), but can
     *          sometimes happen locally.
     * EINVAL:  For F_DUPFD, arg is negative or is greater than the maximum
     *          allowable value. For F_SETSIG, arg is not an allowable signal
     *          number.
     * EMFILE:  For F_DUPFD, the process already has the maximum number of
     *          file descriptors open.
     * ENOLCK:  Too many segment locks open, lock table is full, or a remote
     *          locking protocol failed (e.g. locking over NFS).
     * EPERM:   Attempted to clear the O_APPEND flag on a file that has the
     *          append-only attribute set.
     */
    opts = fcntl(sockfd, F_GETFL);
    if (opts < 0)
    {
        log_warn("fcntl() get socket options failure: %s\n", strerror(errno));
        return -1;
    }
    opts |= O_NONBLOCK;
    if (fcntl(sockfd, F_SETFL, opts) < 0)
    {
        log_warn("fcntl() set socket options failure: %s\n", strerror(errno));
        return -1;
    }
    log_dbg("Set socket[%d] none blocking\n", sockfd);
    return opts;
}
int cp_sock_connect(cp_sock_t *sock)
{
    int                 rv = -1;
    int                 sock_fd = -1;
    char                service[20];
    struct addrinfo     hints, *rp;
    struct addrinfo     *res = NULL;
    struct in_addr      inaddr;
    char                ipstr[20];
    if(!sock)
    {
        log_err("Invalid input argument\n");
        return -1;
    }
    if(SOCK_STAT_CONNECTED == sock->status)
    {
        return 0;
    }
    else if(SOCK_STAT_CONNECTING == sock->status)
    {
        goto connecting;
    }
    log_nrml("Start socket connect to [%s:%d]...\n", sock->host, sock->port);
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_INET; /*   Only support IPv4 */
    hints.ai_socktype = SOCK_STREAM;
    /*  If Hostname is a valid IP address, then don't use name resolution */
    if( inet_aton(sock->host, &inaddr) )
    {
        log_info("%s is a valid IP address, don't use name resolution.\n", sock->host);
        hints.ai_flags |= AI_NUMERICHOST;
    }
    /*  Obtain address(es) matching host/port */
    snprintf(service, sizeof(service), "%d", sock->port);
    if( (rv=getaddrinfo(sock->host, service, &hints, &res)) )
    {
        log_err("getaddrinfo() parser [%s:%s] failed: %s\n", sock->host, service, gai_strerror(rv));
        rv = -2;
        goto failed;
    }
    /*  getaddrinfo() returns a list of address structures. Try each
     *  address until we successfully connect or bind
     */
    rv = -3; /* Connect failure  */
    for (rp=res; rp!=NULL; rp=rp->ai_next)
    {
        /*  Create the socket */
        sock_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if( sock_fd < 0)
        {
            log_err("socket() create failed: %s\n", strerror(errno));
            rv = -4;
            continue;
        }
        inet_ntop(AF_INET, &(((struct sockaddr_in *)(rp->ai_addr))->sin_addr), ipstr, sizeof(ipstr));
        log_dbg("DNS resolve IP address [%s]\n", ipstr);
        cp_sock_set_nonblock(sock_fd);
        /* Nono block Connect to the remote server */
        if(0==connect(sock_fd, rp->ai_addr, rp->ai_addrlen))
        {
            /* Conenct to server successfully */
            memcpy(&sock->saddr, &rp->ai_addr, sizeof(sock->saddr));
            sock->fd = sock_fd;
            sock->status = SOCK_STAT_CONNECTED;
            rv = 0;
            goto connected;
        }
        else
        {
            if(EINPROGRESS == errno)
            {
                /* Connect to server now in progress  */
                memcpy(&sock->saddr, &rp->ai_addr, sizeof(sock->saddr));
                sock->fd = sock_fd;
                sock->status = SOCK_STAT_CONNECTING;
                rv = 0;
                goto connecting;
            }
            else
            {
                /* Connect to server failed. */
                close(sock_fd);
                rv = -5;
                log_err("connect() to server failed: %s\n", strerror(errno));
                goto failed;
            }
        }
        close(sock_fd);
    }
failed:
    log_err("create socket connect to [%s:%d] failed: %s\n", sock->host, sock->port, strerror(errno));
    sock->status = SOCK_STAT_DISCONNECT;
    sock->fd = -1;
    return rv;
connecting:
    if(SOCK_STAT_CONNECTING == sock->status)
    {
        int         len;
        len = sizeof(sock->saddr);
        errno = 0;
        if( 0 == connect(sock->fd, &sock->saddr, len) )
        {
            /* connect() return 0 means it already connected */
            sock->status = SOCK_STAT_CONNECTED;
            rv = 0;
            goto connected;
        }
        /* Connect failure will continue to check */
        switch (errno)
        {
            case EISCONN:
                sock->status = SOCK_STAT_CONNECTED;
                rv = 0;
                goto connected;
            case EALREADY:
            case EINPROGRESS:
                log_dbg("socket[%d] connect to remote [%s:%d] in progress\n", sock->fd, sock->host, sock->port);
                rv = 0;
                goto cleanup;
            default:
                log_err("socket[%d] connect to remote [%s:%d] failed: %s\n", sock->fd, sock->host, sock->port, strerror(errno));
                sock->status = SOCK_STAT_DISCONNECT;
                rv = -7;
                break;
        }
    }
connected:
    if(SOCK_STAT_CONNECTED == sock->status)
    {
        rv = 0;
        log_nrml("socket[%d] connected to remote server [%s:%d]\n", sock->fd, sock->host, sock->port);
        goto cleanup;
    }
cleanup:
    if(res)
        freeaddrinfo(res);  /* No longer needed */
    return rv;
}
void cp_sock_close(cp_sock_t *sock)
{
    close(sock->fd);
    sock->fd = 0;
    sock->status = SOCK_STAT_INIT;
}
void cp_sock_term(cp_sock_t *sock)
{
    close(sock->fd);
    memset(sock, 0, sizeof(*sock));
}
program/converterd/cp_socket.h
New file
@@ -0,0 +1,40 @@
/********************************************************************************
 *      Copyright:  (C) 2014 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_socket.h
 *    Description:  This head file
 *
 *        Version:  1.0.0(11/19/2014)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/19/2014 12:16:45 AM"
 *
 ********************************************************************************/
#ifndef __CP_SOCKET_H_
#define __CP_SOCKET_H_
#include <sys/types.h>
#include <sys/socket.h>
#define DOMAIN_MAX_LEN             128
#define SOCK_STAT_INIT             0
#define SOCK_STAT_CONNECTING       1
#define SOCK_STAT_CONNECTED        2
#define SOCK_STAT_DISCONNECT       3
typedef struct cp_sock_s
{
    char               host[DOMAIN_MAX_LEN];      /*  Connect/Listen hostname or IP address */
    int                port;                      /*  Connect/Listen server port  */
    int                fd;                        /*  Connected/Listen socket fd  */
    int                status;                    /*  Socket connected or not  */
    struct sockaddr    saddr;                     /*  sockaddr for none-block connect */
} cp_sock_t;  /*---  end of struct cp_sock_s  ---*/
extern int cp_sock_connect(cp_sock_t *sock);
extern void cp_sock_close(cp_sock_t *sock);
extern void cp_sock_term(cp_sock_t *sock);
#endif
program/converterd/cvd_conf.c
New file
@@ -0,0 +1,121 @@
/*********************************************************************************
 *      Copyright:  (C) 2014 GuoWenxue<guowenxue@email.com>
 *                  All rights reserved.
 *
 *       Filename:  cvd_conf.c
 *    Description:  This file
 *
 *        Version:  1.0.0(11/19/2014)
 *         Author:  GuoWenxue <guowenxue@email.com>
 *      ChangeLog:  1, Release initial version on "11/19/2014 01:58:28 PM"
 *
 ********************************************************************************/
#include "cp_logger.h"
#include "cvd_conf.h"
#include "cp_iniparser.h"
int parser_cvd_conf(char *ini_name, cp_logger *logger, comport_sock_bind_t *cvd_bind)
{
    dictionary          *ini;
    char                *str;
    int                 val, i;
    if(!ini_name || !logger || !cvd_bind)
    {
        log_err("Invalid input arguments\n");
        return -1 ;
    }
    ini = iniparser_load(ini_name);
    if (ini==NULL)
    {
        log_err("cannot parse file: %s\n", ini_name);
        return -2 ;
    }
    /************************************************
     * Parser the Logger configuration
     ************************************************/
    log_nrml("Parser configure file %s with original logger file [%s]\n", ini_name, logger->file);
    str = iniparser_getstring(ini, "log:file", NULL);
    strncpy(logger->file, (strlen(str)>0 ? str : CVD_DEF_LOG_FILE), FILENAME_LEN);
    log_nrml("Set log file [%d] from configuration.\n", logger->level);
    /*If not set the log level from command line, then use the configure one*/
    if( !(logger->flag&CP_LOGGER_LEVEL_OPT) )
    {
        val = iniparser_getint(ini, "log:level", -1);
        logger->level = (-1==val ? LOG_LEVEL_NRML : val);
        log_nrml("Set log level[%d] from configuration.\n", logger->level);
    }
    /* Set the log maximum file size in the configure file */
    val = iniparser_getint(ini, "log:size", -1);
    logger->size = -1==val ? CVD_DEF_LOG_SIZE : val;
    log_nrml("Set log size [%dKiB] from configuration\n", logger->size);
    if ( cp_log_reopen() )
    {
        printf("Log file reopen failure, exit now...\n");
        return -3;
    }
    log_nrml("Configure Log file \"%s\" with level [%s], maximum size %d KiB.\n",
            logger->file, log_str[logger->level], logger->size);
    for(i=0; i<MAX_BIND_TUNNEL; i++)
    {
        char        key[64];
        snprintf(key, sizeof(key), "TUNNEL%d:comport", i+1);
        str = iniparser_getstring(ini, key, NULL);
        if( NULL!=str && strlen(str) > 0 )
        {
            strncpy(cvd_bind->comport_dev, str, DEVNAME_LEN);
            log_info("Configure comport: %s\n", cvd_bind->comport_dev);
        }
        else
        {
            log_err("Configure file lost serial port configuration\n");
            return -3;
        }
        /*-----------------------------------------------------------------------------
         *  Connect socket configuration
         *-----------------------------------------------------------------------------*/
        snprintf(key, sizeof(key), "TUNNEL%d:conn_host", i+1);
        str = iniparser_getstring(ini, key, NULL);
        if( NULL!=str && strlen(str) > 0 )
        {
            char      *ptr;
            ptr = strtok(str, ":");
            if(ptr)
            {
                strncpy(cvd_bind->sock.host, ptr, DOMAIN_MAX_LEN);
                if( NULL != (ptr=strtok(NULL, ":")) )
                {
                    cvd_bind->sock.port = atoi(ptr);
                }
                else
                {
                    log_err("Configure file lost connect port configuration\n");
                    return -4;
                }
            }
            else
            {
                log_err("Configure file lost connect host configuration\n");
                return -5;
            }
        }
        log_nrml("Bind tunnel serial[%s] <==> socket[%s:%d]\n", cvd_bind->comport_dev, cvd_bind->sock.host, cvd_bind->sock.port);
    }
    return 0;
}
program/converterd/cvd_conf.h
New file
@@ -0,0 +1,31 @@
/********************************************************************************
 *      Copyright:  (C) 2014 GuoWenxue<guowenxue@email.com>
 *                  All rights reserved.
 *
 *       Filename:  cvd_conf.h
 *    Description:  This head file
 *
 *        Version:  1.0.0(11/19/2014)
 *         Author:  GuoWenxue <guowenxue@email.com>
 *      ChangeLog:  1, Release initial version on "11/19/2014 02:28:07 PM"
 *
 ********************************************************************************/
#ifndef __CVD_CONF_
#define __CVD_CONF_
#include "cvd_main.h"
#define MAX_BIND_TUNNEL    1
#define DEF_SERIAL_PORT    "/dev/ttyS1"
//#define DEF_CONN_HOST      "192.168.1.78"
#define DEF_CONN_HOST      "emblinux.com"
#define DEF_CONN_PORT      9001
#define CVD_DEF_LOG_FILE   "/var/log/converterd.log"
#define CVD_DEF_LOG_SIZE   8
extern int parser_cvd_conf(char *ini_name, cp_logger *logger, comport_sock_bind_t *cvd_bind);
#endif
program/converterd/cvd_main.c
New file
@@ -0,0 +1,309 @@
/*********************************************************************************
 *      Copyright:  (C) 2014 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cvd_main.c
 *    Description:  This file
 *
 *        Version:  1.0.0(11/18/2014)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/18/2014 10:30:53 PM"
 *
 ********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/types.h>       /* basic system data types */
#include <sys/socket.h>      /* basic socket definitions */
#include <sys/epoll.h> /* epoll function */
#include "cp_comport.h"
#include "cp_socket.h"
#include "cp_logger.h"
#include "cp_proc.h"
#include "cvd_conf.h"
#include "cvd_main.h"
#include "version.h"
int epoll_add_socket(int epfd, cp_sock_t *sock);
int epoll_add_comport(int epfd, COM_PORT *comport, char *comport_dev);
void epoll_del_fd(int epfd, int fd);
static void prog_usage(const char *progname)
{
    banner(progname);
    printf("Usage: %s [OPTION]...\n", progname);
    printf("Receive date from a serial port and transfer the data to remote server by socket.\n");
    printf("\nMandatory arguments to long options are mandatory for short options too:\n");
    printf(" -d[debug   ]  Running in debug mode\n");
    printf(" -l[level   ]  Set the log level as [0..%d]\n", LOG_LEVEL_MAX-1);
    printf(" -h[help    ]  Display this help information\n");
    printf(" -v[version ]  Display the program version\n");
    return ;
}
int main(int argc, char **argv)
{
    int                    i, epfd, nfds, nbytes;
    comport_sock_bind_t    cvd_bind;
    cp_logger              *logger;
    struct epoll_event     evts[MAXEPOLLSIZE];
    int                    opt;
    int                    debug = 0;
    char                   pid_file[64] = { 0 }; /*  The file used to record the PID */
    char                   *conf_file = CVD_DEF_CONF_FILE;
    char                   *log_file;
    int                    log_level = LOG_LEVEL_TRACE;
    const char             *progname=NULL;
    struct option long_options[] = {
        {"conf", required_argument, NULL, 'c'},
        {"debug", no_argument, NULL, 'd'},
        {"level", required_argument, NULL, 'l'},
        {"version", no_argument, NULL, 'v'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };
    progname = basename(argv[0]);
    /* Parser the command line parameters */
    while ((opt = getopt_long(argc, argv, "c:dl:vh", long_options, NULL)) != -1)
    {
        switch (opt)
        {
            case 'c':  /* Set configure file */
                conf_file = optarg;
                break;
            case 'd': /* Set debug running */
                debug = 1;
                log_file = DBG_LOG_FILE;
                break;
            case 'l': /* Set the log level */
                i = atoi(optarg);
                log_level = i>LOG_LEVEL_MAX ? LOG_LEVEL_MAX-1 : LOG_LEVEL_MAX-1;
                break;
            case 'v':  /* Get software version */
                banner(progname); /* Defined in version.h */
                return EXIT_SUCCESS;
            case 'h':  /* Get help information */
                prog_usage(progname);
                return 0;
            default:
                break;
        } /*  end of "switch(opt)" */
    }
    memset(&cvd_bind, 0, sizeof(cvd_bind));
    if( !debug )
    {
        snprintf(pid_file, sizeof(pid_file), "/var/run/%s.pid", progname);
        if( check_daemon_running(pid_file) )
        {
            printf("Programe already running, exit now.\n");
            return -1;
        }
    }
    if( !(logger=cp_log_init(NULL, log_file, log_level, 0)) || cp_log_open()<0  )
    {
        printf("Init logger system failed, program exit now...\n");
        return -1;
    }
    if( parser_cvd_conf(conf_file, logger, &cvd_bind) < 0)
    {
        printf("Parser configure file '%s' failed, program exit now...\n", conf_file);
        return -1;
    }
    cvd_bind.comport = comport_init(cvd_bind.comport_dev, 115200, "8N1N");
    if( !cvd_bind.comport )
    {
        log_err("Init comport '%s' as 115200 8N1N failure\n", cvd_bind.comport_dev);
        return -2;
    }
    if( (epfd=epoll_create(MAXEPOLLSIZE)) < 0)
    {
        log_err("epoll_create failure: %s\n", strerror(errno));
        goto CleanUp;
    }
    if( !debug )
    {
        if( set_daemon_running(pid_file) )
        {
            log_fatal("Set program \"%s\" running as daemon failure.\n", progname);
            goto CleanUp;
        }
    }
    cp_install_proc_signal();
    while( !g_cp_signal.stop )
    {
        /* Open comport if it's not opened  */
        if( !cvd_bind.comport->is_connted )
        {
            epoll_add_comport(epfd, cvd_bind.comport, cvd_bind.comport_dev);
        }
        /* Connect to host if not connected  */
        if( SOCK_STAT_CONNECTED != cvd_bind.sock.status )
        {
            epoll_add_socket(epfd, &cvd_bind.sock);
        }
        /* Epoll wait the added socket event  */
        nfds=epoll_wait(epfd, evts, MAXEPOLLSIZE, EPOLL_TIMEOUT);
        if (nfds < 0)
        {
            log_err("epoll_wait get error: %s\n", strerror(errno));
            continue;
        }
        for (i=0; i<nfds; ++i)
        {
            /* Comport get data arriving event happened */
            if ( evts[i].data.fd == cvd_bind.comport->fd )
            {
                nbytes = comport_recv(cvd_bind.comport, cvd_bind.buf, sizeof(cvd_bind.buf), COMPORT_TIMEOUT);
                if( nbytes>0 )
                {
                    if( SOCK_STAT_CONNECTED == cvd_bind.sock.status )
                    {
                        log_dbg("Transfer data from comport to socket\n");
                        write(cvd_bind.sock.fd, cvd_bind.buf, nbytes);
                    }
                    else
                    {
                        log_err("Receive data from serial port [%s] but socket to [%s:%d] disconnect.\n",
                                cvd_bind.comport->dev_name, cvd_bind.sock.host, cvd_bind.sock.port);
                    }
                }
            }
            /* Socket get data arriving event happened */
            else if ( evts[i].data.fd == cvd_bind.sock.fd )
            {
                nbytes = read(cvd_bind.sock.fd, cvd_bind.buf, sizeof(cvd_bind.buf));
                /* Socket disconnected  */
                if(nbytes == 0)
                {
                    log_warn("Socket[%d] connect to [%s:%d] disconnect\n",
                            cvd_bind.sock.fd, cvd_bind.sock.host, cvd_bind.sock.port);
                    epoll_del_fd(epfd, evts[i].data.fd);
                    cp_sock_close(&cvd_bind.sock);
                }
                /* Socket read error  */
                else if(nbytes < 0)
                {
                    log_warn("Read data from socket[%d] get error: %s, close socket now.\n",
                            cvd_bind.sock.fd, strerror(errno));
                    epoll_del_fd(epfd, evts[i].data.fd);
                    cp_sock_close(&cvd_bind.sock);
                }
                /* Socket read ok then transmiter to serial port  */
                else if( nbytes>0 )
                {
                    if( cvd_bind.comport->is_connted)
                    {
                        log_dbg("Transfer data from socket to comport\n");
                        write(cvd_bind.comport->fd, cvd_bind.buf, nbytes);
                    }
                    else
                    {
                        log_err("Receive data from socket to [%s:%d] but serial port [%s] disconnect.\n",
                                cvd_bind.sock.host, cvd_bind.sock.port, cvd_bind.comport->dev_name);
                    }
                }
            }
        }
    }
CleanUp:
    comport_term(cvd_bind.comport);
    cp_log_term();
    return 0;
}
void epoll_del_fd(int epfd, int fd)
{
    struct epoll_event     ev;
    log_warn("Remove fd[%d] from epoll\n", fd);
    ev.events = EPOLLIN | EPOLLET;
    epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev);
}
int epoll_add_comport(int epfd, COM_PORT *comport, char *comport_dev)
{
    int                    rv = -1;
    struct epoll_event     ev;
    if( comport_open(comport) < 0 )
    {
        rv = -2;
        log_err("Open comport '%s' as 115200 8N1N failure\n", comport_dev);
        goto failed;
    }
    ev.data.fd = comport->fd;
    ev.events = EPOLLIN | EPOLLET;
    if (epoll_ctl(epfd, EPOLL_CTL_ADD, comport->fd, &ev) < 0)
    {
        rv = -3;
        log_err("epoll add comport fd[%d] failure\n", comport->fd);
        goto failed;
    }
    log_nrml("Add comport [%s] to epoll ok\n", comport_dev);
    return 0;
failed:
    comport->fd = -1;
    return rv;
}
int epoll_add_socket(int epfd, cp_sock_t *sock)
{
    struct epoll_event     ev;
    if(SOCK_STAT_CONNECTED == sock->status)
        return 0;
    /* Try to connect to remote server again */
    cp_sock_connect(sock);
    if( SOCK_STAT_CONNECTED != sock->status )
    {
        return -1;
    }
    ev.data.fd = sock->fd;
    ev.events = EPOLLIN | EPOLLET;
    if (epoll_ctl(epfd, EPOLL_CTL_ADD, sock->fd, &ev) < 0)
    {
        log_err("epoll add socket[%d] failure\n", sock->fd);
        return -2;
    }
    log_nrml("Add socket[%d] connect to [%s:%d] to epoll ok\n", sock->fd, sock->host, sock->port);
    return 0;
}
program/converterd/cvd_main.h
New file
@@ -0,0 +1,40 @@
/********************************************************************************
 *      Copyright:  (C) 2014 GuoWenxue<guowenxue@email.com>
 *                  All rights reserved.
 *
 *       Filename:  cvd_main.h
 *    Description:  This head file
 *
 *        Version:  1.0.0(11/19/2014)
 *         Author:  GuoWenxue <guowenxue@email.com>
 *      ChangeLog:  1, Release initial version on "11/19/2014 02:35:33 PM"
 *
 ********************************************************************************/
#ifndef __CVD_MAIN_H_
#define __CVD_MAIN_H_
#include "cp_comport.h"
#include "cp_socket.h"
#define CVD_DEF_CONF_FILE  "/apps/etc/converterd.conf"
#define MAXEPOLLSIZE       2
#define BUF_SIZE           4096
#define EPOLL_TIMEOUT      2000
#define COMPORT_TIMEOUT    100
typedef struct comport_sock_bind_s
{
    char               buf[BUF_SIZE];              /*  Comport/Socket receive buffer  */
    char               comport_dev[DEVNAME_LEN];   /*  Receive/Transmit comport device name  */
    COM_PORT           *comport;                   /*  Receive/Transmit comport */
    cp_sock_t          sock;                       /*  Connected socket */
} comport_sock_bind_t;  /* ---  end of struct comport_sock_bind_s  ---*/
#endif
program/converterd/makefile
New file
@@ -0,0 +1,114 @@
#*********************************************************************************
#      Copyright:  (C) 2012 Guo Wenxue<Email:guowenxue@gmail.com>
#                  All rights reserved.
#
#       Filename:  Makefile
#    Description:  This Makefile used to call function to compile all the C source
#                  in current folder and links all the objects file into a excutable
#                  binary file.
#
#        Version:  1.0.0(10/08/2011~)
#                  Author:  Guo Wenxue <guowenxue@gmail.com>
#      ChangeLog:  1, Release initial version on "10/08/2011 01:29:33 AM"
#
#********************************************************************************/
PWD=$(shell pwd)
INSTPATH=/tftp
APP_BINARY_NAME = converterd
ARCH?=arm920t
#ARCH?=i386
LINK_MODE=STATIC
MODE=PRODUCTION
DEBUG=1
LDFLAGS+=-lpthread
CFLAGS+=-Wall -Werror
ifeq ("${MODE}", "PRODUCTION")
    CFLAGS+=-DPRODUCTION_MODE
endif
ifdef DEBUG
    CFLAGS+=-g -DDEBUG
endif
COMPILE_DATE=$(shell date -u +"%Y-%m-%d %H:%M")
VPATH= .
SRCS = $(wildcard ${VPATH}/*.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]")
ifneq (,$(filter i386,$(TMP)))
    CROSS_COMPILE=
else
    CROSS_COMPILE=/opt/xtools/arm920t/bin/arm-linux-
endif
CFLAGS+=-I${PWD}
export CC=${CROSS_COMPILE}gcc
export CXX=${CROSS_COMPILE}g++
export AR=${CROSS_COMPILE}ar
export AS=${CROSS_COMPILE}as
export RANLIB=${CROSS_COMPILE}ranlib
export STRIP=${CROSS_COMPILE}strip
export CFLAGS
export LDFLAGS
export ARCH
export LINK_MODE
ifeq ("${LINK_MODE}", "STATIC")
    CFLAGS+=--static
    LDFLAGS+=-static
else
    LDFLAGS+=-ldl
endif
all: entry version $(APP_BINARY_NAME)
    make install
entry:
    @echo " ";
    @echo " =========================================================";
    @echo " **        Compile ${APP_BINARY_NAME} for ${ARCH}         ";
    @echo " =========================================================";
version:
    @echo "/* Generated by makefile, don't Edit it by hand */" > version.h
    @echo "#define DATE \"$(COMPILE_DATE)\"" >> version.h
    @echo "#define MAJOR 1" >>version.h
    @echo "#define MINOR 0" >>version.h
    @echo "#define REVER 0" >>version.h
    @if [ -f .svn/entries ] ; then \
        echo "#define SVNVER `sed -n -e 11p .svn/entries`" >>version.h; \
    else \
        echo "#define SVNVER 0" >>version.h; \
    fi;
    @echo "" >> version.h
    @echo '#define version(progname) printf("%s Version %d.%d.%d Build @%05d (%s)\\n", progname, MAJOR, MINOR, REVER,SVNVER, DATE)'  >> version.h
    @echo '#define copyright() printf("Copyright:  (C) 2012 Guo Wenxue<Email:guowenxue@gmail.com\\n")' >>version.h
    @echo '#define banner(progname) {version(progname); copyright(); printf("\\n");}' >>version.h
    @echo "" >> version.h
$(APP_BINARY_NAME):    $(OBJS)
    $(CC)  -o $@ *.c ${LDFLAGS}
    @$(STRIP) $(APP_BINARY_NAME)
tag:
    @ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R .
    @cscope -Rbq
install:
    @cp $(APP_BINARY_NAME) ${INSTPATH}
clean:
    @rm -f version.h
    @rm -f *.o $(APP_BINARY_NAME)
    @rm -rf *.gdb *.a *.so *.elf*
distclean: clean
    @rm -f  tags cscope*
.PHONY: clean entry
program/cp_library/at91_ioctl.h
New file
@@ -0,0 +1,91 @@
/*********************************************************************************
 *    Copyright:  (C) Guo Wenxue<guowenxue@gmail.com>
 *                All ringhts reserved.
 *
 *     Filename:  at91_ioctl.h
 *  Description:  ioctl() cmd argument for driver definition here
 *
 *      Version:  1.0.0(05/15/2012~)
 *       Author:  Guo Wenxue <guowenxue@gmail.com>
 *    ChangeLog:  1, Release initial version on "05/15/2012 04:28:09 PM"
 *
 ********************************************************************************/
#ifndef __AT91_IOCTL_H
#define __AT91_IOCTL_H
#include <asm/ioctl.h>
#ifndef __KERNEL__
#include <sys/ioctl.h>
#endif
/*===========================================================================
 *                Common ioctl command definition
 *===========================================================================*/
#define PLATDRV_MAGIC           0x60
/*===========================================================================
 *                 ioctl command for all the drivers 0x01~0x0F
 *===========================================================================*/
/*args is enable or disable*/
#define SET_DRV_DEBUG               _IO (PLATDRV_MAGIC, 0x01)
#define GET_DRV_VER                 _IO (PLATDRV_MAGIC, 0x02)
/*===========================================================================
 *                 ioctl command for few ioctl() cmd driver 0x05~0x2F
 *===========================================================================*/
/* ADC driver */
#define GET_BATTERY_STAT            _IO (PLATDRV_MAGIC, 0x06)
#define GET_GMTUBE_VHIGH            _IO (PLATDRV_MAGIC, 0x08)
#define GET_GPRS_VBAT               _IO (PLATDRV_MAGIC, 0x09)
#define GET_ADC_DATA                _IO (PLATDRV_MAGIC, 0x10)
#define SET_ADC_INTERVEL            _IO (PLATDRV_MAGIC, 0x11)
/* Buzzer driver */
#define BUZZER_ON                   _IO (PLATDRV_MAGIC, 0x12)
#define BUZZER_BEEP                 _IO (PLATDRV_MAGIC, 0x13)
#define BUZZER_OFF                  _IO (PLATDRV_MAGIC, 0x14)
#define BUZZER_FREQ                 _IO (PLATDRV_MAGIC, 0x15)
/* Button driver */
#define GET_BUTTON_STATUS           _IO (PLATDRV_MAGIC, 0x17)
/* LED driver */
#define LED_OFF                     _IO (PLATDRV_MAGIC, 0x18)
#define LED_ON                      _IO (PLATDRV_MAGIC, 0x19)
#define LED_BLINK                   _IO (PLATDRV_MAGIC, 0x1A)
#define TURN_ALL_LED                _IO (PLATDRV_MAGIC, 0x1B)
/* Zigbee driver  */
#define ZIGBEE_RESET                _IO (PLATDRV_MAGIC, 0x1E)
#define ZIGBEE_STATUS               _IO (PLATDRV_MAGIC, 0x1F)
/*===========================================================================
 *                   ioctl command for GPS/GPRS driver 0x30~0x3F
 *===========================================================================*/
#define GSM_SET_POWER               _IO (PLATDRV_MAGIC, 0x30)  /* Set GPRS power On(1)/Off(0)/Reset(2) */
#define GSM_GET_POWER               _IO (PLATDRV_MAGIC, 0x31)  /* Get current GPRS power status */
#define GSM_GET_ADC                 _IO (PLATDRV_MAGIC, 0x32)  /* Get current GPRS power status */
#define GPS_SET_POWER               _IO (PLATDRV_MAGIC, 0x3A)  /* Set GPS power On(1)/Off(0) */
#define GPS_GET_POWER               _IO (PLATDRV_MAGIC, 0x3B)  /* Get current GPS power status */
/*===========================================================================
 *                   ioctl command for GM Tube driver 0x40~0x4F
 *===========================================================================*/
#define GM_SET_MEASURE_RADI         _IO (PLATDRV_MAGIC, 0x40)  /* Start/Stop GM tube radioation measurement */
#define GM_GET_MEASURE_DOSE         _IO (PLATDRV_MAGIC, 0x41)  /* Get sample radiation dose, arg=0:get last time, arg=1: Total*/
#define GM_SET_DUTY                 _IO (PLATDRV_MAGIC, 0x42)  /* Set GM tube PWM low duty */
#define GM_SET_INTERVAL             _IO (PLATDRV_MAGIC, 0x43)  /* Set GM tube timer interval */
#define GM_GET_VOLTAGE              _IO (PLATDRV_MAGIC, 0x44)  /* Get GM tube high voltage */
#define GM_SET_POWER                _IO (PLATDRV_MAGIC, 0x45)  /* Enable/Disable GM tube 3.3V power */
#define GM_SET_PWM_TC               _IO (PLATDRV_MAGIC, 0x46)  /* Start/Stop GM tube pwm output TC*/
#define GM_SET_MEASURE_TC           _IO (PLATDRV_MAGIC, 0x47)  /* Start/Stop GM tube measurement TC */
#define GM_SET_TIMER_TC             _IO (PLATDRV_MAGIC, 0x48)  /* Start/Stop GM tube timer TC*/
#endif                          /* End of __AT91_IOCTL_H */
program/cp_library/cp_array.c
New file
@@ -0,0 +1,168 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_array.c
 *    Description:  This file is a dynamic array implement
 *
 *        Version:  1.0.0(12/20/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "12/20/2012 01:48:27 PM"
 *
 ********************************************************************************/
#include <stdlib.h>
#include "cp_array.h"
#include "cp_common.h"
#include "cp_logger.h"
CP_ARRAY *cp_array_init(CP_ARRAY *array, int size)
{
    int        i;
    if( !array )
    {
        if( !(array=t_malloc(sizeof(*array))) )
        {
            return NULL;
        }
        else
        {
            memset(array, 0, sizeof(*array));
            array->flag |= CP_ARRAY_FLAG_MALLOC;
        }
    }
    else
    {
        /* array is a variable,so clear it */
        memset(array, 0, sizeof(*array));
    }
    array->size = size;
    if( !array->data && !(array->data=(void **)malloc(array->size*sizeof(void *))) )
    {
        cp_array_term(array);
        return NULL;
    }
    for(i=0; i<array->size; i++)
    {
        array->data[i] = NULL;
    }
    return array;
}
void cp_array_term(CP_ARRAY *array)
{
    if(!array)
        return;
    if(array->data)
        t_free(array->data);
    if(array->flag&CP_ARRAY_FLAG_MALLOC)
    {
        t_free(array);
    }
    return ;
}
int cp_array_add(CP_ARRAY *array, void *data)
{
    int              i;
    void             *entry;
    if(!array || !data)
    {
        log_err("Invalude input arguments\n");
        return -1;
    }
    /* array already full */
    if(array->items >= array->size)
    {
        log_err("array is full,can not add data [%p]\n", data);
        return -2;
    }
    /* We don't start the array from 0 but 1 */
    cp_list_array_for_each(array, i, entry)
    {
        if( !entry )
        {
            log_dbg("Array[%d] add data[%p] ok\n", i, data);
            array->data[i] = data;
            array->items ++;
            break;
        }
    }
    return i;
}
void cp_array_rm_byindex(CP_ARRAY *array, int index)
{
    /* We don't start the array from 0 but 1 */
    if(!array || index<0)
    {
        log_err("Invalude input arguments\n");
        return;
    }
    if(array->data[index])
    {
        array->items --;
        array->data[index] = NULL;
    }
}
int cp_array_rm_bydata(CP_ARRAY *array, void *data)
{
    int              i, rv = -3;
    void             *entry;
    if(!array || !data)
    {
        log_err("Invalude input arguments\n");
        return -1;
    }
    if(array->items <= 0)
    {
        log_err("array is empty,can not remove data [%p]\n", data);
        return -2;
    }
    /* We don't start the array from 0 but 1 */
    cp_list_array_for_each(array, i, entry)
    {
        if( entry == data )
        {
            array->items --;
            array->data[i] = NULL;
            rv = 0;
            break;
        }
    }
    return rv;
}
void cp_array_travel(CP_ARRAY *array)
{
    int              i;
    void             *data;
    /* We don't start the array from 0 but 1 */
    cp_list_array_for_each(array, i, data)
    {
        log_dbg("array data[%d] save data [%p]\n", i, data);
    }
    return ;
}
program/cp_library/cp_array.h
New file
@@ -0,0 +1,41 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_array.h
 *    Description:  This head file is for the dynaic array implement
 *
 *        Version:  1.0.0(12/20/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "12/20/2012 01:49:11 PM"
 *
 ********************************************************************************/
#ifndef __CP_ARRAY_H
#define __CP_ARRAY_H
#define CP_ARRAY_FLAG_MALLOC     (1<<0)
typedef struct _CP_ARRAY
{
    unsigned char          flag;
    int                    size;
    int                    items;
    void                   **data;
} CP_ARRAY;
#define cp_array_is_full(arr)  ( (arr)->size-1==(arr)->items ? 1 :0 )
#define cp_array_is_empty(arr) ( 0==(arr)->items ? 1 : 0)
#define cp_array_count(arr) ( (arr)->items )
#define cp_array_size(arr) ( (arr)->size-1 )
#define cp_list_array_for_each(arr, i, entry)  for(i=0,entry=arr->data[i]; i<arr->size; ++i,entry=i<arr->size?arr->data[i]:NULL)
CP_ARRAY *cp_array_init(CP_ARRAY *array, int size);
void cp_array_term(CP_ARRAY *array);
int cp_array_add(CP_ARRAY *array, void *data);
void cp_array_rm_byindex(CP_ARRAY *array, int index);
int cp_array_rm_bydata(CP_ARRAY *array, void *data);
void cp_array_travel(CP_ARRAY *array);
#endif /* __CP_ARRAY_H  */
program/cp_library/cp_atcmd.c
New file
@@ -0,0 +1,668 @@
/*********************************************************************************
 *      Copyright:  (C) guowenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_atcmd.c
 *    Description:  This is file is used to send AT command to GPRS module.
 *
 *        Version:  1.0.0(02/02/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "02/02/2012 10:28:44 AM"
 *
 ********************************************************************************/
#include "cp_atcmd.h"
#include "cp_string.h"
#include "cp_logger.h"
#include "cp_time.h"
#ifndef ATCMD_REPLY_LEN
#define ATCMD_REPLY_LEN          512
#endif
/*
 *  Description: Send the AT command which modem will only reply "OK" or "ERROR",
 *               such as AT,ATE0,AT+CNMP=2 etc.
 *
 * Return Value:  0: OK     -X: ERROR
 */
int send_atcmd_check_ok(COM_PORT *comport, char *atcmd, unsigned long timeout)
{
    int  retval;
    retval = send_atcmd(comport, atcmd, "OK\r\n", "ERROR\r\n", timeout, NULL, 0);
    return 0==retval ? 0 : -2;
}
/*
 *  Description: Send the AT command which will reply the value directly in a
 *               single line, such as AT+CGMM, AT+CGSN
 *
 * Output Value: Buf: The AT command query value
 * Return Value:  0: OK     -X: ERROR
 *
 */
int send_atcmd_check_value(COM_PORT *comport, char *atcmd, unsigned long timeout, char *buf, int buf_len)
{
    int         i = 0;
    int         retval=0;
    char        tmp[ATCMD_REPLY_LEN];
    char        *start;
    if(NULL==buf)
    {
        log_err("Function call arguments error!\n");
        return -1;
    }
    memset(tmp, 0, sizeof(tmp));
    retval = send_atcmd(comport, atcmd, "OK\r\n", "ERROR\r\n", timeout, tmp, sizeof(tmp));
    if( 0 != retval)
    {
        return -2;  /* AT command can not get reply  */
    }
    /* Parser the receive string to get the expect value*/
    if(NULL != (start=strchr(tmp, '\n')) )
    {
        start ++;  /* Skip '\n' character */
        while(*start!='\r' && i<buf_len-1)
        {
            buf[i++] = *start;
            start ++;
        }
    }
    buf[i] = '\0'; /* End of the string */
    return ('\0'==buf[0] ? -3 : 0);
}
/*
 *  Description: Send the AT command which will reply the value with a prefix "+CMD: "
 *               single line, such as AT+CGMR  AT+CPIN? AT+CNMP? AT+CSQ
 *
 * Output Value: Buf: The AT command query value by remove "+XXX:" prefix
 * Return Value:  0: OK     -X: ERROR
 *
 */
int send_atcmd_check_request(COM_PORT *comport, char *atcmd, unsigned long timeout, char *buf, int buf_len)
{
    int         retval;
    int         i = 0;
    char        tmp[ATCMD_REPLY_LEN];
    char        *ptr = NULL;
    if(NULL==buf)
    {
        log_err("%s() call arguments error!\n", __FUNCTION__);
        return -1;
    }
    memset(tmp, 0, sizeof(tmp));
    retval = send_atcmd(comport, atcmd, "OK\r\n", "ERROR\r\n", timeout, tmp, sizeof(tmp));
    if( 0 != retval)
    {
        return -2;
    }
    /* Parser the receive string to get the expect value*/
    if(NULL != (ptr=strchr (tmp, ':')) )
    {
        ptr += 2; /* Skip the ':' and SPACE character */
        while(*ptr!='\r' && i<buf_len-1)
        {
            buf[i++] = *ptr;
            ptr ++;
        }
    }
    buf[i] = '\0'; /* End of the string */
    return ('\0'==buf[0] ? -3 : 0);
}
/*
 *  Description: Send ATE0 command to the GSM module to check GSM module ready or not
 * Return Value: 0: Success  !0:Failure
 */
int atcmd_check_at_ready(COM_PORT *comport)
{
    int    retval;
    retval=send_atcmd_check_ok(comport, "ATE0\r", 500);
    if(retval)
    {
        log_err("ATE0 check AT command ready             [FAILED]\n");
    }
    else
    log_nrml("ATE0 check AT command ready           [OK]\n");
    return retval;
}
/*
 *  Description: Send AT+CPIN? command to the GSM module to check SIM card exist or not
 * Return Value: 0: Success  !0:Failure
 */
int atcmd_check_sim_valid(COM_PORT *comport)
{
    int         retval = 0;
    char        recv_buf[ATCMD_REPLY_LEN];
    retval = send_atcmd_check_request(comport, "AT+CPIN?\r", 800, recv_buf, sizeof(recv_buf));
    if(0x00 != retval)
    {
        retval = 1;
        log_warn("AT+CPIN? Check SIM Validation:          [FAILED]\n");
        return retval;
    }
    if(strstr(recv_buf, "READY"))
    {
        log_nrml("AT+CPIN? Check SIM Validataion:       [OK]\n");
        return 0;
    }
    else
        return -1;
}
/*  Send AT+CSQ command to check GPRS signal*/
int atcmd_check_gprs_signal(COM_PORT *comport)
{
    char        recv_buf[ATCMD_REPLY_LEN];
    int         retval;
    int         signal = -1;
    memset(recv_buf, 0, sizeof(recv_buf));
    retval = send_atcmd_check_request(comport, "AT+CSQ\r", 3000, recv_buf, sizeof(recv_buf));
    if( 0 !=  retval)
    {
        log_err("AT+CSQ Check Signal Strength:          [FAILED]\n");
        return retval;
    }
    split_string_to_value(recv_buf, "%d,%d", &signal, NULL);
    log_nrml("AT+CSQ Check Signal Strength:         [%d]\n", signal);
    return signal;
}
/* Send AT+CREG? command to check SIM card register status */
int atcmd_check_gprs_register(COM_PORT *comport)
{
    int         retval, stat = -1;
    char        recv_buf[ATCMD_REPLY_LEN];
    memset(recv_buf, 0, sizeof(recv_buf));
    retval = send_atcmd_check_request(comport, "AT+CREG?\r", 3000, recv_buf, sizeof(recv_buf));
    if( 0 !=  retval)
    {
        log_err("AT+CREG? Check SIM card Register:      [FAILED]\n");
        return stat;
    }
    split_string_to_value(recv_buf, "%d,%d", NULL, &stat);
    log_nrml("AT+CREG? Check SIM Card Register:     [%d]\n", stat);
    return stat;
}
int atcmd_check_gprs_carrier(COM_PORT *comport, char *carrier)
{
    int               retval;
    char              recv_buf[ATCMD_REPLY_LEN];
    if(carrier == NULL)
    {
        return -1;
    }
    retval = send_atcmd_check_request(comport, "AT+COPS?\r", 5000, recv_buf, sizeof(recv_buf));
    if(retval)
    {
        log_warn("AT+COPS? Check SIM Card Carrier:        [FAILED]\n");
        return retval;
    }
    split_string_to_value(recv_buf, "%d,%d,%s,%d", NULL, NULL, carrier, NULL);
    del_char_from_string(carrier, '\"');
    log_nrml("AT+COPS? Check SIM Card Carrier:      [%s]\n", carrier);
    return 0;
}
int atcmd_check_gprs_mcc_mnc(COM_PORT *comport, char *mcc_mnc)
{
    int               retval;
    char              recv_buf[ATCMD_REPLY_LEN];
    int               status;
    char              mcc[5];
    char              mnc[5];
    char              *ptr = NULL;
    retval=send_atcmd_check_ok(comport, "AT+QENG=1\r", 1000);
    if(retval)
    {
        log_err("Send AT command AT+QENG=1 failure\n");
        return retval;
    }
    retval = send_atcmd(comport, "AT+QENG?\r", "OK\r\n", "ERROR\r\n", 5000, recv_buf, sizeof(recv_buf));
    if(retval)
    {
        log_err("AT+QENG? Check GPRS MCC and MNC failure\n");
        return retval;
    }
    /* AT+QENG? respond value:
     * +QENG: 1,0
     * +QENG: 0,460,00,7108,80c4,554,41,-95,18,50,0,10,x,x,x,x,x,x,x
     */
    if(NULL != (ptr=strrchr (recv_buf, ':')) )
    {
        split_string_to_value(ptr, "%d,%s,%s,%s", &status, mcc, mnc, NULL);
        if(!status)
        {
            sprintf(mcc_mnc, "%s-%s", mcc, mnc);
            log_nrml("AT+QGSMLOC=1 Check GPRS Location MCC-MNC: %s\n", mcc_mnc);
            return 0;
        }
    }
    printf("ptr: %s\n", ptr);
    return -1;
}
int atcmd_check_gprs_location(COM_PORT *comport, GPRS_LOCATION *loc)
{
    int               retval;
    char              recv_buf[ATCMD_REPLY_LEN];
    int               status;
    retval=send_atcmd_check_ok(comport, "AT+QIFGCNT=0\r", 1000);
    if(retval)
    {
        log_warn("Send AT command AT+QIFGCNT=0 failure\n");
        return retval;
    }
    retval = send_atcmd_check_request(comport, "AT+QGSMLOC=1\r", 10000, recv_buf, sizeof(recv_buf));
    if(retval)
    {
        log_warn("AT+QGSMLOC=1 Check GPRS Location:         [FAILED]\n");
        return retval;
    }
    /* +QGSMLOC: 0,114.389210,30.500380,2013/01/16,14:03:12, it's GMT time  */
    split_string_to_value(recv_buf, "%d,%s,%s,%s,%s", &status, loc->longitude, loc->latitude, loc->date, loc->time);
    if(status) /* Get LOC failure */
    {
        memset(loc->longitude, 0, sizeof(loc->longitude));
        memset(loc->latitude, 0, sizeof(loc->latitude));
        memset(loc->date, 0, sizeof(loc->date));
        memset(loc->time, 0, sizeof(loc->time));
        log_warn("AT+QGSMLOC=1 Check GPRS Location failure: %s\n", recv_buf);
        return -1;
    }
    log_nrml("GPRS location result=%d latitude,longitude: [%s,%s]\n", status, loc->latitude, loc->longitude);
    log_nrml("GPRS Date and time: %s,%s\n", loc->date, loc->time);
    return retval;
}
int atcmd_set_network_mode(COM_PORT *comport, int mode)
{
    int              retval;
    char             atcmd[64]={0};
    sprintf (atcmd, "AT+CNMP=%d\r", mode);
    if(0 != (retval=send_atcmd_check_ok(comport, atcmd, 3000)) )
    {
        log_warn("AT+CNMP Set Network Mode as %d:      [FAILED]\n", mode);
        return retval;
    }
    log_nrml("AT+CNMP=%d Set Network Mode:          [OK]\n", mode);
    /* AT+CNAOP=?: 0->Automatic, 1->GSM,WCDMA, 2->WCDMA,GSM */
    strncpy (atcmd, "AT+CNAOP=2\r", sizeof(atcmd));
    if(0 != (retval=send_atcmd_check_ok(comport, atcmd, 3000)) )
    {
        log_warn("AT+CNAOP=2 Set Acquisitions order preference to WCDMA,GSM     [FAILED]\n");
        return retval;
    }
    log_nrml("AT+CNAOP=2 Set Network Preference     [OK]\n");
    return 0;
}
int atcmd_check_gprs_name(COM_PORT *comport, char *name)
{
    int               retval;
    char              recv_buf[ATCMD_REPLY_LEN];
    if(name == NULL)
    {
        return -1;
    }
    retval = send_atcmd_check_value(comport, "AT+CGMM\r", 5000, recv_buf, sizeof(recv_buf));
    if(retval)
    {
        log_warn("AT+CGMM Check GPRS Module Name:         [FAILED]\n");
        return retval;
    }
    strcpy(name, recv_buf);
    log_nrml("AT+CGMM Check GPRS Module Name:       [%s]\n", name);
    return 0;
}
int atcmd_check_gprs_version(COM_PORT *comport, char *version)
{
    int               retval;
    char              recv_buf[ATCMD_REPLY_LEN];
    if(version == NULL)
    {
        return -1;
    }
    retval = send_atcmd_check_request(comport, "AT+CGMR\r", 5000, recv_buf, sizeof(recv_buf));
    if(retval)
    {
        log_warn("AT+CGMR Check GPRS Module Version:      [FAILED]\n");
        return retval;
    }
    strcpy(version, recv_buf);
    log_nrml("AT+CGMR Check GPRS Module Version:    [%s]\n", version);
    return 0;
}
int atcmd_check_gprs_iemi(COM_PORT *comport, char *iemi)
{
    int               retval;
    char              recv_buf[ATCMD_REPLY_LEN];
    if(iemi == NULL)
    {
        return -1;
    }
    retval = send_atcmd_check_value(comport, "AT+CGSN\r", 5000, recv_buf, sizeof(recv_buf));
    if(retval)
    {
        log_warn("AT+CGSN Check GPRS Module IEMI:      [FAILED]\n");
        return retval;
    }
    strcpy(iemi, recv_buf);
    log_nrml("AT+CGSN Check GPRS Module IEMI:       [%s]\n", iemi);
    return 0;
}
int atcmd_check_gprs_network(COM_PORT *comport, int *network)
{
    int               retval;
    char              recv_buf[ATCMD_REPLY_LEN];
    if(network == NULL)
    {
        return -1;
    }
    retval = send_atcmd_check_request(comport, "AT+CNSMOD?\r", 5000, recv_buf, sizeof(recv_buf));
    if(retval)
    {
        log_warn("AT+CNSMOD Check Network Mode:        [FAILED]\n");
        return retval;
    }
    split_string_to_value(recv_buf, "%d,%d", NULL, network);
    log_nrml("AT+CNSMOD? Check Network Mode:        [%d]\n", *network);
    return 0;
}
int atcmd_set_apn(COM_PORT *comport, char *apn)
{
    char             atcmd[64]={0};
    int              retval;
    sprintf (atcmd, "AT+CGDCONT=1,\"IP\",\"%s\"\r", apn);
    if(0 != (retval=send_atcmd_check_ok(comport, atcmd, 2000)) )
    {
        log_err("AT+CGDCONT Set APN as \"%s\"         [FAILED]\n", apn);
        return retval;
    }
    log_nrml("AT+CGDCONT Set APN as \"%s\"          [OK]\n");
    return retval;
}
unsigned char at_match (char *p_pcStr, char *p_pcMatch)
{
    char                    acBuf [256],
                            *pcStart = NULL,
                            *pcTab   = NULL;
    pcStart = p_pcMatch;
    while (0 != pcStart)
    {
        memset (acBuf, 0x00, sizeof (acBuf));
        pcTab = strchr (pcStart, 9);    // Find for TAB
        if (0 != pcTab)
        {
            if (pcTab != pcStart)
            {
                strncpy (acBuf, pcStart, pcTab - pcStart);
            }
            pcStart = (0 != *(++pcTab)) ? pcTab : 0;
        }
        else
        {
            strcpy (acBuf, pcStart);
            pcStart = NULL;
        }
        if (0 != acBuf [0] && 0 != strstr (p_pcStr, acBuf))
        {
            return 0x00;
        }
    }
    return 0x01;
}
/*=========================================================================================================
 * Parameter Description:
 *     COM_PORT    *comport:  The GPRS module data port(/dev/ttyS2);
 *     char          *atCmd:  The AT command which will be sent to GPRS module
 *     char         *expect:  The EXPECT reply string by GPRS module for the AT command, such as "OK"
 *     char          *error:  The ERROR  reply string by GPRS module for the AT command, such as "ERROR"
 *   unsigned long  timeout:  Read from data port timeout value
 *     char           reply:  The AT command reply output buffer
 *     int        reply_len:  The AT command reply output buffer length
 *
 * Return Value:
 *     int           retval:   0->command send OK and "expect" string mached. !0->failure
 *     char        *content:   The AT command reply string by modem.
 *
 *=========================================================================================================*/
int send_atcmd(COM_PORT *comport, char *atCmd, char *expect, char *error,
              unsigned long timeout, char *reply, int reply_len)
{
    int                  retval = -1;
    unsigned long        delay = 200;
    unsigned long        gap = 300;
    unsigned long        ulStartTime;
    int                  iCmdLen = 0,
                         iRecvLen = 0,
                         iRecvSize = 0,
                         iSize = 0;
    char                 acRecv[1024];
    char                 *pcRecvPtr = NULL;
    if(comport->is_connted != 0x01) /* Comport not opened */
    {
        log_dbg("Comport not opened.\n");
        return  -1;
    }
#if 0
    /*=========================================
     *=  Pause a while before send AT command =
     *=========================================*/
    if(0 != delay)
    {
        ulStartTime = time_now();
        while (time_elapsed(ulStartTime) < delay)
        {
            micro_second_sleep(1);
        }
    }
#endif
    /*====================
     *=  Throw Rubbish   =
     *====================*/
    ulStartTime = time_now();
    memset(&acRecv, 0, sizeof(acRecv));
    while (time_elapsed(ulStartTime) < delay)
    {
        iSize = comport_recv(comport, acRecv, 1, 50);
        if(iSize <= 0)
        {
            break;
        }
        micro_second_sleep(1);
    }
    /*====================
     *=  Send AT command =
     *====================*/
    iCmdLen = strlen(atCmd);
    retval = comport_send (comport, atCmd, iCmdLen);
    if (0 != retval)
    {
        retval = 0x02;
        goto  CleanUp;
    }
    /*===================================================
     *=  Pause a while before read command response.
     *===================================================*/
    if(0 != gap)
    {
        ulStartTime = time_now();
        while (time_elapsed(ulStartTime) < gap)
        {
            micro_second_sleep(1);
        }
    }
    memset (acRecv, 0, sizeof (acRecv));
    pcRecvPtr = acRecv;
    iRecvLen = 0;
    iRecvSize = sizeof (acRecv);
    retval = -1;
    ulStartTime = time_now();
    while (time_elapsed(ulStartTime) < timeout)
    {
        if ( iRecvLen < (iRecvSize-1) )
        {
            iSize = comport_recv (comport, pcRecvPtr, 1, 50);
            if (iSize >0)
            {
                iRecvLen += iSize;
                pcRecvPtr += iSize;
                acRecv [iRecvSize-1] = 0;
                /*========================================
                 * Match the received with expect String =
                 *========================================*/
                if(NULL != expect)
                {
                    if (0x00 == at_match(acRecv, expect))
                    {
                        retval = 0;
                        goto CleanUp;
                    }
                }
                /*========================================
                 * Match the received with error String  =
                 *========================================*/
                if(NULL != error)
                {
                    if (0x00 == at_match(acRecv, error))
                    {
                        retval = -3;
                        goto CleanUp;
                    }
                }
            } /*End of (iSize > 0)  */
        } /* End of (iRecvLen < (iRecvSize-1))  */
        micro_second_sleep(1);
    } /* End of time_elapsed(ulStartTime) < timeout */
    if(NULL==expect)
        retval = 0x00;
    else
        retval = -4;
CleanUp:
    //printf("acRecv:\n %s\n", acRecv);
    if( NULL != reply)
    {
        strncpy(reply, acRecv, reply_len);
    }
#if 1  /* Log the command result to log system  */
    {
        char   log[512] = {0};
        snprintf(log, 512, "Send AT command: \"%s\" get reply \"%s\"", atCmd, acRecv);
        int i = 0;
        for (i=0; i<512; i++)
        {
            if('\r'==log[i] || '\n'==log[i] || '\t'==log[i])
            {
                log[i]=' ';
            }
            else if (0 == log[i])
            {
                break;
            }
        }
        log_info("%s\n", log);
    }
#endif
    return retval;
}
program/cp_library/cp_atcmd.h
New file
@@ -0,0 +1,68 @@
/********************************************************************************
 *      Copyright:  (C) guowenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  atcmd.h
 *    Description:  This is the head file for atcmd.c
 *
 *        Version:  1.0.0(05/15/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "05/15/2012 05:31:10 PM"
 *
 ********************************************************************************/
#ifndef __CP_ATCMD_H
#define __CP_ATCMD_H
#include "cp_comport.h"
/* AT+CPSI command return important result*/
typedef struct _GPRS_LOCATION
{
    char            longitude[15];
    char            latitude[15];
    char            date[15];
    char            time[15];
    char            mcc_mnc[16];/*   Mobile Country Code, China is 460 */
} GPRS_LOCATION;
typedef struct _REGISTER_INFO
{
    int             type;       /*  SIM card register type: REG_HOMEWORK,REG_SEARCHING... */
    int             signal;     /*  GPRS signal */
    char            carrier[64];/*  Network operator */
    GPRS_LOCATION   loc;        /*  Location */
} REGISTER_INFO;
typedef struct _HARDWARE_INFO
{
    char            model[64];  /*  AT+CGMM check GPRS module model */
    char            mrev[64];   /*  AT+CGMR check GPRS module revision */
    char            iemi[64];   /*  AT+CGSN check GPRS module IEMI(International Mobile station Equipment Identity) number */
} HW_INFO;
extern int send_atcmd(COM_PORT *st_comport, char *atCmd, char *expect, char *error,
       unsigned long timeout, char *reply, int reply_len);
extern int send_atcmd_check_ok(COM_PORT *comport, char *atcmd, unsigned long timeout);
extern int send_atcmd_check_value(COM_PORT *comport, char *atcmd, unsigned long timeout, char *buf, int buf_len);
extern int send_atcmd_check_request(COM_PORT *comport, char *atcmd, unsigned long timeout, char *buf, int buf_len);
extern int atcmd_check_at_ready(COM_PORT *comport); /* Send ATE0 command */
extern int atcmd_check_sim_valid(COM_PORT *comport); /* Send AT+CPIN? command */
extern int atcmd_check_gprs_signal(COM_PORT *comport); /* Send AT+CSQ command */
extern int atcmd_check_gprs_register(COM_PORT *comport);
extern int atcmd_check_gprs_carrier(COM_PORT *comport, char *carrier);
extern int atcmd_check_gprs_name(COM_PORT *comport, char *name);
extern int atcmd_check_gprs_version(COM_PORT *comport, char *version);
extern int atcmd_check_gprs_iemi(COM_PORT *comport, char *iemi);
extern int atcmd_check_gprs_network(COM_PORT *comport, int *network);
extern int atcmd_check_gprs_location(COM_PORT *comport, GPRS_LOCATION *location);
extern int atcmd_check_gprs_mcc_mnc(COM_PORT *comport, char *mcc_mnc);
extern int atcmd_set_network_mode(COM_PORT *comport, int mode);
extern int atcmd_set_apn(COM_PORT *comport, char *apn);
#endif /* _CP_ATCMD_H */
program/cp_library/cp_common.h
New file
@@ -0,0 +1,68 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_common.h
 *    Description:  This head file is for some common definition
 *
 *        Version:  1.0.0(11/13/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/13/2012 01:48:01 PM"
 *
 ********************************************************************************/
#ifndef __CP_COMMON_H
#define __CP_COMMON_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#define container_of(ptr, type, member) ({   \
        const typeof( ((type *)0)->member ) *__mptr = (ptr); \
        (type *)( (char *)__mptr - offsetof(type,member) );})
//#define MEM_LEAK_CHECK
static inline void *_t_malloc(size_t size
#ifdef MEM_LEAK_CHECK
, const char *file, unsigned int line
#endif
        )
{
    void *ptr;
    if ((ptr = malloc (size)))
        memset (ptr, 0, size);
#ifdef MEM_LEAK_CHECK
    printf ("MALLOC,0x%p @%s:%u\n", ptr, file, line);
#endif
    return ptr;
}
static inline void _t_free(void *ptr
#ifdef MEM_LEAK_CHECK
, const char *file, unsigned int line
#endif
        )
{
#ifdef MEM_LEAK_CHECK
    printf ("FREE,0x%p @%s:%u\n", ptr, file, line);
#endif
    free(ptr);
}
#ifdef MEM_LEAK_CHECK
#define t_free(p)    if(p){ _t_free(p, __FILE__, __LINE__); p=NULL; }
#define t_malloc(s)  _t_malloc(s, __FILE__, __LINE__)
#else
#define t_free(p)    if(p){ _t_free(p); p=NULL; }
#define t_malloc(s)  _t_malloc(s)
#endif
#endif
program/cp_library/cp_comport.c
New file
@@ -0,0 +1,600 @@
/*  ********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_comport.c
 *    Description:  It's the comport operate library.
 *
 *        Version:  1.0.0(10/17/2011~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/17/2011 03:33:25 PM"
 *
 ********************************************************************************/
#include    "cp_comport.h"
/**************************************************************************************
 *  Description: Set the comport structure
 *   Input Args: dev_name:  The comport device name path, such as '/dev/ttyS3'
 *               baudrate:  The baudrate, such as 115200
 *               settings:  The databit,parity,stopbit,flowctrl settings, such as '8N1N'
 *  Output Args: NONE
 * Return Value: The COM_PORT structure pointer.
 *************************************************************************************/
COM_PORT *comport_init(const char *dev_name, int baudrate, const char *settings)
{
    COM_PORT *comport = NULL;
    if (NULL == (comport = (COM_PORT *) malloc(sizeof(COM_PORT))))
    {
        return NULL;
    }
    memset(comport, 0, sizeof(COM_PORT));
    comport->is_connted = 0;
    comport->frag_size = 128;
    strncpy(comport->dev_name, dev_name, DEVNAME_LEN);
    comport->baudrate = baudrate;
    set_settings(comport, settings);
#ifdef  COM_DEBUG
    disp_settings(comport);
#endif
    return comport;
}
#ifdef  COM_DEBUG
void disp_settings(COM_PORT * comport)
{
    COM_PRINT("Device:\t\t\t\"%s\"\n", comport->dev_name);
    COM_PRINT("Baudrate:\t\t%ld\n", comport->baudrate);
    COM_PRINT("DataBit:\t\t\'%d\'\n", comport->databit);
    switch (comport->parity)
    {
      case 0:
          COM_PRINT("Parity:\t\t\t\'N\'\n");
          break;
      case 1:
          COM_PRINT("Parity:\t\t\t\'O\'\n");
          break;
      case 2:
          COM_PRINT("Parity:\t\t\t\'E\'\n");
          break;
      case 3:
          COM_PRINT("Parity:\t\t\t\'S\'\n");
          break;
    }
    COM_PRINT("StopBit:\t\t\'%ld\'\n", (long int)comport->stopbit);
    switch (comport->flowctrl)
    {
      case 0:
          COM_PRINT("FlowCtrl:\t\t\'N\'\n");
          break;
      case 1:
          COM_PRINT("FlowCtrl:\t\t\'S\'\n");
          break;
      case 2:
          COM_PRINT("FlowCtrl:\t\t\'H\'\n");
          break;
      case 3:
          COM_PRINT("FlowCtrl:\t\t\'B\'\n");
          break;
    }
    COM_PRINT("\n");
    return;
}
#endif
/**************************************************************************************
 *  Description: Set the comport databit,parity,stopbit,flowctrl
 *   Input Args: comport: the COM_PORT pointer
 *               settings: The databit/parity/stopbit/flowctrl settings as like "8N1N"
 *  Output Args: NONE
 * Return Value: NONE
 *************************************************************************************/
void set_settings(COM_PORT * comport, const char *settings)
{
    if(NULL==settings || NULL==comport)
        return ;
    switch (settings[0])        /* data bit */
    {
      case '7':
          comport->databit = 7;
          break;
      case '8':
      default:
          comport->databit = 8;
          break;
    }
    switch (settings[1])        /* parity */
    {
      case 'O':
      case 'o':
          comport->parity = 1;
          break;
      case 'E':
      case 'e':
          comport->parity = 2;
          break;
      case 'S':
      case 's':
          comport->parity = 3;
          break;
      case 'N':
      case 'n':
      default:
          comport->parity = 0;
          break;
    }
    switch (settings[2])        /* stop bit */
    {
      case '0':
          comport->stopbit = 0;
          break;
      case '1':
      default:
          comport->stopbit = 1;
          break;
    }
    switch (settings[3])        /* flow control */
    {
      case 'S':
      case 's':
          comport->flowctrl = 1;
          break;
      case 'H':
      case 'h':
          comport->flowctrl = 2;
          break;
      case 'B':
      case 'b':
          comport->flowctrl = 3;
          break;
      case 'N':
      case 'n':
      default:
          comport->flowctrl = 0;
          break;
    }
}
void comport_close(COM_PORT * comport)
{
    if (0 != comport->fd)
    {
        COM_PRINT("Close device \"%s\"\n", comport->dev_name);
        close(comport->fd);
    }
    comport->is_connted = 0x00;
    comport->fd = -1;
}
void comport_term(COM_PORT * comport)
{
    if(NULL == comport)
        return;
    if (0 != comport->fd)
    {
        comport_close(comport);
    }
    memset(comport, 0x00, sizeof(COM_PORT));
    free(comport);
    comport = NULL;
    return;
}
int comport_open(COM_PORT * comport)
{
    int retval = -1;
    struct termios old_cfg, new_cfg;
    int old_flags;
    long tmp;
    if(NULL==comport)
        return -1;
    comport_close(comport);
    /* Not a TTY device */
    if( !strstr(comport->dev_name, "tty"))
    {
        COM_PRINT("Open Not tty device \"%s\"\n", comport->dev_name);
        comport->fd = open(comport->dev_name, O_RDWR);
        retval = comport->fd<0 ? -2 : comport->fd;
        goto CleanUp;
    }
    comport->fd = open(comport->dev_name, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (comport->fd < 0)
    {
        retval = -3;
        goto CleanUp;
    }
    COM_PRINT("Open device \"%s\"\n", comport->dev_name);
    if ((-1 != (old_flags = fcntl(comport->fd, F_GETFL, 0)))
        && (-1 != fcntl(comport->fd, F_SETFL, old_flags & ~O_NONBLOCK)))
    {
        // Flush input and output
        if (-1 == tcflush(comport->fd, TCIOFLUSH))
        {
            retval = -4;
            goto CleanUp;
        }
    }
    else                        // Failure
    {
        retval = -5;
        goto CleanUp;
    }
    if (0 != tcgetattr(comport->fd, &old_cfg))
    {
        retval = -6;          // Failed to get Com settings
        goto CleanUp;
    }
    memset(&new_cfg, 0, sizeof(new_cfg));
    /*=====================================*/
    /*       Configure comport         */
    /*=====================================*/
    new_cfg.c_cflag &= ~CSIZE;
    new_cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    new_cfg.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
    new_cfg.c_oflag &= ~(OPOST);
    /* Set the data bit */
    switch (comport->databit)
    {
      case 0x07:
          new_cfg.c_cflag |= CS7;
          break;
      case 0x06:
          new_cfg.c_cflag |= CS6;
          break;
      case 0x05:
          new_cfg.c_cflag |= CS5;
          break;
      default:
          new_cfg.c_cflag |= CS8;
          break;
    }
    /* Set the parity */
    switch (comport->parity)
    {
      case 0x01:               // Odd
          new_cfg.c_cflag |= (PARENB | PARODD);
          new_cfg.c_cflag |= (INPCK | ISTRIP);
          break;
      case 0x02:               // Even
          new_cfg.c_cflag |= PARENB;
          new_cfg.c_cflag &= ~PARODD;;
          new_cfg.c_cflag |= (INPCK | ISTRIP);
          break;
      case 0x03:
          new_cfg.c_cflag &= ~PARENB;
          new_cfg.c_cflag &= ~CSTOPB;
          break;
      default:
          new_cfg.c_cflag &= ~PARENB;
    }
    /* Set Stop bit */
    if (0x01 != comport->stopbit)
    {
        new_cfg.c_cflag |= CSTOPB;
    }
    else
    {
        new_cfg.c_cflag &= ~CSTOPB;
    }
    /* Set flow control */
    switch (comport->flowctrl)
    {
      case 1:                  // Software control
      case 3:
          new_cfg.c_cflag &= ~(CRTSCTS);
          new_cfg.c_iflag |= (IXON | IXOFF);
          break;
      case 2:                  // Hardware control
          new_cfg.c_cflag |= CRTSCTS;   // Also called CRTSCTS
          new_cfg.c_iflag &= ~(IXON | IXOFF);
          break;
      default:                 // NONE
          new_cfg.c_cflag &= ~(CRTSCTS);
          new_cfg.c_iflag &= ~(IXON | IXOFF);
          break;
    }
    /* Set baudrate */
    switch (comport->baudrate)
    {
      case 115200:
          tmp = B115200;
          break;
      case 57600:
          tmp = B57600;
          break;
      case 38400:
          tmp = B38400;
          break;
      case 19200:
          tmp = B19200;
          break;
      case 9600:
          tmp = B9600;
          break;
      case 4800:
          tmp = B4800;
          break;
      case 2400:
          tmp = B2400;
          break;
      case 1800:
          tmp = B1800;
          break;
      case 1200:
          tmp = B1200;
          break;
      case 600:
          tmp = B600;
          break;
      case 300:
          tmp = B300;
          break;
      case 200:
          tmp = B200;
          break;
      case 150:
          tmp = B150;
          break;
      case 134:
          tmp = B134;
          break;
      case 110:
          tmp = B110;
          break;
      case 75:
          tmp = B75;
          break;
      case 50:
          tmp = B50;
          break;
      default:
          tmp = B115200;
    }
    cfsetispeed(&new_cfg, tmp);
    cfsetispeed(&new_cfg, tmp);
    /* Set the Com port timeout settings */
    new_cfg.c_cc[VMIN] = 0;
    new_cfg.c_cc[VTIME] = 0;
    tcflush(comport->fd, TCIFLUSH);
    if (0 != tcsetattr(comport->fd, TCSANOW, &new_cfg))
    {
        retval = -7;          // Failed to set device com port settings
        goto CleanUp;
    }
    COM_PRINT("Connected device \"%s\".\n", comport->dev_name);
    comport->is_connted = 0x01;
    retval = comport->fd;
CleanUp:
    COM_PRINT("Open device \"%s\" %s.\n", comport->dev_name, retval>0 ? "successfully" : "failure");
    return retval;
}
void nonblock()
{
    struct termios ttystate;
    //get the terminal state
    tcgetattr(STDIN_FILENO, &ttystate);
    //turn off canonical mode
    ttystate.c_lflag &= ~ICANON;
    //minimum of number input read.
    ttystate.c_cc[VMIN] = 1;
    //set the terminal attributes.
    tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
}
int kbhit()
{
    struct timeval tv;
    fd_set fds;
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
    select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
    return FD_ISSET(STDIN_FILENO, &fds);
}
int comport_recv(COM_PORT * comport, char *buf, int buf_size, unsigned long timeout)
{
    int retval = 0;             // Function return value
    int iRet;
    fd_set stReadFds, stExcpFds;
    struct timeval stTime;
    if (NULL == buf || 0 >= buf_size)
    {
        COM_PRINT("%s() usage error.\n", __FUNCTION__);
        retval = -1;
        goto CleanUp;
    }
    if (0x01 != comport->is_connted)
    {
        COM_PRINT("%s() comport not connected.\n", __FUNCTION__);
        retval = -2;
        goto CleanUp;
    }
    //printf("bufsize=%d timeout=%lu\n", buf_size, timeout);
    FD_ZERO(&stReadFds);
    FD_ZERO(&stExcpFds);
    FD_SET(comport->fd, &stReadFds);
    FD_SET(comport->fd, &stExcpFds);
    if (0xFFFFFFFF != timeout)
    {
        stTime.tv_sec = (time_t) (timeout / 1000);
        stTime.tv_usec = (long)(1000 * (timeout % 1000));
        iRet = select(comport->fd + 1, &stReadFds, 0, &stExcpFds, &stTime);
        if (0 == iRet)
        {
            retval = 0;         // No data in Com port buffer
            goto CleanUp;
        }
        else if (0 < iRet)
        {
            if (0 != FD_ISSET(comport->fd, &stExcpFds))
            {
                retval = -6;  // Error during checking recv status
                COM_PRINT("Error checking recv status.\n");
                goto CleanUp;
            }
            if (0 == FD_ISSET(comport->fd, &stReadFds))
            {
                retval = 0;  // No incoming data
                COM_PRINT("No incoming data.\n");
                goto CleanUp;
            }
        }
        else
        {
            if (EINTR == errno)
            {
                COM_PRINT("catch interrupt signal.\n");
                retval = 0;  // Interrupted signal catched
            }
            else
            {
                COM_PRINT("Check recv status failure.\n");
                retval = -7;  // Error during checking recv status
            }
            goto CleanUp;
        }
    }
    usleep(10000); /* sleep for 10ms for data incoming */
    // Get data from Com port
    iRet = read(comport->fd, buf, buf_size);
    if (0 > iRet)
    {
        if (EINTR == errno)
            retval = 0;      // Interrupted signal catched
        else
            retval = -3;      // Failed to read Com port
        goto CleanUp;
    }
#if 0
    {
        int   i=0;
        printf("Receive %d bytes data: \n", iRet);
        for(i=0; i<iRet; i++)
        {
            printf("0x%02x ", buf[i]);
        }
        printf("\n");
    }
#endif
    retval = iRet;
  CleanUp:
    return retval;
}
int comport_send(COM_PORT * comport, char *buf, int send_bytes)
{
    char *ptr, *end;
    int retval = 0;
    int send = 0;
    if (NULL == buf || 0 >= send_bytes)
    {
        COM_PRINT("%s() Usage error.\n", __FUNCTION__);
        retval = -1;
        goto CleanUp;
    }
    if (0x01 != comport->is_connted)    // Comport not opened ?
    {
        retval = -3;
        COM_PRINT("Serail not connected.\n");
        goto CleanUp;
    }
    //printf("Send %s with %d bytes.\n", buf, send_bytes);
    // Large data, then slice them and send
    if (comport->frag_size < send_bytes)
    {
        ptr = buf;
        end = buf + send_bytes;
        do
        {
            // Large than frag_size
            if (comport->frag_size < (end - ptr))
            {
                send = write(comport->fd, ptr, comport->frag_size);
                if (0 >= send || comport->frag_size != send)
                {
                    retval = -4;
                    goto CleanUp;
                }
                ptr += comport->frag_size;
            }
            else                // Less than frag_size, maybe last fragmention.
            {
                send = write(comport->fd, ptr, (end - ptr));
                if (0 >= send || (end - ptr) != send)
                {
                    retval = -4;
                    goto CleanUp;
                }
                ptr += (end - ptr);
            }
        }
        while (ptr < end);
    }
    else                        // The send data is not large than a fragmention.
    {
        send = write(comport->fd, buf, send_bytes);
        if (0 >= send || send_bytes != send)
        {
            retval = -5;
            goto CleanUp;
        }
    }
  CleanUp:
    return retval;
}
program/cp_library/cp_comport.h
New file
@@ -0,0 +1,67 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_comport.h
 *    Description:  This head file is for the common TTY/Serial port operator library
 *
 *        Version:  1.0.0(10/17/2011~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/17/2011 03:33:25 PM"
 *
 ********************************************************************************/
#ifndef  _CP_COMPORT_H
#define  _CP_COMPORT_H
#include  <stdio.h>
#include  <stdlib.h>
#include  <unistd.h>
#include  <string.h>
#include  <getopt.h>
#include  <fcntl.h>
#include  <errno.h>
#include  <termios.h>
#include  <sys/stat.h>
#include  <sys/wait.h>
#include  <sys/types.h>
#include  <sys/stat.h>
#include  <sys/select.h>
#define BUF_64  64
#ifndef DEVNAME_LEN
#define DEVNAME_LEN          64
#endif
//#define COM_DEBUG
#ifdef  COM_DEBUG
#define COM_PRINT(format,args...) printf(format, ##args)
#else
#define COM_PRINT(format,args...) do{} while(0);
#endif
//#define msleep(m)               {struct timespec cSleep; cSleep.tv_sec = 0; cSleep.tv_nsec = m * 1000; nanosleep(&cSleep, 0);}
typedef struct __COM_PORT
{
    unsigned char databit, parity, stopbit, flowctrl, is_connted;
    char dev_name[DEVNAME_LEN];
    unsigned char  used;     /* This comport used or not now */
    int fd;
    int frag_size;
    long baudrate;
} COM_PORT;
COM_PORT *comport_init(const char *dev_name, int baudrate, const char *settings);
void comport_close(COM_PORT * comport);
int comport_open(COM_PORT * comport);
void comport_term(COM_PORT * comport);
int comport_recv(COM_PORT * comport, char *buf, int buf_size, unsigned long timeout);
int comport_send(COM_PORT * comport, char *buf, int send_bytes);
void set_settings(COM_PORT * comport, const char *settings);
void disp_settings(COM_PORT * comport);
void nonblock();
int kbhit();
#endif
program/cp_library/cp_dictionary.c
New file
@@ -0,0 +1,398 @@
/*-------------------------------------------------------------------------*/
/**
   @file    cp_dictionary.c
   @author  N. Devillard
   @brief   Implements a dictionary for string variables.
   This module implements a simple dictionary object, i.e. a list
   of string/string associations. This object is useful to store e.g.
   informations retrieved from a configuration file (ini files).
*/
/*--------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
                                Includes
 ---------------------------------------------------------------------------*/
#include "cp_dictionary.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/** Maximum value size for integers and doubles. */
#define MAXVALSZ    1024
/** Minimal allocated number of entries in a dictionary */
#define DICTMINSZ   128
/** Invalid key token */
#define DICT_INVALID_KEY    ((char*)-1)
/*---------------------------------------------------------------------------
                            Private functions
 ---------------------------------------------------------------------------*/
/* Doubles the allocated size associated to a pointer */
/* 'size' is the current allocated size. */
static void * mem_double(void * ptr, int size)
{
    void * newptr ;
    newptr = calloc(2*size, 1);
    if (newptr==NULL) {
        return NULL ;
    }
    memcpy(newptr, ptr, size);
    free(ptr);
    return newptr ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Duplicate a string
  @param    s String to duplicate
  @return   Pointer to a newly allocated string, to be freed with free()
  This is a replacement for strdup(). This implementation is provided
  for systems that do not have it.
 */
/*--------------------------------------------------------------------------*/
static char * xstrdup(const char * s)
{
    char * t ;
    if (!s)
        return NULL ;
    t = (char*)malloc(strlen(s)+1) ;
    if (t) {
        strcpy(t,s);
    }
    return t ;
}
/*---------------------------------------------------------------------------
                            Function codes
 ---------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/**
  @brief    Compute the hash key for a string.
  @param    key     Character string to use for key.
  @return   1 unsigned int on at least 32 bits.
  This hash function has been taken from an Article in Dr Dobbs Journal.
  This is normally a collision-free function, distributing keys evenly.
  The key is stored anyway in the struct so that collision can be avoided
  by comparing the key itself in last resort.
 */
/*--------------------------------------------------------------------------*/
unsigned dictionary_hash(const char * key)
{
    int         len ;
    unsigned    hash ;
    int         i ;
    len = strlen(key);
    for (hash=0, i=0 ; i<len ; i++) {
        hash += (unsigned)key[i] ;
        hash += (hash<<10);
        hash ^= (hash>>6) ;
    }
    hash += (hash <<3);
    hash ^= (hash >>11);
    hash += (hash <<15);
    return hash ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Create a new dictionary object.
  @param    size    Optional initial size of the dictionary.
  @return   1 newly allocated dictionary objet.
  This function allocates a new dictionary object of given size and returns
  it. If you do not know in advance (roughly) the number of entries in the
  dictionary, give size=0.
 */
/*--------------------------------------------------------------------------*/
dictionary * dictionary_new(int size)
{
    dictionary  *   d ;
    /* If no size was specified, allocate space for DICTMINSZ */
    if (size<DICTMINSZ) size=DICTMINSZ ;
    if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) {
        return NULL;
    }
    d->size = size ;
    d->val  = (char **)calloc(size, sizeof(char*));
    d->key  = (char **)calloc(size, sizeof(char*));
    d->hash = (unsigned int *)calloc(size, sizeof(unsigned));
    return d ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Delete a dictionary object
  @param    d   dictionary object to deallocate.
  @return   void
  Deallocate a dictionary object and all memory associated to it.
 */
/*--------------------------------------------------------------------------*/
void dictionary_del(dictionary * d)
{
    int     i ;
    if (d==NULL) return ;
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]!=NULL)
            free(d->key[i]);
        if (d->val[i]!=NULL)
            free(d->val[i]);
    }
    free(d->val);
    free(d->key);
    free(d->hash);
    free(d);
    return ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get a value from a dictionary.
  @param    d       dictionary object to search.
  @param    key     Key to look for in the dictionary.
  @param    def     Default value to return if key not found.
  @return   1 pointer to internally allocated character string.
  This function locates a key in a dictionary and returns a pointer to its
  value, or the passed 'def' pointer if no such key can be found in
  dictionary. The returned character pointer points to data internal to the
  dictionary object, you should not try to free it or modify it.
 */
/*--------------------------------------------------------------------------*/
char * dictionary_get(dictionary * d, const char * key, char * def)
{
    unsigned    hash ;
    int         i ;
    hash = dictionary_hash(key);
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]==NULL)
            continue ;
        /* Compare hash */
        if (hash==d->hash[i]) {
            /* Compare string, to avoid hash collisions */
            if (!strcmp(key, d->key[i])) {
                return d->val[i] ;
            }
        }
    }
    return def ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Set a value in a dictionary.
  @param    d       dictionary object to modify.
  @param    key     Key to modify or add.
  @param    val     Value to add.
  @return   int     0 if Ok, anything else otherwise
  If the given key is found in the dictionary, the associated value is
  replaced by the provided one. If the key cannot be found in the
  dictionary, it is added to it.
  It is Ok to provide a NULL value for val, but NULL values for the dictionary
  or the key are considered as errors: the function will return immediately
  in such a case.
  Notice that if you dictionary_set a variable to NULL, a call to
  dictionary_get will return a NULL value: the variable will be found, and
  its value (NULL) is returned. In other words, setting the variable
  content to NULL is equivalent to deleting the variable from the
  dictionary. It is not possible (in this implementation) to have a key in
  the dictionary without value.
  This function returns non-zero in case of failure.
 */
/*--------------------------------------------------------------------------*/
int dictionary_set(dictionary * d, const char * key, const char * val)
{
    int         i ;
    unsigned    hash ;
    if (d==NULL || key==NULL) return -1 ;
    /* Compute hash for this key */
    hash = dictionary_hash(key) ;
    /* Find if value is already in dictionary */
    if (d->n>0) {
        for (i=0 ; i<d->size ; i++) {
            if (d->key[i]==NULL)
                continue ;
            if (hash==d->hash[i]) { /* Same hash value */
                if (!strcmp(key, d->key[i])) {   /* Same key */
                    /* Found a value: modify and return */
                    if (d->val[i]!=NULL)
                        free(d->val[i]);
                    d->val[i] = val ? xstrdup(val) : NULL ;
                    /* Value has been modified: return */
                    return 0 ;
                }
            }
        }
    }
    /* Add a new value */
    /* See if dictionary needs to grow */
    if (d->n==d->size) {
        /* Reached maximum size: reallocate dictionary */
        d->val  = (char **)mem_double(d->val,  d->size * sizeof(char*)) ;
        d->key  = (char **)mem_double(d->key,  d->size * sizeof(char*)) ;
        d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ;
        if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) {
            /* Cannot grow dictionary */
            return -1 ;
        }
        /* Double size */
        d->size *= 2 ;
    }
    /* Insert key in the first empty slot. Start at d->n and wrap at
       d->size. Because d->n < d->size this will necessarily
       terminate. */
    for (i=d->n ; d->key[i] ; ) {
        if(++i == d->size) i = 0;
    }
    /* Copy key */
    d->key[i]  = xstrdup(key);
    d->val[i]  = val ? xstrdup(val) : NULL ;
    d->hash[i] = hash;
    d->n ++ ;
    return 0 ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Delete a key in a dictionary
  @param    d       dictionary object to modify.
  @param    key     Key to remove.
  @return   void
  This function deletes a key in a dictionary. Nothing is done if the
  key cannot be found.
 */
/*--------------------------------------------------------------------------*/
void dictionary_unset(dictionary * d, const char * key)
{
    unsigned    hash ;
    int         i ;
    if (key == NULL) {
        return;
    }
    hash = dictionary_hash(key);
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]==NULL)
            continue ;
        /* Compare hash */
        if (hash==d->hash[i]) {
            /* Compare string, to avoid hash collisions */
            if (!strcmp(key, d->key[i])) {
                /* Found key */
                break ;
            }
        }
    }
    if (i>=d->size)
        /* Key not found */
        return ;
    free(d->key[i]);
    d->key[i] = NULL ;
    if (d->val[i]!=NULL) {
        free(d->val[i]);
        d->val[i] = NULL ;
    }
    d->hash[i] = 0 ;
    d->n -- ;
    return ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Dump a dictionary to an opened file pointer.
  @param    d   Dictionary to dump
  @param    f   Opened file pointer.
  @return   void
  Dumps a dictionary onto an opened file pointer. Key pairs are printed out
  as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
  output file pointers.
 */
/*--------------------------------------------------------------------------*/
void dictionary_dump(dictionary * d, FILE * out)
{
    int     i ;
    if (d==NULL || out==NULL) return ;
    if (d->n<1) {
        fprintf(out, "empty dictionary\n");
        return ;
    }
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]) {
            fprintf(out, "%20s\t[%s]\n",
                    d->key[i],
                    d->val[i] ? d->val[i] : "UNDEF");
        }
    }
    return ;
}
/* Test code */
#ifdef TESTDIC
#define NVALS 20000
int main(int argc, char *argv[])
{
    dictionary  *   d ;
    char    *   val ;
    int         i ;
    char        cval[90] ;
    /* Allocate dictionary */
    printf("allocating...\n");
    d = dictionary_new(0);
    /* Set values in dictionary */
    printf("setting %d values...\n", NVALS);
    for (i=0 ; i<NVALS ; i++) {
        sprintf(cval, "%04d", i);
        dictionary_set(d, cval, "salut");
    }
    printf("getting %d values...\n", NVALS);
    for (i=0 ; i<NVALS ; i++) {
        sprintf(cval, "%04d", i);
        val = dictionary_get(d, cval, DICT_INVALID_KEY);
        if (val==DICT_INVALID_KEY) {
            printf("cannot get value for key [%s]\n", cval);
        }
    }
    printf("unsetting %d values...\n", NVALS);
    for (i=0 ; i<NVALS ; i++) {
        sprintf(cval, "%04d", i);
        dictionary_unset(d, cval);
    }
    if (d->n != 0) {
        printf("error deleting values\n");
    }
    printf("deallocating...\n");
    dictionary_del(d);
    return 0 ;
}
#endif
/* vim: set ts=4 et sw=4 tw=75 */
program/cp_library/cp_dictionary.h
New file
@@ -0,0 +1,165 @@
/*-------------------------------------------------------------------------*/
/**
   @file    cp_dictionary.h
   @author  N. Devillard
   @brief   Implements a dictionary for string variables.
   This module implements a simple dictionary object, i.e. a list
   of string/string associations. This object is useful to store e.g.
   informations retrieved from a configuration file (ini files).
*/
/*--------------------------------------------------------------------------*/
#ifndef _CP_DICTIONARY_H_
#define _CP_DICTIONARY_H_
/*---------------------------------------------------------------------------
                                Includes
 ---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/*---------------------------------------------------------------------------
                                New types
 ---------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/**
  @brief    Dictionary object
  This object contains a list of string/string associations. Each
  association is identified by a unique string key. Looking up values
  in the dictionary is speeded up by the use of a (hopefully collision-free)
  hash function.
 */
/*-------------------------------------------------------------------------*/
typedef struct _dictionary_ {
    int             n ;     /** Number of entries in dictionary */
    int             size ;  /** Storage size */
    char        **  val ;   /** List of string values */
    char        **  key ;   /** List of string keys */
    unsigned     *  hash ;  /** List of hash values for keys */
} dictionary ;
/*---------------------------------------------------------------------------
                            Function prototypes
 ---------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/**
  @brief    Compute the hash key for a string.
  @param    key     Character string to use for key.
  @return   1 unsigned int on at least 32 bits.
  This hash function has been taken from an Article in Dr Dobbs Journal.
  This is normally a collision-free function, distributing keys evenly.
  The key is stored anyway in the struct so that collision can be avoided
  by comparing the key itself in last resort.
 */
/*--------------------------------------------------------------------------*/
unsigned dictionary_hash(const char * key);
/*-------------------------------------------------------------------------*/
/**
  @brief    Create a new dictionary object.
  @param    size    Optional initial size of the dictionary.
  @return   1 newly allocated dictionary objet.
  This function allocates a new dictionary object of given size and returns
  it. If you do not know in advance (roughly) the number of entries in the
  dictionary, give size=0.
 */
/*--------------------------------------------------------------------------*/
dictionary * dictionary_new(int size);
/*-------------------------------------------------------------------------*/
/**
  @brief    Delete a dictionary object
  @param    d   dictionary object to deallocate.
  @return   void
  Deallocate a dictionary object and all memory associated to it.
 */
/*--------------------------------------------------------------------------*/
void dictionary_del(dictionary * vd);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get a value from a dictionary.
  @param    d       dictionary object to search.
  @param    key     Key to look for in the dictionary.
  @param    def     Default value to return if key not found.
  @return   1 pointer to internally allocated character string.
  This function locates a key in a dictionary and returns a pointer to its
  value, or the passed 'def' pointer if no such key can be found in
  dictionary. The returned character pointer points to data internal to the
  dictionary object, you should not try to free it or modify it.
 */
/*--------------------------------------------------------------------------*/
char * dictionary_get(dictionary * d, const char * key, char * def);
/*-------------------------------------------------------------------------*/
/**
  @brief    Set a value in a dictionary.
  @param    d       dictionary object to modify.
  @param    key     Key to modify or add.
  @param    val     Value to add.
  @return   int     0 if Ok, anything else otherwise
  If the given key is found in the dictionary, the associated value is
  replaced by the provided one. If the key cannot be found in the
  dictionary, it is added to it.
  It is Ok to provide a NULL value for val, but NULL values for the dictionary
  or the key are considered as errors: the function will return immediately
  in such a case.
  Notice that if you dictionary_set a variable to NULL, a call to
  dictionary_get will return a NULL value: the variable will be found, and
  its value (NULL) is returned. In other words, setting the variable
  content to NULL is equivalent to deleting the variable from the
  dictionary. It is not possible (in this implementation) to have a key in
  the dictionary without value.
  This function returns non-zero in case of failure.
 */
/*--------------------------------------------------------------------------*/
int dictionary_set(dictionary * vd, const char * key, const char * val);
/*-------------------------------------------------------------------------*/
/**
  @brief    Delete a key in a dictionary
  @param    d       dictionary object to modify.
  @param    key     Key to remove.
  @return   void
  This function deletes a key in a dictionary. Nothing is done if the
  key cannot be found.
 */
/*--------------------------------------------------------------------------*/
void dictionary_unset(dictionary * d, const char * key);
/*-------------------------------------------------------------------------*/
/**
  @brief    Dump a dictionary to an opened file pointer.
  @param    d   Dictionary to dump
  @param    f   Opened file pointer.
  @return   void
  Dumps a dictionary onto an opened file pointer. Key pairs are printed out
  as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
  output file pointers.
 */
/*--------------------------------------------------------------------------*/
void dictionary_dump(dictionary * d, FILE * out);
#endif
program/cp_library/cp_fds.c
New file
@@ -0,0 +1,633 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_fds.c
 *    Description:  This file is the linux epoll basic library
 *
 *        Version:  1.0.0(10/25/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/25/2012 04:55:30 PM"
 *
 ********************************************************************************/
#include <sys/resource.h>
#include "cp_fds.h"
#include "cp_sock.h"
#include "cp_time.h"
#include "cp_common.h"
/* set maximum file descriptor number that can be opened in this process */
int cp_fds_setrlimit(int maxfd)
{
    struct  rlimit    res;
    if(getrlimit(RLIMIT_NOFILE, &res) <0)
    {
        log_fatal("getrlimit failed: %s\n", strerror(errno));
        return -1;
    }
    if(res.rlim_cur < maxfd)
    {
        res.rlim_cur = maxfd;
        if(setrlimit(RLIMIT_NOFILE, &res) <0)
        {
            log_fatal("setrlimit failed: %s\n", strerror(errno));
            return -2;
        }
    }
    return 0;
}
/* Initialze $fds context, if $fds is NULL, then malloc it */
CP_FDS *cp_fds_init(CP_FDS *fds, int maxevents, int timeout)
{
    int          rv = 0;
    if(NULL != fds)
    {
        memset(fds, 0, sizeof(*fds));
        fds->epfd = -1;
    }
    else
    {
        if( !(fds=(CP_FDS *)t_malloc(sizeof(*fds))) )
        {
            log_err("fds context malloc failed: %s\n", strerror(errno));
            return NULL;
        }
        else
        {
            log_trace("malloc fds with address [%p]\n", fds);
            memset(fds, 0, sizeof(*fds));
            fds->epfd = -1;
            fds->flag |= FLAG_FDS_MALLOC;
        }
    }
    /* set maximum file descriptor number that can be opened in this process */
    maxevents = maxevents<CP_DEF_MAX_EVENTS ? maxevents : CP_DEF_MAX_EVENTS;
    if( cp_fds_setrlimit(maxevents) )
    {
        rv = -2;
        goto cleanup;
    }
    /* Create epoll file description */
    fds->epfd = epoll_create(maxevents);
    if(fds->epfd < 0)
    {
        rv = -3;
        log_fatal("epoll_create failed: %s\n", strerror(errno));
        goto cleanup;
    }
    log_trace("Open epoll file description [%d]\n", fds->epfd);
    /* Initialise the server/client/task list */
    INIT_LIST_HEAD(&fds->server_list);
    INIT_LIST_HEAD(&fds->client_list);
    fds->task_array = cp_array_init(NULL, maxevents);
    fds->event_queue = cp_queue_init(NULL, maxevents);
    fds->timeout = timeout<0 ? -1 : timeout;
    fds->max_event = maxevents;
    fds->flag |= FLAG_FDS_INIT;
cleanup:
    if(rv)
    {
        log_err("Initialise fds contex failed\n");
        cp_fds_term(fds);
        return NULL;
    }
    log_nrml("Initialise fds contex [%p] ok\n", fds);
    return fds;
}
/* Terminate $fds context, if $fds malloced, then free it */
void cp_fds_term(CP_FDS *fds)
{
    log_dbg("terminate epoll fds contex now\n");
    if(!fds)
    {
        log_err("Invalude input arguments\n");
        return;
    }
    if(fds->epfd >= 0)
    {
        log_dbg("Close epoll file description [%d]\n", fds->epfd);
        close(fds->epfd);
    }
    if(fds->task_array)
    {
        cp_array_term(fds->task_array);
    }
    if(fds->event_queue)
    {
        cp_queue_destroy(fds->event_queue);
    }
    if(fds->flag& FLAG_FDS_MALLOC)
    {
        t_free(fds);
    }
    log_nrml("Terminate epoll fds contex ok.\n");
    return ;
}
/* epoll_ctl() to add this socket to epoll   */
int cp_add_epoll_event(CP_SOCK *sock)
{
    int                     rv = 0;
    CP_FDS                  *fds;
    if( !sock || !(fds=sock->fds) )
    {
        log_err("Invalude input arguments\n");
        return -1;
    }
    if( sock->flag&FLAG_SOCK_EPOLLED )
        return 0; /* already put in epoll */
    if(fds->event_cnt > fds->max_event)
    {
        log_fatal("No more epoll event space [%d/%d] for socket[%d]\n",
                fds->event_cnt, fds->max_event, sock->fd);
        return -2;
    }
    memset(&sock->event, 0, sizeof(sock->event));
    sock->event.events = EPOLLIN;
    sock->event.data.ptr = sock;
    if ( epoll_ctl (fds->epfd, EPOLL_CTL_ADD, sock->fd, &sock->event) < 0)
    {
        if(EEXIST == errno)
        {
            log_warn("socket[%d] already registe in epoll\n", sock->fd);
            goto cleanup;
        }
        else
        {
            log_err("socket[%d] registe in epoll failed: %s\n", sock->fd, strerror(errno));
            rv = -3;
            goto cleanup;
        }
    }
    fds->event_cnt++;
    sock->flag |= FLAG_SOCK_EPOLLED;
cleanup:
    if(rv)
        log_err("add socket [%d] to epoll event failed\n", sock->fd);
    else
        log_dbg("add socket [%d] to epoll event ok\n", sock->fd);
    return rv;
}
/* epoll_ctl() to mod this socket in epoll */
int cp_mod_epoll_event(CP_SOCK *sock, int event)
{
    CP_FDS                  *fds;
    if( !sock || !(fds=sock->fds) )
    {
        log_err("Invalude input arguments\n");
        return -1;
    }
    if( !(sock->flag&FLAG_SOCK_EPOLLED) )
    {
        return -2;  /* not in epoll  */
    }
    sock->event.events = event;
    if ( epoll_ctl (fds->epfd, EPOLL_CTL_MOD, sock->fd, &sock->event) < 0)
    {
        log_err("modidfy socket [%d] epoll event failed: %s\n", sock->fd, strerror(errno));
        return -3;
    }
    log_dbg("modidfy socket [%d] epoll event ok\n", sock->fd);
    return 0;
}
void cp_del_epoll_event(CP_SOCK *sock)
{
    CP_FDS                  *fds;
    if( !sock || !(fds=sock->fds) )
    {
        log_err("Invalude input arguments\n");
        return;
    }
    if( !(sock->flag&FLAG_SOCK_EPOLLED) )
        return; /* not in epoll  */
    sock->flag &= ~FLAG_SOCK_EPOLLED;
    epoll_ctl(fds->epfd, EPOLL_CTL_DEL, sock->fd, NULL);
    fds->event_cnt--;
    log_dbg("remove socket [%d] from epoll event ok\n", sock->fd);
    return ;
}
/* add the listen/connect socket into server_list/client_list */
int cp_fds_add_sock_registry(CP_SOCK *sock)
{
    CP_FDS                  *fds;
    if( !sock || !(fds=sock->fds) )
    {
        log_err("Invalude input arguments\n");
        return -1;
    }
    if( sock->flag&FLAG_SOCK_REGISTRY )
        return 0;  /* already in registry list  */
    if(CP_SOCK_MODE_CONNECT == sock->mode)
    {
        log_dbg("regist socket [%p] on CONNECT mode into client list ok\n", sock);
        list_add_tail(&sock->rlist, &fds->client_list);
    }
    else if(CP_SOCK_MODE_LISTEN == sock->mode)
    {
        log_dbg("regist socket [%p] on LISTEN mode into server list ok\n", sock);
        list_add_tail(&sock->rlist, &fds->server_list);
    }
    else if(CP_SOCK_MODE_ACCEPT==sock->mode && sock->serv_sock)
    {
        log_dbg("regist socket [%p] on ACCEPT mode into server list ok\n", sock);
        list_add_tail(&sock->rlist, &sock->serv_sock->accept_list);
        sock->serv_sock->accept_cnt++;
    }
    else
    {
        log_err("regist socket [%p] on mode %d into client/server list failed: Unsupport mode.\n", sock, sock->mode);
        return -2;
    }
    sock->flag |= FLAG_SOCK_REGISTRY;
    return 0;
}
/*  remove the listen/connect socket from server_list/client_list */
void cp_fds_del_sock_registry(CP_SOCK *sock)
{
    if(!sock || !(sock->flag&FLAG_SOCK_REGISTRY) )
        return;  /* not in registry list  */
    if(CP_SOCK_MODE_ACCEPT==sock->mode && sock->serv_sock)
        sock->serv_sock->accept_cnt--;
    log_dbg("remove socket [%d] from socket registry list ok\n", sock->fd);
    list_del(&sock->rlist);
    sock->flag &= ~FLAG_SOCK_REGISTRY;
    return ;
}
/* Add a socket in task list */
int cp_fds_add_sock_task(CP_SOCK *sock)
{
    CP_FDS                  *fds;
    int                     rv;
    if( !sock || !(fds=sock->fds) )
    {
        log_err("Invalude input arguments\n");
        return -1;
    }
    if( sock->flag&FLAG_SOCK_TASKED )
        return 0; /* already in a list */
    log_info("add socket [%d] into task list\n", sock->fd);
    if( (rv=cp_array_add(fds->task_array, sock)) >=0 )
    {
        sock->index = rv;
        sock->flag |= FLAG_SOCK_TASKED;
        return 0;
    }
    return -2;
}
void cp_fds_del_sock_task(CP_SOCK *sock)
{
    if(!sock || !(sock->flag&FLAG_SOCK_TASKED))
        return ;
    log_info("remove socket [%d:%p] from task list[%p] by index [%d]\n", sock->fd, sock, sock->fds->task_array, sock->index);
    if(sock->index >= 0)
        cp_array_rm_byindex(sock->fds->task_array, sock->index);
    else
        cp_array_rm_bydata(sock->fds->task_array, sock);
    sock->flag &= ~FLAG_SOCK_TASKED;
    sock->index = -1;
    memset(&sock->event, 0, sizeof(struct epoll_event));
    return ;
}
void *cp_fds_sock_enqueue(CP_SOCK *sock)
{
    if(!sock || sock->flag&FLAG_SOCK_INQUEUE || sock->flag&FLAG_SOCK_TASKED || !sock->fds)
        return NULL;
    sock->flag |= FLAG_SOCK_INQUEUE;
    return cp_enqueue(sock->fds->event_queue, sock);
}
void *cp_fds_sock_dequeue(CP_FDS *fds)
{
    CP_SOCK    *sock = NULL;
    if( !fds )
        return NULL;
    sock = cp_dequeue(fds->event_queue);
    sock->flag &= ~FLAG_SOCK_INQUEUE;
    return sock;
}
void *cp_fds_sock_rmqueue(CP_SOCK *sock)
{
    if(!sock || !(sock->flag&FLAG_SOCK_INQUEUE) || !sock->fds)
        return NULL;
    sock->flag &= ~FLAG_SOCK_INQUEUE;
    return cp_rmqueue(sock->fds->event_queue, sock);
}
void cp_fds_list_sock_task(CP_FDS *fds)
{
    int               i;
    CP_SOCK           *sock;
    if(!fds)
        return ;
    log_dbg("list all the socket in task list:\n");
    /* list all the socket from task list */
    cp_list_array_for_each(fds->task_array, i, sock)
    {
        if(sock)
            log_dbg("socket[%d:%p] in task list\n", sock->fd, sock);
    }
    return ;
}
void cp_fds_destroy_sock(CP_SOCK *sock)
{
    cp_fds_del_sock_task(sock);
    cp_fds_sock_rmqueue(sock);
    cp_del_epoll_event(sock);
    cp_fds_del_sock_registry(sock);
    cp_sock_term(sock);
    return ;
}
int cp_fds_detect_event(CP_FDS *fds)
{
    int                   i=0, nfds=0;
    CP_SOCK               *sock;
    struct epoll_event    evts[CP_MAX_EVENT_ONCE];
    if( !fds )
        return -1;
    nfds = epoll_wait(fds->epfd, evts, CP_MAX_EVENT_ONCE, fds->timeout);
    ///if(nfds<0 && errno!=EINTR)
    if(nfds<0)
    {
        log_fatal("epoll_wait failure: %s\n", strerror(errno));
        return -2;
    }
    if(nfds == 0)
        return 0;
    log_dbg("epoll_wait get [%d] events\n", nfds);
    for (i=0; i<nfds; i++)
    {
        sock=(CP_SOCK *)evts[i].data.ptr;
        sock->event = evts[i];
        sock->actv_time = time_now();
        log_dbg("socket [%d] get event [0x%0x] and added to event queue ok\n", sock->fd, sock->event.events);
        if( SOCK_STAT_ALREADY==sock->status )
            cp_fds_sock_enqueue(sock);
    }
    return 0;
}
void cp_fds_proc_event(CP_FDS *fds)
{
    int                    i;
    CP_SOCK                *sock;
    int                    rv;
    if( !fds )
        return;
    //cp_fds_list_sock_task(fds);
    //log_trace("Start process the events....\n");
    /* Process all the socket in task list first, its urgent */
    cp_list_array_for_each(fds->task_array, i, sock)
    {
        if(sock)
        {
            if(sock->cbfunc)
            {
                log_dbg("Process socket [%d] in task list on event [%d]\n", sock->fd, sock->event.events);
                rv = sock->cbfunc(sock);
            }
            else
            {
                log_err("Process Socket [%d:%p] not implement event callback and remove it\n", sock->fd, sock);
                cp_fds_del_sock_task(sock);
            }
        }
    }
    /* Process all the socket in event queue now */
    while(!cp_queue_is_empty(fds->event_queue))
    {
        if( NULL!= (sock=cp_fds_sock_dequeue(fds)) )
        {
            //log_dbg("after handle one socket count: %d\n", cp_queue_count(fds->event_queue));
            if(sock->cbfunc)
            {
                log_dbg("Process socket [%d %p] in event queue on event [%d]\n", sock->fd, sock, sock->event.events);
                rv = sock->cbfunc(sock);
            }
            else
            {
                log_err("Process Socket [%d:%p] not implement event callback and remove it\n", sock->fd, sock);
            }
        }
    }
    //log_trace("End process the events....\n");
    return;
}
void cp_sock_term_server(CP_SOCK *serv_sock)
{
    CP_SOCK           *sock, *tsock;
    log_warn("terminate server socket [%d] and [%d] accept client now\n", serv_sock->fd, serv_sock->accept_cnt);
    list_for_each_entry_safe(sock, tsock, &serv_sock->accept_list, rlist)
    {
        /*remove all the accept socket from task and registry list, then destroy it*/
        //log_warn("destroy accept socket [%d:%p]\n", sock->fd, sock);
        cp_fds_destroy_sock(sock);
    }
    /*remove this server socket from task and registry list, then destroy it*/
    log_warn("terminate server socket [%d] and its accept client ok\n", serv_sock->fd);
    cp_fds_destroy_sock(serv_sock);
    return ;
}
void cp_sock_term_all_server(CP_FDS *fds)
{
    CP_SOCK           *sock, *tsock;
    log_dbg("destroy all the listen socket now\n");
    /* Terminate all the listen socket */
    list_for_each_entry_safe(sock, tsock, &fds->server_list, rlist)
    {
        cp_sock_term_server(sock);
    }
    log_warn("destroy all the listen socket ok\n");
    return ;
}
void cp_sock_term_all_client(CP_FDS *fds)
{
    CP_SOCK           *sock = NULL, *tsock;
    log_dbg("destroy all the connect socket now\n");
    /* Terminate all the listen socket */
    list_for_each_entry_safe(sock, tsock, &fds->client_list, rlist)
    {
        /*remove all the connect socket from task and registry list, then destroy it*/
        cp_fds_destroy_sock(sock);
    }
    log_warn("destroy all the connect socket ok\n");
}
/* Checkout the socket timeout happened or not, if happened then put it in task list */
void cp_sock_detect_timeout(CP_FDS *fds)
{
    CP_SOCK           *sock, *tsock, *serv_sock;
    /* check all the connect socket timeout */
    list_for_each_entry_safe(sock, tsock, &fds->client_list, rlist)
    {
        /*If the socket timeout value and timeout, then disconnect it */
        if( sock->idle_timeout>0 && time_elapsed(sock->actv_time)>sock->idle_timeout )
        {
            log_warn("socket[%d] idle timeout happened and add to task list\n", sock->fd);
            log_dbg("last: %lu elapsed time: %lu idel timeout: %lu\n", sock->actv_time, time_elapsed(sock->actv_time), sock->idle_timeout);
            sock->event.events = CP_SOCK_EVENT_IDLE_TIMEOUT;
            cp_fds_add_sock_task(sock);
        }
        else if( sock->msg_timeout>0 && sock->msg_time>0 && time_elapsed(sock->msg_time)>sock->msg_timeout )
        {
            log_warn("socket[%d] message timeout happened and add to task list\n", sock->fd);
            sock->event.events = CP_SOCK_EVENT_MSG_TIMEOUT;
            cp_fds_add_sock_task(sock);
        }
    }
    /* check all the accept socket timeout */
    list_for_each_entry(serv_sock, &fds->server_list, rlist)
    {
        list_for_each_entry_safe(sock, tsock, &serv_sock->accept_list, rlist)
        {
            /*If the socket timeout value and timeout, then disconnect it */
            if( sock->idle_timeout>0 && time_elapsed(sock->actv_time)>sock->idle_timeout )
            {
                sock->event.events = CP_SOCK_EVENT_IDLE_TIMEOUT;
                log_warn("socket[%d] idle timeout happened and add to task list\n", sock->fd);
                log_dbg("last: %lu elapsed time: %lu idel timeout: %lu\n", sock->actv_time, time_elapsed(sock->actv_time), sock->idle_timeout);
                cp_fds_add_sock_task(sock);
            }
            else if( sock->msg_timeout>0 && sock->msg_time>0 && time_elapsed(sock->msg_time)>sock->msg_timeout )
            {
                sock->event.events = CP_SOCK_EVENT_MSG_TIMEOUT;
                log_warn("socket[%d] message timeout happened and add to task list\n", sock->fd);
                cp_fds_add_sock_task(sock);
            }
        } /* list_for_each_entry_safe server accept socket list */
    } /* list_for_each_entry all the server socket list */
}
void cp_sock_term_all_task(CP_FDS *fds)
{
    int               i;
    CP_SOCK           *sock;
    log_dbg("remove all the socket in task list now\n");
    /* remove all the socket from task array */
    cp_list_array_for_each(fds->task_array, i, sock)
    {
        //log_warn("remove socket[%d] in task list ok\n", sock->fd);
        if(sock)
            cp_fds_del_sock_task(sock);
    }
    while( !cp_queue_is_empty(fds->event_queue) )
    {
        cp_dequeue(fds->event_queue);
    }
    log_warn("remove all the socket in task list ok\n");
    return ;
}
program/cp_library/cp_fds.h
New file
@@ -0,0 +1,114 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_fds.h
 *    Description:  This head file
 *
 *        Version:  1.0.0(10/25/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/25/2012 04:55:37 PM"
 *
 ********************************************************************************/
#ifndef __CP_FDS_H
#define __CP_FDS_H
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/epoll.h>
#include "cp_klist.h"
#include "cp_logger.h"
#include "cp_sock.h"
#include "cp_queue.h"
#include "cp_array.h"
#define CP_MAX_EVENT_ONCE    128
#define CP_DEF_MAX_EVENTS    1024
#define CP_DEF_FDS_TIMEOUT   10
#define IN_EVENT_LIST        0
#define IN_TASK_LIST         1
#define FLAG_FDS_INIT        (1<<0)
#define FLAG_FDS_MALLOC      (1<<1)
struct _CP_SOCK;
struct _CP_FDS;
typedef struct _CP_FDS
{
    unsigned char         flag;         /* Refer to follow definition  */
    int                   epfd;         /* the epoll_create() returns file description */
    int                   timeout;      /* epoll_wait timeout value  */
    int                   max_event;    /* Maximum monitor FD number */
    int                   event_cnt;    /* current socket regist in epoll */
    struct list_head      server_list;  /* a list keep all the listen sockets */
    struct list_head      client_list;  /* a list keep all the connect sockets */
    CP_QUEUE              *event_queue; /* a queue keep all these sockets get event happened */
    CP_ARRAY              *task_array;  /* an array keep all these pending/or other special task socket */
  /*  flag definitions
   *  0 0 0 0 0 1 1 1
   *  |       | | | |______ Initial or not  - 0: No          1: Yes
   *  |       | | |________ Malloc or not   - 0: Variable,   1: Malloc
   *  |       | |__________ Stop or not     - 0: Not stop    1: Stop
   *  |       |____________ Reserved
   *  |____________________ Reserved
   */
} CP_FDS;
/* Initialze $fds context, if $fds is NULL, then malloc it */
extern CP_FDS *cp_fds_init(CP_FDS *fds, int maxevents, int timeout);
/* Terminate $fds context, if $fds malloced, then free it */
extern void cp_fds_term(CP_FDS *fds);
#define cp_fds_term_clear(fds) {cp_fds_term(fds); fds=NULL;}
/* epoll_ctl() to add this socket to epoll   */
int cp_add_epoll_event(struct _CP_SOCK *sock);
/* epoll_ctl() to mod this socket in epoll */
int cp_mod_epoll_event(struct _CP_SOCK *sock, int event);
/* epoll_ctl() to del this socket from epoll */
void cp_del_epoll_event(struct _CP_SOCK *sock);
/* add the socket into the socket registry list */
int cp_fds_add_sock_registry(struct _CP_SOCK *sock);
/* remove the socket from the socket registry list */
void cp_fds_del_sock_registry(struct _CP_SOCK *sock);
/* add the socket into task list */
int cp_fds_add_sock_task(struct _CP_SOCK *sock);
/* remove the socket from event or task list */
void cp_fds_del_sock_task(struct _CP_SOCK *sock);
/* list all the socket from task list */
void cp_fds_list_sock_task(CP_FDS *fds);
void *cp_fds_sock_enqueue(struct _CP_SOCK *sock);
void *cp_fds_sock_rmqueue(struct _CP_SOCK *sock);
void *cp_fds_sock_dequeue(CP_FDS *fds);
/* remove the socket from task and registry list and destroy it */
void cp_fds_destroy_sock(struct _CP_SOCK *sock);
#define cp_fds_destroy_sock_clear(sock) {cp_fds_destroy_sock(sock); sock=NULL;}
/* epoll_wait detect all these socket get event and add it to task list */
extern int cp_fds_detect_event(CP_FDS *fds);
/* process all these socket get event and add it to task list */
extern void cp_fds_proc_event(CP_FDS *fds);
/* Detect all these socket get timeout and add it to task list */
extern void cp_sock_detect_timeout(CP_FDS *fds);
extern void cp_sock_term_server(struct _CP_SOCK *serv_sock);
extern void cp_sock_term_all_server(CP_FDS *fds);
extern void cp_sock_term_all_client(CP_FDS *fds);
extern void cp_sock_term_all_task(CP_FDS *fds);
#endif /* __CP_FDS_H */
program/cp_library/cp_gprs.c
New file
@@ -0,0 +1,705 @@
/*********************************************************************************
 *      Copyright:  (C) guowenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  module.c
 *    Description:  This is the GPRS Power/SIM card control source code
 *
 *        Version:  1.0.0(02/07/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "02/07/2012 03:08:25 PM"
 *
 ********************************************************************************/
#include "cp_gprs.h"
#include "cp_hal.h"
#include "cp_proc.h"
#include "cp_gsmmux.h"
#include "at91_ioctl.h"
int init_gsm_module(MODULE_INFO *module)
{
    int                   i=0;
    char                  devname[DEVNAME_LEN];
    log_info("Initialize GSM module context\n");
    memset(module, 0, sizeof(*module));
    module->event = REQ_POWER_RESET;  /* Request to power on GPRS */
    pthread_mutex_init(&module->lock, NULL);
    if( !(module->gsmport=comport_init(GSM_DATAPORT, 115200, "8N1N")) )
    {
        return -1;
    }
    /*  Initialize the GPRS dataport pointer */
    module->comport_cnt = MAX_DATAPORT;
    for(i=0; i<module->comport_cnt; i++)
    {
        snprintf(devname, DEVNAME_LEN, "%s%d", CMUX_DATAPORT, i+CMUX_PORT_START_INDEX);
        module->comport[i] = comport_init(devname, 115200, "8N1N");
        if(NULL == module->comport[i])
            goto ERROR;
        //log_dbg("Initialise comport [%p] on %s on baudrate 115200 with 8N1N\n", module->comport[i], devname);
    }
    return 0;
ERROR:
    while(i-- >= 0)
    {
        comport_term(module->comport[i]);
    }
    return -2;
}
/*
 *  Description: close all the GPRS control port device.
 *
 * Return Value: NONE
 */
void close_gsm_dataport(MODULE_INFO *module)
{
    int  i;
    for(i=0; i<module->comport_cnt; i++)
    {
        log_nrml("Close GPRS dataport %s=>[fd:%d]\n", module->comport[i]->dev_name, module->comport[i]->fd);
        comport_close(module->comport[i]);
    }
    return ;
}
/*
 *  Description: open all the GPRS data port device.
 *
 * Return Value: 0: Open successfully  !0: Open failure
 */
int open_gsm_dataport(MODULE_INFO *module)
{
    int i, retval = -1;
    for(i=0; i<module->comport_cnt; i++)
    {
        if( (retval=comport_open(module->comport[i])) < 0)
        {
            log_err("Open GPRS dataport %s failure: %d\n", module->comport[i]->dev_name, retval);
            goto ERROR;
        }
        log_nrml("Open GPRS dataport[%p] %s=>[fd:%d]\n", module->comport, module->comport[i]->dev_name, module->comport[i]->fd);
    }
    return 0;
ERROR:
    close_gsm_dataport(module);
    return retval;
}
/*
 *  Description: Alloc a comport from the comport poor for used, for we must make sure
 *               PPP thread can grasp a comport to work, so we will always preserved
 *               first comport for PPP thread.
 *
 * Return Value: NULL: No comport left  !NULL: The alloced comport pointer
 */
COM_PORT *alloc_gsm_dataport(char *who, MODULE_INFO *module)
{
    static int     lock = 0;
    int            i;
    COM_PORT       *comport = NULL;
    if(lock)
        return NULL;
    lock = 1;
    /* Preserve first comport for PPP thread */
    for(i=0; i<module->comport_cnt; i++)
    {
        if(module->comport[i]->used != YES)
        {
            comport = module->comport[i];
            comport->used = YES;
            break;
        }
    }
    lock = 0;
    if(comport)
    {
        log_dbg("%s allocate GPRS dataport[%d] %s=>[fd:%d] ok\n", who, i, comport->dev_name, comport->fd);
        module->users++;
    }
    else
    {
        log_dbg("%s allocate GPRS dataport failure\n", who);
    }
    return comport;
}
/*
 *  Description: Free a comport to the comport poor when we no need it.
 *
 * Return Value: NONE
 */
void free_gsm_dataport(char *who, MODULE_INFO *module, COM_PORT  **comport)
{
    int            i;
    /* Preserve first comport for PPP thread */
    for(i=0; i<module->comport_cnt; i++)
    {
        if(module->comport[i] == *comport)
        {
            log_dbg("%s free GPRS dataport %s=>[fd:%d]\n", who, (*comport)->dev_name, (*comport)->fd);
            module->comport[i]->used = NO;
            module->users--;
            *comport = NULL;
            break;
        }
    }
    return ;
}
/*
 *  Description: Power on the GPRS module and open all the gprs data port. For when GPRS power off,
 *               the GPRS module USB convert serial comport device lost, so we must bind them together.
 * Return Value: 0: Open successfully  !0: Open failure
 */
int power_on_module(MODULE_INFO *module)
{
    int     rv = 0;
    log_dbg("Turn on GPRS module now\n");
    if( ON == (module->pwr_status=hal_get_gprs_power()) )
    {
        rv = 0;
        log_dbg("GPRS module already power on\n");
        goto cleanup;
    }
    if( (rv=hal_turn_gprs_power(ON)) || ON!=hal_get_gprs_power())
    {
        log_err("Turn on GPRS module failure: rv=%d power=%d\n", rv, hal_get_gprs_power());
        rv = -1;
        goto cleanup;
    }
    micro_second_sleep(500);
    if( comport_open(module->gsmport) < 0)
    {
        log_err("Open GSM serial port [%s] failure\n", module->gsmport->dev_name);
        return -2;
    }
    if( !atcmd_check_power_on(module->gsmport) )
    {
        log_err("Send ATE0 check GPRS module AT command failure\n", module->gsmport->dev_name);
        return -2;
    }
    attach_gsm0710(module->gsmport);
    if( 0 != open_gsm_dataport(module) )
    {
        rv = -3;
        log_err("Open GPRS module comport failure\n");
        goto cleanup;
    }
cleanup:
    if(!rv)
    {
        module->ready = MODULE_READY;
        log_nrml("Turn on GPRS module succesfully\n");
    }
    else
    {
        module->ready = NOT_READY;
        log_nrml("Turn on GPRS module failed, rv=%d\n", rv);
    }
    module->ready = 0!=rv ? NOT_READY : MODULE_READY;
    memset(&(module->reg), 0, sizeof(REGISTER_INFO));
    module->pwr_status = hal_get_gprs_power();
    return rv;
}
/*
 *  Description: Power off the GPRS module and close all the gprs data port. For when GPRS power off,
 *               the GPRS module USB convert serial comport device lost, so we must bind them together.
 * Return Value: 0: Open successfully  !0: Open failure
 */
int power_off_module(MODULE_INFO *module)
{
    if( OFF  == (module->pwr_status=hal_get_gprs_power()) )
    {
        log_dbg("GPRS module already power off\n");
        return 0;
    }
    while(module->users)
    {
        log_warn("%d application still use the GPRS module dataport, wait released...\n", module->users);
        sleep(1);
    }
    log_nrml("Turn off GPRS module now\n");
    close_gsm_dataport(module);
    comport_close(module->gsmport);
    hal_turn_gprs_power(OFF);
    module->ready = NOT_READY;
    memset(&(module->reg), 0, sizeof(REGISTER_INFO));
    module->pwr_status = hal_get_gprs_power();
    micro_second_sleep(800);
    return 0;
}
void set_module_event(MODULE_INFO *module, int request)
{
    log_dbg("Set the module event request[%d]\n", request);
    pthread_mutex_lock(&module->lock);
    module->event = request;
    pthread_mutex_unlock(&module->lock);
}
/*
 *  Description: Set the GPRS power status according to the module request event.
 *               the GPRS module USB convert serial comport device lost, so we must bind them together.
 * Return Value: 0:Set GPRS power status successfully  !0: Open failure
 */
int set_module_event_power(MODULE_INFO *module)
{
    int           rv = 0;
    switch (module->event)
    {
        case REQ_POWER_ON:
            rv = power_on_module(module);
            break;
        case REQ_POWER_OFF:
            rv = power_off_module(module);
            break;
        case REQ_POWER_RESET:
            rv = power_off_module(module);
            rv = power_on_module(module);
            break;
    }
    if( rv )
    {
        log_nrml("Response for the GPRS request event %d failure, rv=%d\n", module->event, rv);
        return rv;
    }
    else
    {
        log_nrml("Response for the GPRS request event %d and clear this event ok\n", module->event);
        set_module_event(module, REQ_EVENT_NONE);
        return 0;
    }
}
int atcmd_inspect_status(MODULE_INFO *module)
{
    COM_PORT        *comport;
    REGISTER_INFO   *reg = &(module->reg);   /* SIM card Register information  */
    char            *who = "atcmd_inspect_status()";
    static unsigned long start_time ;
    /* Every 10 seconds we will inspect it */
    if(start_time && time_elapsed(start_time) < 10000)
    {
        return 0;
    }
    start_time= time_now();
    comport = alloc_gsm_dataport(who, module);
    if(NULL != comport)
    {
        log_dbg("Alloc dataport %s=>[fd:%d]\n", comport->dev_name, comport->fd);
    }
    else
        return -1;
    reg->signal = atcmd_check_gprs_signal(comport);
    atcmd_check_gprs_location(comport, &reg->loc);
    log_dbg("Free dataport %s=>[fd:%d]\n", comport->dev_name, comport->fd);
    free_gsm_dataport(who, module, &comport);
    return 0;
}
/*
 * Description: Check the AT command and SIM card ready or not
 * Input value: times:  Max check times
 *Return Value: 1: Already OK   0: Still on test  -1: Failure
 *
 */
int atcmd_check_module_ready(COM_PORT *comport, int times)
{
    int           rv;
    static int    fail_cnt = 0;
    /* Send ATE0 to check GPRS module AT ready or not  */
    rv = atcmd_check_at_ready(comport);
    if(rv)
        goto cleanup;
    /* Send AT+CPIN? to check SIM card valid or not  */
    rv = atcmd_check_sim_valid(comport);
cleanup:
    if(rv)
    {
        if(fail_cnt < times)
        {
            fail_cnt ++;
            return 0;
        }
        else
        {
            fail_cnt = 0;
            return -1;
        }
    }
    else
    {
        fail_cnt = 0;
        return 1;
    }
}
int atcmd_check_power_on(COM_PORT *comport)
{
    int           i, rv = 0;
    for(i=0; i<10; i++)
    {
        if( !atcmd_check_at_ready(comport) )
        {
            rv = 1;
            break;
        }
    }
    return rv;
}
/*
 * Some preset command here, such as set Module as 2G mode
 */
int atcmd_module_preset(COM_PORT *comport)
{
    int           retval = 0;
    /* Send AT+COPS=0 to set GPRS module auto select an operator  */
    if(0 != (retval=send_atcmd_check_ok(comport, "AT+COPS=0\r", 3000)) )
    {
        log_warn("AT+COPS=0 Set Auto Select Carrier:     [FAILED]\n");
        return -2;
    }
    log_nrml("AT+COPS=0 Set Auto Select Carrier:   [OK]\n");
    return retval;
}
int atcmd_check_hwinfo(COM_PORT *comport, HW_INFO *hw, int times)
{
    int           rv;
    static int    fail_cnt = 0;
    /* Send AT+CGMM to check GPRS module hardware name and type */
    rv = atcmd_check_gprs_name(comport, hw->model);
    if(rv)
        goto cleanup;
    /* Send AT+CGMR to check GPRS module hardware version */
    rv = atcmd_check_gprs_version(comport, hw->mrev);
    if(rv)
        goto cleanup;
    /* Send AT+CGSN to check GPRS module hardware IEMI number*/
    rv = atcmd_check_gprs_iemi(comport, hw->iemi);
cleanup:
    if(rv)
    {
        if(fail_cnt < times)
        {
            fail_cnt ++;
            return 0;
        }
        else
        {
            fail_cnt = 0;
            return -1;
        }
    }
    else
    {
        fail_cnt = 0;
        return 1;
    }
}
int atcmd_check_regist(COM_PORT *comport, REGISTER_INFO *reg, int times)
{
    int           rv = 0;
    static int    fail_cnt = 0;
    /* Send AT+CSQ to check GPRS signal strength */
    reg->signal = atcmd_check_gprs_signal(comport);
    if(reg->signal<2 && reg->signal>31)
    {
        rv = -1;
        goto cleanup;
    }
    /* Send AT+CREG? to check SIM card regist to network or not */
    reg->type = atcmd_check_gprs_register(comport);
    if(REG_HOMEWORK==reg->type || REG_ROAMING== reg->type)
    {
        /* SIM card register successfully */
        log_nrml("SIM card register successfully.\n");
        rv = 0;
    }
    else if(REG_DENIED==reg->type)
    {
        /* SIM card can not register, so request to switch SIM card */
        log_err("SIM card regist denied.\n");
        rv = -2;
        goto cleanup;
    }
    else
    {
        log_err("SIM card regist failure.\n");
        rv = -3;
        goto cleanup;
    }
    rv = atcmd_check_gprs_carrier(comport, reg->carrier);
    if(rv)
    {
        rv = -4;
        log_err("Check SIM card acrrier failure.\n");
        goto cleanup;
    }
    rv = atcmd_check_gprs_mcc_mnc(comport, reg->loc.mcc_mnc);
    if(rv)
    {
        rv = -4;
        log_err("Check SIM card register MCC-MNC failure\n");
        goto cleanup;
    }
cleanup:
    if(rv)
    {
        if(fail_cnt < times)
        {
            fail_cnt ++;
            return 0;
        }
        else
        {
            fail_cnt = 0;
            return -1;
        }
    }
    else
    {
        fail_cnt = 0;
        return 1;
    }
}
int atcmd_check_network_info(COM_PORT *comport, REGISTER_INFO *reg)
{
    int           retval = 0;
    /* Send AT+COPS to check SIM card registed network carrier */
    retval = atcmd_check_gprs_carrier(comport, reg->carrier);
    if(retval) return -1;
    /* Send AT+QGSMLOC=1 to check GPRS module location */
    retval = atcmd_check_gprs_location(comport, &(reg->loc));
    if(retval) return -3;
    return retval;
}
int atcmd_check_ready(MODULE_INFO *module)
{
    int             rv;
    COM_PORT        *comport;
    char            *who = "atcmd_check_ready()";
    log_nrml("AT command check GPRS registry status now\n");
    /* Alloc a comport to send AT command */
    comport = alloc_gsm_dataport(who, module);
    if(NULL == comport)
    {
        log_warn("Alloc dataport for %s() failure.\n", __FUNCTION__);
        return -1;
    }
    log_dbg("Alloc dataport %s=>[fd:%d]\n", comport->dev_name, comport->fd);
    switch(module->ready)
    {
        case MODULE_READY:
            rv = atcmd_check_module_ready(comport, 10);
            if(rv > 0)
            {
                log_nrml("GPRS AT command ready and SIM card valid successfully\n");
                module->ready++;   /* Continue to check, not break */
            }
            else if(rv == 0)
            {
                log_nrml("GPRS AT command ready and SIM card valid check continue...\n");
            }
            else if(rv < 0)
            {
                log_nrml("GPRS AT command ready and SIM card valid check failed\n");
                set_module_event(module, REQ_POWER_RESET);
            }
            break;
        case CHECK_HWINFO:
            rv = atcmd_check_hwinfo(comport, &(module->hw), 10);
            if(rv > 0)
            {
                log_nrml("Check the GPRS Module hardware information successfully\n");
                module->ready++;   /* Continue to check, not break */
            }
            else if(rv == 0)
            {
                log_nrml("Check the GPRS Module hardware information continue...\n");
            }
            else if(rv < 0)
            {
                log_nrml("Check the GPRS Module hardware information failed...\n");
                set_module_event(module, REQ_POWER_RESET);
            }
            break;
        case CHECK_REGISTRY:
            rv = atcmd_check_regist(comport, &(module->reg), 10);
            if(rv > 0)
            {
                log_nrml("Check the SIM card registry successfully\n");
                module->ready++;   /* Continue to check, not break */
            }
            else if(rv == 0)
            {
                log_nrml("Check the SIM card registry continue...\n");
            }
            else if(rv < 0)
            {
                log_nrml("Check the SIM card registry failed\n");
                set_module_event(module, REQ_POWER_RESET);
            }
            break;
    }
    free_gsm_dataport(who, module, &comport);
    return rv;
}
/*
 * Description: Terminate the control thread work context
 * Return Value: NONE
 */
void ctrl_thread_term(void *thread_arg)
{
    int                i=0;
    MODULE_INFO        *module = (MODULE_INFO *)thread_arg;
    log_nrml("start terminate GPRS main(control) thread\n");
    power_off_module(module);
    for(i=0; i<module->comport_cnt; i++)
    {
        comport_term(module->comport[i]);
    }
}
/* Description: Continue the main thread as the control thread, which used to control/inspect the GPRS
 *              module power status. If it exit, then whole program exit.So when it exit, we must
 *              make sure all other threads exit.
 *
 *Return Value: NONE
 */
void ctrl_thread_start(void *thread_arg)
{
    MODULE_INFO        *module = (MODULE_INFO *)thread_arg;
    log_nrml("GPRS power control thread start running\n");
    while( !g_cp_signal.stop )
    {
        /*  If someone request to change the power status, then set the power*/
        if(module->event)
        {
            set_module_event_power(module);
        }
        if(ALL_READY == module->ready)
        {
            /* If GPRS already registed then we just need to inspect the GPRS
             * module status, such as signal, location */
            atcmd_inspect_status(module);
        }
        else
        {
            /* If GPRS module just already power on, then we use AT command to
             * check the SIM card can work or not now. */
            if( ON == module->pwr_status )
            {
                atcmd_check_ready(module);
            }
        }
        sleep(1);
    }
    /* thread exit  */
    ctrl_thread_term(thread_arg);
    return ;
}
program/cp_library/cp_gprs.h
New file
@@ -0,0 +1,126 @@
/********************************************************************************
 *      Copyright:  (C) guowenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  module.h
 *    Description:  This is the GPRS module head file
 *
 *        Version:  1.0.0(02/02/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "02/02/2012 11:33:33 AM"
 *
 ********************************************************************************/
#ifndef __CP_GPRS_H
#define __CP_GPRS_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "cp_common.h"
#include "cp_logger.h"
#include "cp_comport.h"
#include "cp_atcmd.h"
#include "cp_time.h"
#include "cp_hal.h"
#define YES                   1
#define NO                    0
#define GSM_CTRLPORT          "/dev/gprs"
#define GSM_DATAPORT          "/dev/ttyS2"
#define MAX_DATAPORT          4  /* CMUX driver will generate 4 TTY port */
#define CMUX_PORT_START_INDEX 1
#define CMUX_DATAPORT         "/dev/gsmtty"
/*GPRS module power status control request event*/
enum
{
    REQ_EVENT_NONE = 0,
    REQ_POWER_OFF,
    REQ_POWER_ON,
    REQ_POWER_RESET,
};
/* GPRS Module Ready status */
enum
{
    NOT_READY,
    MODULE_READY,    /* GPRS AT command active and SIM card valid */
    CHECK_HWINFO,    /* Get GPRS hardware Information */
    CHECK_REGISTRY,  /* Check GPRS register network information */
    ALL_READY,
};
/* AT+CREG? command show SIM card register status */
enum
{
    REG_UNREGIST = 0, /* not registered, ME is not currently searching a new operator to register to */
    REG_HOMEWORK,     /* registered, home network */
    REG_SEARCHING,    /* not registered, but ME is currently searching a new operator to register to  */
    REG_DENIED,       /* registration denied */
    REG_UNKNOW,       /* unknow */
    REG_ROAMING,      /* registered, roaming */
};
/* AT+CNMP=? command to set GPRS module work on which mode */
#define MODE_AUTO     2   /* Automatic */
#define MODE_GSM      13  /* GSM Only */
#define MODE_WCDMA    14  /* WCDMA Only */
/* AT+CNSMOD? command show network system mode */
enum
{
    NS_NONE = 0,      /* No service */
    NS_GSM,           /* GSM */
    NS_GPRS,          /* GPRS */
    NS_EGPRS,         /* EGPRS(EDGE) */
    NS_WCDMA,         /* WCDMA */
    NS_HSDPA,         /* HSDPA only */
    NS_HSUPA,         /* HSUPA only */
    NS_HSPA,          /* HSDPA and HSUPA */
};
typedef struct __MODULE_INFO
{
    int             users;     /* How many users use the module now  */
    unsigned char   ready;     /* SIM card regist and can work or not */
    unsigned char   event;     /* Request to set GPRS power REQ_POWER_ON, REQ_POWER_OFF or REQ_POWER_RESET */
    unsigned char   pwr_status; /* Current module power status */
    pthread_mutex_t lock;      /* Module control mutex lock */
    HW_INFO         hw;        /* GPRS Hardware information */
    REGISTER_INFO   reg;       /* SIM card register network information */
    COM_PORT        *gsmport;  /* The GSM hardware UART port  */
    int             comport_cnt; /* GPRS data channel count */
    COM_PORT        *comport[MAX_DATAPORT]; /* CMUX driver generate CMUX port */
} MODULE_INFO;
extern int init_gsm_module(MODULE_INFO *module);
extern int  open_gsm_dataport(MODULE_INFO *module);
extern void close_gsm_dataport(MODULE_INFO *module);
extern COM_PORT *alloc_gsm_dataport(char *who, MODULE_INFO *module);
extern void free_gsm_dataport(char *who, MODULE_INFO *module, COM_PORT  **comport);
extern int power_on_module(MODULE_INFO *module);
extern int power_off_module(MODULE_INFO *module);
extern int atcmd_check_ready(MODULE_INFO *module);
extern int atcmd_inspect_status(MODULE_INFO *module);
extern int atcmd_check_power_on(COM_PORT *comport);
//unsigned char atcmd_inspect(MODULE_INFO *module, COM_PORT *comport);
extern void set_module_event(MODULE_INFO *module, int request);
extern int set_module_event_power(MODULE_INFO  *module);
extern void ctrl_thread_start(void *thread_arg);
extern void ctrl_thread_term(void *thread_arg);
#endif /* End of __CP_GPRS_H */
program/cp_library/cp_gsmmux.c
New file
@@ -0,0 +1,75 @@
/*********************************************************************************
 *      Copyright:  (C) 2013 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_gsmmux.c
 *    Description:  This file is the application for GSM0710(A.K.A CMUX) protocal
 *                  which implement in Linux kernel
 *
 *        Version:  1.0.0(01/16/2013~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "01/16/2013 05:37:15 PM"
 *
 ********************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include "cp_logger.h"
#include "cp_gsmmux.h"
int attach_gsm0710(COM_PORT *comport)
{
    int                    ldisc = N_GSM0710;
    struct gsm_config      c;
    log_nrml("Attach GMUX on GSM port \"%s\" now\n", comport->dev_name);
    if( send_atcmd_check_ok(comport, "AT+CMUX=0\r", 3000) )
    {
        log_err("Send \"AT+CMUX=0\" command check %s failure\n", comport->dev_name);
        return -1;
    }
    if (ioctl(comport->fd, TIOCSETD, &ldisc) < 0)
    {
        log_err("Can not attach N_GSM0710 to comport \"%s\" \n", comport->dev_name);
        return -2;
    }
    ioctl(comport->fd, GSMIOC_GETCONF, &c);
    /*  we are initiator and need encoding 0 (basic) */
    c.initiator = 1;
    c.encapsulation = 0;
    /* our modem defaults to a maximum size of 127 bytes */
    c.mru = 127;
    c.mtu = 127;
    /* set the new configuration */
    ioctl(comport->fd, GSMIOC_SETCONF, &c);
    log_nrml("Attach GMUX on GSM port \"%s\" OK\n", comport->dev_name);
    sleep(1);
    return 0;
}
#if 0
int detach_gsm0710(COM_PORT *comport)
{
    log_nrml("Dettach GMUX on GSM port \"%s\" now\n", comport->dev_name);
    return 0;
}
#endif
program/cp_library/cp_gsmmux.h
New file
@@ -0,0 +1,44 @@
/********************************************************************************
 *      Copyright:  (C) 2013 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_gsmmux.h
 *    Description:  This head file is application for GSM0710(A.K.A CMUX) protocal
 *                  which implement in Linux kernel
 *
 *        Version:  1.0.0(01/16/2013~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "01/16/2013 05:43:48 PM"
 *
 ********************************************************************************/
#ifndef __CP_GSMMUX_H_
#define __CP_GSMMUX_H_
#include "cp_atcmd.h"
struct gsm_config
{
    unsigned int adaption;
    unsigned int encapsulation;
    unsigned int initiator;
    unsigned int t1;
    unsigned int t2;
    unsigned int t3;
    unsigned int n2;
    unsigned int mru;
    unsigned int mtu;
    unsigned int k;
    unsigned int i;
    unsigned int unused[8];   /* Padding for expansion without breaking stuff */
};
#define GSMIOC_GETCONF      _IOR('G', 0, struct gsm_config)
#define GSMIOC_SETCONF      _IOW('G', 1, struct gsm_config)
#define N_GSM0710           21  /*   GSM 0710 Mux */
int attach_gsm0710(COM_PORT *comport);
//int detach_gsm0710(COM_PORT *comport);
#endif /* __CP_GSMMUX_H_  */
program/cp_library/cp_hal.c
New file
@@ -0,0 +1,257 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_led_buzzer.c
 *    Description:  This file is is the HAL(Hardware Abstraction Layer) for
 *                  AT91SAM9xxx family devices.
 *
 *        Version:  1.0.0(12/05/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "12/05/2012 01:26:33 PM"
 *
 ********************************************************************************/
#include "cp_hal.h"
int hal_turn_led_on(int  led)
{
    int         fd = -1;
    if((fd=open(DEV_LED_PATH, O_RDWR)) < 0)
    {
        return -1;
    }
    ioctl(fd, LED_ON, led);
    close(fd);
    return 0;
}
int hal_turn_led_off(int led)
{
    int         fd = -1;
    if((fd=open(DEV_LED_PATH, O_RDWR)) < 0)
    {
        return -1;
    }
    ioctl(fd, LED_OFF, led);
    close(fd);
    return 0;
}
int hal_turn_led_blink(int led, int mode)
{
    int         fd = -1;
    int         arg = led|(mode<<3);
    if((fd=open(DEV_LED_PATH, O_RDWR)) < 0)
    {
        return -1;
    }
    ioctl(fd, LED_BLINK, arg);
    close(fd);
    return 0;
}
/*
 * Description: Turn GPRS ON or OFF
 *  Input Args: RESET(2)/ON(1)/OFF(0)
 */
int hal_turn_gprs_power(int status)
{
    int         fd = -1;
    int         rv = 0;
    if((fd=open(DEV_GSM_PATH, O_RDWR)) < 0)
    {
        return -1;
    }
    if( (rv=ioctl(fd, GSM_SET_POWER, status)) < 0)
    {
        close(fd);
        return -2;
    }
    close(fd);
    return rv;
}
/*
 *  Description: Get current GPRS power status
 * Return Value: ON(1)/OFF(0)
 */
int hal_get_gprs_power(void)
{
    int         fd = -1;
    int         status;
    if((fd=open(DEV_GSM_PATH, O_RDWR)) < 0)
    {
        return -1;
    }
    if( (status=ioctl(fd, GSM_GET_POWER, 0)) < 0)
    {
        close(fd);
        return -2;
    }
    close(fd);
    return status;
}
/*
 * Description: Turn GPS ON or OFF
 *  Input Args: ON(1)/OFF(0)
 */
int hal_turn_gps_power(int status)
{
    int         fd = -1;
    int         rv = 0;
    if((fd=open(DEV_GPS_PATH, O_RDWR)) < 0)
    {
        return -1;
    }
    if( (rv=ioctl(fd, GPS_SET_POWER, status)) < 0)
    {
        close(fd);
        return -2;
    }
    close(fd);
    return rv;
}
/*
 *  Description: Get current GPS power status
 * Return Value: ON(1)/OFF(0)
 */
int hal_get_gps_power(void)
{
    int         fd = -1;
    int         status;
    if((fd=open(DEV_GPS_PATH, O_RDWR)) < 0)
    {
        return -1;
    }
    if( (status=ioctl(fd, GPS_GET_POWER, 0)) < 0)
    {
        close(fd);
        return -2;
    }
    close(fd);
    return status;
}
/*
 * Description: Reset zigbee module
 */
int hal_reset_zigbee(void)
{
    int         fd = -1;
    if((fd=open(DEV_ZIGBEE_PATH, O_RDWR)) < 0)
    {
        return -1;
    }
    if( ioctl(fd, ZIGBEE_RESET, 0) < 0)
    {
        close(fd);
        return -2;
    }
    close(fd);
    return 0;
}
/*
 *  Description: Get Zigbee status
 */
int hal_get_zigbee_status(void)
{
    int         fd = -1;
    int         status;
    if((fd=open(DEV_ZIGBEE_PATH, O_RDWR)) < 0)
    {
        return -1;
    }
    if( (status=ioctl(fd, ZIGBEE_STATUS, 0)) < 0)
    {
        close(fd);
        return -2;
    }
    close(fd);
    return status;
}
/*
 * Description: Start/Stop Radiation Moniter sample
 *  Input Args: Start(1)/Stop(0) the sample
 *  Return Val: If status=1(start), it will return this time sample dose
 *              If status=0(stop), it will return last time sample dose
 */
int hal_set_gmtube(status)
{
    int         fd = -1;
    int         dose = 0;
    if((fd=open(DEV_GMTUBE_PATH, O_RDWR)) < 0)
    {
        return -1;
    }
    if( (dose=ioctl(fd, GM_SET_MEASURE_RADI, status)) < 0)
    {
        close(fd);
        return -2;
    }
    close(fd);
    return dose;
}
/*
 * Description: Start/Stop Radiation Moniter sample
 *  Input Args: Start(1)/Stop(0) the sample
 *  Return Val: Return last time sample dose
 */
int hal_get_gmtube_dose(void)
{
    int         fd = -1;
    int         dose = 0;
    if((fd=open(DEV_GMTUBE_PATH, O_RDWR)) < 0)
    {
        return -1;
    }
    if( (dose=ioctl(fd, GM_GET_MEASURE_DOSE, 0)) < 0)
    {
        close(fd);
        return -2;
    }
    close(fd);
    return dose;
}
program/cp_library/cp_hal.h
New file
@@ -0,0 +1,56 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_hal.h
 *    Description:  This head file
 *
 *        Version:  1.0.0(12/05/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "12/05/2012 02:21:55 PM"
 *
 ********************************************************************************/
#ifndef __CP_HAL_H
#define __CP_HAL_H
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "at91_ioctl.h"
#define DEV_LED_PATH            "/dev/led"
#define DEV_GSM_PATH            "/dev/gprs"
#define DEV_GPS_PATH            "/dev/gps"
#define DEV_ZIGBEE_PATH         "/dev/zigbee"
#define DEV_GMTUBE_PATH         "/dev/gmtube"
#define OFF                     0
#define ON                      1
#define BLINK                   2
#define RESET                   2
#define MODE_SLOW               0
#define MODE_FAST               1
#define START                   1
#define STOP                    0
#define LED_SYS                 0
extern int hal_turn_led_on(int led);
extern int hal_turn_led_off(int led);
extern int hal_turn_led_blink(int led, int mode);
extern int hal_turn_gprs_power(int status);
extern int hal_get_gprs_power(void);
extern int hal_turn_gps_power(int status);
extern int hal_get_gps_power(void);
#endif /* Endof __CP_HAL_H  */
program/cp_library/cp_iniparser.c
New file
@@ -0,0 +1,807 @@
/*-------------------------------------------------------------------------*/
/**
   @file    cp_iniparser.c
   @author  N. Devillard
   @brief   Parser for ini files.
*/
/*--------------------------------------------------------------------------*/
/*---------------------------- Includes ------------------------------------*/
#include <ctype.h>
#include "cp_iniparser.h"
/*---------------------------- Defines -------------------------------------*/
#define ASCIILINESZ         (1024)
#define INI_INVALID_KEY     ((char*)-1)
/*---------------------------------------------------------------------------
                        Private to this module
 ---------------------------------------------------------------------------*/
/**
 * This enum stores the status for each parsed line (internal use only).
 */
typedef enum _line_status_ {
    LINE_UNPROCESSED,
    LINE_ERROR,
    LINE_EMPTY,
    LINE_COMMENT,
    LINE_SECTION,
    LINE_VALUE
} line_status ;
/*-------------------------------------------------------------------------*/
/**
  @brief    Convert a string to lowercase.
  @param    s   String to convert.
  @return   ptr to statically allocated string.
  This function returns a pointer to a statically allocated string
  containing a lowercased version of the input string. Do not free
  or modify the returned string! Since the returned string is statically
  allocated, it will be modified at each function call (not re-entrant).
 */
/*--------------------------------------------------------------------------*/
static char * strlwc(const char * s)
{
    static char l[ASCIILINESZ+1];
    int i ;
    if (s==NULL) return NULL ;
    memset(l, 0, ASCIILINESZ+1);
    i=0 ;
    while (s[i] && i<ASCIILINESZ) {
        l[i] = (char)tolower((int)s[i]);
        i++ ;
    }
    l[ASCIILINESZ]=(char)0;
    return l ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Remove blanks at the beginning and the end of a string.
  @param    s   String to parse.
  @return   ptr to statically allocated string.
  This function returns a pointer to a statically allocated string,
  which is identical to the input string, except that all blank
  characters at the end and the beg. of the string have been removed.
  Do not free or modify the returned string! Since the returned string
  is statically allocated, it will be modified at each function call
  (not re-entrant).
 */
/*--------------------------------------------------------------------------*/
static char * strstrip(const char * s)
{
    static char l[ASCIILINESZ+1];
    char * last ;
    if (s==NULL) return NULL ;
    while (isspace((int)*s) && *s) s++;
    memset(l, 0, ASCIILINESZ+1);
    strcpy(l, s);
    last = l + strlen(l);
    while (last > l) {
        if (!isspace((int)*(last-1)))
            break ;
        last -- ;
    }
    *last = (char)0;
    return (char*)l ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get number of sections in a dictionary
  @param    d   Dictionary to examine
  @return   int Number of sections found in dictionary
  This function returns the number of sections found in a dictionary.
  The test to recognize sections is done on the string stored in the
  dictionary: a section name is given as "section" whereas a key is
  stored as "section:key", thus the test looks for entries that do not
  contain a colon.
  This clearly fails in the case a section name contains a colon, but
  this should simply be avoided.
  This function returns -1 in case of error.
 */
/*--------------------------------------------------------------------------*/
int iniparser_getnsec(dictionary * d)
{
    int i ;
    int nsec ;
    if (d==NULL) return -1 ;
    nsec=0 ;
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]==NULL)
            continue ;
        if (strchr(d->key[i], ':')==NULL) {
            nsec ++ ;
        }
    }
    return nsec ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get name for section n in a dictionary.
  @param    d   Dictionary to examine
  @param    n   Section number (from 0 to nsec-1).
  @return   Pointer to char string
  This function locates the n-th section in a dictionary and returns
  its name as a pointer to a string statically allocated inside the
  dictionary. Do not free or modify the returned string!
  This function returns NULL in case of error.
 */
/*--------------------------------------------------------------------------*/
char * iniparser_getsecname(dictionary * d, int n)
{
    int i ;
    int foundsec ;
    if (d==NULL || n<0) return NULL ;
    foundsec=0 ;
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]==NULL)
            continue ;
        if (strchr(d->key[i], ':')==NULL) {
            foundsec++ ;
            if (foundsec>n)
                break ;
        }
    }
    if (foundsec<=n) {
        return NULL ;
    }
    return d->key[i] ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Dump a dictionary to an opened file pointer.
  @param    d   Dictionary to dump.
  @param    f   Opened file pointer to dump to.
  @return   void
  This function prints out the contents of a dictionary, one element by
  line, onto the provided file pointer. It is OK to specify @c stderr
  or @c stdout as output files. This function is meant for debugging
  purposes mostly.
 */
/*--------------------------------------------------------------------------*/
void iniparser_dump(dictionary * d, FILE * f)
{
    int     i ;
    if (d==NULL || f==NULL) return ;
    for (i=0 ; i<d->size ; i++) {
        if (d->key[i]==NULL)
            continue ;
        if (d->val[i]!=NULL) {
            fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
        } else {
            fprintf(f, "[%s]=UNDEF\n", d->key[i]);
        }
    }
    return ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Save a dictionary to a loadable ini file
  @param    d   Dictionary to dump
  @param    f   Opened file pointer to dump to
  @return   void
  This function dumps a given dictionary into a loadable ini file.
  It is Ok to specify @c stderr or @c stdout as output files.
 */
/*--------------------------------------------------------------------------*/
void iniparser_dump_ini(dictionary * d, FILE * f)
{
    int     i ;
    int     nsec ;
    char *  secname ;
    if (d==NULL || f==NULL) return ;
    nsec = iniparser_getnsec(d);
    if (nsec<1) {
        /* No section in file: dump all keys as they are */
        for (i=0 ; i<d->size ; i++) {
            if (d->key[i]==NULL)
                continue ;
            fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
        }
        return ;
    }
    for (i=0 ; i<nsec ; i++) {
        secname = iniparser_getsecname(d, i) ;
        iniparser_dumpsection_ini(d, secname, f) ;
    }
    fprintf(f, "\n");
    return ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Save a dictionary section to a loadable ini file
  @param    d   Dictionary to dump
  @param    s   Section name of dictionary to dump
  @param    f   Opened file pointer to dump to
  @return   void
  This function dumps a given section of a given dictionary into a loadable ini
  file.  It is Ok to specify @c stderr or @c stdout as output files.
 */
/*--------------------------------------------------------------------------*/
void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f)
{
    int     j ;
    char    keym[ASCIILINESZ+1];
    int     seclen ;
    if (d==NULL || f==NULL) return ;
    if (! iniparser_find_entry(d, s)) return ;
    seclen  = (int)strlen(s);
    fprintf(f, "\n[%s]\n", s);
    sprintf(keym, "%s:", s);
    for (j=0 ; j<d->size ; j++) {
        if (d->key[j]==NULL)
            continue ;
        if (!strncmp(d->key[j], keym, seclen+1)) {
            fprintf(f,
                    "%-30s = %s\n",
                    d->key[j]+seclen+1,
                    d->val[j] ? d->val[j] : "");
        }
    }
    fprintf(f, "\n");
    return ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the number of keys in a section of a dictionary.
  @param    d   Dictionary to examine
  @param    s   Section name of dictionary to examine
  @return   Number of keys in section
 */
/*--------------------------------------------------------------------------*/
int iniparser_getsecnkeys(dictionary * d, char * s)
{
    int     seclen, nkeys ;
    char    keym[ASCIILINESZ+1];
    int j ;
    nkeys = 0;
    if (d==NULL) return nkeys;
    if (! iniparser_find_entry(d, s)) return nkeys;
    seclen  = (int)strlen(s);
    sprintf(keym, "%s:", s);
    for (j=0 ; j<d->size ; j++) {
        if (d->key[j]==NULL)
            continue ;
        if (!strncmp(d->key[j], keym, seclen+1))
            nkeys++;
    }
    return nkeys;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the number of keys in a section of a dictionary.
  @param    d   Dictionary to examine
  @param    s   Section name of dictionary to examine
  @return   pointer to statically allocated character strings
  This function queries a dictionary and finds all keys in a given section.
  Each pointer in the returned char pointer-to-pointer is pointing to
  a string allocated in the dictionary; do not free or modify them.
  This function returns NULL in case of error.
 */
/*--------------------------------------------------------------------------*/
char ** iniparser_getseckeys(dictionary * d, char * s)
{
    char **keys;
    int i, j ;
    char    keym[ASCIILINESZ+1];
    int     seclen, nkeys ;
    keys = NULL;
    if (d==NULL) return keys;
    if (! iniparser_find_entry(d, s)) return keys;
    nkeys = iniparser_getsecnkeys(d, s);
    keys = (char**) malloc(nkeys*sizeof(char*));
    seclen  = (int)strlen(s);
    sprintf(keym, "%s:", s);
    i = 0;
    for (j=0 ; j<d->size ; j++) {
        if (d->key[j]==NULL)
            continue ;
        if (!strncmp(d->key[j], keym, seclen+1)) {
            keys[i] = d->key[j];
            i++;
        }
    }
    return keys;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key
  @param    d       Dictionary to search
  @param    key     Key string to look for
  @param    def     Default value to return if key not found.
  @return   pointer to statically allocated character string
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the pointer passed as 'def' is returned.
  The returned char pointer is pointing to a string allocated in
  the dictionary, do not free or modify it.
 */
/*--------------------------------------------------------------------------*/
char * iniparser_getstring(dictionary * d, const char * key, char * def)
{
    char * lc_key ;
    char * sval ;
    if (d==NULL || key==NULL)
        return def ;
    lc_key = strlwc(key);
    sval = dictionary_get(d, lc_key, def);
    return sval ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key, convert to an int
  @param    d Dictionary to search
  @param    key Key string to look for
  @param    notfound Value to return in case of error
  @return   integer
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the notfound value is returned.
  Supported values for integers include the usual C notation
  so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
  are supported. Examples:
  "42"      ->  42
  "042"     ->  34 (octal -> decimal)
  "0x42"    ->  66 (hexa  -> decimal)
  Warning: the conversion may overflow in various ways. Conversion is
  totally outsourced to strtol(), see the associated man page for overflow
  handling.
  Credits: Thanks to A. Becker for suggesting strtol()
 */
/*--------------------------------------------------------------------------*/
int iniparser_getint(dictionary * d, const char * key, int notfound)
{
    char    *   str ;
    str = iniparser_getstring(d, key, INI_INVALID_KEY);
    if (str==INI_INVALID_KEY) return notfound ;
    return (int)strtol(str, NULL, 0);
}
int iniparser_getlong(dictionary * d, const char * key, int notfound)
{
    char    *   str ;
    str = iniparser_getstring(d, key, INI_INVALID_KEY);
    if (str==INI_INVALID_KEY) return notfound ;
    return strtol(str, NULL, 0);
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key, convert to a double
  @param    d Dictionary to search
  @param    key Key string to look for
  @param    notfound Value to return in case of error
  @return   double
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the notfound value is returned.
 */
/*--------------------------------------------------------------------------*/
double iniparser_getdouble(dictionary * d, const char * key, double notfound)
{
    char    *   str ;
    str = iniparser_getstring(d, key, INI_INVALID_KEY);
    if (str==INI_INVALID_KEY) return notfound ;
    return atof(str);
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key, convert to a boolean
  @param    d Dictionary to search
  @param    key Key string to look for
  @param    notfound Value to return in case of error
  @return   integer
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the notfound value is returned.
  A true boolean is found if one of the following is matched:
  - A string starting with 'y'
  - A string starting with 'Y'
  - A string starting with 't'
  - A string starting with 'T'
  - A string starting with '1'
  A false boolean is found if one of the following is matched:
  - A string starting with 'n'
  - A string starting with 'N'
  - A string starting with 'f'
  - A string starting with 'F'
  - A string starting with '0'
  The notfound value returned if no boolean is identified, does not
  necessarily have to be 0 or 1.
 */
/*--------------------------------------------------------------------------*/
int iniparser_getboolean(dictionary * d, const char * key, int notfound)
{
    char    *   c ;
    int         ret ;
    c = iniparser_getstring(d, key, INI_INVALID_KEY);
    if (c==INI_INVALID_KEY) return notfound ;
    if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
        ret = 1 ;
    } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
        ret = 0 ;
    } else {
        ret = notfound ;
    }
    return ret;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Finds out if a given entry exists in a dictionary
  @param    ini     Dictionary to search
  @param    entry   Name of the entry to look for
  @return   integer 1 if entry exists, 0 otherwise
  Finds out if a given entry exists in the dictionary. Since sections
  are stored as keys with NULL associated values, this is the only way
  of querying for the presence of sections in a dictionary.
 */
/*--------------------------------------------------------------------------*/
int iniparser_find_entry(
    dictionary  *   ini,
    const char  *   entry
)
{
    int found=0 ;
    if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
        found = 1 ;
    }
    return found ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Set an entry in a dictionary.
  @param    ini     Dictionary to modify.
  @param    entry   Entry to modify (entry name)
  @param    val     New value to associate to the entry.
  @return   int 0 if Ok, -1 otherwise.
  If the given entry can be found in the dictionary, it is modified to
  contain the provided value. If it cannot be found, -1 is returned.
  It is Ok to set val to NULL.
 */
/*--------------------------------------------------------------------------*/
int iniparser_set(dictionary * ini, const char * entry, const char * val)
{
    return dictionary_set(ini, strlwc(entry), val) ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Delete an entry in a dictionary
  @param    ini     Dictionary to modify
  @param    entry   Entry to delete (entry name)
  @return   void
  If the given entry can be found, it is deleted from the dictionary.
 */
/*--------------------------------------------------------------------------*/
void iniparser_unset(dictionary * ini, const char * entry)
{
    dictionary_unset(ini, strlwc(entry));
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Load a single line from an INI file
  @param    input_line  Input line, may be concatenated multi-line input
  @param    section     Output space to store section
  @param    key         Output space to store key
  @param    value       Output space to store value
  @return   line_status value
 */
/*--------------------------------------------------------------------------*/
static line_status iniparser_line(
    char * input_line,
    char * section,
    char * key,
    char * value)
{
    line_status sta ;
    char        line[ASCIILINESZ+1];
    static char left_line[ASCIILINESZ+1];
    int         len, offset ;
    strcpy(line, strstrip(input_line));
    len = (int)strlen(line);
    sta = LINE_UNPROCESSED ;
    if (len<1) {
        /* Empty line */
        sta = LINE_EMPTY ;
        memset(input_line, 0, len);
    } else if (line[0]=='#' || line[0]==';') {
        /* Comment line */
        sta = LINE_COMMENT ;
        memset(input_line, 0, len);
    } else if (line[0]=='[') {
        /* Section name */
        sscanf(line, "[%[^]]", section);
        strcpy(section, strstrip(section));
        strcpy(section, strlwc(section));
        /* Left configure will go to next time to parser */
        offset = strlen(section) + 2;
        strcpy( left_line, strstrip(&(line[offset])) );
        strcpy( left_line, strstrip(left_line));
        if( strlen(left_line) > 0)
        {
            strcpy(input_line, left_line);
            strcat(input_line, "\n");
        }
        else
        {
            memset(input_line, 0, len);
        }
        sta = LINE_SECTION ;
    } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
           ||  sscanf (line, "%[^=] = '%[^\']'",   key, value) == 2
           ||  sscanf (line, "%[^=] = %[^;#]",     key, value) == 2) {
        char      *ptr = NULL;
        /* Usual key=value, with or without comments */
        strcpy(key, strstrip(key));
        strcpy(key, strlwc(key));
        strcpy(value, strstrip(value));
        /*
         * sscanf cannot handle '' or "" as empty values
         * this is done here
         */
        if (!strncmp(value, "\"\"", 2) || (!strncmp(value, "''", 2)) ) {
            value[0]=0 ;
        }
        ptr = strchr(line, '=');
        if('\''==*(ptr+1) || '\"'==*(ptr+1))
        {
            offset = strlen(key)+strlen(value) + 1 + 2; /* Skip $key='$val' */
        }
        else
        {
            offset = strlen(key)+strlen(value) + 1; /* Skip $key=$val */
        }
        strcpy( left_line, strstrip(&(line[offset])) );
        if( strlen(left_line) > 0)
        {
            strcpy(input_line, left_line);
            strcat(input_line, "\n");
        }
        else
        {
            memset(input_line, 0, len);
        }
        sta = LINE_VALUE ;
    } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2
           ||  sscanf(line, "%[^=] %[=]", key, value) == 2) {
        /*
         * Special cases:
         * key=
         * key=;
         * key=#
         */
        strcpy(key, strstrip(key));
        strcpy(key, strlwc(key));
        value[0]=0 ;
        sta = LINE_VALUE ;
    } else {
        /* Generate syntax error */
        sta = LINE_ERROR ;
        memset(input_line, 0, len);
    }
    return sta ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Parse an ini file and return an allocated dictionary object
  @param    ininame Name of the ini file to read.
  @return   Pointer to newly allocated dictionary
  This is the parser for ini files. This function is called, providing
  the name of the file to be read. It returns a dictionary object that
  should not be accessed directly, but through accessor functions
  instead.
  The returned dictionary must be freed using iniparser_freedict().
 */
/*--------------------------------------------------------------------------*/
dictionary * iniparser_load(const char * ininame)
{
    FILE * in ;
    char line    [ASCIILINESZ+1] ;
    char section [ASCIILINESZ+1] ;
    char key     [ASCIILINESZ+1] ;
    char tmp     [ASCIILINESZ+1] ;
    char val     [ASCIILINESZ+1] ;
    int  last=0 ;
    int  len ;
    int  lineno=0 ;
    int  errs=0;
    dictionary * dict ;
    if ((in=fopen(ininame, "r"))==NULL) {
        fprintf(stderr, "iniparser: cannot open %s\n", ininame);
        return NULL ;
    }
    dict = dictionary_new(0) ;
    if (!dict) {
        fclose(in);
        return NULL ;
    }
    memset(line,    0, ASCIILINESZ);
    memset(section, 0, ASCIILINESZ);
    memset(key,     0, ASCIILINESZ);
    memset(val,     0, ASCIILINESZ);
    last=0 ;
    while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
        lineno++ ;
CONTINUE_PARSER:
        len = (int)strlen(line)-1;
        if (len==0)
            continue;
        /* Safety check against buffer overflows */
        if (line[len]!='\n') {
            fprintf(stderr,
                    "iniparser: input line too long in %s (%d)\n",
                    ininame,
                    lineno);
            dictionary_del(dict);
            fclose(in);
            return NULL ;
        }
        /* Get rid of \n and spaces at end of line */
        while ((len>=0) &&
                ((line[len]=='\n') || (isspace(line[len])))) {
            line[len]=0 ;
            len-- ;
        }
        /* Detect multi-line */
        if (line[len]=='\\') {
            /* Multi-line value */
            last=len ;
            continue ;
        } else {
            last=0 ;
        }
        switch ( iniparser_line(line, section, key, val) ) {
            case LINE_EMPTY:
            case LINE_COMMENT:
            break ;
            case LINE_SECTION:
            errs = dictionary_set(dict, section, NULL);
            break ;
            case LINE_VALUE:
            sprintf(tmp, "%s:%s", section, key);
            errs = dictionary_set(dict, tmp, val) ;
            break ;
            case LINE_ERROR:
            fprintf(stderr, "iniparser: syntax error in %s (%d):\n",
                    ininame,
                    lineno);
            fprintf(stderr, "-> %s\n", line);
            errs++ ;
            break;
            default:
            break ;
        }
        if( strlen(line) > 0)
        {
            goto CONTINUE_PARSER;
        }
        memset(line, 0, ASCIILINESZ);
        last=0;
        if (errs<0) {
            fprintf(stderr, "iniparser: memory allocation failure\n");
            break ;
        }
    }
    if (errs) {
        dictionary_del(dict);
        dict = NULL ;
    }
    fclose(in);
    return dict ;
}
/*-------------------------------------------------------------------------*/
/**
  @brief    Free all memory associated to an ini dictionary
  @param    d Dictionary to free
  @return   void
  Free all memory associated to an ini dictionary.
  It is mandatory to call this function before the dictionary object
  gets out of the current context.
 */
/*--------------------------------------------------------------------------*/
void iniparser_freedict(dictionary * d)
{
    dictionary_del(d);
}
/* vim: set ts=4 et sw=4 tw=75 */
program/cp_library/cp_iniparser.h
New file
@@ -0,0 +1,308 @@
/*-------------------------------------------------------------------------*/
/**
   @file    cp_iniparser.h
   @author  N. Devillard
   @brief   Parser for ini files.
*/
/*--------------------------------------------------------------------------*/
#ifndef _CP_INIPARSER_H_
#define _CP_INIPARSER_H_
/*---------------------------------------------------------------------------
                                Includes
 ---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
 * The following #include is necessary on many Unixes but not Linux.
 * It is not needed for Windows platforms.
 * Uncomment it if needed.
 */
/* #include <unistd.h> */
#include "cp_dictionary.h"
/*-------------------------------------------------------------------------*/
/**
  @brief    Get number of sections in a dictionary
  @param    d   Dictionary to examine
  @return   int Number of sections found in dictionary
  This function returns the number of sections found in a dictionary.
  The test to recognize sections is done on the string stored in the
  dictionary: a section name is given as "section" whereas a key is
  stored as "section:key", thus the test looks for entries that do not
  contain a colon.
  This clearly fails in the case a section name contains a colon, but
  this should simply be avoided.
  This function returns -1 in case of error.
 */
/*--------------------------------------------------------------------------*/
int iniparser_getnsec(dictionary * d);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get name for section n in a dictionary.
  @param    d   Dictionary to examine
  @param    n   Section number (from 0 to nsec-1).
  @return   Pointer to char string
  This function locates the n-th section in a dictionary and returns
  its name as a pointer to a string statically allocated inside the
  dictionary. Do not free or modify the returned string!
  This function returns NULL in case of error.
 */
/*--------------------------------------------------------------------------*/
char * iniparser_getsecname(dictionary * d, int n);
/*-------------------------------------------------------------------------*/
/**
  @brief    Save a dictionary to a loadable ini file
  @param    d   Dictionary to dump
  @param    f   Opened file pointer to dump to
  @return   void
  This function dumps a given dictionary into a loadable ini file.
  It is Ok to specify @c stderr or @c stdout as output files.
 */
/*--------------------------------------------------------------------------*/
void iniparser_dump_ini(dictionary * d, FILE * f);
/*-------------------------------------------------------------------------*/
/**
  @brief    Save a dictionary section to a loadable ini file
  @param    d   Dictionary to dump
  @param    s   Section name of dictionary to dump
  @param    f   Opened file pointer to dump to
  @return   void
  This function dumps a given section of a given dictionary into a loadable ini
  file.  It is Ok to specify @c stderr or @c stdout as output files.
 */
/*--------------------------------------------------------------------------*/
void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f);
/*-------------------------------------------------------------------------*/
/**
  @brief    Dump a dictionary to an opened file pointer.
  @param    d   Dictionary to dump.
  @param    f   Opened file pointer to dump to.
  @return   void
  This function prints out the contents of a dictionary, one element by
  line, onto the provided file pointer. It is OK to specify @c stderr
  or @c stdout as output files. This function is meant for debugging
  purposes mostly.
 */
/*--------------------------------------------------------------------------*/
void iniparser_dump(dictionary * d, FILE * f);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the number of keys in a section of a dictionary.
  @param    d   Dictionary to examine
  @param    s   Section name of dictionary to examine
  @return   Number of keys in section
 */
/*--------------------------------------------------------------------------*/
int iniparser_getsecnkeys(dictionary * d, char * s);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the number of keys in a section of a dictionary.
  @param    d   Dictionary to examine
  @param    s   Section name of dictionary to examine
  @return   pointer to statically allocated character strings
  This function queries a dictionary and finds all keys in a given section.
  Each pointer in the returned char pointer-to-pointer is pointing to
  a string allocated in the dictionary; do not free or modify them.
  This function returns NULL in case of error.
 */
/*--------------------------------------------------------------------------*/
char ** iniparser_getseckeys(dictionary * d, char * s);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key
  @param    d       Dictionary to search
  @param    key     Key string to look for
  @param    def     Default value to return if key not found.
  @return   pointer to statically allocated character string
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the pointer passed as 'def' is returned.
  The returned char pointer is pointing to a string allocated in
  the dictionary, do not free or modify it.
 */
/*--------------------------------------------------------------------------*/
char * iniparser_getstring(dictionary * d, const char * key, char * def);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key, convert to an int
  @param    d Dictionary to search
  @param    key Key string to look for
  @param    notfound Value to return in case of error
  @return   integer
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the notfound value is returned.
  Supported values for integers include the usual C notation
  so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
  are supported. Examples:
  - "42"      ->  42
  - "042"     ->  34 (octal -> decimal)
  - "0x42"    ->  66 (hexa  -> decimal)
  Warning: the conversion may overflow in various ways. Conversion is
  totally outsourced to strtol(), see the associated man page for overflow
  handling.
  Credits: Thanks to A. Becker for suggesting strtol()
 */
/*--------------------------------------------------------------------------*/
int iniparser_getint(dictionary * d, const char * key, int notfound);
int iniparser_getlong(dictionary * d, const char * key, int notfound);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key, convert to a double
  @param    d Dictionary to search
  @param    key Key string to look for
  @param    notfound Value to return in case of error
  @return   double
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the notfound value is returned.
 */
/*--------------------------------------------------------------------------*/
double iniparser_getdouble(dictionary * d, const char * key, double notfound);
/*-------------------------------------------------------------------------*/
/**
  @brief    Get the string associated to a key, convert to a boolean
  @param    d Dictionary to search
  @param    key Key string to look for
  @param    notfound Value to return in case of error
  @return   integer
  This function queries a dictionary for a key. A key as read from an
  ini file is given as "section:key". If the key cannot be found,
  the notfound value is returned.
  A true boolean is found if one of the following is matched:
  - A string starting with 'y'
  - A string starting with 'Y'
  - A string starting with 't'
  - A string starting with 'T'
  - A string starting with '1'
  A false boolean is found if one of the following is matched:
  - A string starting with 'n'
  - A string starting with 'N'
  - A string starting with 'f'
  - A string starting with 'F'
  - A string starting with '0'
  The notfound value returned if no boolean is identified, does not
  necessarily have to be 0 or 1.
 */
/*--------------------------------------------------------------------------*/
int iniparser_getboolean(dictionary * d, const char * key, int notfound);
/*-------------------------------------------------------------------------*/
/**
  @brief    Set an entry in a dictionary.
  @param    ini     Dictionary to modify.
  @param    entry   Entry to modify (entry name)
  @param    val     New value to associate to the entry.
  @return   int 0 if Ok, -1 otherwise.
  If the given entry can be found in the dictionary, it is modified to
  contain the provided value. If it cannot be found, -1 is returned.
  It is Ok to set val to NULL.
 */
/*--------------------------------------------------------------------------*/
int iniparser_set(dictionary * ini, const char * entry, const char * val);
/*-------------------------------------------------------------------------*/
/**
  @brief    Delete an entry in a dictionary
  @param    ini     Dictionary to modify
  @param    entry   Entry to delete (entry name)
  @return   void
  If the given entry can be found, it is deleted from the dictionary.
 */
/*--------------------------------------------------------------------------*/
void iniparser_unset(dictionary * ini, const char * entry);
/*-------------------------------------------------------------------------*/
/**
  @brief    Finds out if a given entry exists in a dictionary
  @param    ini     Dictionary to search
  @param    entry   Name of the entry to look for
  @return   integer 1 if entry exists, 0 otherwise
  Finds out if a given entry exists in the dictionary. Since sections
  are stored as keys with NULL associated values, this is the only way
  of querying for the presence of sections in a dictionary.
 */
/*--------------------------------------------------------------------------*/
int iniparser_find_entry(dictionary * ini, const char * entry) ;
/*-------------------------------------------------------------------------*/
/**
  @brief    Parse an ini file and return an allocated dictionary object
  @param    ininame Name of the ini file to read.
  @return   Pointer to newly allocated dictionary
  This is the parser for ini files. This function is called, providing
  the name of the file to be read. It returns a dictionary object that
  should not be accessed directly, but through accessor functions
  instead.
  The returned dictionary must be freed using iniparser_freedict().
 */
/*--------------------------------------------------------------------------*/
dictionary * iniparser_load(const char * ininame);
/*-------------------------------------------------------------------------*/
/**
  @brief    Free all memory associated to an ini dictionary
  @param    d Dictionary to free
  @return   void
  Free all memory associated to an ini dictionary.
  It is mandatory to call this function before the dictionary object
  gets out of the current context.
 */
/*--------------------------------------------------------------------------*/
void iniparser_freedict(dictionary * d);
#endif
program/cp_library/cp_klist.h
New file
@@ -0,0 +1,723 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_list.h
 *    Description:  This file is copied from Linux kernel, which provide link list API.
 *
 *        Version:  1.0.0(08/09/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "08/09/2012 02:24:34 AM"
 *
 ********************************************************************************/
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
#include <linux/stddef.h>
/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:    the pointer to the member.
 * @type:   the type of the container struct this is embedded in.
 * @member: the name of the member within the struct.
 *
 */
#undef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({          \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})
/*
 * Architectures might want to move the poison pointer offset
 * into some well-recognized area such as 0xdead000000000000,
 * that is also not mappable by user-space exploits:
 */
#ifdef CONFIG_ILLEGAL_POINTER_VALUE
# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
#else
# define POISON_POINTER_DELTA 0
#endif
/*
 * These are non-NULL pointers that will result in page faults
 * under normal circumstances, used to verify that nobody uses
 * non-initialized list entries.
 */
#define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
#define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)
#ifndef ARCH_HAS_PREFETCH
#define ARCH_HAS_PREFETCH
static inline void prefetch(const void *x) {;}
#endif
/*
 * Simple doubly linked list implementation.
 *
 * Some of the internal functions ("__xxx") are useful when
 * manipulating whole lists rather than single entries, as
 * sometimes we already know the next/prev entries and we can
 * generate better code by using them directly rather than
 * using the generic single-entry routines.
 */
struct list_head {
    struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
    list->next = list;
    list->prev = list;
}
/*
 * Insert a new entry between two known consecutive entries.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next)
{
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
}
/**
 * list_add - add a new entry
 * @new: new entry to be added
 * @head: list head to add it after
 *
 * Insert a new entry after the specified head.
 * This is good for implementing stacks.
 */
static inline void list_add(struct list_head *new, struct list_head *head)
{
    __list_add(new, head, head->next);
}
/**
 * list_add_tail - add a new entry
 * @new: new entry to be added
 * @head: list head to add it before
 *
 * Insert a new entry before the specified head.
 * This is useful for implementing queues.
 */
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
    __list_add(new, head->prev, head);
}
/*
 * Delete a list entry by making the prev/next entries
 * point to each other.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
    next->prev = prev;
    prev->next = next;
}
/**
 * list_del - deletes entry from list.
 * @entry: the element to delete from the list.
 * Note: list_empty() on entry does not return true after this, the entry is
 * in an undefined state.
 */
static inline void list_del(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    entry->next = LIST_POISON1;
    entry->prev = LIST_POISON2;
}
/**
 * list_replace - replace old entry by new one
 * @old : the element to be replaced
 * @new : the new element to insert
 *
 * If @old was empty, it will be overwritten.
 */
static inline void list_replace(struct list_head *old,
                struct list_head *new)
{
    new->next = old->next;
    new->next->prev = new;
    new->prev = old->prev;
    new->prev->next = new;
}
static inline void list_replace_init(struct list_head *old,
                    struct list_head *new)
{
    list_replace(old, new);
    INIT_LIST_HEAD(old);
}
/**
 * list_del_init - deletes entry from list and reinitialize it.
 * @entry: the element to delete from the list.
 */
static inline void list_del_init(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    INIT_LIST_HEAD(entry);
}
/**
 * list_move - delete from one list and add as another's head
 * @list: the entry to move
 * @head: the head that will precede our entry
 */
static inline void list_move(struct list_head *list, struct list_head *head)
{
    __list_del(list->prev, list->next);
    list_add(list, head);
}
/**
 * list_move_tail - delete from one list and add as another's tail
 * @list: the entry to move
 * @head: the head that will follow our entry
 */
static inline void list_move_tail(struct list_head *list,
                  struct list_head *head)
{
    __list_del(list->prev, list->next);
    list_add_tail(list, head);
}
/**
 * list_is_last - tests whether @list is the last entry in list @head
 * @list: the entry to test
 * @head: the head of the list
 */
static inline int list_is_last(const struct list_head *list,
                const struct list_head *head)
{
    return list->next == head;
}
/**
 * list_empty - tests whether a list is empty
 * @head: the list to test.
 */
static inline int list_empty(const struct list_head *head)
{
    return head->next == head;
}
/**
 * list_empty_careful - tests whether a list is empty and not being modified
 * @head: the list to test
 *
 * Description:
 * tests whether a list is empty _and_ checks that no other CPU might be
 * in the process of modifying either member (next or prev)
 *
 * NOTE: using list_empty_careful() without synchronization
 * can only be safe if the only activity that can happen
 * to the list entry is list_del_init(). Eg. it cannot be used
 * if another CPU could re-list_add() it.
 */
static inline int list_empty_careful(const struct list_head *head)
{
    struct list_head *next = head->next;
    return (next == head) && (next == head->prev);
}
/**
 * list_is_singular - tests whether a list has just one entry.
 * @head: the list to test.
 */
static inline int list_is_singular(const struct list_head *head)
{
    return !list_empty(head) && (head->next == head->prev);
}
static inline void __list_cut_position(struct list_head *list,
        struct list_head *head, struct list_head *entry)
{
    struct list_head *new_first = entry->next;
    list->next = head->next;
    list->next->prev = list;
    list->prev = entry;
    entry->next = list;
    head->next = new_first;
    new_first->prev = head;
}
/**
 * list_cut_position - cut a list into two
 * @list: a new list to add all removed entries
 * @head: a list with entries
 * @entry: an entry within head, could be the head itself
 *    and if so we won't cut the list
 *
 * This helper moves the initial part of @head, up to and
 * including @entry, from @head to @list. You should
 * pass on @entry an element you know is on @head. @list
 * should be an empty list or a list you do not care about
 * losing its data.
 *
 */
static inline void list_cut_position(struct list_head *list,
        struct list_head *head, struct list_head *entry)
{
    if (list_empty(head))
        return;
    if (list_is_singular(head) &&
        (head->next != entry && head != entry))
        return;
    if (entry == head)
        INIT_LIST_HEAD(list);
    else
        __list_cut_position(list, head, entry);
}
static inline void __list_splice(const struct list_head *list,
                 struct list_head *prev,
                 struct list_head *next)
{
    struct list_head *first = list->next;
    struct list_head *last = list->prev;
    first->prev = prev;
    prev->next = first;
    last->next = next;
    next->prev = last;
}
/**
 * list_splice - join two lists, this is designed for stacks
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice(const struct list_head *list,
                struct list_head *head)
{
    if (!list_empty(list))
        __list_splice(list, head, head->next);
}
/**
 * list_splice_tail - join two lists, each list being a queue
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice_tail(struct list_head *list,
                struct list_head *head)
{
    if (!list_empty(list))
        __list_splice(list, head->prev, head);
}
/**
 * list_splice_init - join two lists and reinitialise the emptied list.
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 *
 * The list at @list is reinitialised
 */
static inline void list_splice_init(struct list_head *list,
                    struct list_head *head)
{
    if (!list_empty(list)) {
        __list_splice(list, head, head->next);
        INIT_LIST_HEAD(list);
    }
}
/**
 * list_splice_tail_init - join two lists and reinitialise the emptied list
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 *
 * Each of the lists is a queue.
 * The list at @list is reinitialised
 */
static inline void list_splice_tail_init(struct list_head *list,
                     struct list_head *head)
{
    if (!list_empty(list)) {
        __list_splice(list, head->prev, head);
        INIT_LIST_HEAD(list);
    }
}
/**
 * list_entry - get the struct for this entry
 * @ptr:    the &struct list_head pointer.
 * @type:    the type of the struct this is embedded in.
 * @member:    the name of the list_struct within the struct.
 */
#define list_entry(ptr, type, member) \
    container_of(ptr, type, member)
/**
 * list_first_entry - get the first element from a list
 * @ptr:    the list head to take the element from.
 * @type:    the type of the struct this is embedded in.
 * @member:    the name of the list_struct within the struct.
 *
 * Note, that list is expected to be not empty.
 */
#define list_first_entry(ptr, type, member) \
    list_entry((ptr)->next, type, member)
/**
 * list_for_each    -    iterate over a list
 * @pos:    the &struct list_head to use as a loop cursor.
 * @head:    the head for your list.
 */
#define list_for_each(pos, head) \
    for (pos = (head)->next; prefetch(pos->next), pos != (head); \
        pos = pos->next)
/**
 * __list_for_each    -    iterate over a list
 * @pos:    the &struct list_head to use as a loop cursor.
 * @head:    the head for your list.
 *
 * This variant differs from list_for_each() in that it's the
 * simplest possible list iteration code, no prefetching is done.
 * Use this for code that knows the list to be very short (empty
 * or 1 entry) most of the time.
 */
#define __list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)
/**
 * list_for_each_prev    -    iterate over a list backwards
 * @pos:    the &struct list_head to use as a loop cursor.
 * @head:    the head for your list.
 */
#define list_for_each_prev(pos, head) \
    for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
        pos = pos->prev)
/**
 * list_for_each_safe - iterate over a list safe against removal of list entry
 * @pos:    the &struct list_head to use as a loop cursor.
 * @n:        another &struct list_head to use as temporary storage
 * @head:    the head for your list.
 */
#define list_for_each_safe(pos, n, head) \
    for (pos = (head)->next, n = pos->next; pos != (head); \
        pos = n, n = pos->next)
/**
 * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
 * @pos:    the &struct list_head to use as a loop cursor.
 * @n:        another &struct list_head to use as temporary storage
 * @head:    the head for your list.
 */
#define list_for_each_prev_safe(pos, n, head) \
    for (pos = (head)->prev, n = pos->prev; \
         prefetch(pos->prev), pos != (head); \
         pos = n, n = pos->prev)
/**
 * list_for_each_entry    -    iterate over list of given type
 * @pos:    the type * to use as a loop cursor.
 * @head:    the head for your list.
 * @member:    the name of the list_struct within the struct.
 */
#define list_for_each_entry(pos, head, member)                \
    for (pos = list_entry((head)->next, typeof(*pos), member);    \
         prefetch(pos->member.next), &pos->member != (head);    \
         pos = list_entry(pos->member.next, typeof(*pos), member))
/**
 * list_for_each_entry_reverse - iterate backwards over list of given type.
 * @pos:    the type * to use as a loop cursor.
 * @head:    the head for your list.
 * @member:    the name of the list_struct within the struct.
 */
#define list_for_each_entry_reverse(pos, head, member)            \
    for (pos = list_entry((head)->prev, typeof(*pos), member);    \
         prefetch(pos->member.prev), &pos->member != (head);    \
         pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
 * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
 * @pos:    the type * to use as a start point
 * @head:    the head of the list
 * @member:    the name of the list_struct within the struct.
 *
 * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
 */
#define list_prepare_entry(pos, head, member) \
    ((pos) ? : list_entry(head, typeof(*pos), member))
/**
 * list_for_each_entry_continue - continue iteration over list of given type
 * @pos:    the type * to use as a loop cursor.
 * @head:    the head for your list.
 * @member:    the name of the list_struct within the struct.
 *
 * Continue to iterate over list of given type, continuing after
 * the current position.
 */
#define list_for_each_entry_continue(pos, head, member)         \
    for (pos = list_entry(pos->member.next, typeof(*pos), member);    \
         prefetch(pos->member.next), &pos->member != (head);    \
         pos = list_entry(pos->member.next, typeof(*pos), member))
/**
 * list_for_each_entry_continue_reverse - iterate backwards from the given point
 * @pos:    the type * to use as a loop cursor.
 * @head:    the head for your list.
 * @member:    the name of the list_struct within the struct.
 *
 * Start to iterate over list of given type backwards, continuing after
 * the current position.
 */
#define list_for_each_entry_continue_reverse(pos, head, member)        \
    for (pos = list_entry(pos->member.prev, typeof(*pos), member);    \
         prefetch(pos->member.prev), &pos->member != (head);    \
         pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
 * list_for_each_entry_from - iterate over list of given type from the current point
 * @pos:    the type * to use as a loop cursor.
 * @head:    the head for your list.
 * @member:    the name of the list_struct within the struct.
 *
 * Iterate over list of given type, continuing from current position.
 */
#define list_for_each_entry_from(pos, head, member)            \
    for (; prefetch(pos->member.next), &pos->member != (head);    \
         pos = list_entry(pos->member.next, typeof(*pos), member))
/**
 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @pos:    the type * to use as a loop cursor.
 * @n:        another type * to use as temporary storage
 * @head:    the head for your list.
 * @member:    the name of the list_struct within the struct.
 */
#define list_for_each_entry_safe(pos, n, head, member)            \
    for (pos = list_entry((head)->next, typeof(*pos), member),    \
        n = list_entry(pos->member.next, typeof(*pos), member);    \
         &pos->member != (head);                    \
         pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
 * list_for_each_entry_safe_continue
 * @pos:    the type * to use as a loop cursor.
 * @n:        another type * to use as temporary storage
 * @head:    the head for your list.
 * @member:    the name of the list_struct within the struct.
 *
 * Iterate over list of given type, continuing after current point,
 * safe against removal of list entry.
 */
#define list_for_each_entry_safe_continue(pos, n, head, member)         \
    for (pos = list_entry(pos->member.next, typeof(*pos), member),        \
        n = list_entry(pos->member.next, typeof(*pos), member);        \
         &pos->member != (head);                        \
         pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
 * list_for_each_entry_safe_from
 * @pos:    the type * to use as a loop cursor.
 * @n:        another type * to use as temporary storage
 * @head:    the head for your list.
 * @member:    the name of the list_struct within the struct.
 *
 * Iterate over list of given type from current point, safe against
 * removal of list entry.
 */
#define list_for_each_entry_safe_from(pos, n, head, member)            \
    for (n = list_entry(pos->member.next, typeof(*pos), member);        \
         &pos->member != (head);                        \
         pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
 * list_for_each_entry_safe_reverse
 * @pos:    the type * to use as a loop cursor.
 * @n:        another type * to use as temporary storage
 * @head:    the head for your list.
 * @member:    the name of the list_struct within the struct.
 *
 * Iterate backwards over list of given type, safe against removal
 * of list entry.
 */
#define list_for_each_entry_safe_reverse(pos, n, head, member)        \
    for (pos = list_entry((head)->prev, typeof(*pos), member),    \
        n = list_entry(pos->member.prev, typeof(*pos), member);    \
         &pos->member != (head);                    \
         pos = n, n = list_entry(n->member.prev, typeof(*n), member))
/*
 * Double linked lists with a single pointer list head.
 * Mostly useful for hash tables where the two pointer list head is
 * too wasteful.
 * You lose the ability to access the tail in O(1).
 */
struct hlist_head {
    struct hlist_node *first;
};
struct hlist_node {
    struct hlist_node *next, **pprev;
};
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
    h->next = NULL;
    h->pprev = NULL;
}
static inline int hlist_unhashed(const struct hlist_node *h)
{
    return !h->pprev;
}
static inline int hlist_empty(const struct hlist_head *h)
{
    return !h->first;
}
static inline void __hlist_del(struct hlist_node *n)
{
    struct hlist_node *next = n->next;
    struct hlist_node **pprev = n->pprev;
    *pprev = next;
    if (next)
        next->pprev = pprev;
}
static inline void hlist_del(struct hlist_node *n)
{
    __hlist_del(n);
    n->next = LIST_POISON1;
    n->pprev = LIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
{
    if (!hlist_unhashed(n)) {
        __hlist_del(n);
        INIT_HLIST_NODE(n);
    }
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
    struct hlist_node *first = h->first;
    n->next = first;
    if (first)
        first->pprev = &n->next;
    h->first = n;
    n->pprev = &h->first;
}
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
                    struct hlist_node *next)
{
    n->pprev = next->pprev;
    n->next = next;
    next->pprev = &n->next;
    *(n->pprev) = n;
}
static inline void hlist_add_after(struct hlist_node *n,
                    struct hlist_node *next)
{
    next->next = n->next;
    n->next = next;
    next->pprev = &n->next;
    if(next->next)
        next->next->pprev  = &next->next;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
    for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
         pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
    for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
         pos = n)
/**
 * hlist_for_each_entry    - iterate over list of given type
 * @tpos:    the type * to use as a loop cursor.
 * @pos:    the &struct hlist_node to use as a loop cursor.
 * @head:    the head for your list.
 * @member:    the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry(tpos, pos, head, member)             \
    for (pos = (head)->first;                     \
         pos && ({ prefetch(pos->next); 1;}) &&             \
        ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
         pos = pos->next)
/**
 * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
 * @tpos:    the type * to use as a loop cursor.
 * @pos:    the &struct hlist_node to use as a loop cursor.
 * @member:    the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry_continue(tpos, pos, member)         \
    for (pos = (pos)->next;                         \
         pos && ({ prefetch(pos->next); 1;}) &&             \
        ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
         pos = pos->next)
/**
 * hlist_for_each_entry_from - iterate over a hlist continuing from current point
 * @tpos:    the type * to use as a loop cursor.
 * @pos:    the &struct hlist_node to use as a loop cursor.
 * @member:    the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry_from(tpos, pos, member)             \
    for (; pos && ({ prefetch(pos->next); 1;}) &&             \
        ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
         pos = pos->next)
/**
 * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @tpos:    the type * to use as a loop cursor.
 * @pos:    the &struct hlist_node to use as a loop cursor.
 * @n:        another &struct hlist_node to use as temporary storage
 * @head:    the head for your list.
 * @member:    the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry_safe(tpos, pos, n, head, member)         \
    for (pos = (head)->first;                     \
         pos && ({ n = pos->next; 1; }) &&                 \
        ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
         pos = n)
#endif
program/cp_library/cp_logger.c
New file
@@ -0,0 +1,420 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_log.c
 *    Description:  This file is the linux infrastructural logger system library
 *
 *        Version:  1.0.0(08/08/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "08/08/2012 04:24:01 PM"
 *
 ********************************************************************************/
#include "cp_logger.h"
#include "cp_common.h"
#define PRECISE_TIME_FACTOR 1000
static unsigned long log_rollback_size = LOG_ROLLBACK_NONE;
static cp_logger *logger = NULL;
char *log_str[LOG_LEVEL_MAX + 1] = { "", "F", "E", "W", "N", "D", "I", "T", "M" };
static char *cp_time_format = DEFAULT_TIME_FORMAT;
void cp_log_set_time_format(char *time_format)
{
    cp_time_format = time_format;
}
static void cp_log_default_signal_handler(int sig)
{
    if(!logger)
        return ;
    if (sig == SIGHUP)
    {
        signal(SIGHUP, cp_log_default_signal_handler);
        log_fatal("SIGHUP received - reopenning log file [%s]", logger->file);
        cp_log_reopen();
    }
}
static void log_banner(char *prefix)
{
    if(!logger)
        return ;
    fprintf(logger->fp, "%s log \"%s\" on level [%s] size [%lu], log system version %s\n",
            prefix, logger->file, log_str[logger->level], log_rollback_size / 1024, LOG_VERSION_STR);
#ifdef LOG_FILE_LINE
    fprintf(logger->fp, " [Date]    [Time]   [Level] [PID/TID] [File/Line]  [Content]\n");
#else
    fprintf(logger->fp, " [Date]    [Time]   [Level] [PID/TID] [Content]\n");
#endif
    fprintf(logger->fp, "-------------------------------------------------------------\n");
}
static void check_and_rollback(void)
{
    if(!logger)
        return ;
    if (log_rollback_size != LOG_ROLLBACK_NONE)
    {
        long _curOffset = ftell(logger->fp);
        if ((_curOffset != -1) && (_curOffset >= log_rollback_size))
        {
            char cmd[512];
            snprintf(cmd, sizeof(cmd), "cp -f %s %s.roll", logger->file, logger->file);
            system(cmd);
            if (-1 == fseek(logger->fp, 0L, SEEK_SET))
                fprintf(logger->fp, "log rollback fseek failed \n");
            rewind(logger->fp);
            truncate(logger->file, 0);
            log_banner("Already rollback");
        }
    }
}
cp_logger *cp_log_init(cp_logger *log, char *filename, int level, int log_size)
{
    if(NULL == log)
    {
        logger = t_malloc(sizeof(cp_logger));
        memset(logger, 0, sizeof(cp_logger));
        logger->flag |= CP_LOGGER_MALLOC;
    }
    else
    {
        logger = log;
        memset(logger, 0, sizeof(cp_logger));
        logger->flag |= CP_LOGGER_ARGUMENT;
    }
    if(NULL == logger)
    {
        return NULL;
    }
    strncpy(logger->file, filename, FILENAME_LEN);
    logger->level = level;
    logger->size = log_size;
    return logger;
}
int cp_log_open(void)
{
    struct sigaction act;
    char *filemode;
    if(!logger)
    {
        return -1;
    }
    log_rollback_size = logger->size <= 0 ? LOG_ROLLBACK_NONE : logger->size*1024;    /* Unit KiB */
    if ('\0' == logger->file)
        return -1;
    if (!strcmp(logger->file, DBG_LOG_FILE))
    {
        logger->fp = stderr;
        log_rollback_size = LOG_ROLLBACK_NONE;
        logger->flag |= CP_LOGGER_CONSOLE;
        goto OUT;
    }
    //filemode = (log_rollback_size==LOG_ROLLBACK_NONE) ? "a+" : "w+";
    filemode = "a+";
    logger->fp = fopen(logger->file, filemode);
    if (NULL == logger->fp)
    {
        fprintf(stderr, "Open log file \"%s\" in %s failure\n", logger->file, filemode);
        return -2;
    }
    act.sa_handler = cp_log_default_signal_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGHUP, &act, NULL);
  OUT:
    log_banner("Initialize");
    return 0;
}
void cp_log_close(void)
{
    if (!logger || !logger->fp )
        return;
    log_banner("\nTerminate");
    cp_log_raw("\n\n\n\n");
    fflush(logger->fp);
    fclose(logger->fp);
    logger->fp = NULL;
    return ;
}
int cp_log_reopen(void)
{
    int rc = 0;
    char *filemode;
    if( !logger )
        return -1;
    if (logger->flag & CP_LOGGER_CONSOLE )
    {
        fflush(logger->fp);
        logger->fp = stderr;
        return 0;
    }
    if (logger->fp)
    {
        cp_log_close();
        //filemode = log_rollback_size == LOG_ROLLBACK_NONE ? "a+" : "w+";
        filemode = "a+";
        logger->fp = fopen(logger->file, filemode);
        if (logger->fp == NULL)
            rc = -2;
    }
    else
    {
        rc = -3;
    }
    if (!rc)
    {
        log_banner("\nReopen");
    }
    return rc;
}
void cp_log_term(void)
{
    if(!logger)
        return ;
    cp_log_close();
    if (logger->flag & CP_LOGGER_MALLOC )
    {
        t_free(logger);
    }
    logger = NULL;
}
void cp_log_raw(const char *fmt, ...)
{
    va_list argp;
    if (!logger || !logger->fp)
        return;
    check_and_rollback();
    va_start(argp, fmt);
    vfprintf(logger->fp, fmt, argp);
    va_end(argp);
}
static void cp_printout(char *level, char *fmt, va_list argp)
{
    char buf[MAX_LOG_MESSAGE_LEN];
    struct tm *local;
    struct timeval now;
    char timestr[256];
    if(!logger)
        return ;
    pthread_t tid;
    check_and_rollback();
#ifdef MULTHREADS
    tid = pthread_self();
#else
    tid = getpid();
#endif
    gettimeofday(&now, NULL);
    local = localtime(&now.tv_sec);
    strftime(timestr, 256, cp_time_format, local);
    vsnprintf(buf, MAX_LOG_MESSAGE_LEN, fmt, argp);
#ifdef DUMPLICATE_OUTPUT
    printf("%s.%03ld [%s] [%06lu]: %s",
           timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, buf);
#endif
    if (logger->fp)
        fprintf(logger->fp, "%s.%03ld [%s] [%06lu]: %s", timestr, now.tv_usec / PRECISE_TIME_FACTOR,
                level, tid, buf);
    if (logger->fp)
        fflush(logger->fp);
}
static void cp_printout_line(char *level, char *fmt, char *file, int line, va_list argp)
{
    char buf[MAX_LOG_MESSAGE_LEN];
    struct tm *local;
    struct timeval now;
    char timestr[256];
    if(!logger)
        return ;
    pthread_t tid;
    check_and_rollback();
#ifdef MULTHREADS
    tid = pthread_self();
#else
    tid = getpid();
#endif
    gettimeofday(&now, NULL);
    local = localtime(&now.tv_sec);
    strftime(timestr, 256, cp_time_format, local);
    vsnprintf(buf, MAX_LOG_MESSAGE_LEN, fmt, argp);
#ifdef DUMPLICATE_OUTPUT
    printf("%s.%03ld [%s] [%06lu] (%s [%04d]) : %s",
           timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, file, line, buf);
#endif
    if (logger->fp)
        fprintf(logger->fp, "%s.%03ld [%s] [%06lu] (%s [%04d]) : %s",
                timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, file, line, buf);
    if (logger->fp)
        fflush(logger->fp);
}
void cp_log(int level, char *fmt, ...)
{
    va_list argp;
    if (!logger || level>logger->level)
        return;
    va_start(argp, fmt);
    cp_printout(log_str[level], fmt, argp);
    va_end(argp);
}
void cp_log_line(int level, char *file, int line, char *fmt, ...)
{
    va_list argp;
    if (!logger || level>logger->level)
        return;
    va_start(argp, fmt);
    cp_printout_line(log_str[level], fmt, file, line, argp);
    va_end(argp);
}
#define LINELEN 81
#define CHARS_PER_LINE 16
static char *print_char =
    "                "
    "                "
    " !\"#$%&'()*+,-./"
    "0123456789:;<=>?"
    "@ABCDEFGHIJKLMNO"
    "PQRSTUVWXYZ[\\]^_"
    "`abcdefghijklmno"
    "pqrstuvwxyz{|}~ "
    "                "
    "                "
    " ???????????????"
    "????????????????"
    "????????????????"
    "????????????????"
    "????????????????"
    "????????????????";
void cp_log_dump(int level, char *buf, int len)
{
    int rc;
    int idx;
    char prn[LINELEN];
    char lit[CHARS_PER_LINE + 2];
    char hc[4];
    short line_done = 1;
    if (!logger || level>logger->level)
        return;
    rc = len;
    idx = 0;
    lit[CHARS_PER_LINE] = '\0';
    while (rc > 0)
    {
        if (line_done)
            snprintf(prn, LINELEN, "%08X: ", idx);
        do
        {
            unsigned char c = buf[idx];
            snprintf(hc, 4, "%02X ", c);
            strncat(prn, hc, LINELEN);
            lit[idx % CHARS_PER_LINE] = print_char[c];
        }
        while (--rc > 0 && (++idx % CHARS_PER_LINE != 0));
        line_done = (idx % CHARS_PER_LINE) == 0;
        if (line_done)
        {
#ifdef DUMPLICATE_OUTPUT
            printf("%s  %s\n", prn, lit);
#endif
            if (logger->fp)
                fprintf(logger->fp, "%s  %s\n", prn, lit);
        }
    }
    if (!line_done)
    {
        int ldx = idx % CHARS_PER_LINE;
        lit[ldx++] = print_char[(int)buf[idx]];
        lit[ldx] = '\0';
        while ((++idx % CHARS_PER_LINE) != 0)
            strncat(prn, "   ", LINELEN);
#ifdef DUMPLICATE_OUTPUT
        printf("%s  %s\n", prn, lit);
#endif
        if (logger->fp)
            fprintf(logger->fp, "%s  %s\n", prn, lit);
    }
}
program/cp_library/cp_logger.h
New file
@@ -0,0 +1,110 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_logger.h
 *    Description:  This file is the linux infrastructural logger system library
 *
 *        Version:  1.0.0(08/08/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "08/08/2012 05:16:56 PM"
 *
 ********************************************************************************/
#ifndef __CP_LOG_H
#define __CP_LOG_H
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/time.h>
#define LOG_VERSION_STR             "1.0.0"
#ifndef FILENAME_LEN
#define FILENAME_LEN                64
#endif
#define DEFAULT_LOGFILE             "cp_logger.log"
#define DBG_LOG_FILE                "console"  /*  Debug mode log file is console */
#define LOG_ROLLBACK_SIZE           512    /* Default rollback log size  */
#define LOG_ROLLBACK_NONE           0      /* Set rollback size to 0 will not rollback  */
#define DEFAULT_TIME_FORMAT         "%Y-%m-%d %H:%M:%S"
#define MAX_LOG_MESSAGE_LEN         0x1000
//#define DUMPLICATE_OUTPUT  /* Log to file and printf on console  */
#define LOG_FILE_LINE      /* Log the file and line */
enum
{
    LOG_LEVEL_DISB = 0,               /*  Disable "Debug" */
    LOG_LEVEL_FATAL,                  /*  Debug Level "Fatal" */
    LOG_LEVEL_ERROR,                  /*  Debug Level "ERROR" */
    LOG_LEVEL_WARN,                   /*  Debug Level "warnning" */
    LOG_LEVEL_NRML,                   /*  Debug Level "Normal" */
    LOG_LEVEL_DEBUG,                  /*  Debug Level "Debug" */
    LOG_LEVEL_INFO,                   /*  Debug Level "Information" */
    LOG_LEVEL_TRACE,                  /*  Debug Level "Trace" */
    LOG_LEVEL_MAX,
};
#define CP_LOGGER_MALLOC              1<<0
#define CP_LOGGER_ARGUMENT            0<<0
#define CP_LOGGER_CONSOLE             1<<1
#define CP_LOGGER_FILE                0<<1
#define CP_LOGGER_LEVEL_OPT           1<<2 /*  The log level is sepcified by the command option */
typedef struct _cp_logger
{
    unsigned char      flag;  /* This logger pointer is malloc() or passed by argument */
    char               file[FILENAME_LEN];
    int                level;
    int                size;
    FILE               *fp;
} cp_logger;
extern char *log_str[];
extern cp_logger *cp_log_init(cp_logger *log, char *filename, int level, int log_size);
extern int  cp_log_open(void);
extern void cp_log_set_time_format(char *time_format);
extern int  cp_log_reopen(void);
extern void cp_log_term(void);
extern void cp_log_raw(const char *fmt, ...);
extern void cp_log(int level, char *fmt, ...);
extern void cp_log_line(int level, char *file, int line, char *fmt, ...);
extern void cp_log_dump(int level, char *buf, int len);
#ifdef LOG_FILE_LINE
#define log_trace(fmt, ...) cp_log_line(LOG_LEVEL_TRACE, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define log_info(fmt, ...) cp_log_line(LOG_LEVEL_INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define log_dbg(fmt, ...) cp_log_line(LOG_LEVEL_DEBUG, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define log_nrml(fmt, ...) cp_log_line(LOG_LEVEL_NRML, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define log_warn(fmt, ...) cp_log_line(LOG_LEVEL_WARN, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define log_err(fmt, ...) cp_log_line(LOG_LEVEL_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define log_fatal(fmt, ...) cp_log_line(LOG_LEVEL_FATAL, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#else
#define log_trace(fmt, ...) cp_log(LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__)
#define log_info(fmt, ...) cp_log(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
#define log_dbg(fmt, ...) cp_log(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
#define log_nrml(fmt, ...) cp_log(LOG_LEVEL_NRML, fmt, ##__VA_ARGS__)
#define log_warn(fmt, ...) cp_log(LOG_LEVEL_WARN, fmt, ##__VA_ARGS__)
#define log_err(fmt, ...) cp_log(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define log_fatal(fmt, ...) cp_log(LOG_LEVEL_FATAL, fmt, ##__VA_ARGS__)
#endif
#endif /* __CP_LOG_H  */
program/cp_library/cp_network.c
New file
@@ -0,0 +1,358 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_network.c
 *    Description:  This file is the high level network library API
 *
 *        Version:  1.0.0(10/31/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/31/2012 11:22:38 AM"
 *
 ********************************************************************************/
#include <netinet/in.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <arpa/inet.h>
#include "cp_sock.h"
#include "cp_fds.h"
#include "cp_network.h"
#include "cp_network.h"
#include "cp_proc.h"
/*  Description: Configure the NIC MAC/IP address
 *   Input args: $nic: configure for which NIC(Network Interface Card): eth0, eth1
 *               $mac: MAC address        $ip: IP address
 * Return Value: 0: Test OK, <0: Failed
 */
int nic_network_config(char *nic, char *mac, char *ip)
{
    if(!nic)
        return -1;
    /*MAC address format: aa:bb:cc:dd:ee:ff */
    if(mac && 17==strlen(mac))
    {
        /* shutdown the ethernet and clear the original IP address  */
        exec_system_cmd("ifconfig %s down", nic, nic);
        sleep(1);
        exec_system_cmd("ifconfig %s hw ether %s up", nic, mac);
    }
    /* IP address specified and valid  */
    if(ip && inet_addr(ip))
    {
        exec_system_cmd("ifconfig %s down && ifconfig %s 0.0.0.0", nic, nic);
        sleep(2);
        exec_system_cmd("ifconfig %s %s up", nic, ip);
    }
    return 0;
}
int nic_get_ipaddr(char *nic, char *ipaddr)
{
    int                   fd;
    struct ifreq          ifr;
    struct sockaddr_in    *sin;
    if( !nic || !ipaddr )
        return -1;
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    strcpy(ifr.ifr_name, nic);
    if ((ioctl(fd, SIOCGIFADDR, (caddr_t)&ifr, sizeof(struct ifreq))) < 0)
    {
        log_fatal("System call ioctl() with SIOCGIFADDR get %s IP address failure.\n", nic);
        return -2;
    }
    sin = (struct sockaddr_in *)&ifr.ifr_addr;
    strcpy(ipaddr, (const char *)inet_ntoa(sin->sin_addr));
    log_dbg("Get %s local IP address: %s\n", nic, ipaddr);
    return 0;
}
int nic_get_ptpaddr(char *nic, char *ptpaddr)
{
    int                   fd;
    struct ifreq          ifr;
    struct sockaddr_in    *sin;
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    strcpy(ifr.ifr_name, nic);
    if ((ioctl(fd, SIOCGIFDSTADDR, (caddr_t) & ifr, sizeof(struct ifreq))) < 0)
    {
        log_fatal("System call ioctl() with SIOCGIFDSTADDR get %s IP address failure.\n", nic);
        return -1;
    }
    sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
    strcpy(ptpaddr, (const char *)inet_ntoa(sin->sin_addr));
    log_dbg("Get %s remote IP address: %s\n", nic, ptpaddr);
    return 0;
}
/*  Description: Use ping do network test
 *   Input args: $from: : use which NIC(Network Interface Card: eth0, eth1) or
 *               source IP address do ping test. if it's NULL, use default route
 *               $ping_ip:  The ping test destination IP address
 *  Output args: NONE
 * Return Value: >=0 ping test packet lost percent, <0: failure
 */
int network_ping_test(char *from, char *ping_ip)
{
    FILE                 *fp;
    char                 cmd[256];
    char                 buf[512];
    int                  lost_percent = 100;
    unsigned long        tx_packets = 0;
    unsigned long        rx_packets = 0;
    memset(cmd, 0, sizeof(cmd));
    if(from)
    {
        snprintf(cmd, sizeof(cmd), "ping -W1 -c5 -s4 %s -I %s", ping_ip, from);
    }
    else
    {
        snprintf(cmd, sizeof(cmd), "ping -W1 -c5 -s4 %s", ping_ip);
    }
    if (NULL == (fp = popen(cmd, "r")))
    {
        return -2;
    }
    while (NULL != fgets(buf, sizeof(buf), fp))
    {
        if (strstr(buf, "transmitted"))
        {
            split_string_to_value(buf, "%l,%l,%d", &tx_packets, &rx_packets, &lost_percent);
            break;
        }
    }
    pclose(fp);
    return lost_percent;
}
int cp_sock_accept_regist(CP_SOCK *serv_sock)
{
    CP_SOCK                *new_sock = NULL;
    int                    rv = 0;
    if(!serv_sock)
    {
        log_err("Invalude input arguments\n");
        return -1;
    }
    log_dbg("Accept and regist new client from server [%d] on [%s:%d] now\n",
            serv_sock->fd, serv_sock->laddr, serv_sock->lport);
    if(serv_sock->accept_cnt >= serv_sock->max_client)
    {
        log_err("No more client resource aviable on server socket [%d]\n", serv_sock->fd);
        goto exit_out;
    }
    if( !(new_sock=cp_sock_init(NULL, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) )
    {
        log_err("Create a new socket contex for accept new client failed.\n");
        goto exit_out;
    }
    new_sock->serv_sock = serv_sock;
    new_sock->fds = serv_sock->fds;
    new_sock->privt = serv_sock->privt;
    new_sock->cbfunc = serv_sock->client_func;
    new_sock->mode = CP_SOCK_MODE_ACCEPT;
    /* add accept new client into the socket registry list */
    if( cp_fds_add_sock_registry(new_sock) )
    {
        rv = -2;
        goto term_sock;
    }
    /* accept the new client from server socket */
    if( cp_sock_accept(serv_sock, new_sock) )
    {
        rv = -3;
        goto  del_regist;
    }
    if( cp_add_epoll_event(new_sock) )
    {
        rv =  -4;
        goto del_regist;
    }
    log_dbg("Accept and regist new client from server [%d] on [%s:%d] ok\n",
            serv_sock->fd, serv_sock->laddr, serv_sock->lport);
    return 0;
del_regist:
    cp_fds_del_sock_registry(new_sock);
term_sock:
    if(new_sock)
        cp_sock_term_clear(new_sock);
exit_out:
    log_err("Accept and regist new client from server [%d] on [%s:%d] failed\n",
            serv_sock->fd, serv_sock->laddr, serv_sock->lport);
    cp_fds_del_sock_task(serv_sock);
    return rv;
}
CP_SOCK *cp_sock_connect_regist(CP_FDS *fds, CP_SOCK *sock, char *raddr, int rport, int lport, CP_SOCK_EVENT_CALLBACK service_route)
{
    if(!fds || !raddr || rport<0)
    {
        log_err("Invalude input arguments\n");
        goto exit_out;
    }
    if( !sock && !(sock=cp_sock_init(sock, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) )
    {
        goto exit_out;
    }
    if( SOCK_STAT_CONNECTED == sock->status )
        return sock; /* already ok now  */
    if( !(sock->flag&FLAG_SOCK_REGISTRY) )
    {
        sock->fds = fds;
        sock->cbfunc = service_route;
        sock->mode = CP_SOCK_MODE_CONNECT;
        strncpy(sock->laddr, "0.0.0.0", sizeof(sock->laddr));
        log_dbg("Connect and regist socket to remote [%s:%d] now\n", raddr, rport);
        if( cp_fds_add_sock_registry( sock) )
            goto term_sock; /* regist to the list failed */
    }
    if ( cp_sock_connect(sock, raddr, rport, lport) )
    {
        log_dbg("socket [%d] connect failed, start to remove registry it now.\n", sock->fd);
        goto del_regist;
    }
    else
    {
        if( cp_add_epoll_event(sock) )
            goto del_regist;
    }
    return sock;
del_regist:
    cp_fds_del_sock_registry(sock);
term_sock:
    cp_fds_del_sock_task(sock);
    if(sock)
        cp_sock_term(sock);
exit_out:
    log_err("Connect and regist new socket to remote server [%s:%d] failed\n", raddr, rport);
    return NULL;
}
CP_SOCK *cp_sock_server_regist(CP_FDS *fds, char *addr, int port, int max_client, CP_SOCK_EVENT_CALLBACK service_route, void *data)
{
    int  rv = 0;
    CP_SOCK   *sock = NULL;
    log_dbg("Regist socket server listen on [%s:%d] now\n", addr?addr:"local", port);
    if(!fds || port < 0)
    {
        rv = -1;
        log_err("Invalude input arguments\n");
        goto exit_out;
    }
    if( !(sock=cp_sock_init(NULL, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) )
    {
        rv = -2;
        goto exit_out;
    }
    INIT_LIST_HEAD(&sock->accept_list);
    sock->fds = fds;
    sock->cbfunc = cp_sock_accept_regist;
    sock->client_func = service_route;
    sock->privt = data;
    sock->mode = CP_SOCK_MODE_LISTEN;
    if( cp_fds_add_sock_registry(sock) )
    {
        rv = -3;
        goto term_sock;
    }
    /* If specified maximum clients <=0, then use the default one */
    sock->max_client = max_client<=0 ? CP_DEF_MAX_CLIENTS : max_client;
    /*  If specified maximum clients larger than FDS monitor maxevents, then use the default one */
    sock->max_client = max_client<fds->max_event ? sock->max_client : CP_DEF_MAX_CLIENTS;
    if( cp_sock_listen(sock, addr, port, sock->max_client) )
    {
        rv = -4;
        goto del_regist;
    }
    /* Add server socket FD to the epoll monitor list */
    if( cp_add_epoll_event(sock) )
    {
        rv = -5;
        goto del_regist;
    }
    log_nrml("Registe socket[%d] server listen on [%s:%d] ok.\n", sock->fd, sock->laddr, sock->lport);
    return sock;
del_regist:
    cp_fds_del_sock_registry(sock);
term_sock:
    cp_fds_del_sock_task(sock);
    if(sock)
        cp_sock_term_clear(sock);
exit_out:
    log_err("Registe socket server listen on [%s:%d] failed.\n", addr, port);
    return NULL;
}
void cp_sock_term_all_service(CP_FDS *fds)
{
    if(!fds)
        return;
    log_dbg("Terminate all the service now\n");
    cp_sock_term_all_task(fds);
    cp_sock_term_all_server(fds);
    cp_sock_term_all_client(fds);
    cp_fds_term(fds);
    log_warn("Terminate all the service ok\n");
}
program/cp_library/cp_network.h
New file
@@ -0,0 +1,37 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_network.h
 *    Description:  This head file
 *
 *        Version:  1.0.0(10/31/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/31/2012 11:24:06 AM"
 *
 ********************************************************************************/
#ifndef __CP_NETWORK_H
#define __CP_NETWORK_H
#include "cp_fds.h"
#include "cp_sock.h"
#define CP_DEF_MAX_CLIENTS           1024
#define CP_DEF_TIMEOUT               10
extern int nic_network_config(char *nic, char *mac, char *ip);
extern int nic_get_ipaddr(char *nic, char *ipaddr);
extern int nic_get_ptpaddr(char *nic, char *ptpaddr);
extern int network_ping_test(char *from, char *ping_ip);
extern int cp_sock_accept_regist(CP_SOCK *serv_sock);
extern CP_SOCK *cp_sock_connect_regist(CP_FDS *fds, CP_SOCK *sock, char *raddr, int rport, int lport, CP_SOCK_EVENT_CALLBACK service_route);
extern CP_SOCK *cp_sock_server_regist(CP_FDS *fds, char *addr, int port, int max_client, CP_SOCK_EVENT_CALLBACK service_route, void *data);
extern void cp_sock_term_all_service(CP_FDS *fds);
#define cp_sock_term_all_service_clear(fds) {cp_sock_term_all_service(fds); fds=NULL;}
#endif
program/cp_library/cp_ppp.c
New file
@@ -0,0 +1,552 @@
/********************************************************************************
 *      Copyright:  (C) guowenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  ppp.c
 *    Description:  This file is the ppp thread file,used to do PPP dial up
 *
 *        Version:  1.0.0(02/02/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "02/02/2012 11:33:33 AM"
 *
 ********************************************************************************/
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <arpa/inet.h>
#include "cp_ppp.h"
#include "cp_string.h"
#include "cp_iniparser.h"
#include "cp_network.h"
//#include "gsmd.h"
/*
 * Description: Check PPP10 device exist or not, and set the PPP context status
 *
 *
 * Return Value: 0: PPP10 device exist    -1:PPP10 device not exist
 *
 */
int check_ppp_interface(char *ppp_dev)
{
    int           fd = -1;
    int           retval = -1;
    char          buf[512];
    if ((fd = open("/proc/net/dev", O_RDONLY, 0666)) < 0)
    {
        return -1;      /* System error, take as PPP10 device not exist too */
    }
    while (read(fd, buf, sizeof(buf)) > 0)
    {
        if (NULL != strstr(buf, ppp_dev))
        {
            retval = 0;
            break;
        }
    }
    close(fd);
    return retval;
}
int check_ppp_ipaddr(PPPD_INFO  *pppd_info, char *ppp_dev)
{
    int                   fd;
    struct ifreq          ifr;
    struct sockaddr_in    *sin;
    if(check_ppp_interface(ppp_dev))
        return -2;
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    strcpy(ifr.ifr_name, ppp_dev);
    if ((ioctl(fd, SIOCGIFADDR, (caddr_t) & ifr, sizeof(struct ifreq))) < 0)
    {
        log_fatal("System call ioctl() with SIOCGIFADDR failure.\n", ppp_dev);
        return -1;
    }
    sin = (struct sockaddr_in *)&ifr.ifr_addr;
    strcpy(pppd_info->netaddr, (const char *)inet_ntoa(sin->sin_addr));
    log_nrml("Get %s local IP address: %s\n", ppp_dev, pppd_info->netaddr);
    if ((ioctl(fd, SIOCGIFDSTADDR, (caddr_t) & ifr, sizeof(struct ifreq))) < 0)
    {
        log_fatal("System call ioctl() with SIOCGIFDSTADDR failure.\n", ppp_dev);
        return -1;
    }
    sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
    strcpy(pppd_info->ptpaddr, (const char *)inet_ntoa(sin->sin_addr));
    log_nrml("Get %s remote IP address: %s\n", ppp_dev, pppd_info->ptpaddr);
    return 0;
}
int check_ppp_stat(PPP_STAT  *ppp_stat, char *ppp_dev)
{
    int                 retval;
    FILE                *fp;
    char                *ptr;
    char                buf[512];
    if( NULL == (fp=fopen(PPP_PROC_NET_DEV, "r")) )
    {
        log_err("Can not open %s.\n", PPP_PROC_NET_DEV);
        return -1;
    }
    fgets(buf, sizeof(buf), fp);
    fgets(buf, sizeof(buf), fp);
    while (fgets(buf, sizeof(buf), fp))
    {
        ptr=strstr(buf, ppp_dev);
        if(NULL == ptr)
        {
            log_err("Can not find %s interface statistic data in %s\n", ppp_dev, PPP_PROC_NET_DEV);
            retval = -1;
            break;
        }
        else
        {
             ptr = strchr(ptr, ':');
             ptr++;
             sscanf(ptr, "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu",
                     &(ppp_stat->ullRx_Bytes),
                     &(ppp_stat->ullRx_Packets),
                     &(ppp_stat->ulRx_Errors),
                     &(ppp_stat->ulRx_Dropped),
                     &(ppp_stat->ulRx_FIFO_Errors),
                     &(ppp_stat->ulRx_Frame_Errors),
                     &(ppp_stat->ulRx_Compressed),
                     &(ppp_stat->ulRx_Multicast),
                     &(ppp_stat->ullTx_Bytes),
                     &(ppp_stat->ullTx_Packets),
                     &(ppp_stat->ulTx_Errors),
                     &(ppp_stat->ulTx_Dropped),
                     &(ppp_stat->ulTx_FIFO_Errors),
                     &(ppp_stat->ulCollisions),
                     &(ppp_stat->ulTx_Carrier_Errors),
                     &(ppp_stat->ulTx_Compressed)
                   );
             retval = 0;
             break;
        }
    }
    if(0 == retval )
        log_dbg("Check PPP network traffic: Tx %llu bytes, Rx %llu bytes.\n", ppp_stat->ullTx_Bytes, ppp_stat->ullRx_Bytes);
    fclose(fp);
    return retval;
}
int kill_pppd_process(COM_PORT *comport)
{
    int           pid = -1;
    while( (pid=check_pppd_pid(comport->dev_name)) > 0)
    {
        log_nrml("Terminate pppd process [pid=%d]\n", pid);
        kill(pid, SIGTERM);
        sleep(1); /* Wait pppd process exit */
    }
    return 0;
}
int stop_ppp_connect(PPP_CTX *ppp_ctx)
{
    log_warn("Stop PPP connection now.\n");
    if(check_ppp_interface(ppp_ctx->dev))
        return 0;
    kill_pppd_process(ppp_ctx->comport);
    if(ppp_ctx->comport)
    {
        free_gsm_dataport("stop_ppp_connect()", ppp_ctx->module, &(ppp_ctx->comport));
    }
    return 0;
}
int get_apn_conf(char *ini_name, char *ini_key, APN_ACCOUNT *apn, unsigned char type)
{
    dictionary       *ini ;
    char             tmp[64];
    char             *str;
    if(NULL==ini_name || NULL==ini_key || NULL==apn)
    {
        return -1;
    }
    ini = iniparser_load(ini_name);
    if (ini==NULL)
    {
        log_err("cannot load default APN configure file: %s\n", ini_name);
        return -2 ;
    }
    log_dbg("Parser default APN configure file %s\n", ini_name);
    /* Parser APN configure */
    snprintf(tmp, 64, "%s:%s", ini_key, APN_3G==type?"3g_apn":"apn");
    if( !(str=iniparser_getstring(ini, tmp, NULL)) )
    {
        log_err("cannot find APN setting for SIM [%s] in file: %s\n", ini_key, ini_name);
        memset(apn, 0, sizeof(APN_ACCOUNT));
        return -1;
    }
    else
    {
        strncpy(apn->apn, str, APN_LEN);
    }
    /* Paser APN username information  */
    snprintf(tmp, 64, "%s:%s", ini_key, APN_3G==type?"3g_uid":"uid");
    str = iniparser_getstring(ini, tmp, NULL);
    strncpy(apn->uid, str, UID_LEN);
    /* Paser APN password information  */
    snprintf(tmp, 64, "%s:%s", ini_key, APN_3G==type?"3g_pwd":"pwd");
    str = iniparser_getstring(ini, tmp, NULL);
    strncpy(apn->pwd, str, PWD_LEN);
    iniparser_freedict(ini);
    return 0;
}
int select_apn(PPP_CTX *ppp_ctx, char *key)
{
    int                 retval;
    unsigned char       type = APN_2G;
    log_nrml("GPRS module work on GPRS mode, select APN now.\n");
    retval = get_apn_conf(APN_DEF_CONF_FILE, key, &(ppp_ctx->apn), type);
    if(!retval)
    {
        log_err("Get default APN [%s] from %s ok\n", ppp_ctx->apn.apn, APN_DEF_CONF_FILE);
        return 0;
    }
    return -1;
}
#define PPPD_CMD_LEN  512
int start_ppp_dial_cmd(COM_PORT  *comport, APN_ACCOUNT *apn, char *ppp_dev)
{
    char                tmp[64];
    char                pppd_cmd[PPPD_CMD_LEN];
    pid_t               pid;
    if( !comport || !comport->is_connted )
    {
        log_err("GPRS module data port %s is not opened.\n", comport->dev_name);
        return -1;
    }
    if( !apn || strlen(apn->apn)<=0 )
    {
        log_err("No valid APN was set.\n");
        return -1;
    }
    log_nrml("Start PPP connection with APN \"%s\" now.\n", apn->apn);
    memset(pppd_cmd, 0, PPPD_CMD_LEN);
    snprintf(pppd_cmd, PPPD_CMD_LEN, "%s -d %s ", PPPD_DIAL_SCRIPTS, comport->dev_name);
    snprintf(tmp, sizeof(tmp), " -a %s ", apn->apn);
    strncat(pppd_cmd, tmp, PPPD_CMD_LEN);
    if( strlen(apn->uid) > 0 )
    {
        snprintf(tmp, sizeof(tmp), " -u %s ", apn->uid);
        strncat(pppd_cmd, tmp, PPPD_CMD_LEN);
    }
    if( strlen(apn->pwd) > 0 )
    {
        snprintf(tmp, sizeof(tmp), " -p %s ", apn->pwd);
        strncat(pppd_cmd, tmp, PPPD_CMD_LEN);
    }
    if( strlen(apn->auth) > 0 )
    {
        snprintf(tmp, sizeof(tmp), " -v %s ", apn->auth);
        strncat(pppd_cmd, tmp, PPPD_CMD_LEN);
    }
    strncat(pppd_cmd, ppp_dev, PPPD_CMD_LEN);
    log_nrml("ppp dial up command: %s\n", pppd_cmd);
    pid = fork();
    if( 0 == pid ) /* Child process */
    {
        system(pppd_cmd);
        exit(0);
    }
    else if (pid < 0)
    {
        log_err("Create new process failure.\n");
        return -1;
    }
    else
    {
        log_dbg("pppd program already running.\n");
        micro_second_sleep(1000);
    }
    return 0;
}
int check_pppd_pid(char *find_key)
{
    char       buf[10];
    char       cmd[128];
    FILE       *fp = NULL;
    int        pid = -1;
    snprintf(cmd, sizeof(cmd), "ps | grep -v grep | grep pppd | grep %s | awk '{print $1}'", find_key);
    fp = popen(cmd, "r");
    if(NULL == fp)
    {
        log_fatal("popen() to check the pppd process ID failure.\n");
        return -1;
    }
    memset(buf, 0, sizeof(buf));
    fgets(buf, sizeof(buf), fp);
    pid = atoi(buf);
    if(pid <= 1)
    {
        log_err("Get pppd program running pid failure\n");
        pid = -1;
    }
#if 0
    else
    {
        log_trace("pppd program running pid is [%d]\n", pid);
    }
#endif
    pclose(fp);
    return pid;
}
void set_ppp_disconnect(PPP_CTX *ppp_ctx)
{
    ppp_ctx->status = DISCONNECT;
    ppp_ctx->pppd_info.start_time = 0;
    memset(&(ppp_ctx->pppd_info), 0, sizeof(PPPD_INFO));
    memset(&(ppp_ctx->ppp_stat), 0, sizeof(PPP_STAT));
    ppp_ctx->network = PPP_STOP;
}
int ppp_context_init(PPP_CTX *ppp_ctx, MODULE_INFO *module)
{
    memset(ppp_ctx, 0, sizeof(*ppp_ctx));
    ppp_ctx->thread_id = pthread_self();
    ppp_ctx->module = module;
    strncpy(ppp_ctx->dev, PPP_INTERFACE_NAME, sizeof(ppp_ctx->dev));
    strncpy(ppp_ctx->ping_ip, DEF_PING_DST, sizeof(ppp_ctx->ping_ip));
    ppp_ctx->ping_interval  = PING_INTERVAL_TIME;
    set_ppp_disconnect(ppp_ctx);
    log_nrml("Initialize PPP thread context ok\n");
    return 0;
}
void ppp_context_term(PPP_CTX *ppp_ctx)
{
    stop_ppp_connect(ppp_ctx);
    set_ppp_disconnect(ppp_ctx);
    log_nrml("Terminate PPP thread context ok\n");
}
int start_ppp_connect(PPP_CTX *ppp_ctx)
{
    int                 retval;
    MODULE_INFO         *module = ppp_ctx->module;
    if( !ppp_ctx->comport )
    {
        ppp_ctx->comport=alloc_gsm_dataport("start_ppp_connect()", ppp_ctx->module);
        if(!ppp_ctx->comport)
            return -1;
        log_dbg("PPP thread alloc GPRS dataport %s=>[fd:%d]\n", ppp_ctx->comport->dev_name, ppp_ctx->comport->fd);
    }
    switch(ppp_ctx->status)
    {
        case DISCONNECT: /*  Select the APN now */
            set_ppp_disconnect(ppp_ctx);
            retval = select_apn(ppp_ctx, module->reg.loc.mcc_mnc);
            if(!retval)
            {
                log_nrml("Select APN successfully, go to next stage.\n");
                ppp_ctx->fail_cnt = 0;
                ppp_ctx->status++;
            }
            else
            {
                log_warn("Select APN failure, request to reset GPRS module\n");
                ppp_ctx->fail_cnt ++;
                set_module_event(module, REQ_POWER_RESET);
                break;
            }
        case SELECTED_APN: /*  Select the APN now */
            log_warn("Run pppd program to start PPP connection now\n");
            ppp_ctx->network = PPP_CONN;
            start_ppp_dial_cmd(ppp_ctx->comport, &(ppp_ctx->apn), ppp_ctx->dev);
            ppp_ctx->status++;
            break;
    }
    return 0;
}
int inspect_network_status(PPP_CTX *ppp_ctx)
{
    PPPD_INFO              *pppd_info = &(ppp_ctx->pppd_info);
    PPP_STAT               *ppp_stat = &(ppp_ctx->ppp_stat);
    int                    lost_percent;
    unsigned long long     last_tx_bytes= ppp_stat->ullTx_Bytes;
    unsigned long long     last_rx_bytes= ppp_stat->ullRx_Bytes;
    if( CONNECTED != ppp_ctx->status)
    {
        ppp_ctx->pppd_info.ping_time = 0;
        memset(ppp_stat, 0, sizeof(PPP_STAT));
        pppd_info->pid = check_pppd_pid(ppp_ctx->comport->dev_name);
        if(pppd_info->pid <= 0)
        {
            /*  pppd can not connect in 30s, then set it to DISCONNECT status */
            if(time_elapsed(pppd_info->start_time) >= PPPD_DIAL_TIMEOUT)
            {
                /* Sleep for 2 seconds, make sure the exit pppd process release the TTY device */
                micro_second_sleep(2000);
                log_err("pppd process exit when do ppp dialing, set status to DISCONNECT.\n");
                set_ppp_disconnect(ppp_ctx);
            }
        }
        else
        {
            if(strlen(pppd_info->netaddr) <=0 )
            {
                check_ppp_ipaddr(pppd_info, ppp_ctx->dev);
                log_dbg("pppd running process ID [%d].\n", pppd_info->pid);
            }
        }
    }
    if(  time_elapsed(pppd_info->ping_time) >= ppp_ctx->ping_interval*1000  )
    {
        if(ppp_ctx->fail_cnt >= MAX_PPP_FAIL_CNT)
        {
            /* Sleep for 2 seconds, make sure the exit pppd process release the TTY device */
            micro_second_sleep(2000);
            log_warn("PPP network inspect status failure, set status to DISCONNECT.\n");
            set_ppp_disconnect(ppp_ctx);
            return 0;
        }
        lost_percent = network_ping_test(ppp_ctx->dev, ppp_ctx->ping_ip);
        ppp_ctx->network = lost_percent<=60 ? PPP_GOOD : PPP_BAD;
        if(lost_percent <= 80)
        {
            check_ppp_stat(ppp_stat, ppp_ctx->dev);
            if(last_tx_bytes==ppp_stat->ullTx_Bytes || last_rx_bytes==ppp_stat->ullRx_Bytes)
            {
                log_warn("PPP interface traffic not increased, maybe ppp disconnected?\n");
                ppp_ctx->fail_cnt++;
            }
            else
            {
                log_nrml("Set PPP connection status to CONNECTED.\n");
                set_ppp_disconnect(ppp_ctx);
                ppp_ctx->fail_cnt=0;
            }
        }
        else
        {
            ppp_ctx->fail_cnt++;
        }
        ppp_ctx->pppd_info.ping_time = time_now();
    }
    return 0;
}
void *ppp_thread_workbody(void *thread_arg)
{
    PPP_CTX             ppp_ctx;
    MODULE_INFO         *module;
    module = (MODULE_INFO *)thread_arg;
    ppp_context_init(&ppp_ctx, module);
    log_nrml("GPRS PPP thread start running\n");
    while( !g_cp_signal.stop )
    {
        if(ALL_READY != module->ready)
        {
            if(ppp_ctx.status>=CONNECTING)
            {
                log_nrml("Stop exist PPP connection and free TTY data port\n");
                stop_ppp_connect(&ppp_ctx);
            }
            /*  GPRS not ready, sleep for 200ms and check again */
            micro_second_sleep(200);
            continue;
        }
        else
        {
            if(ppp_ctx.status>=CONNECTING)
            {
                inspect_network_status(&ppp_ctx);
            }
            else
            {
                start_ppp_connect(&ppp_ctx);
            }
        }
        sleep(1);
    }
    ppp_context_term(&ppp_ctx);
    pthread_exit(0);
    return NULL;
}
int start_thread_ppp(MODULE_INFO *module)
{
    pthread_t           tid;
    return thread_start(&tid, ppp_thread_workbody, module);
}
program/cp_library/cp_ppp.h
New file
@@ -0,0 +1,138 @@
/********************************************************************************
 *      Copyright:  (C) guowenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  ppp.h
 *    Description:  This head file is for PPP dial up thread.
 *
 *        Version:  1.0.0(02/17/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "02/17/2012 11:11:54 AM"
 *
 ********************************************************************************/
#ifndef __PPP_H
#define __PPP_H
#include <netinet/in.h>
#include "cp_comport.h"
#include "cp_proc.h"
#include "cp_gprs.h"
#define PPPD_DIAL_TIMEOUT             20000  /* 20 seconds */
#define PING_INTERVAL_TIME            10000  /* 10 seconds */
#define DEFAULT_PING_INTERVAL         30
#define APN_LEN                       128
#define UID_LEN                       64
#define PWD_LEN                       64
#define APN_3G                        3
#define APN_2G                        2
#define PPPD_DIAL_SCRIPTS             "/apps/tools/ifup-ppp"
#define PPP_INTERFACE_NAME            "ppp10"
#define PPP_PROC_NET_DEV              "/proc/net/dev"
#define DEF_PING_DST                  "4.2.2.2"
#define APN_DEF_CONF_FILE             "/apps/etc/ppp/default_apn.conf"
enum
{
    DISCONNECT = 0,
    SELECTED_APN,
    CONNECTING,
    CONNECTED,
};
typedef struct __APN_ACCOUNT
{
    char            apn[APN_LEN];
    char            uid[UID_LEN];
    char            pwd[PWD_LEN];
    char            auth[10];  /*  PAP or CHAP */
} APN_ACCOUNT;
typedef struct __PPPD_INFO
{
    char            netaddr[INET_ADDRSTRLEN];
    char            ptpaddr[INET_ADDRSTRLEN];
    unsigned long   start_time;
    unsigned long   ping_time;
    pid_t           pid;
} PPPD_INFO;
typedef struct __PPP_STAT
{
    unsigned long long ullRx_Packets;   // total packets received
    unsigned long long ullTx_Packets;   // total packets transmitted
    unsigned long long ullRx_Bytes; // total bytes received
    unsigned long long ullTx_Bytes; // total bytes transmitted
    unsigned long ulRx_Errors;  // bad packets received
    unsigned long ulTx_Errors;  // packet transmit problems
    unsigned long ulRx_Dropped; // no space in linux buffers
    unsigned long ulTx_Dropped; // no space available in linux
    unsigned long ulRx_Multicast;   // multicast packets received
    unsigned long ulRx_Compressed;
    unsigned long ulTx_Compressed;
    unsigned long ulCollisions;
    /* detailed rx_errors */
    unsigned long ulRx_Length_Errors;
    unsigned long ulRx_Over_Errors; // receiver ring buff overflow
    unsigned long ulRx_CRC_Errors;  // recved pkt with crc error
    unsigned long ulRx_Frame_Errors;    // recv'd frame alignment error
    unsigned long ulRx_FIFO_Errors; // recv'r fifo overrun
    unsigned long ulRx_Missed_Errors;   // receiver missed packet
    /* detailed tx_errors */
    unsigned long ulTx_Aborted_Errors;
    unsigned long ulTx_Carrier_Errors;
    unsigned long ulTx_FIFO_Errors;
    unsigned long ulTx_Heartbeat_Errors;
    unsigned long ulTx_Window_Errors;
} PPP_STAT;
#define MAX_PPP_FAIL_CNT             3
#define PPP_STOP                     0  /* PPP not work, but signal good */
#define SIG_WEAK                     1  /* PPP not work and signal is very weak */
#define PPP_CONN                     2  /* PPP is connecting  */
#define PPP_BAD                      3  /* PPP is connected, but network/signal not good */
#define PPP_GOOD                     4  /* PPP is connected and network/signal good */
typedef struct __PPP_CTX
{
    unsigned char      enable;       /* Enable PPP thread running or not, RFU */
    unsigned char      status;       /* Current PPP connection status */
    unsigned char      network;      /* PPP network status: PPP_FAIL,PPP_BAD,PPP_GOOD */
    char               dev[10];      /* PPP dial up device name, such as PPP10  */
    pthread_t          thread_id;    /* PPP Thread ID, RFU */
    PPPD_INFO          pppd_info;    /* pppd process information */
    PPP_STAT           ppp_stat;     /* PPP network statistic */
    unsigned char      fail_cnt;     /* PPP failure count */
    APN_ACCOUNT        apn;          /* PPP dial up APN */
    char               ping_ip[INET_ADDRSTRLEN];
    long               ping_interval;
    COM_PORT           *comport;
    MODULE_INFO        *module;
} PPP_CTX;
int get_apn_conf(char *ini_name, char *ini_key, APN_ACCOUNT *apn, unsigned char type);
int check_pppd_pid(char *find_key);
int check_ppp_interface(char *ppp_inf);
int start_ppp_dial_cmd(COM_PORT  *comport, APN_ACCOUNT *apn, char *ppp_inf);
int check_ppp_ipaddr(PPPD_INFO  *pppd_info, char *ppp_inf);
int check_ppp_stat(PPP_STAT  *ppp_stat, char *ppp_inf);
int stop_ppp_connect(PPP_CTX *ppp_ctx);
int start_thread_ppp(MODULE_INFO *module);
#endif /*  End of __PPP_H */
program/cp_library/cp_proc.c
New file
@@ -0,0 +1,341 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_proc.c
 *    Description:  This file is the process API
 *
 *        Version:  1.0.0(11/06/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/06/2012 09:19:02 PM"
 *
 ********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libgen.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "cp_proc.h"
#include "cp_logger.h"
CP_PROC_SIG     g_cp_signal={0};
void cp_proc_sighandler(int sig)
{
    switch(sig)
    {
        case SIGINT:
            log_warn("SIGINT - stopping\n");
            g_cp_signal.stop = 1;
            break;
        case SIGTERM:
            //log_warn("SIGTERM - stopping\n");
            g_cp_signal.stop = 1;
            break;
#if 0
        case SIGSEGV:
            log_err("SIGSEGV - stopping\n");
            if(g_cp_signal.stop)
                exit(0);
            g_cp_signal.stop = 1;
            break;
#endif
        case SIGPIPE:
            log_warn("SIGPIPE - warnning\n");
            g_cp_signal.stop = 1;
            break;
        default:
            break;
    }
}
void cp_install_proc_signal(void)
{
    struct sigaction sigact, sigign;
    log_nrml("Install default signal handler.\n");
    /*  Initialize the catch signal structure. */
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigact.sa_handler = cp_proc_sighandler;
    /*  Setup the ignore signal. */
    sigemptyset(&sigign.sa_mask);
    sigign.sa_flags = 0;
    sigign.sa_handler = SIG_IGN;
    sigaction(SIGTERM, &sigact, 0); /*  catch terminate signal "kill" command */
    sigaction(SIGINT,  &sigact, 0); /*  catch interrupt signal CTRL+C */
    //sigaction(SIGSEGV, &sigact, 0); /*  catch segmentation faults  */
    sigaction(SIGPIPE, &sigact, 0); /*  catch broken pipe */
#if 0
    sigaction(SIGCHLD, &sigact, 0); /*  catch child process return */
    sigaction(SIGUSR2, &sigact, 0); /*  catch USER signal */
#endif
}
/* ****************************************************************************
 * FunctionName: daemonize
 * Description : Set the programe runs as daemon in background
 * Inputs      : nodir: DON'T change the work directory to / :  1:NoChange 0:Change
 *               noclose: close the opened file descrtipion or not 1:Noclose 0:Close
 * Output      : NONE
 * Return      : NONE
 * *****************************************************************************/
void daemonize(int nochdir, int noclose)
{
    int retval, fd;
    int i;
    /*  already a daemon */
    if (1 == getppid())
        return;
    /*  fork error */
    retval = fork();
    if (retval < 0) exit(1);
    /*  parent process exit */
    if (retval > 0)
        exit(0);
    /*  obtain a new process session group */
    setsid();
    if (!noclose)
    {
        /*  close all descriptors */
        for (i = getdtablesize(); i >= 0; --i)
        {
            //if (i != g_logPtr->fd)
                close(i);
        }
        /*  Redirect Standard input [0] to /dev/null */
        fd = open("/dev/null", O_RDWR);
        /* Redirect Standard output [1] to /dev/null */
        dup(fd);
        /* Redirect Standard error [2] to /dev/null */
        dup(fd);
    }
    umask(0);
    if (!nochdir)
        chdir("/");
    return;
}
/* ****************************************************************************
 * FunctionName: record_daemon_pid
 * Description : Record the running daemon program PID to the file "pid_file"
 * Inputs      : pid_file:The record PID file path
 * Output      : NONE
 * Return      : 0: Record successfully  Else: Failure
 * *****************************************************************************/
int record_daemon_pid(const char *pid_file)
{
    struct stat fStatBuf;
    int fd = -1;
    int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;
    char ipc_dir[64] = { 0 };
    strncpy(ipc_dir, pid_file, 64);
    /* dirname() will modify ipc_dir and save the result */
    dirname(ipc_dir);
    /* If folder pid_file PATH doesnot exist, then we will create it" */
    if (stat(ipc_dir, &fStatBuf) < 0)
    {
        if (mkdir(ipc_dir, mode) < 0)
        {
            log_fatal("cannot create %s: %s\n", ipc_dir, strerror(errno));
            return -1;
        }
        (void)chmod(ipc_dir, mode);
    }
    /*  Create the process running PID file */
    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    if ((fd = open(pid_file, O_RDWR | O_CREAT | O_TRUNC, mode)) >= 0)
    {
        char pid[PID_ASCII_SIZE];
        snprintf(pid, sizeof(pid), "%u\n", (unsigned)getpid());
        write(fd, pid, strlen(pid));
        close(fd);
        log_dbg("Record PID<%u> to file %s.\n", getpid(), pid_file);
    }
    else
    {
        log_fatal("cannot create %s: %s\n", pid_file, strerror(errno));
        return -1;
    }
    return 0;
}
/* ****************************************************************************
 * FunctionName: get_daemon_pid
 * Description : Get the daemon process PID from the PID record file "pid_file"
 * Inputs      : pid_file: the PID record file
 * Output      : NONE
 * Return      : pid_t: The daemon process PID number
 * *****************************************************************************/
pid_t get_daemon_pid(const char *pid_file)
{
    FILE *f;
    pid_t pid;
    if ((f = fopen(pid_file, "rb")) != NULL)
    {
        char pid_ascii[PID_ASCII_SIZE];
        (void)fgets(pid_ascii, PID_ASCII_SIZE, f);
        (void)fclose(f);
        pid = atoi(pid_ascii);
    }
    else
    {
        log_fatal("Can't open PID record file %s: %s\n", pid_file, strerror(errno));
        return -1;
    }
    return pid;
}
/* ****************************************************************************
 * FunctionName: check_daemon_running
 * Description : Check the daemon program already running or not
 * Inputs      : pid_file: The record running daemon program PID
 * Output      : NONE
 * Return      : 1: The daemon program alread running   0: Not running
 * *****************************************************************************/
int check_daemon_running(const char *pid_file)
{
    int retVal = -1;
    struct stat fStatBuf;
    retVal = stat(pid_file, &fStatBuf);
    if (0 == retVal)
    {
        pid_t pid = -1;
        printf("PID record file \"%s\" exist.\n", pid_file);
        pid = get_daemon_pid(pid_file);
        if (pid > 0)  /*  Process pid exist */
        {
            if ((retVal = kill(pid, 0)) == 0)
            {
                printf("Program with PID[%d] seems running.\n", pid);
                return 1;
            }
            else   /* Send signal to the old process get no reply. */
            {
                printf("Program with PID[%d] seems exit.\n", pid);
                remove(pid_file);
                return 0;
            }
        }
        else if (0 == pid)
        {
            printf("Can not read program PID form record file.\n");
            remove(pid_file);
            return 0;
        }
        else  /* Read pid from file "pid_file" failure */
        {
            printf("Read record file \"%s\" failure, maybe program still running.\n", pid_file);
            return 1;
        }
    }
    return 0;
}
/* ****************************************************************************
 * FunctionName: set_daemon_running
 * Description : Set the programe running as daemon if it's not running and record
 *               its PID to the pid_file.
 * Inputs      : pid_file: The record running daemon program PID
 * Output      : NONE
 * Return      : 0: Successfully. 1: Failure
 * *****************************************************************************/
int set_daemon_running(const char *pid_file)
{
    daemonize(0, 1);
    log_nrml("Program running as daemon [PID:%d].\n", getpid());
    if (record_daemon_pid(pid_file) < 0)
    {
        log_fatal("Record PID to file \"%s\" failure.\n", pid_file);
        return -2;
    }
    return 0;
}
int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg)
{
    int        retval = 0;
    pthread_attr_t thread_attr;
    /* Initialize the thread  attribute */
    retval = pthread_attr_init(&thread_attr);
    if(retval)
        return -1;
    /* Set the stack size of the thread */
    retval = pthread_attr_setstacksize(&thread_attr, 120 * 1024);
    if(retval)
        goto CleanUp;
    /* Set thread to detached state:Don`t need pthread_join */
    retval = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
    if(retval)
        goto CleanUp;
    /* Create the thread */
    retval = pthread_create(thread_id, &thread_attr, thread_workbody, thread_arg);
    if(retval)
        goto CleanUp;
CleanUp:
    /* Destroy the  attributes  of  thread */
    pthread_attr_destroy(&thread_attr);
    return retval;
}
void exec_system_cmd(const char *format, ...)
{
    char                cmd[256];
    va_list             args;
    int                 done;
    memset(cmd, 0, sizeof(cmd));
    va_start(args, format);
    done = vsnprintf(cmd, sizeof(cmd), format, args);
    va_end(args);
    system(cmd);
}
program/cp_library/cp_proc.h
New file
@@ -0,0 +1,42 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_proc.h
 *    Description:  This head file is for Linux process API
 *
 *        Version:  1.0.0(11/06/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/06/2012 09:21:33 PM"
 *
 ********************************************************************************/
#ifndef __CP_PROC_H
#define __CP_PROC_H
#include <signal.h>
#define PID_ASCII_SIZE  11
typedef struct __CP_PROC_SIG
{
    int       signal;
    unsigned  stop;     /* 0: Not term  1: Stop  */
}  CP_PROC_SIG;
typedef void *(THREAD_BODY) (void *thread_arg);
extern CP_PROC_SIG     g_cp_signal;
extern void cp_install_proc_signal(void);
extern void daemonize(int nochdir, int noclose);
extern int record_daemon_pid(const char *pid_file);
extern pid_t get_daemon_pid(const char *pid_file);
extern int check_daemon_running(const char *pid_file);
extern int set_daemon_running(const char *pid_file);
extern void exec_system_cmd(const char *format, ...);
extern int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg);
#endif
program/cp_library/cp_queue.c
New file
@@ -0,0 +1,155 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_queue.c
 *    Description:  This file is the queue implement based on link list.
 *
 *        Version:  1.0.0(11/12/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/12/2012 01:25:26 PM"
 *
 ********************************************************************************/
#include "cp_queue.h"
#include "cp_common.h"
CP_QUEUE *cp_queue_init(CP_QUEUE *queue, int size)
{
    if(!queue)
    {
        queue = t_malloc(sizeof(*queue));
    }
    memset(queue, 0, sizeof(*queue));
    queue->size = size;
    queue->items = 0;
    queue->rear = queue->front = NULL;
    return queue;
}
void *cp_enqueue(CP_QUEUE *queue, void *data)
{
    CP_QNODE         *node;
    if(!queue || cp_queue_is_full(queue))
    {
        return NULL;
    }
    node = t_malloc(sizeof(*node));
    if(NULL == node)
    {
        return NULL;
    }
    node->item = data;
    node->next = NULL;
    if(cp_queue_is_empty(queue))
    {
        queue->front = node;
    }
    else
    {
        queue->rear->next = node;
    }
    queue->rear = node;
    queue->items++;
    return data;
}
void cp_travel_queue(CP_QUEUE *queue)
{
    CP_QNODE       *node;
    for(node=queue->front; node!=NULL; node=node->next)
    {
        printf("queue node[%p] save data [%p]\n", node, node->item);
    }
}
void *cp_rmqueue(CP_QUEUE *queue, void *data)
{
    CP_QNODE       *node, *tmp;
    if(!queue || cp_queue_is_empty(queue))
    {
        return NULL;
    }
    /* The first node->item is the data, we find it */
    if(queue->front->item==data)
    {
        tmp = queue->front;
        queue->front = queue->front->next;
        queue->items -= 1;
        t_free(tmp);
        return data;
    }
    for(node=queue->front; node!=NULL; node=node->next)
    {
        if(node->next->item == data)
        {
            tmp = node->next;
            queue->items -= 1;
            if(node->next != queue->rear)
                node->next = node->next->next;
            else
            {
                queue->rear = node;
                queue->rear->next = NULL;
            }
            t_free(tmp);
            return data;
        }
    }
    return data;
}
void *cp_dequeue(CP_QUEUE *queue)
{
    CP_QNODE       *node;
    void           *item;
    if(!queue || cp_queue_is_empty(queue))
    {
        return NULL;
    }
    node = queue->front;
    queue->front = queue->front->next;
    item = node->item;
    t_free(node);
    queue->items--;
    if(queue->items == 0)
        queue->rear = NULL;
    return item;
}
void cp_queue_destroy(CP_QUEUE *queue)
{
    if(!queue)
        return ;
    while( !cp_queue_is_empty(queue) )
    {
        cp_dequeue(queue);
    }
    t_free(queue);
    return ;
}
program/cp_library/cp_queue.h
New file
@@ -0,0 +1,49 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_queue.h
 *    Description:  This head file is for the queue implement based on link list.
 *
 *        Version:  1.0.0(11/12/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/12/2012 01:26:34 PM"
 *
 ********************************************************************************/
#ifndef __CP_QUEUE
#define __CP_QUEUE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
typedef  struct _CP_QNODE
{
    void               *item;
    struct _CP_QNODE   *next;
} CP_QNODE;
typedef struct _CP_QUEUE
{
    CP_QNODE           *front;
    CP_QNODE           *rear;
    int                items;
    int                size;
} CP_QUEUE;
#define cp_queue_is_full(pq)  ( (pq)->size==(pq)->items ? 1 :0 )
#define cp_queue_is_empty(pq) ( 0==(pq)->items ? 1 : 0)
#define cp_queue_count(pq) ( (pq)->items )
#define cp_queue_size(pq) ( (pq)->size )
CP_QUEUE *cp_queue_init(CP_QUEUE *queue, int size);
void *cp_enqueue(CP_QUEUE *queue, void *data);
void cp_travel_queue(CP_QUEUE *queue);
void *cp_rmqueue(CP_QUEUE *queue, void *data);
void *cp_dequeue(CP_QUEUE *queue);
void cp_queue_destroy(CP_QUEUE *queue);
#define cp_queue_destroy_clear(queue) {cp_queue_destroy(queue); queue=NULL;}
#endif
program/cp_library/cp_ringbuf.c
New file
@@ -0,0 +1,103 @@
/*
    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.
    Based on ringbuffer.c by Patrick Prasse (patrick.prasse@gmx.net). Code
    has been modified by Telenor and Gemalto.
 */
#include <string.h>
#include <assert.h>
#include "cp_ringbuf.h"
void rb_init (struct ring_buffer *ring, u_char* buff, int size) {
    memset (ring, 0, sizeof (struct ring_buffer));
    ring->rd_pointer = 0;
    ring->wr_pointer = 0;
    ring->buffer= buff;
    ring->size = size;
}
int
rb_write (struct ring_buffer *rb, u_char * buf, int len)
{
    int total;
    int i;
    /* total = len = min(space, len) */
    total = rb_free_size(rb);
    if(len > total)
        len = total;
    else
        total = len;
    i = rb->wr_pointer;
    if(i + len > rb->size)
    {
        memcpy(rb->buffer + i, buf, rb->size - i);
        buf += rb->size - i;
        len -= rb->size - i;
        i = 0;
    }
    memcpy(rb->buffer + i, buf, len);
    rb->wr_pointer = i + len;
    return total;
}
int rb_free_size (struct ring_buffer *rb){
    return (rb->size - 1 - rb_data_size(rb));
}
int rb_read (struct ring_buffer *rb, u_char * buf, int max) {
    int total;
    int i;
    /* total = len = min(used, len) */
    total = rb_data_size(rb);
    if(max > total)
        max = total;
    else
        total = max;
    i = rb->rd_pointer;
    if(i + max > rb->size)
    {
        memcpy(buf, rb->buffer + i, rb->size - i);
        buf += rb->size - i;
        max -= rb->size - i;
        i = 0;
    }
    memcpy(buf, rb->buffer + i, max);
    rb->rd_pointer = i + max;
    return total;
}
int rb_data_size (struct ring_buffer *rb) {
    return ((rb->wr_pointer - rb->rd_pointer) & (rb->size-1));
}
void rb_clear (struct ring_buffer *rb) {
    memset(rb->buffer,0,rb->size);
    rb->rd_pointer=0;
    rb->wr_pointer=0;
}
u_char rb_peek(struct ring_buffer* rb, int index) {
    assert(index < rb_data_size(rb));
    return rb->buffer[((rb->rd_pointer + index) % rb->size)];
}
program/cp_library/cp_ringbuf.h
New file
@@ -0,0 +1,57 @@
/*
    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.
    Based on ringbuffer.h by Patrick Prasse (patrick.prasse@gmx.net). Code
    has been modified by Telenor and Gemalto.
 */
#ifndef __CP_RINGBUF_H_
#define __CP_RINGBUF_H_
#include <sys/types.h>
struct ring_buffer {
    u_char *buffer;
    int wr_pointer;
    int rd_pointer;
    int size;
};
/* Initial the ring buffer */
void rb_init (struct ring_buffer *ring, u_char* buff, int size) ;
/*  Description: Write $len bytes data in $buf into ring buffer $rb
 * Return Value: The actual written into ring buffer data size, if ring buffer
 * left space size small than $len, then only part of the data be written into.
 */
int rb_write (struct ring_buffer *rb, u_char * buf, int len) ;
/* Get ring buffer left free size  */
int rb_free_size (struct ring_buffer *rb);
/* Read $max bytes data from ring buffer $rb to $buf */
int rb_read (struct ring_buffer *rb, u_char * buf, int max);
/* Read a specify $index byte data in ring buffer $rb  */
u_char rb_peek(struct ring_buffer* rb, int index);
/* Get data size in the ring buffer  */
int rb_data_size (struct ring_buffer *);
/* Clear the ring buffer data  */
void rb_clear (struct ring_buffer *rb) ;
#endif /* __CP_RINGBUF_H_ */
program/cp_library/cp_sock.c
New file
@@ -0,0 +1,854 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_sock.c
 *    Description:  This file is the Linux TCP socket basic library.
 *
 *        Version:  1.0.0(10/26/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/26/2012 01:20:41 PM"
 *
 ********************************************************************************/
#include "cp_sock.h"
#include "cp_logger.h"
#include "cp_common.h"
#include "cp_time.h"
CP_SOCK *cp_sock_init(CP_SOCK *sock, unsigned int rsize, unsigned int ssize, int keepintvl, int keepcnt)
{
    if(!sock)
    {
        if( !(sock=(CP_SOCK *)t_malloc(sizeof(*sock))) )
        {
            log_err("socket context malloc failed: %s\n", strerror(errno));
            goto failed;
        }
        else
        {
            memset(sock, 0, sizeof(*sock));
            sock->flag |= FLAG_SOCK_MALLOC;
        }
    }
    else
    {
        memset(sock, 0, sizeof(*sock));
    }
    if( !(sock->rbuf=cp_string_create_empty(CP_DEF_RCVBUF_SIZE)) )
    {
        log_err("socket context create recv buffer failed\n");
        cp_sock_term(sock);
        goto failed;
    }
    if( !(sock->sbuf=cp_string_create_empty(CP_DEF_SNDBUF_SIZE)) )
    {
        log_err("socket context create send buffer failed\n");
        cp_sock_term(sock);
        goto failed;
    }
    log_dbg("socket context [%p] initialise ok\n", sock);
    sock->rsize = rsize;
    sock->ssize = ssize;
    sock->keepintvl = keepintvl;
    sock->keepcnt = keepcnt;
    sock->idle_timeout = CP_SOCK_DEF_IDLE_TIMEOUT;
    sock->msg_timeout = CP_SOCK_DEF_MSG_TIMEOUT;
    sock->fd = -1;
    sock->index = -1;
    sock->actv_time = time_now();
    sock->flag |= FLAG_SOCK_INIT;
    return sock;
failed:
    log_err("socket context initialize failed\n");
    return NULL;
}
void cp_sock_term(CP_SOCK *sock)
{
    if(!sock)
        return;
    log_dbg("terminate socket [%p:%d] now\n", sock, sock->fd);
    if(sock->flag & FLAG_SOCK_INIT)
        cp_sock_close(sock);
    if(sock->rbuf)
    {
        cp_string_destroy(sock->rbuf);
    }
    if(sock->privt && sock->privt_free)
    {
        sock->privt_free();
    }
    if(sock->sbuf)
    {
        cp_string_destroy(sock->sbuf);
    }
    if(sock->flag & FLAG_SOCK_MALLOC)
    {
        //memset(sock, 0, sizeof(*sock));
        t_free(sock);
        return ;
    }
    //memset(sock, 0, sizeof(*sock));
    sock->fd = -1;
    return ;
}
int cp_sock_close(CP_SOCK *sock)
{
    int        rv = 0;
    int        force = 0;
    if(!sock)
        return -1;
    if(sock->fd>0)
    {
        log_dbg("Close socket[%d] bind [%s:%d]\n", sock->fd, sock->laddr, sock->lport);
        if(force)
        {
            /*
             * If l_onoff is nonzero and l_linger is zero, TCP aborts the connection when it is closed.
             * That is, TCP discards any data still remaining in the socket send buffer and sends an RST
             * to the peer, not the normal four-packet connection termination sequence.
             */
            struct linger so_linger;
            so_linger.l_onoff = 1;  /* Turn on linger */
            so_linger.l_linger = 0; /* Set the timeout to 0  */
            setsockopt (sock->fd, SOL_SOCKET, SO_LINGER, (char *) &so_linger, sizeof (struct linger));
        }
        if(CP_SOCK_MODE_ACCEPT == sock->mode || CP_SOCK_MODE_CONNECT == sock->mode)
        {
            shutdown (sock->fd, SHUT_RDWR);
        }
        if( (rv=close(sock->fd)) )
        {
            return -2;
        }
    }
    sock->fd = -1;
    return rv;
}
int cp_sock_listen(CP_SOCK *sock, char *laddr, int lport, int backlog)
{
    int                 rv = 0;
    int                 fd = -1;
    char                service[20];
    struct addrinfo     hints, *rp;
    struct addrinfo     *res = NULL;
    struct in_addr      inaddr;
    if(!sock || !(sock->flag&FLAG_SOCK_INIT) || lport<=0 || backlog <=0)
    {
        log_err("Invalide input arguments\n");
        rv = -1;
        goto cleanup;
    }
    strncpy(sock->laddr, (!laddr?"0.0.0.0":laddr), sizeof(sock->laddr));
    log_dbg("Create socket listen on [%s:%d] now\n", sock->laddr, lport);
    cp_sock_close(sock);
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_INET; /*  Only support IPv4 */
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP; /*  TCP protocol */
    hints.ai_flags = AI_PASSIVE;
    /* If 'laddr' is a valid IP address, then don't use name resolution */
    if(laddr && inet_aton(laddr, &inaddr))
    {
        log_info("%s is a valid IP address, don't use name resolution.\n", laddr);
        hints.ai_flags |= AI_NUMERICHOST;
    }
    /* Obtain address(es) matching host/port */
    snprintf(service, sizeof(service), "%d", lport);
    if( (rv=getaddrinfo(laddr, service, &hints, &res)) )
    {
        log_err("getaddrinfo() parser [%s:%s] failed: %s\n", laddr, service, gai_strerror(rv));
        rv = -2;
        goto cleanup;
    }
    /*  getaddrinfo() returns a list of address structures. Try each
     *  address until we successfully connect or bind*/
    sock->fd = -1;
    for (rp=res; rp!=NULL; rp=rp->ai_next)
    {
        /* Create the socket */
        if( (fd=socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0)
        {
            log_err("socket() create failed: %s\n", strerror(errno));
            rv = -3;
            continue;
        }
        cp_sock_set_reuseaddr(fd);
        cp_sock_set_keepalive(fd, sock->keepintvl, sock->keepcnt);
        cp_sock_set_nonblock(fd);
        if( 0==bind(fd, rp->ai_addr, rp->ai_addrlen) )
        {
            struct sockaddr_in    *saddr = (struct sockaddr_in *)rp->ai_addr;
            sock->fd = fd;
            sock->lport = lport;
            strncpy (sock->laddr, inet_ntoa (saddr->sin_addr), sizeof(sock->laddr)-1);
            log_dbg("Bind socket[%d] ok\n", fd);
            rv = 0;
            break;
        }
        else
        {
            rv = -4;
            log_err("Bind socket[%d] failed: %s\n", fd, strerror(errno));
        }
        close(fd);
    } /* for (rp=res; rp!=NULL; rp=rp->ai_next)  */
    if(sock->fd < 0)
    {
        close(fd);
        goto cleanup;
    }
    if(listen(sock->fd, backlog))
    {
        log_err("Listen on socket[%d] failed: %s\n", sock->fd, strerror(errno));
        rv = -6;
        goto cleanup;
    }
    sock->mode = CP_SOCK_MODE_LISTEN;
    sock->rport = 0;
    memset(&sock->raddr, 0, sizeof(sock->raddr));
cleanup:
    if( rv )
    {
        log_err("Create socket listen on [%s:%d] failed\n", sock->laddr, lport);
        if(sock->fd > 0)
            close(sock->fd);
    }
    else
    {
        sock->actv_time = time_now();
        sock->status = SOCK_STAT_LISTENED;
        log_nrml("Create socket[%p:%d] listen [%s:%d] ok\n", sock, sock->fd, sock->laddr, lport);
    }
    if(res)
        freeaddrinfo(res);  /* No longer needed */
    return rv;
}
int cp_sock_accept(CP_SOCK *serv_sock, CP_SOCK *new_sock)
{
    struct sockaddr_in       saddr;
    socklen_t                len = sizeof(saddr);
    int                      fd = -1;
    int                      rv = 0;
    if(!serv_sock || !new_sock || serv_sock->fd<0 )
    {
        log_err("Invalide input arguments\n");
        rv = -1;
        goto cleanup;
    }
    log_dbg("accept new client from server [fd=%d %s:%d] now\n", serv_sock->fd, serv_sock->laddr, serv_sock->lport);
    if( (fd=accept(serv_sock->fd, (struct sockaddr *)&saddr, &len)) < 0 )
    {
        log_err("Accept new client from server [fd=%d %s:%d] failed: %s\n",
                serv_sock->fd, serv_sock->laddr, serv_sock->lport, strerror(errno));
        rv = -2;
        goto cleanup;
    }
    /* Set socket buffer size  */
    cp_sock_set_buffer(fd, new_sock->rsize, new_sock->ssize);
    /* Enable socket keepalive to detect network  */
    cp_sock_set_keepalive(fd, new_sock->keepintvl, new_sock->keepcnt);
    cp_sock_set_nonblock(fd);
    new_sock->fd = fd;
    new_sock->mode = CP_SOCK_MODE_ACCEPT;
    /* get remote address */
    strncpy (new_sock->raddr, inet_ntoa(saddr.sin_addr), sizeof(new_sock->raddr)-1);
    new_sock->rport = ntohs(saddr.sin_port);
    /* Get local address */
    len = sizeof(saddr);
    if (getsockname (new_sock->fd, (struct sockaddr *) &saddr, (socklen_t *) &len))
    {
        strncpy(new_sock->laddr, serv_sock->laddr, sizeof(new_sock->laddr)-1);
        new_sock->lport = serv_sock->lport;
    }
    else
    {
        strncpy (new_sock->laddr, inet_ntoa (saddr.sin_addr), sizeof (new_sock->laddr) - 1);
        new_sock->lport = ntohs (saddr.sin_port);
    }
cleanup:
    if(!rv)
    {
        new_sock->status = SOCK_STAT_ACCEPTED;
        new_sock->actv_time = time_now();
        log_nrml("Accept new client socket [%d %s:%d] <== [%s:%d]\n",
                new_sock->fd, new_sock->laddr, new_sock->lport, new_sock->raddr, new_sock->rport);
    }
    else
    {
        log_err("Accept new client from server [%d] on [%s:%d] failed\n",
                serv_sock->fd, serv_sock->raddr, serv_sock->rport);
        close(fd);
    }
    return rv;
}
/*
 *  Description:  Create a socket connect to the remove server
 *   Input args:  $sock: The socket contex   $raddr: Remote server address
 *                $rport: Remote server listened port
 *                $lport: Use this local port connect to remote server
 *  Output args:  None
 * Return value:  <0:connect failed  ==0:connect ok  >0:connect in progress
 *
 */
int cp_sock_connect(CP_SOCK *sock, char *raddr, int rport, int lport)
{
    int                 rv = 0;
    int                 fd = -1;
    char                service[20];
    struct addrinfo     hints, *rp;
    struct addrinfo     *res = NULL;
    struct in_addr      inaddr;
    struct sockaddr_in  saddr;
    int                 len = sizeof(saddr);
    if(!sock || !(sock->flag&FLAG_SOCK_INIT) || !raddr || rport<=0)
    {
        log_err("Invalide input arguments\n");
        rv = -1;
        goto failed;
    }
    if(SOCK_STAT_CONNECTED == sock->status)
    {
        return 0;
    }
    else if(SOCK_STAT_CONNECTING == sock->status)
    {
        goto connecting;
    }
    log_dbg("create socket connect to remote server [%s:%d] now\n", raddr, rport);
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_INET; /*  Only support IPv4 */
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP; /*  TCP protocol */
    hints.ai_flags = AI_PASSIVE;
    /* If 'raddr' is a valid IP address, then don't use name resolution */
    if(raddr && inet_aton(raddr, &inaddr))
    {
        log_info("%s is a valid IP address, don't use name resolution.\n", raddr);
        hints.ai_flags |= AI_NUMERICHOST;
    }
    /* Obtain address(es) matching host/port */
    snprintf(service, sizeof(service), "%d", rport);
    if( (rv=getaddrinfo(raddr, service, &hints, &res)) )
    {
        log_err("getaddrinfo() parser [%s:%s] failed: %s\n", raddr, service, gai_strerror(rv));
        rv = -2;
        goto failed;
    }
    cp_sock_close(sock); /* close any opened socket on it */
    sock->fd = -1;
    /*  getaddrinfo() returns a list of address structures. Try each
     *  address until we successfully connect or bind*/
    for (rp=res; rp!=NULL; rp=rp->ai_next)
    {
        fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        /* Create the socket */
        if( fd < 0)
        {
            log_err("socket() create failed: %s\n", strerror(errno));
            rv = -3;
            continue;
        }
        log_trace("create socket[%p:%d] with connect mode ok\n", sock, fd);
        /* We need bind lport to this socket */
        if(lport > 0)
        {
            memset(&saddr, 0, len);
            saddr.sin_family = AF_INET;
            saddr.sin_port = htons ((u_short) lport);
            if ( bind(fd, (struct sockaddr *)&saddr, len) )
            {
                rv = -4;
                close(fd);
                log_err("Bind port[%d] to connect socket [%d] failed: %s\n", lport, fd, strerror(errno));
                continue;
            }
            else
            {
                sock->lport = lport;
                rv = 0;
                log_dbg("Bind port[%d] to connect socket [%d] OK\n", lport, fd);
            }
        }
        /* Set socket options */
        cp_sock_set_buffer(fd, sock->rsize, sock->ssize);
        cp_sock_set_keepalive(fd, sock->keepintvl, sock->keepcnt);
        cp_sock_set_nonblock(fd);
        /* Nono block Connect to the remote server */
        if(0==connect(fd, rp->ai_addr, rp->ai_addrlen))
        {
            /* Conenct to server successfully */
            sock->fd = fd;
            sock->status = SOCK_STAT_CONNECTING;
            memcpy(&sock->saddr, &rp->ai_addr, sizeof(sock->saddr));
            rv = 0;
            goto connected;
        }
        else
        {
            if(EINPROGRESS == errno)
            {
                /* Connect to server now in progress  */
                sock->fd = fd;
                sock->status = SOCK_STAT_CONNECTING;
                memcpy(&sock->saddr, &rp->ai_addr, sizeof(sock->saddr));
                rv = 0;
                goto connecting;
            }
            else
            {
                /* Connect to server failed. */
                close(fd);
                rv = -5;
                log_err("connect() to server failed: %s\n", strerror(errno));
                goto failed;
            }
        }
        close(fd);
    }  /* for (rp=res; rp!=NULL; rp=rp->ai_next)  */
    if(sock->fd < 0)
    {
        close(fd);
        goto failed;
    }
connecting:
    if(SOCK_STAT_CONNECTING == sock->status)
    {
        len = sizeof(sock->saddr);
        errno = 0;
        if( !connect(sock->fd, &sock->saddr, len) )
        {
            /* connect() return 0 means it already connected */
            sock->status = SOCK_STAT_CONNECTED;
            rv = 0;
            goto connected;
        }
        /* Connect failure will continue to check */
        switch (errno)
        {
            case EISCONN:
                sock->status = SOCK_STAT_CONNECTED;
                rv = 0;
                goto connected;
            case EALREADY:
            case EINPROGRESS:
                log_dbg("socket[%d] connect to remote [%s:%d] in progress\n", sock->fd, raddr, rport);
                rv = 0;
                goto cleanup;
            default:
                log_err("socket[%d] connect to remote [%s:%d] failed: %s\n", sock->fd, raddr, rport, strerror(errno));
                sock->status = SOCK_STAT_DISCONNECT;
                rv = -7;
                break;
        }
    }
connected:
    if(SOCK_STAT_CONNECTED == sock->status)
    {
        rv = 0;
        log_nrml("socket[%d] connected to remote server [%s:%d]\n", sock->fd, raddr, rport);
        /* Set remote address */
        sock->rport=rport;
        strncpy (sock->raddr, raddr, sizeof(sock->raddr)-1);
        sock->actv_time = time_now();
        /* Get local address */
        memset(&saddr, 0, len);
        len = sizeof(saddr);
        if (!getsockname (sock->fd, (struct sockaddr *) &saddr, (socklen_t *) &len))
        {
            strncpy (sock->laddr, inet_ntoa (saddr.sin_addr), sizeof (sock->laddr) - 1);
            sock->lport = ntohs (saddr.sin_port);
        }
        else
        {
            memset(&sock->laddr, 0, sizeof(sock->laddr));
            sock->lport = lport;
        }
        goto cleanup;
    }
failed:
    log_err("Create socket connect to [%s:%d] failed\n", raddr, rport);
    if(sock && sock->fd >= 0)
        close(sock->fd);
cleanup:
    if(res)
        freeaddrinfo(res);  /* No longer needed */
    return rv;
}
int cp_sock_recv(CP_SOCK *sock)
{
    int               rv, left;
    int               flag;
    cp_string         *rbuf;
    if(!sock || !sock->rbuf || !sock->rbuf->data || sock->fd<0)
    {
        log_err("Invalide input arguments\n");
        return -1;
    }
    rbuf = sock->rbuf;
    left = rbuf->size-rbuf->len;
    flag = left ? 0 : MSG_PEEK;
    if(left <= 0)
        return 0;
    rv=recv(sock->fd, &rbuf->data[rbuf->len], left, flag);
    if( rv > 0)
    {
        rbuf->len += rv;
    }
    else if(rv<0)
    {
        if(EAGAIN==errno || EINPROGRESS==errno)
        {
            log_warn("socket [%d] please recv data again: %s\n", sock->fd, strerror(errno));
            rv = 0;
        }
        else
        {
            log_err("socket [%d] recv data failed: %s\n", sock->fd, strerror(errno));
            rv = -2;
        }
    }
    if(rv > 0)
    {
        sock->actv_time = sock->msg_time = time_now();
    }
    return rv;
}
int cp_sock_send(CP_SOCK *sock)
{
    int                      rv;
    struct pollfd            sock_poll;
    if(!sock || sock->fd<0 || !sock->sbuf->data || sock->sbuf->len<=0)
    {
        log_err("Invalide input arguments\n");
        return -1;
    }
    sock_poll.events = POLLOUT;
    sock_poll.fd = sock->fd;
    if( (rv=poll(&sock_poll, 1, 0)) > 0 )
    {
        if( !(POLLOUT &sock_poll.events) )
        {
            return -2;
        }
        if ( (rv=send(sock->fd, sock->sbuf->data, sock->sbuf->len, MSG_NOSIGNAL)) < 0)
        {
            if (EAGAIN == errno)
            {
                log_warn("socket [%d] please send data again: %s\n", sock->fd, strerror(errno));
                return 0;
            }
            else
            {
                log_err("socket [%d] send data failed: %s\n", sock->fd, strerror(errno));
                return -4;
            }
        }
        else
        {
            sock->sbuf->len -= rv;
            sock->actv_time = time_now();
            memmove (sock->sbuf->data, sock->sbuf->data+rv, sock->sbuf->len);
            return rv;
        }
    }
    else /* poll()<0 means failed, poll()==0 means timeout */
    {
        log_err("send data from socket [%d] poll failed: %s\n", sock->fd, strerror(errno));
        return 0;
    }
    return 0;
}
int cp_sock_set_nonblock(int sockfd)
{
    int opts;
    /*
     * fcntl may set:
     *
     * EACCES, EAGAIN: Operation is prohibited by locks held by other
     *          processes. Or, operation is prohibited because the file has
     *          been memory-mapped by another process.
     * EBADF:   fd is not an open file descriptor, or the command was F_SETLK
     *          or F_SETLKW and the file descriptor open mode doesn't match
     *          with the type of lock requested.
     * EDEADLK: It was detected that the specified F_SETLKW command would
     *          cause a deadlock.
     * EFAULT:  lock is outside your accessible address space.
     * EINTR:   For F_SETLKW, the command was interrupted by a signal. For
     *          F_GETLK and F_SETLK, the command was interrupted by a signal
     *          before the lock was checked or acquired. Most likely when
     *          locking a remote file (e.g. locking over NFS), but can
     *          sometimes happen locally.
     * EINVAL:  For F_DUPFD, arg is negative or is greater than the maximum
     *          allowable value. For F_SETSIG, arg is not an allowable signal
     *          number.
     * EMFILE:  For F_DUPFD, the process already has the maximum number of
     *          file descriptors open.
     * ENOLCK:  Too many segment locks open, lock table is full, or a remote
     *          locking protocol failed (e.g. locking over NFS).
     * EPERM:   Attempted to clear the O_APPEND flag on a file that has the
     *          append-only attribute set.
     */
    opts = fcntl(sockfd, F_GETFL);
    if (opts < 0)
    {
        log_warn("fcntl() get socket options failure: %s\n", strerror(errno));
        return -1;
    }
    opts |= O_NONBLOCK;
    if (fcntl(sockfd, F_SETFL, opts) < 0)
    {
        log_warn("fcntl() set socket options failure: %s\n", strerror(errno));
        return -1;
    }
    log_dbg("Set socket[%d] none blocking\n", sockfd);
    return opts;
}
int cp_sock_set_buffer(int sockfd, int rsize, int ssize)
{
    int        opt;
    socklen_t  optlen = sizeof(opt);
    if(sockfd < 0)
        return -1;
    /* Get system default receive buffer size, Linux X86: 85K */
    if (getsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, &optlen))
    {
        log_warn("getsockopt() get receive buffer failure: %s\n", strerror(errno));
        return -2;
    }
    /* Only when current receive buffer size larger than the default one will change it  */
    if(rsize > opt)
    {
        opt = (int) rsize;
        if (setsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, optlen))
        {
            log_warn("setsockopt() set receive buffer to %d failure: %s\n", opt, strerror(errno));
            return -2;
        }
    }
    /* Get system default send buffer size, Linux X86: 16K */
    if (getsockopt (sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, &optlen))
    {
        log_warn("getsockopt() get send buffer failure: %s\n", strerror(errno));
        return -3;
    }
    /* Only when current receive buffer size larger than the default one will change it  */
    if(ssize > opt)
    {
        opt = (int) ssize;
        if (setsockopt (sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, optlen))
        {
            log_warn("setsockopt() set send buffer to %d failure: %s\n", opt, strerror(errno));
            return -3;
        }
    }
    log_info("Set socket[%d] RCVBUF size:%d  SNDBUF size:%d\n", sockfd, rsize, ssize);
    return 0;
}
int cp_sock_set_reuseaddr(int sockfd)
{
    int opt = 1;
    int len = sizeof (int);
    if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, len))
    {
        log_err("Set socket[%d] option SO_REUSEADDR failed:%s\n", sockfd, strerror(errno));
        return -1;
    }
    log_dbg("Set socket[%d] option SO_REUSEADDR ok\n", sockfd);
    return 0;
}
/*
 * Enable socket SO_KEEPALIVE, if the connection disconnected, any system call on socket
 * will return immediately and errno will be set to "WSAENOTCONN"
 *
 * keepalive is not program related, but socket related, * so if you have multiple sockets,
 * you can handle keepalive for each of them separately.
 *
 * Reference: http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/
 */
int cp_sock_set_keepalive(int sockfd, int keepintvl, int keepcnt)
{
    int  opt;
    if(sockfd < 0)
        return -1;
    /* Enable the KEEPALIVE flag */
    opt = 1;
    if (setsockopt (sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof (opt)))
    {
        log_warn("setsockopt() enable SO_KEEPALIVE failure: %s\n", strerror(errno));
        return -2;
    }
    if(keepintvl || keepcnt)
    {
        /*
         *  The tcp_keepidle parameter specifies the interval between the last data packet sent
         *  (simple ACKs are not considered data) and the first keepalive probe; after the
         *  connection is marked to need keepalive, this counter is not used any further.
         *  ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_time
         *  7200
         */
        opt = 3; /* 3 seconds  */
        if (setsockopt (sockfd, SOL_TCP, TCP_KEEPIDLE, (char *) &opt, sizeof (opt)))
        {
            log_err("setsockopt() set TCP_KEEPIDLE to %d seconds failure: %s\n", opt, strerror(errno));
            return -3;
        }
        if((opt=keepintvl) > 0)
        {
            /*
             * The tcp_keepintvl parameter specifies the interval between subsequential keepalive
             * probes, regardless of what the connection has exchanged in the meantime.
             * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_intvl
             * 75
             */
            if (setsockopt (sockfd, SOL_TCP, TCP_KEEPINTVL, (char *) &opt, sizeof (opt)))
            {
                log_err("setsockopt() set TCP_KEEPINTVL to %d failure: %s\n", opt, strerror(errno));
                return -4;
            }
        }
        if((opt=keepcnt) > 0)
        {
            /*
             * The TCP_KEEPCNT option specifies the maximum number of unacknowledged probes to
             * send before considering the connection dead and notifying the application layer
             * probes to be sent. The value of TCP_KEEPCNT is an integer value between 1 and n,
             * where n is the value of the systemwide tcp_keepcnt parameter.
             * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_probes
             * 9
             */
            if (setsockopt (sockfd, SOL_TCP, TCP_KEEPCNT, (char *) &opt, sizeof (opt)))
            {
                log_err("setsockopt() set TCP_KEEPCNT to %d failure: %s\n", opt, strerror(errno));
                return -5;
            }
        }
    }
    log_dbg("Set socket[%d] KEEPINTVL:%d  KEEPCNT:%d\n", sockfd, keepintvl, keepcnt);
    return 0;
}
program/cp_library/cp_sock.h
New file
@@ -0,0 +1,184 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_sock.h
 *    Description:  This head file
 *
 *        Version:  1.0.0(10/26/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/26/2012 01:21:38 PM"
 *
 ********************************************************************************/
#ifndef __CP_SOCK_H
#define __CP_SOCK_H
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/un.h>
#include <poll.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/sockios.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include "cp_klist.h"
#include "cp_string.h"
#include "cp_fds.h"
#define CP_DEF_RCVBUF_SIZE                2048
#define CP_DEF_SNDBUF_SIZE                2048
#define CP_SOCK_RCVBUF                    2048
#define CP_SOCK_SNDBUF                    2048
#define CP_SOCK_DEF_IDLE_TIMEOUT          120*1000 /* 2 minutes */
#define CP_SOCK_DEF_MSG_TIMEOUT           120*1000 /* 2 minutes */
#define CP_SOCK_KEEPINTVL                 600
#define CP_SOCK_KEEPCNT                   3
#define CP_SOCK_MODE_NONE                 0
#define CP_SOCK_MODE_ACCEPT               1
#define CP_SOCK_MODE_CONNECT              2
#define CP_SOCK_MODE_LISTEN               3
enum
{
    CP_SOCK_EVENT_READ         =          EPOLLIN,   /* compatilbe with EPOLLIN  */
    CP_SOCK_EVENT_WRITE        =          EPOLLOUT,  /* compatilbe with EPOLLOUT */
    CP_SOCK_EVENT_ERROR        =          EPOLLERR,  /* compatilbe with EPOLLERR  */
    CP_SOCK_EVENT_HUP          =          EPOLLHUP,  /* compatilbe with EPOLLHUP */
    CP_SOCK_EVENT_IDLE_TIMEOUT =          (1<<16),   /* compatilbe with EPOLL reserved*/
    CP_SOCK_EVENT_MSG_TIMEOUT  =          (1<<17),   /* compatible with EPOLL reserved*/
};
struct _CP_SOCK;
struct _CP_FDS;
typedef void (*PRIVT_FREE)(void);
typedef int (*CP_SOCK_EVENT_CALLBACK)(struct _CP_SOCK *sock);
typedef struct _CP_SOCK_CALLBACK
{
    CP_SOCK_EVENT_CALLBACK  error;
    CP_SOCK_EVENT_CALLBACK  read;
    CP_SOCK_EVENT_CALLBACK  write;
} CP_SOCK_CALLBACK;
#define FLAG_SOCK_INIT             (1<<0)
#define FLAG_SOCK_MALLOC           (1<<1)
#define FLAG_SOCK_EPOLLED          (1<<2)
#define FLAG_SOCK_REGISTRY         (1<<3)
#define FLAG_SOCK_INQUEUE          (1<<4)
#define FLAG_SOCK_TASKED           (1<<5)
#define SOCK_STAT_INIT             0
#define SOCK_STAT_CONNECTING       1
#define SOCK_STAT_CONNECTED        2
#define SOCK_STAT_LISTENED         2
#define SOCK_STAT_ACCEPTED         2
#define SOCK_STAT_ALREADY          2
#define SOCK_STAT_DISCONNECT       3
typedef struct _CP_SOCK
{
    int                      fd;          /* the socket file description */
    int                      mode;        /* socket work mode: listen, accept, connect */
    unsigned short           flag;        /* Refer to the follow definition  */
    unsigned char            status;      /* current socket status */
    unsigned long            actv_time;     /* The last time get event(send/recv) data in this socket */
    unsigned long            msg_time;      /* The last time get incoming data in this socket */
    unsigned long            idle_timeout;  /* this is set to the socket idle timeout value, when timeout will disconnect */
    unsigned long            msg_timeout;   /* this is set to the socket recv data timeout value,  */
    int                      keepintvl;   /* heartbeat(keepalive) detect interval */
    int                      keepcnt;     /* heartbeat(keepalive) count */
    int                      rsize;       /* ioctl() set socket recv buffer size  */
    int                      ssize;       /* ioctl() set socket send buffer size  */
    struct epoll_event       event;       /* epoll_wait returned event */
    cp_string                *sbuf;       /* send buffer */
    cp_string                *rbuf;       /* receive buffer  */
    struct sockaddr          saddr;       /* sockaddr for connect */
    char                     laddr[16];   /* local IP address*/
    int                      lport;       /* local port */
    char                     raddr[16];   /* remote IP address  */
    int                      rport;       /* remote port */
    struct _CP_FDS           *fds;        /* epoll fds contex */
    CP_SOCK_EVENT_CALLBACK   cbfunc;      /* event callback function */
    CP_SOCK_EVENT_CALLBACK   client_func; /* client data callback function, only server socket use it */
    struct _CP_SOCK          *serv_sock;  /* Accept socket used to point to the server socket */
    int                      max_client;  /* max clients, only listen socket use it*/
    int                      accept_cnt;  /* current clients number, only listen socket use it*/
    struct list_head         accept_list; /* all the accept client list head, only listen socket use it */
    void                     *privt;      /* socket private data */
    PRIVT_FREE               privt_free;  /* private data free function if it's malloc */
    int                      index;       /* The index member position in the task array */
    struct list_head         rlist;       /* The list_head member position just for the registry list */
  /*  flag definitions
   *  1 1 1 1 1 1 1 1
   *  | | | | | | | |______ Initial    flag  - 0: no            1: yes
   *  | | | | | | |________ Malloc     flag  - 0: variable,     1: malloc
   *  | | | | | |__________ registry   flag  - 0: not in,       1: in the registry list
   *  | | | | |____________ epolled    flag  - 0: not in,       1: put in epoll
   *  | | | |______________ in queue   flag  - 0: not in,       1: put in queue
   *  | | |________________ task       flag  - 0: not in,       1: in the task list
   *  | |__________________ reserved
   *  |____________________ reserved
   */
} CP_SOCK;
static void inline cp_sock_set_idle_timeout(CP_SOCK *sock, unsigned long timeout)
{
    sock->idle_timeout = timeout;
}
static void inline cp_sock_set_msg_timeout(CP_SOCK *sock, unsigned long timeout)
{
    sock->msg_timeout = timeout;
}
static void inline cp_sock_set_private_data(CP_SOCK *sock, void *data, PRIVT_FREE free)
{
    sock->privt = data;
    sock->privt_free = free;
}
extern CP_SOCK *cp_sock_init(CP_SOCK *sock, unsigned int rsize, unsigned int ssize, int keepintvl, int keepcnt);
extern int cp_sock_close(CP_SOCK *sock);
extern void cp_sock_term(CP_SOCK *sock);
#define cp_sock_term_clear(sock) {cp_sock_term(sock); sock=NULL;}
extern int cp_sock_listen(CP_SOCK *sock, char *laddr, int lport, int backlog);
extern int cp_sock_connect(CP_SOCK *sock, char *raddr, int rport, int lport);
extern int cp_sock_accept(CP_SOCK *serv_sock, CP_SOCK *new_sock);
extern int cp_sock_recv(CP_SOCK *sock);
extern int cp_sock_send(CP_SOCK *sock);
extern int cp_sock_set_reuseaddr(int sockfd);
extern int cp_sock_set_keepalive(int sockfd, int keepintvl, int keepcnt);
extern int cp_sock_set_nonblock(int sockfd);
extern int cp_sock_set_buffer(int sockfd, int rsize, int ssize);
#endif /* __CP_SOCK_H */
program/cp_library/cp_string.c
New file
@@ -0,0 +1,673 @@
/**
 * @addtogroup cp_string
 */
/** @{ */
/**
 * @file
 * cp_string - 'safe' string implementation
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "cp_string.h"
#include "cp_common.h"
cp_string *cp_string_create(char *data, int len)
{
    cp_string *str;
#ifdef DEBUG
    if (len < 0)
    {
        return NULL;
    }
#endif
    str = t_malloc(sizeof(cp_string));
    if (str)
    {
        str->len = len;
        str->size = str->len + 1;
        str->data = t_malloc(str->size * sizeof(char));
        if (str->data)
            memcpy(str->data, data, str->len);
        else
        {
            t_free(str);
            str = NULL;
        }
    }
    return str;
}
cp_string *cp_string_create_empty(int initial_size)
{
    cp_string *str = t_malloc(sizeof(cp_string));
    if (str)
    {
        str->len = 0;
        str->size = initial_size;
        str->data = (char *) t_malloc(str->size * sizeof(char));
        if (str->data == NULL)
        {
            t_free(str);
            str = NULL;
        }
    }
    return str;
}
void cp_string_destroy(cp_string *str)
{
    if (str)
    {
        if (str->data)
        {
            t_free(str->data);
        }
        t_free(str);
    }
}
void cp_string_clear_data(cp_string *str)
{
    if (str && str->data)
    {
        memset(str->data, 0, str->size);
        str->len = 0;
    }
}
cp_string *cp_string_cstrcpy(cp_string *str, char *cstr)
{
    if (str)
    {
        str->len = strlen(cstr);
        if (str->size < str->len + 1)
        {
            str->size = str->len + 1;
            str->data = t_malloc(str->size * sizeof(char));
        }
        if (str->data)
            memcpy(str->data, cstr, str->size * sizeof(char));
        else
        {
            t_free(str);
            str = NULL;
        }
    }
    return str;
}
int cp_string_copy(cp_string *dst, cp_string *src)
{
    int        left;
    int        size;
    if(!dst || !dst->data || !src || !src->data)
        return 0;
    left=dst->size - dst->len;
    size = left>src->len ? src->len : left;
    memcpy(&dst->data[dst->len], src->data, size);
    dst->len += size;
    return size;
}
int cp_string_cstrcopy(cp_string *dst, char *string, int len)
{
    int        left;
    int        size;
    if(!dst || !dst->data || !string || len<=0)
        return 0;
    left=dst->size - dst->len;
    size = left>len ? len : left;
    memcpy(&dst->data[dst->len], string, size);
    dst->len += size;
    return size;
}
int cp_string_move(cp_string *dst, cp_string *src)
{
    int        left;
    int        size;
    if(!dst || !dst->data || !src || !src->data)
        return 0;
    /* Check how many left size in $dst and set the size */
    left=dst->size - dst->len;
    size = left>src->len ? src->len : left;
    /* copy the $src data to $dst  */
    memcpy(&dst->data[dst->len], src->data, size);
    dst->len += size;
    /* remove the $src copied data in it*/
    src->len -= size;
    memmove (src->data, src->data+size, src->len);
    return size;
}
cp_string *cp_string_dup(cp_string *src)
{
    cp_string *str = t_malloc(sizeof(cp_string));
    if (str)
    {
        *str = *src; /* bitwise copy */
        str->data = t_malloc((str->len + 1) * sizeof(char));
        if (str->data)
            memcpy(str->data, src->data, (str->len  + 1) * sizeof(char));
        else
        {
            t_free(str);
            str = NULL;
        }
    }
    return str;
}
cp_string *cp_string_cstrdup(char *src)
{
    cp_string *str = t_malloc(sizeof(cp_string));
    if (str)
    {
        str->len = strlen(src);
        str->size = str->len + 1;
        str->data = t_malloc(str->size * sizeof(char));
        if (str->data == NULL)
        {
            t_free(str);
            return NULL;
        }
        memcpy(str->data, src, str->size);
    }
    return str;
}
cp_string *cp_string_cat(cp_string *str, cp_string *appendum)
{
    int len = str->len;
    str->len += appendum->len;
    if (str->len + 1 > str->size)
    {
        str->size = str->len + 1;
        str->data = realloc(str->data, str->size * sizeof(char));
    }
    if (str->data)
        memcpy(str->data + len * sizeof(char), appendum->data,
            appendum->len * sizeof(char));
    return str;
}
cp_string *cp_string_cstrcat(cp_string *str, char *cstr)
{
    int len = str->len;
    int clen = strlen(cstr);
    str->len += clen * sizeof(char);
    if (str->len + 1 > str->size)
    {
//        str->size = str->len + 0x400 - (str->len % 0x400); /* align to 1kb block */
        str->size = str->len + 1;
        str->data = realloc(str->data, str->size * sizeof(char));
    }
    if (str->data)
        memcpy(str->data + len * sizeof(char), cstr, clen);
    return str;
}
cp_string *cp_string_append_char(cp_string *str, char ch)
{
    if (str->len + 1 > str->size)
    {
        str->size = str->len + 0x100;
        str->data = realloc(str->data, str->size * sizeof(char));
        if (str->data == NULL) return NULL;
    }
    str->data[str->len++] = ch;
    return str;
}
cp_string *cp_string_cat_bin(cp_string *str, void *bin, int len)
{
    int olen = str->len;
    str->len += len;
    if (str->len > str->size)
    {
        str->size = str->len + 0x400 - (str->len % 0x400); /* align to 1kb block */
        str->data = realloc(str->data, str->size * sizeof(char));
    }
    memcpy(&str->data[olen], bin, len);
    return str;
}
int cp_string_cmp(cp_string *s1, cp_string *s2)
{
    if (s1 == s2) return 0; //~~ implies cp_string_cmp(NULL, NULL) == 0
    if (s1 == NULL) return -1;
    if (s2 == NULL) return 1;
    if (s1->len == s2->len)
        return memcmp(s1->data, s2->data, s1->len);
    else
    {
        int p = (s1->len > s2->len) ? s2->len : s1->len;
        int rc = memcmp(s1->data, s2->data, p);
        if (rc == 0)
            return s1->len - s2->len;
        return rc;
    }
}
char *cp_string_tocstr(cp_string *str)
{
    char *cstr = NULL;
    if (str)
    {
        str->data[str->len * sizeof(char)] = '\0';
//        str->data[str->len * sizeof(char) + 1] = '\0';
        cstr = str->data;
    }
    return cstr;
}
int cp_string_len(cp_string *s)
{
    return s->len;
}
char *cp_string_data(cp_string *s)
{
    return s->data;
}
#define CHUNK 0x1000
cp_string *cp_string_read(int fd, int len)
{
    char buf[CHUNK];
    int read_len;
    cp_string *res = NULL;
    if (len == 0)
        read_len = CHUNK;
    else
        read_len = len < CHUNK ? len : CHUNK;
    while (len == 0 || res == NULL || res->len < len)
    {
        int rc =
            read(fd, buf, read_len);
        if (rc <= 0) break;
        if (res == NULL)
        {
            res = cp_string_create(buf, rc);
            if (res == NULL) return NULL;
        }
        else
            cp_string_cat_bin(res, buf, rc);
    }
    return res;
}
int cp_string_write(cp_string *str, int fd)
{
    int rc;
    int total = 0;
    while (total < str->len)
    {
        rc = write(fd, &str->data[total], str->len - total);
        /* write sets EAGAIN when a socket is marked non-blocking and the
         * write would block. trying to write again could result in spinning
         * on the write call.
         */
        if (rc == -1)
        {
            if (errno == EINTR /* || errno == EAGAIN */) /* try again */
                continue;
            else
                break;
        }
        total += rc;
    }
    return total;
}
cp_string *cp_string_read_file(char *filename)
{
    cp_string *res;
    FILE *fp = fopen(filename, "rb");
    if (fp == NULL) return NULL;
    res = cp_string_read(fileno(fp), 0);
    fclose(fp);
    return res;
}
int cp_string_write_file(cp_string *str, char *filename)
{
    int rc;
    FILE *fp = fopen(filename, "wb");
    if (fp == NULL) return 0;
    rc = cp_string_write(str, fileno(fp));
    fclose(fp);
    return rc;
}
#define LINELEN 81
#define CHARS_PER_LINE 16
static char *print_char =
    "                "
    "                "
    " !\"#$%&'()*+,-./"
    "0123456789:;<=>?"
    "@ABCDEFGHIJKLMNO"
    "PQRSTUVWXYZ[\\]^_"
    "`abcdefghijklmno"
    "pqrstuvwxyz{|}~ "
    "                "
    "                "
    " ???????????????"
    "????????????????"
    "????????????????"
    "????????????????"
    "????????????????"
    "????????????????";
void cp_cstring_dump(char *data, int len)
{
    int rc;
    int idx;
    char prn[LINELEN];
    char lit[CHARS_PER_LINE + 1];
    char hc[4];
    short line_done = 1;
    rc = len;
    idx = 0;
    lit[CHARS_PER_LINE] = '\0';
    while (rc > 0)
    {
        if (line_done)
            snprintf(prn, LINELEN, "%08X: ", idx);
        do
        {
            unsigned char c = data[idx];
            snprintf(hc, 4, "%02X ", c);
            strncat(prn, hc, 4);
            lit[idx % CHARS_PER_LINE] = print_char[c];
            ++idx;
        } while (--rc > 0 && (idx % CHARS_PER_LINE != 0));
        line_done = (idx % CHARS_PER_LINE) == 0;
        if (line_done)
            printf("%s  %s\n", prn, lit);
        else if (rc == 0)
            strncat(prn, "   ", LINELEN);
    }
    if (!line_done)
    {
        lit[(idx % CHARS_PER_LINE)] = '\0';
        while ((++idx % CHARS_PER_LINE) != 0)
            strncat(prn, "   ", LINELEN);
        printf("%s  %s\n", prn, lit);
    }
}
const char *cp_hexdump_string(const void *data, size_t len)
{
    static char string[1024];
    unsigned char *d = (unsigned char *)data;
    unsigned int i, left;
    string[0] = '\0';
    left = sizeof(string);
    for (i = 0; len--; i += 3) {
        if (i >= sizeof(string) - 4)
            break;
        snprintf(string + i, 4, " %02x", *d++);
    }
    return string;
}
void cp_string_dump(cp_string *str)
{
    int rc;
    int idx;
    char prn[LINELEN];
    char lit[CHARS_PER_LINE + 1];
    char hc[4];
    short line_done = 1;
    rc = str->len;
    idx = 0;
    lit[CHARS_PER_LINE] = '\0';
    while (rc > 0)
    {
        if (line_done)
            snprintf(prn, LINELEN, "%08X: ", idx);
        do
        {
            unsigned char c = str->data[idx];
            snprintf(hc, 4, "%02X ", c);
            strncat(prn, hc, 4);
            lit[idx % CHARS_PER_LINE] = print_char[c];
            ++idx;
        } while (--rc > 0 && (idx % CHARS_PER_LINE != 0));
        line_done = (idx % CHARS_PER_LINE) == 0;
        if (line_done)
            printf("%s  %s\n", prn, lit);
        else if (rc == 0)
            strncat(prn, "   ", LINELEN);
    }
    if (!line_done)
    {
        lit[(idx % CHARS_PER_LINE)] = '\0';
        while ((++idx % CHARS_PER_LINE) != 0)
            strncat(prn, "   ", LINELEN);
        printf("%s  %s\n", prn, lit);
    }
}
/** flip the contents of a cp_string */
void cp_string_flip(cp_string *str)
{
    if (str->len)
    {
        char *i, *f, ch;
        f = &str->data[str->len - 1];
        i = str->data;
        while (i < f)
        {
            ch = *i;
            *i = *f;
            *f = ch;
            i++;
            f--;
        }
    }
}
/* remove all occurrences of letters from str */
cp_string *cp_string_filter(cp_string *str, char *letters)
{
    char *i;
    char *f;
    str->data[str->len] = '\0';
    i = str->data;
    while ((f = strpbrk(i, letters)))
    {
        i = f;
        while (*f && strchr(letters, *f)) f++;
        if (*f)
        {
            memmove(i, f, str->len - (f - str->data));
            str->len -= f - i;
            str->data[str->len] = '\0';
        }
        else
        {
            *i = '\0';
            str->len -= str->len - (i - str->data);
            break;
        }
    }
    return str;
}
/** @} */
char *del_char_from_string(char *str, char delchar)
{
    char *idx = str;
    char *end = str;
    while (*idx)
    {
        if (*idx == delchar)
        {
            ++idx;
        }
        else
        {
            *end = *idx;
            ++end;
            ++idx;
        }
    }
    *end = '\0';
    return str;
}
int split_string_to_value(char *str, char *fmt, ...)
{
    va_list     ap;
    int         *iPtr;
    long        *lPtr;
    char        *pcPtr;
    char        delim[2]={*(fmt+2), '\0'};
    char        *result;
    va_start(ap, fmt);
    result = strtok( str, delim );
    while(*fmt)
    {
        switch (*fmt++)
        {
            case 's':  /* string */
                pcPtr = va_arg(ap, char *);
                if(NULL!= result)
                {
                    if(NULL!=pcPtr)
                    {
                        strcpy(pcPtr, result);
                    }
                    result = strtok( NULL, delim );
                }
                else
                    goto OUT;
                break;
            case 'd':  /*  int */
                iPtr = va_arg(ap, int *);
                if(NULL!= result)
                {
                    if(NULL!=iPtr)
                    {
                        *iPtr = atoi(result);
                    }
                    result = strtok( NULL, delim );
                }
                else
                    goto OUT;
                break;
            case 'l':  /*  long */
                lPtr = va_arg(ap, long *);
                if(NULL!= result)
                {
                    if(NULL!=lPtr)
                    {
                        *lPtr = strtol(result, NULL, 10);
                    }
                    result = strtok( NULL, delim );
                }
                else
                    goto OUT;
                break;
            case 'x':  /*  long hex*/
                lPtr = va_arg(ap, long *);
                if(NULL!= result)
                {
                    if(NULL!=lPtr)
                    {
                        *lPtr = strtol(result, NULL, 16);
                    }
                    result = strtok( NULL, delim );
                }
                else
                    goto OUT;
                break;
        }
    }
OUT:
    va_end(ap);
    return 0;
}
program/cp_library/cp_string.h
New file
@@ -0,0 +1,86 @@
#ifndef _CP_STRING_H
#define _CP_STRING_H
/** @{ */
/**
 * @file
 * cp_string - 'safe' string allowing binary content
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
/** cp_string definition */
typedef struct _cp_string
{
    int size;    /**< size allocated   */
    int len;     /**< size used        */
    char *data;  /**< internal buffer  */
} cp_string;
/** allocate a new cp_string */
cp_string *cp_string_create(char *data, int len);
/** allocate an empty cp_string with a given buffer size */
cp_string *cp_string_create_empty(int initial_size);
/** deallocate a cp_string */
void cp_string_destroy(cp_string *str);
/** Sets string data to 0 */
void cp_string_clear_data(cp_string *str);
/** copies the content of a null terminated c string */
cp_string *cp_string_cstrcpy(cp_string *str, char *cstr);
/** copies the content of a cp_string */
//cp_string *cp_string_cp(cp_string *dst, cp_string *src);
int cp_string_copy(cp_string *dst, cp_string *src);
int cp_string_move(cp_string *dst, cp_string *src);
/** copy the string into *dst  */
int cp_string_cstrcopy(cp_string *dst, char *string, int len);
/** creates a copy of src string. internal buffer is duplicated. */
cp_string *cp_string_dup(cp_string *src);
/** creates a cp_string with src as its content */
cp_string *cp_string_cstrdup(char *src);
/** concatenate cp_strings */
cp_string *cp_string_cat(cp_string *str, cp_string *appendum);
/** append data from a buffer */
cp_string *cp_string_cat_bin(cp_string *str, void *bin, int len);
/** append data from a null terminated c string */
cp_string *cp_string_cstrcat(cp_string *str, char *cstr);
/** append a character to a string */
cp_string *cp_string_append_char(cp_string *str, char ch);
/** compare cp_strings */
int cp_string_cmp(cp_string *s1, cp_string *s2);
/** return a pointer to the internal buffer */
char *cp_string_tocstr(cp_string *str);
/** return the length of the internal buffer */
int cp_string_len(cp_string *s);
/** return the internal buffer */
char *cp_string_data(cp_string *s);
/** read len bytes from an open file descriptor (blocking) */
cp_string *cp_string_read(int fd, int len);
/** write the content of a cp_string to a file descriptor (blocking) */
int cp_string_write(cp_string *str, int fd);
/** read the contents of a file into a cp_string */
cp_string *cp_string_read_file(char *filename);
/** write the contents of a cp_string to a file */
int cp_string_write_file(cp_string *str, char *filename);
/** flip the contents of a cp_string */
void cp_string_flip(cp_string *str);
/** remove all occurrences of letters from str */
cp_string *cp_string_filter(cp_string *str, char *letters);
/** dump a cp_string to stdout */
const char *cp_hexdump_string(const void *data, size_t len);
void cp_string_dump(cp_string *str);
void cp_cstring_dump(char *data, int len);
char *del_char_from_string(char *str, char delchar);
int split_string_to_value(char *str, char *fmt, ...);
/** @} */
#endif
program/cp_library/cp_time.h
New file
@@ -0,0 +1,123 @@
/********************************************************************************
 *      Copyright:  (C) 2012 CoherentPlus Sdn. Bhd.
 *                  All rights reserved.
 *
 *       Filename:  cp_time.h
 *    Description:  This head file
 *
 *        Version:  1.0.0(02/23/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "02/23/2012 07:46:37 AM"
 *
 ********************************************************************************/
#ifndef __CP_TIME_H
#define __CP_TIME_H
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
typedef struct __DATE_TIME
{
    int iYear;
    int iMonth;
    int iDay;
    int iHour;
    int iMinute;
    int iSecond;
    int iDayOfWeek;
} DATE_TIME;
static inline void micro_second_sleep(unsigned long ms)
{
    struct timespec cSleep;
    unsigned long ulTmp;
    cSleep.tv_sec = ms / 1000;
    if (cSleep.tv_sec == 0)
    {
        ulTmp = ms * 10000;
        cSleep.tv_nsec = ulTmp * 100;
    }
    else
    {
        cSleep.tv_nsec = 0;
    }
    nanosleep(&cSleep, 0);
}
/*UNIT: micro second*/
static inline unsigned long time_now()
{
    struct timeval now;
    gettimeofday(&now, 0);
    return (now.tv_sec * 1000) + (now.tv_usec / 1000);
}
/*UNIT: micro second*/
static inline unsigned long time_elapsed(unsigned long start)
{
    unsigned long current = time_now();
    if (current < start)
    {
        return (0xFFFFFFFF - start) + current;
    }
    //printf("time_elapsed: %ld\n", current-start);
    return current - start;
}
static inline void get_current_time(DATE_TIME * date)
{
    time_t now = time(NULL);
    struct tm *tnow = localtime(&now);
    memset(date, 0, sizeof(DATE_TIME));
    date->iYear = 1900 + tnow->tm_year;
    date->iMonth = 1 + tnow->tm_mon;
    date->iDay = tnow->tm_mday;
    date->iHour = tnow->tm_hour;
    date->iMinute = tnow->tm_min;
    date->iSecond = tnow->tm_sec;
    date->iDayOfWeek = tnow->tm_wday;
    return;
}
#define get_sys_time(date)   get_current_time(date)
static inline int get_rtc_time(DATE_TIME *date)
{
    int                 rv, fd = -1;
    struct rtc_time     rtc_tm;
    memset(date, 0, sizeof(DATE_TIME));
    if ((fd=open("/dev/rtc0", O_RDONLY)) < 0)
        return -1;
    if((rv=ioctl(fd, RTC_RD_TIME, &rtc_tm)) < 0)
        return -2;
    date->iYear = 1900 + rtc_tm.tm_year;
    date->iMonth = 1 + rtc_tm.tm_mon;
    date->iDay = rtc_tm.tm_mday;
    date->iHour = rtc_tm.tm_hour;
    date->iMinute = rtc_tm.tm_min;
    date->iSecond = rtc_tm.tm_sec;
    date->iDayOfWeek = rtc_tm.tm_wday;
    close(fd);
    return 0;
}
#endif
program/cp_library/cp_vector.c
New file
@@ -0,0 +1,96 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_vector.c
 *    Description:  This file is for a dynamic array
 *
 *        Version:  1.0.0(11/12/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/12/2012 11:20:30 AM"
 *
 ********************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "cp_vector.h"
#include "cp_common.h"
CP_VECTOR *cp_vector_init(int size)
{
    CP_VECTOR  *vector = NULL;
    if(size < 0)
        return NULL;
    vector = (CP_VECTOR *)t_malloc(sizeof(CP_VECTOR));
    if(!vector)
    {
        return NULL;
    }
    vector->mem = t_malloc(size*sizeof(void *));
    if(!vector->mem)
    {
        t_free(vector);
        return NULL;
    }
    memset(vector->mem, 0, size);
    vector->size = size;
    vector->used = 0;
    return vector;
}
void *cp_vector_add(CP_VECTOR *vector, int index, void *item)
{
    if(index<0 || index>vector->size)
        return NULL;
    vector->mem[index]=item;
    vector->used++;
    return item;
}
void *cp_vector_del(CP_VECTOR *vector, int index)
{
    void    *save;
    if(index<0 ||index>vector->size)
        return NULL;
    save = vector->mem[index];
    vector->mem[index]=NULL;
    vector->used--;
    return save;
}
void *cp_vector_get(CP_VECTOR *vector, int index)
{
    if(index<0 ||index>vector->size)
        return NULL;
    return vector->mem[index];
}
void cp_vector_destroy(CP_VECTOR *vector)
{
    if(!vector)
       return;
    if(vector->mem)
    {
        t_free(vector->mem);
    }
    t_free(vector);
}
program/cp_library/cp_vector.h
New file
@@ -0,0 +1,40 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  cp_vector.h
 *    Description:  This head file is for dynamic array
 *
 *        Version:  1.0.0(11/12/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/12/2012 11:20:53 AM"
 *
 ********************************************************************************/
#ifndef __CP_VECTOR
#define __CP_VECTOR
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
typedef struct _CP_VECTOR
{
    int           size;
    int           used;
    void          **mem;
} CP_VECTOR;
#define cp_vector_count(v)  ((v) ? (v)->used : 0)
#define cp_vector_size(v)  ((v) ? (v)->size : 0)
CP_VECTOR *cp_vector_init(int size);
void *cp_vector_add(CP_VECTOR *vector, int index, void *item);
void *cp_vector_del(CP_VECTOR *vector, int index);
void *cp_vector_get(CP_VECTOR *vector, int index);
void cp_vector_destroy(CP_VECTOR *vector);
#endif
program/cp_library/cscope.in.out
Binary files differ
program/cp_library/cscope.out
New file
Diff too large
program/cp_library/cscope.po.out
Binary files differ
program/cp_library/makefile
New file
@@ -0,0 +1,107 @@
#*********************************************************************************
#      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
#                  All rights reserved.
#
#       Filename:  Makefile
#    Description:  This is the common subdir Makefile which to compile all the C
#                  source code to object files and then generate the shared or
#                  static library named lib$(FOLDER_NAME).a orlib $(FOLDER_NAME).so,
#                  which depends on the variable $LINK_MODE.
#
#        Version:  1.0.0(10/08/2011~)
#                  Author:  Guo Wenxue <guowenxue@gmail.com>
#      ChangeLog:  1, Release initial version on "10/08/2011 01:29:33 AM"
#
#********************************************************************************/
PWD=$(shell pwd)
#If wanna compile in the subdir, not called by top makefile, uncomment it
ifneq (${TOP_COMPILE}, YES)
LOCAL_COMPILE=YES
endif
LINK_MODE=STATIC
#MULTHREADS=YES
LIBNAME=$(shell basename ${PWD})
STALIB=lib${LIBNAME}.a
DYNLIB=lib${LIBNAME}.so
VPATH= .
SRCS = $(wildcard ${VPATH}/*.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
#======================================================
#  ---> Doesn't call by top makefile, compile by local
#======================================================
ifeq (${LOCAL_COMPILE}, YES)
ARCH?=arm920t
#ARCH?=i386
CFLAGS+=-fPIC
TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]")
ifneq (,$(filter i386,$(TMP)))
    CROSS_COMPILE=
else
    CROSS_COMPILE=/opt/xtools/arm920t/bin/arm-linux-
endif
PRJDIR?=$(shell dirname ${PWD})
CFLAGS+=-I${PRJDIR} -g -Wall -Werror
CC = ${CROSS_COMPILE}gcc
AR = ${CROSS_COMPILE}ar
endif #End local compile
ifeq ("${LINK_MODE}", "STATIC")
    LIBS = ${STALIB}
else
    LIBS=${DYNLIB} ${STALIB}
endif
ifeq ("${MULTHREADS}", "YES")
LDFLAGS+=-lpthread
CFLAGS+=-DMULTHREADS
endif
all: entry clean ${LIBS} install
entry:
    @echo " ";
    @echo " =========================================================";
    @echo " **     Compile subdir ${LIBNAME} for ${ARCH}             ";
    @echo " =========================================================";
#$(LD) -g --relocatable $(OBJS) -o lib${LIBNAME}.o
${STALIB}:    $(OBJS)
    $(AR) -rcu $@ $(OBJS)
${DYNLIB}:   $(OBJS)
    $(CC) -fPIC -shared -o $@ $(OBJS)
%.o : %.c
    $(CC) -c $< $(CFLAGS)
test: clean ${LIBS}
    make -C test ARCH=${ARCH}
tag:
    @ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R .
    @cscope -Rbq
install:
    @if [ ! -z "${LIBS_PATH}" ] ; then \
        mkdir -p ${LIBS_PATH} ; \
        cp ${LIBS} ${LIBS_PATH}; \
    fi;
clean:
    @rm -f *.o *.lo *~
    @rm -rf *.gdb *.a *.so
    @make clean -C test
    @rm -f *.log
distclean: clean
    @rm -f  tags cscope*
.PHONY: clean entry
program/cp_library/tags
New file
@@ -0,0 +1,1322 @@
!_TAG_FILE_FORMAT    2    /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED    1    /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR    Darren Hiebert    /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME    Exuberant Ctags    //
!_TAG_PROGRAM_URL    http://ctags.sourceforge.net    /official site/
!_TAG_PROGRAM_VERSION    5.9~svn20110310    //
ALL_READY    cp_gprs.h    /^    ALL_READY,$/;"    e    enum:__anon4
APN_2G    cp_ppp.h    31;"    d
APN_3G    cp_ppp.h    30;"    d
APN_ACCOUNT    cp_ppp.h    /^} APN_ACCOUNT;  $/;"    t    typeref:struct:__APN_ACCOUNT
APN_DEF_CONF_FILE    cp_ppp.h    39;"    d
APN_LEN    cp_ppp.h    26;"    d
AR    makefile    /^AR = ${CROSS_COMPILE}ar$/;"    m
AR    test/makefile    /^export AR=${CROSS_COMPILE}ar$/;"    m
ARCH    makefile    /^ARCH?=arm920t$/;"    m
ARCH    test/makefile    /^ARCH?=arm920t$/;"    m
ARCH_HAS_PREFETCH    cp_klist.h    54;"    d
AS    test/makefile    /^export AS=${CROSS_COMPILE}as$/;"    m
ASCIILINESZ    cp_iniparser.c    14;"    d    file:
ATCMD_REPLY_LEN    cp_atcmd.c    20;"    d    file:
BINARIES    test/makefile    /^BINARIES=$(SRCFILES:%.c=%)$/;"    m
BLINK    cp_hal.h    35;"    d
BUF_64    cp_comport.h    30;"    d
BUZZER_BEEP    at91_ioctl.h    50;"    d
BUZZER_FREQ    at91_ioctl.h    52;"    d
BUZZER_OFF    at91_ioctl.h    51;"    d
BUZZER_ON    at91_ioctl.h    49;"    d
CC    makefile    /^CC = ${CROSS_COMPILE}gcc$/;"    m
CC    test/makefile    /^export CC=${CROSS_COMPILE}gcc$/;"    m
CHARS_PER_LINE    cp_logger.c    343;"    d    file:
CHARS_PER_LINE    cp_string.c    397;"    d    file:
CHECK_HWINFO    cp_gprs.h    /^    CHECK_HWINFO,    \/* Get GPRS hardware Information *\/$/;"    e    enum:__anon4
CHECK_REGISTRY    cp_gprs.h    /^    CHECK_REGISTRY,  \/* Check GPRS register network information *\/$/;"    e    enum:__anon4
CHUNK    cp_string.c    317;"    d    file:
CMUX_DATAPORT    cp_gprs.h    37;"    d
CMUX_PORT_START_INDEX    cp_gprs.h    36;"    d
COMPILE_DATE    test/makefile    /^COMPILE_DATE=$(shell date -u +"%Y-%m-%d %H:%M")$/;"    m
COM_PORT    cp_comport.h    /^} COM_PORT;$/;"    t    typeref:struct:__COM_PORT
COM_PRINT    cp_comport.h    38;"    d
COM_PRINT    cp_comport.h    40;"    d
CONNECTED    cp_ppp.h    /^    CONNECTED,$/;"    e    enum:__anon2
CONNECTING    cp_ppp.h    /^    CONNECTING,$/;"    e    enum:__anon2
CP_ARRAY    cp_array.h    /^} CP_ARRAY;$/;"    t    typeref:struct:_CP_ARRAY
CP_ARRAY_FLAG_MALLOC    cp_array.h    17;"    d
CP_DEF_FDS_TIMEOUT    cp_fds.h    33;"    d
CP_DEF_MAX_CLIENTS    cp_network.h    19;"    d
CP_DEF_MAX_EVENTS    cp_fds.h    32;"    d
CP_DEF_RCVBUF_SIZE    cp_sock.h    39;"    d
CP_DEF_SNDBUF_SIZE    cp_sock.h    40;"    d
CP_DEF_TIMEOUT    cp_network.h    20;"    d
CP_FDS    cp_fds.h    /^} CP_FDS;$/;"    t    typeref:struct:_CP_FDS
CP_LOGGER_ARGUMENT    cp_logger.h    62;"    d
CP_LOGGER_CONSOLE    cp_logger.h    64;"    d
CP_LOGGER_FILE    cp_logger.h    65;"    d
CP_LOGGER_LEVEL_OPT    cp_logger.h    67;"    d
CP_LOGGER_MALLOC    cp_logger.h    61;"    d
CP_MAX_EVENT_ONCE    cp_fds.h    31;"    d
CP_PROC_SIG    cp_proc.h    /^}  CP_PROC_SIG;$/;"    t    typeref:struct:__CP_PROC_SIG
CP_QNODE    cp_queue.h    /^} CP_QNODE;$/;"    t    typeref:struct:_CP_QNODE
CP_QUEUE    cp_queue.h    /^} CP_QUEUE;$/;"    t    typeref:struct:_CP_QUEUE
CP_SOCK    cp_sock.h    /^} CP_SOCK;$/;"    t    typeref:struct:_CP_SOCK
CP_SOCK_CALLBACK    cp_sock.h    /^} CP_SOCK_CALLBACK; $/;"    t    typeref:struct:_CP_SOCK_CALLBACK
CP_SOCK_DEF_IDLE_TIMEOUT    cp_sock.h    45;"    d
CP_SOCK_DEF_MSG_TIMEOUT    cp_sock.h    46;"    d
CP_SOCK_EVENT_CALLBACK    cp_sock.h    /^typedef int (*CP_SOCK_EVENT_CALLBACK)(struct _CP_SOCK *sock);$/;"    t
CP_SOCK_EVENT_ERROR    cp_sock.h    /^    CP_SOCK_EVENT_ERROR        =          EPOLLERR,  \/* compatilbe with EPOLLERR  *\/$/;"    e    enum:__anon7
CP_SOCK_EVENT_HUP    cp_sock.h    /^    CP_SOCK_EVENT_HUP          =          EPOLLHUP,  \/* compatilbe with EPOLLHUP *\/$/;"    e    enum:__anon7
CP_SOCK_EVENT_IDLE_TIMEOUT    cp_sock.h    /^    CP_SOCK_EVENT_IDLE_TIMEOUT =          (1<<16),   \/* compatilbe with EPOLL reserved*\/  $/;"    e    enum:__anon7
CP_SOCK_EVENT_MSG_TIMEOUT    cp_sock.h    /^    CP_SOCK_EVENT_MSG_TIMEOUT  =          (1<<17),   \/* compatible with EPOLL reserved*\/$/;"    e    enum:__anon7
CP_SOCK_EVENT_READ    cp_sock.h    /^    CP_SOCK_EVENT_READ         =          EPOLLIN,   \/* compatilbe with EPOLLIN  *\/$/;"    e    enum:__anon7
CP_SOCK_EVENT_WRITE    cp_sock.h    /^    CP_SOCK_EVENT_WRITE        =          EPOLLOUT,  \/* compatilbe with EPOLLOUT *\/$/;"    e    enum:__anon7
CP_SOCK_KEEPCNT    cp_sock.h    49;"    d
CP_SOCK_KEEPINTVL    cp_sock.h    48;"    d
CP_SOCK_MODE_ACCEPT    cp_sock.h    52;"    d
CP_SOCK_MODE_CONNECT    cp_sock.h    53;"    d
CP_SOCK_MODE_LISTEN    cp_sock.h    54;"    d
CP_SOCK_MODE_NONE    cp_sock.h    51;"    d
CP_SOCK_RCVBUF    cp_sock.h    42;"    d
CP_SOCK_SNDBUF    cp_sock.h    43;"    d
CP_VECTOR    cp_vector.h    /^} CP_VECTOR;$/;"    t    typeref:struct:_CP_VECTOR
CROSS_COMPILE    makefile    /^    CROSS_COMPILE=$/;"    m
CROSS_COMPILE    makefile    /^    CROSS_COMPILE=\/opt\/xtools\/arm920t\/bin\/arm-linux-$/;"    m
CROSS_COMPILE    test/makefile    /^    CROSS_COMPILE=$/;"    m
CROSS_COMPILE    test/makefile    /^    CROSS_COMPILE=\/opt\/buildroot-2012.08\/$(ARCH)\/usr\/bin\/arm-linux-$/;"    m
CXX    test/makefile    /^export CXX=${CROSS_COMPILE}g++$/;"    m
DATE_TIME    cp_time.h    /^} DATE_TIME;$/;"    t    typeref:struct:__DATE_TIME
DBG_LOG_FILE    cp_logger.h    37;"    d
DEBUG    test/makefile    /^DEBUG=1$/;"    m
DEFAULT_LOGFILE    cp_logger.h    36;"    d
DEFAULT_PING_INTERVAL    cp_ppp.h    25;"    d
DEFAULT_TIME_FORMAT    cp_logger.h    42;"    d
DEF_PING_DST    cp_ppp.h    37;"    d
DEVNAME_LEN    cp_comport.h    33;"    d
DEV_GMTUBE_PATH    cp_hal.h    31;"    d
DEV_GPS_PATH    cp_hal.h    29;"    d
DEV_GSM_PATH    cp_hal.h    28;"    d
DEV_LED_PATH    cp_hal.h    27;"    d
DEV_ZIGBEE_PATH    cp_hal.h    30;"    d
DICTMINSZ    cp_dictionary.c    27;"    d    file:
DICT_INVALID_KEY    cp_dictionary.c    30;"    d    file:
DISCONNECT    cp_ppp.h    /^    DISCONNECT = 0,$/;"    e    enum:__anon2
DOMAIN    test/test_sock_server.c    23;"    d    file:
DYNLIB    makefile    /^DYNLIB=lib${LIBNAME}.so$/;"    m
FILENAME_LEN    cp_logger.h    33;"    d
FLAG_FDS_INIT    cp_fds.h    38;"    d
FLAG_FDS_MALLOC    cp_fds.h    39;"    d
FLAG_SOCK_EPOLLED    cp_sock.h    81;"    d
FLAG_SOCK_INIT    cp_sock.h    79;"    d
FLAG_SOCK_INQUEUE    cp_sock.h    83;"    d
FLAG_SOCK_MALLOC    cp_sock.h    80;"    d
FLAG_SOCK_REGISTRY    cp_sock.h    82;"    d
FLAG_SOCK_TASKED    cp_sock.h    84;"    d
FLAG_TPDU_INIT    test/swe_tpdud.h    26;"    d
FLAG_TPDU_STOP    test/swe_tpdud.h    27;"    d
GET_ADC_DATA    at91_ioctl.h    44;"    d
GET_BATTERY_STAT    at91_ioctl.h    41;"    d
GET_BUTTON_STATUS    at91_ioctl.h    55;"    d
GET_DRV_VER    at91_ioctl.h    34;"    d
GET_GMTUBE_VHIGH    at91_ioctl.h    42;"    d
GET_GPRS_VBAT    at91_ioctl.h    43;"    d
GM_GET_MEASURE_DOSE    at91_ioctl.h    81;"    d
GM_GET_VOLTAGE    at91_ioctl.h    84;"    d
GM_SET_DUTY    at91_ioctl.h    82;"    d
GM_SET_INTERVAL    at91_ioctl.h    83;"    d
GM_SET_MEASURE_RADI    at91_ioctl.h    80;"    d
GM_SET_MEASURE_TC    at91_ioctl.h    88;"    d
GM_SET_POWER    at91_ioctl.h    86;"    d
GM_SET_PWM_TC    at91_ioctl.h    87;"    d
GM_SET_TIMER_TC    at91_ioctl.h    89;"    d
GPRS_LOCATION    cp_atcmd.h    /^} GPRS_LOCATION;$/;"    t    typeref:struct:_GPRS_LOCATION
GPS_GET_POWER    at91_ioctl.h    75;"    d
GPS_SET_POWER    at91_ioctl.h    74;"    d
GSMIOC_GETCONF    cp_gsmmux.h    36;"    d
GSMIOC_SETCONF    cp_gsmmux.h    37;"    d
GSM_CTRLPORT    cp_gprs.h    32;"    d
GSM_DATAPORT    cp_gprs.h    33;"    d
GSM_GET_ADC    at91_ioctl.h    72;"    d
GSM_GET_POWER    at91_ioctl.h    71;"    d
GSM_SET_POWER    at91_ioctl.h    70;"    d
HAL_LIBRARY_TEST    test/test_hal.c    18;"    d    file:
HH_DATAPORT    test/test_hh.c    16;"    d    file:
HLIST_HEAD    cp_klist.h    587;"    d
HLIST_HEAD_INIT    cp_klist.h    586;"    d
HOSTSIM_IP    test/swe_tpdud.h    20;"    d
HOSTSIM_PORT    test/swe_tpdud.h    19;"    d
HW_INFO    cp_atcmd.h    /^} HW_INFO;$/;"    t    typeref:struct:_HARDWARE_INFO
INIT_HLIST_HEAD    cp_klist.h    588;"    d
INIT_HLIST_NODE    cp_klist.h    /^static inline void INIT_HLIST_NODE(struct hlist_node *h)$/;"    f
INIT_LIST_HEAD    cp_klist.h    /^static inline void INIT_LIST_HEAD(struct list_head *list)$/;"    f
INI_CONF    test/test_ini.c    17;"    d    file:
INI_INVALID_KEY    cp_iniparser.c    15;"    d    file:
INSTPATH    test/makefile    /^INSTPATH=\/tftp$/;"    m
IN_EVENT_LIST    cp_fds.h    35;"    d
IN_TASK_LIST    cp_fds.h    36;"    d
IPADDR    test/test_sock_server.c    24;"    d    file:
LED_BLINK    at91_ioctl.h    60;"    d
LED_OFF    at91_ioctl.h    58;"    d
LED_ON    at91_ioctl.h    59;"    d
LED_SYS    cp_hal.h    44;"    d
LIBNAME    makefile    /^LIBNAME=$(shell basename ${PWD})$/;"    m
LIBS    makefile    /^    LIBS = ${STALIB} $/;"    m
LIBS    makefile    /^    LIBS=${DYNLIB} ${STALIB}$/;"    m
LIB_NAME    test/makefile    /^LIB_NAME=$(shell basename ${LIB_PATH})$/;"    m
LIB_PATH    test/makefile    /^LIB_PATH=$(shell dirname ${PWD})$/;"    m
LINELEN    cp_logger.c    342;"    d    file:
LINELEN    cp_string.c    396;"    d    file:
LINE_COMMENT    cp_iniparser.c    /^    LINE_COMMENT,$/;"    e    enum:_line_status_    file:
LINE_EMPTY    cp_iniparser.c    /^    LINE_EMPTY,$/;"    e    enum:_line_status_    file:
LINE_ERROR    cp_iniparser.c    /^    LINE_ERROR,$/;"    e    enum:_line_status_    file:
LINE_SECTION    cp_iniparser.c    /^    LINE_SECTION,$/;"    e    enum:_line_status_    file:
LINE_UNPROCESSED    cp_iniparser.c    /^    LINE_UNPROCESSED,$/;"    e    enum:_line_status_    file:
LINE_VALUE    cp_iniparser.c    /^    LINE_VALUE$/;"    e    enum:_line_status_    file:
LINK_MODE    makefile    /^LINK_MODE=STATIC$/;"    m
LIST_HEAD    cp_klist.h    74;"    d
LIST_HEAD_INIT    cp_klist.h    72;"    d
LIST_POISON1    cp_klist.h    50;"    d
LIST_POISON2    cp_klist.h    51;"    d
LOCAL_COMPILE    makefile    /^LOCAL_COMPILE=YES$/;"    m
LOG_FILE_LINE    cp_logger.h    46;"    d
LOG_LEVEL_DEBUG    cp_logger.h    /^    LOG_LEVEL_DEBUG,                  \/*  Debug Level "Debug" *\/$/;"    e    enum:__anon1
LOG_LEVEL_DISB    cp_logger.h    /^    LOG_LEVEL_DISB = 0,               \/*  Disable "Debug" *\/$/;"    e    enum:__anon1
LOG_LEVEL_ERROR    cp_logger.h    /^    LOG_LEVEL_ERROR,                  \/*  Debug Level "ERROR" *\/$/;"    e    enum:__anon1
LOG_LEVEL_FATAL    cp_logger.h    /^    LOG_LEVEL_FATAL,                  \/*  Debug Level "Fatal" *\/$/;"    e    enum:__anon1
LOG_LEVEL_INFO    cp_logger.h    /^    LOG_LEVEL_INFO,                   \/*  Debug Level "Information" *\/$/;"    e    enum:__anon1
LOG_LEVEL_MAX    cp_logger.h    /^    LOG_LEVEL_MAX,$/;"    e    enum:__anon1
LOG_LEVEL_NRML    cp_logger.h    /^    LOG_LEVEL_NRML,                   \/*  Debug Level "Normal" *\/$/;"    e    enum:__anon1
LOG_LEVEL_TRACE    cp_logger.h    /^    LOG_LEVEL_TRACE,                  \/*  Debug Level "Trace" *\/$/;"    e    enum:__anon1
LOG_LEVEL_WARN    cp_logger.h    /^    LOG_LEVEL_WARN,                   \/*  Debug Level "warnning" *\/$/;"    e    enum:__anon1
LOG_ROLLBACK_NONE    cp_logger.h    40;"    d
LOG_ROLLBACK_SIZE    cp_logger.h    39;"    d
LOG_VERSION_STR    cp_logger.h    30;"    d
MAXVALSZ    cp_dictionary.c    24;"    d    file:
MAX_DATAPORT    cp_gprs.h    35;"    d
MAX_ITEMS    test/test_array.c    22;"    d    file:
MAX_ITEMS    test/test_queue.c    21;"    d    file:
MAX_LOG_MESSAGE_LEN    cp_logger.h    43;"    d
MAX_PPP_FAIL_CNT    cp_ppp.h    99;"    d
MODE    test/makefile    /^MODE=PRODUCTION$/;"    m
MODE_AUTO    cp_gprs.h    70;"    d
MODE_FAST    cp_hal.h    39;"    d
MODE_GSM    cp_gprs.h    71;"    d
MODE_SLOW    cp_hal.h    38;"    d
MODE_WCDMA    cp_gprs.h    72;"    d
MODULE_INFO    cp_gprs.h    /^} MODULE_INFO;$/;"    t    typeref:struct:__MODULE_INFO
MODULE_READY    cp_gprs.h    /^    MODULE_READY,    \/* GPRS AT command active and SIM card valid *\/$/;"    e    enum:__anon4
NO    cp_gprs.h    30;"    d
NOT_READY    cp_gprs.h    /^    NOT_READY,$/;"    e    enum:__anon4
NS_EGPRS    cp_gprs.h    /^    NS_EGPRS,         \/* EGPRS(EDGE) *\/$/;"    e    enum:__anon6
NS_GPRS    cp_gprs.h    /^    NS_GPRS,          \/* GPRS *\/$/;"    e    enum:__anon6
NS_GSM    cp_gprs.h    /^    NS_GSM,           \/* GSM *\/$/;"    e    enum:__anon6
NS_HSDPA    cp_gprs.h    /^    NS_HSDPA,         \/* HSDPA only *\/$/;"    e    enum:__anon6
NS_HSPA    cp_gprs.h    /^    NS_HSPA,          \/* HSDPA and HSUPA *\/$/;"    e    enum:__anon6
NS_HSUPA    cp_gprs.h    /^    NS_HSUPA,         \/* HSUPA only *\/$/;"    e    enum:__anon6
NS_NONE    cp_gprs.h    /^    NS_NONE = 0,      \/* No service *\/$/;"    e    enum:__anon6
NS_WCDMA    cp_gprs.h    /^    NS_WCDMA,         \/* WCDMA *\/$/;"    e    enum:__anon6
NVALS    cp_dictionary.c    359;"    d    file:
N_GSM0710    cp_gsmmux.h    39;"    d
OBJS    makefile    /^OBJS = $(patsubst %.c,%.o,$(SRCS))$/;"    m
OBJS    test/makefile    /^OBJS = $(patsubst %.c,%.o,$(SRCS))$/;"    m
OFF    cp_hal.h    33;"    d
ON    cp_hal.h    34;"    d
PID_ASCII_SIZE    cp_proc.h    19;"    d
PING_INTERVAL_TIME    cp_ppp.h    23;"    d
PLATDRV_MAGIC    at91_ioctl.h    26;"    d
POISON_POINTER_DELTA    cp_klist.h    40;"    d
POISON_POINTER_DELTA    cp_klist.h    42;"    d
PPPD_CMD_LEN    cp_ppp.c    242;"    d    file:
PPPD_DIAL_SCRIPTS    cp_ppp.h    33;"    d
PPPD_DIAL_TIMEOUT    cp_ppp.h    22;"    d
PPPD_INFO    cp_ppp.h    /^} PPPD_INFO;$/;"    t    typeref:struct:__PPPD_INFO
PPP_BAD    cp_ppp.h    104;"    d
PPP_CONN    cp_ppp.h    103;"    d
PPP_CTX    cp_ppp.h    /^} PPP_CTX;$/;"    t    typeref:struct:__PPP_CTX
PPP_GOOD    cp_ppp.h    105;"    d
PPP_INTERFACE_NAME    cp_ppp.h    34;"    d
PPP_PROC_NET_DEV    cp_ppp.h    35;"    d
PPP_STAT    cp_ppp.h    /^} PPP_STAT;$/;"    t    typeref:struct:__PPP_STAT
PPP_STOP    cp_ppp.h    101;"    d
PRECISE_TIME_FACTOR    cp_logger.c    17;"    d    file:
PRIVT_FREE    cp_sock.h    /^typedef void (*PRIVT_FREE)(void);$/;"    t
PRJDIR    makefile    /^PRJDIR?=$(shell dirname ${PWD})$/;"    m
PWD    makefile    /^PWD=$(shell pwd)$/;"    m
PWD    test/makefile    /^PWD=$(shell pwd)$/;"    m
PWD_LEN    cp_ppp.h    28;"    d
RANLIB    test/makefile    /^export RANLIB=${CROSS_COMPILE}ranlib$/;"    m
REGISTER_INFO    cp_atcmd.h    /^} REGISTER_INFO;$/;"    t    typeref:struct:_REGISTER_INFO
REG_DENIED    cp_gprs.h    /^    REG_DENIED,       \/* registration denied *\/$/;"    e    enum:__anon5
REG_HOMEWORK    cp_gprs.h    /^    REG_HOMEWORK,     \/* registered, home network *\/$/;"    e    enum:__anon5
REG_ROAMING    cp_gprs.h    /^    REG_ROAMING,      \/* registered, roaming *\/$/;"    e    enum:__anon5
REG_SEARCHING    cp_gprs.h    /^    REG_SEARCHING,    \/* not registered, but ME is currently searching a new operator to register to  *\/$/;"    e    enum:__anon5
REG_UNKNOW    cp_gprs.h    /^    REG_UNKNOW,       \/* unknow *\/$/;"    e    enum:__anon5
REG_UNREGIST    cp_gprs.h    /^    REG_UNREGIST = 0, \/* not registered, ME is not currently searching a new operator to register to *\/$/;"    e    enum:__anon5
REQ_EVENT_NONE    cp_gprs.h    /^    REQ_EVENT_NONE = 0,$/;"    e    enum:__anon3
REQ_POWER_OFF    cp_gprs.h    /^    REQ_POWER_OFF,$/;"    e    enum:__anon3
REQ_POWER_ON    cp_gprs.h    /^    REQ_POWER_ON,$/;"    e    enum:__anon3
REQ_POWER_RESET    cp_gprs.h    /^    REQ_POWER_RESET,$/;"    e    enum:__anon3
RESET    cp_hal.h    36;"    d
SELECTED_APN    cp_ppp.h    /^    SELECTED_APN,$/;"    e    enum:__anon2
SERV_ADDR    test/test_sock_client.c    21;"    d    file:
SERV_PORT    test/test_sock_client.c    23;"    d    file:
SERV_PORT1    test/test_sock_server.c    20;"    d    file:
SERV_PORT2    test/test_sock_server.c    21;"    d    file:
SET_ADC_INTERVEL    at91_ioctl.h    45;"    d
SET_DRV_DEBUG    at91_ioctl.h    33;"    d
SIG_WEAK    cp_ppp.h    102;"    d
SOCK_STAT_ACCEPTED    cp_sock.h    90;"    d
SOCK_STAT_ALREADY    cp_sock.h    91;"    d
SOCK_STAT_CONNECTED    cp_sock.h    88;"    d
SOCK_STAT_CONNECTING    cp_sock.h    87;"    d
SOCK_STAT_DISCONNECT    cp_sock.h    92;"    d
SOCK_STAT_INIT    cp_sock.h    86;"    d
SOCK_STAT_LISTENED    cp_sock.h    89;"    d
SRCFILES    test/makefile    /^SRCFILES = $(wildcard *.c)$/;"    m
SRCS    makefile    /^SRCS = $(wildcard ${VPATH}\/*.c)$/;"    m
SRCS    test/makefile    /^SRCS = $(wildcard ${VPATH}\/*.c)$/;"    m
STALIB    makefile    /^STALIB=lib${LIBNAME}.a$/;"    m
START    cp_hal.h    41;"    d
STOP    cp_hal.h    42;"    d
STRIP    test/makefile    /^export STRIP=${CROSS_COMPILE}strip$/;"    m
SWE_TPDU    test/swe_tpdud.h    /^} SWE_TPDU;$/;"    t    typeref:struct:_SWE_TPDU
THREAD_BODY    cp_proc.h    /^typedef void *(THREAD_BODY) (void *thread_arg);$/;"    t
TMP    makefile    /^TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]")$/;"    m
TMP    test/makefile    /^TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]")$/;"    m
TPDUD_PORT    test/swe_tpdud.h    22;"    d
TURN_ALL_LED    at91_ioctl.h    61;"    d
UID_LEN    cp_ppp.h    27;"    d
UPLINK_ADDR    test/swe_tpdud.h    23;"    d
UPLINK_PORT    test/swe_tpdud.h    24;"    d
VPATH    makefile    /^VPATH= .$/;"    m
VPATH    test/makefile    /^VPATH= .$/;"    m
YES    cp_gprs.h    29;"    d
ZIGBEE_RESET    at91_ioctl.h    64;"    d
ZIGBEE_STATUS    at91_ioctl.h    65;"    d
_CP_ARRAY    cp_array.h    /^typedef struct _CP_ARRAY$/;"    s
_CP_COMPORT_H    cp_comport.h    14;"    d
_CP_DICTIONARY_H_    cp_dictionary.h    15;"    d
_CP_FDS    cp_fds.h    /^struct _CP_FDS;$/;"    x
_CP_FDS    cp_fds.h    /^typedef struct _CP_FDS$/;"    s
_CP_FDS    cp_sock.h    /^struct _CP_FDS;$/;"    x
_CP_INIPARSER_H_    cp_iniparser.h    11;"    d
_CP_QNODE    cp_queue.h    /^typedef  struct _CP_QNODE$/;"    s
_CP_QUEUE    cp_queue.h    /^typedef struct _CP_QUEUE$/;"    s
_CP_SOCK    cp_fds.h    /^struct _CP_SOCK;$/;"    x
_CP_SOCK    cp_sock.h    /^struct _CP_SOCK;$/;"    x
_CP_SOCK    cp_sock.h    /^typedef struct _CP_SOCK$/;"    s
_CP_SOCK_CALLBACK    cp_sock.h    /^typedef struct _CP_SOCK_CALLBACK$/;"    s
_CP_STRING_H    cp_string.h    2;"    d
_CP_VECTOR    cp_vector.h    /^typedef struct _CP_VECTOR$/;"    s
_GPRS_LOCATION    cp_atcmd.h    /^typedef struct _GPRS_LOCATION$/;"    s
_HARDWARE_INFO    cp_atcmd.h    /^typedef struct _HARDWARE_INFO$/;"    s
_LINUX_LIST_H    cp_klist.h    15;"    d
_REGISTER_INFO    cp_atcmd.h    /^typedef struct _REGISTER_INFO$/;"    s
_SWE_TPDU    test/swe_tpdud.h    /^typedef struct _SWE_TPDU$/;"    s
__APN_ACCOUNT    cp_ppp.h    /^typedef struct __APN_ACCOUNT$/;"    s
__AT91_IOCTL_H    at91_ioctl.h    15;"    d
__COM_PORT    cp_comport.h    /^typedef struct __COM_PORT$/;"    s
__CP_ARRAY_H    cp_array.h    15;"    d
__CP_ATCMD_H    cp_atcmd.h    15;"    d
__CP_COMMON_H    cp_common.h    15;"    d
__CP_FDS_H    cp_fds.h    15;"    d
__CP_GPRS_H    cp_gprs.h    15;"    d
__CP_GSMMUX_H_    cp_gsmmux.h    16;"    d
__CP_HAL_H    cp_hal.h    14;"    d
__CP_LOG_H    cp_logger.h    15;"    d
__CP_NETWORK_H    cp_network.h    14;"    d
__CP_PROC_H    cp_proc.h    15;"    d
__CP_PROC_SIG    cp_proc.h    /^typedef struct __CP_PROC_SIG$/;"    s
__CP_QUEUE    cp_queue.h    14;"    d
__CP_RINGBUF_H_    cp_ringbuf.h    22;"    d
__CP_SOCK_H    cp_sock.h    14;"    d
__CP_TIME_H    cp_time.h    14;"    d
__CP_VECTOR    cp_vector.h    15;"    d
__DATE_TIME    cp_time.h    /^typedef struct __DATE_TIME$/;"    s
__MODULE_INFO    cp_gprs.h    /^typedef struct __MODULE_INFO$/;"    s
__PPPD_INFO    cp_ppp.h    /^typedef struct __PPPD_INFO$/;"    s
__PPP_CTX    cp_ppp.h    /^typedef struct __PPP_CTX$/;"    s
__PPP_H    cp_ppp.h    14;"    d
__PPP_STAT    cp_ppp.h    /^typedef struct __PPP_STAT$/;"    s
__SWE_TPDUD_H    test/swe_tpdud.h    15;"    d
__hlist_del    cp_klist.h    /^static inline void __hlist_del(struct hlist_node *n)$/;"    f
__list_add    cp_klist.h    /^static inline void __list_add(struct list_head *new,$/;"    f
__list_cut_position    cp_klist.h    /^static inline void __list_cut_position(struct list_head *list,$/;"    f
__list_del    cp_klist.h    /^static inline void __list_del(struct list_head *prev, struct list_head *next)$/;"    f
__list_for_each    cp_klist.h    405;"    d
__list_splice    cp_klist.h    /^static inline void __list_splice(const struct list_head *list,$/;"    f
_cp_logger    cp_logger.h    /^typedef struct _cp_logger$/;"    s
_cp_string    cp_string.h    /^typedef struct _cp_string$/;"    s
_curOffset    cp_logger.c    /^        long _curOffset = ftell(logger->fp);$/;"    l
_dictionary_    cp_dictionary.h    /^typedef struct _dictionary_ {$/;"    s
_line_status_    cp_iniparser.c    /^typedef enum _line_status_ {$/;"    g    file:
_t_free    cp_common.h    /^static inline void _t_free(void *ptr$/;"    f
_t_malloc    cp_common.h    /^static inline void *_t_malloc(size_t size$/;"    f
acBuf    cp_atcmd.c    /^    char                    acBuf [256],$/;"    l
acRecv    cp_atcmd.c    /^    char                 acRecv[1024];$/;"    l
accept_cnt    cp_sock.h    /^    int                      accept_cnt;  \/* current clients number, only listen socket use it*\/$/;"    m    struct:_CP_SOCK
accept_list    cp_sock.h    /^    struct list_head         accept_list; \/* all the accept client list head, only listen socket use it *\/$/;"    m    struct:_CP_SOCK    typeref:struct:_CP_SOCK::list_head
act    cp_logger.c    /^    struct sigaction act;$/;"    l
actv_time    cp_sock.h    /^    unsigned long            actv_time;     \/* The last time get event(send\/recv) data in this socket *\/$/;"    m    struct:_CP_SOCK
adaption    cp_gsmmux.h    /^    unsigned int adaption;$/;"    m    struct:gsm_config
alloc_gsm_dataport    cp_gprs.c    /^COM_PORT *alloc_gsm_dataport(char *who, MODULE_INFO *module)$/;"    f
ap    cp_string.c    /^    va_list     ap;$/;"    l
apn    cp_ppp.h    /^    APN_ACCOUNT        apn;          \/* PPP dial up APN *\/$/;"    m    struct:__PPP_CTX
apn    cp_ppp.h    /^    char            apn[APN_LEN];$/;"    m    struct:__APN_ACCOUNT
arg    cp_hal.c    /^    int         arg = led|(mode<<3);$/;"    l
arg    test/swe_tpdud.c    /^        SWE_TPDU    *arg = dlink->serv_sock->privt;$/;"    l
argp    cp_logger.c    /^    va_list argp;$/;"    l
args    cp_proc.c    /^    va_list             args;$/;"    l
array    test/test_array.c    /^    CP_ARRAY *array = NULL;$/;"    l
at_match    cp_atcmd.c    /^unsigned char at_match (char *p_pcStr, char *p_pcMatch)$/;"    f
atcmd    cp_atcmd.c    /^    char             atcmd[64]={0}; $/;"    l
atcmd    cp_atcmd.c    /^    char             atcmd[64]={0};$/;"    l
atcmd_check_at_ready    cp_atcmd.c    /^int atcmd_check_at_ready(COM_PORT *comport)$/;"    f
atcmd_check_gprs_carrier    cp_atcmd.c    /^int atcmd_check_gprs_carrier(COM_PORT *comport, char *carrier)$/;"    f
atcmd_check_gprs_iemi    cp_atcmd.c    /^int atcmd_check_gprs_iemi(COM_PORT *comport, char *iemi)$/;"    f
atcmd_check_gprs_location    cp_atcmd.c    /^int atcmd_check_gprs_location(COM_PORT *comport, GPRS_LOCATION *loc)$/;"    f
atcmd_check_gprs_mcc_mnc    cp_atcmd.c    /^int atcmd_check_gprs_mcc_mnc(COM_PORT *comport, char *mcc_mnc)$/;"    f
atcmd_check_gprs_name    cp_atcmd.c    /^int atcmd_check_gprs_name(COM_PORT *comport, char *name)$/;"    f
atcmd_check_gprs_network    cp_atcmd.c    /^int atcmd_check_gprs_network(COM_PORT *comport, int *network)$/;"    f
atcmd_check_gprs_register    cp_atcmd.c    /^int atcmd_check_gprs_register(COM_PORT *comport)$/;"    f
atcmd_check_gprs_signal    cp_atcmd.c    /^int atcmd_check_gprs_signal(COM_PORT *comport)$/;"    f
atcmd_check_gprs_version    cp_atcmd.c    /^int atcmd_check_gprs_version(COM_PORT *comport, char *version)$/;"    f
atcmd_check_hwinfo    cp_gprs.c    /^int atcmd_check_hwinfo(COM_PORT *comport, HW_INFO *hw, int times)$/;"    f
atcmd_check_module_ready    cp_gprs.c    /^int atcmd_check_module_ready(COM_PORT *comport, int times)$/;"    f
atcmd_check_network_info    cp_gprs.c    /^int atcmd_check_network_info(COM_PORT *comport, REGISTER_INFO *reg)$/;"    f
atcmd_check_power_on    cp_gprs.c    /^int atcmd_check_power_on(COM_PORT *comport)$/;"    f
atcmd_check_ready    cp_gprs.c    /^int atcmd_check_ready(MODULE_INFO *module)$/;"    f
atcmd_check_regist    cp_gprs.c    /^int atcmd_check_regist(COM_PORT *comport, REGISTER_INFO *reg, int times)$/;"    f
atcmd_check_sim_valid    cp_atcmd.c    /^int atcmd_check_sim_valid(COM_PORT *comport)$/;"    f
atcmd_inspect_status    cp_gprs.c    /^int atcmd_inspect_status(MODULE_INFO *module)$/;"    f
atcmd_module_preset    cp_gprs.c    /^int atcmd_module_preset(COM_PORT *comport)$/;"    f
atcmd_set_apn    cp_atcmd.c    /^int atcmd_set_apn(COM_PORT *comport, char *apn)$/;"    f
atcmd_set_network_mode    cp_atcmd.c    /^int atcmd_set_network_mode(COM_PORT *comport, int mode)$/;"    f
attach_gsm0710    cp_gsmmux.c    /^int attach_gsm0710(COM_PORT *comport)$/;"    f
auth    cp_ppp.h    /^    char            auth[10];  \/*  PAP or CHAP *\/$/;"    m    struct:__APN_ACCOUNT
baudrate    cp_comport.h    /^    long baudrate;$/;"    m    struct:__COM_PORT
baudrate    test/comport.c    /^    int baudrate = 115200;$/;"    l
buf    cp_logger.c    /^    char buf[MAX_LOG_MESSAGE_LEN];$/;"    l
buf    cp_network.c    /^    char                 buf[512];$/;"    l
buf    cp_ppp.c    /^    char                buf[512];$/;"    l
buf    cp_ppp.c    /^    char          buf[512];$/;"    l
buf    cp_ppp.c    /^    char       buf[10];$/;"    l
buf    cp_string.c    /^    char buf[CHUNK];$/;"    l
buf    test/comport.c    /^    char buf[512];$/;"    l
buf    test/test_logger.c    /^    char    buf[30]="Hello World!\\n";$/;"    l
buffer    cp_ringbuf.h    /^    u_char *buffer;$/;"    m    struct:ring_buffer
c    cp_gsmmux.c    /^    struct gsm_config      c;$/;"    l
c    cp_iniparser.c    /^    char    *   c ;$/;"    l
c    cp_logger.c    /^            unsigned char c = buf[idx];$/;"    l
c    cp_string.c    /^            unsigned char c = data[idx];$/;"    l
c    cp_string.c    /^            unsigned char c = str->data[idx];$/;"    l
cSleep    cp_time.h    /^    struct timespec cSleep;$/;"    l
carrier    cp_atcmd.h    /^    char            carrier[64];\/*  Network operator *\/$/;"    m    struct:_REGISTER_INFO
cbfunc    cp_sock.h    /^    CP_SOCK_EVENT_CALLBACK   cbfunc;      \/* event callback function *\/$/;"    m    struct:_CP_SOCK
ch    cp_string.c    /^        char *i, *f, ch;$/;"    l
check_and_rollback    cp_logger.c    /^static void check_and_rollback(void)$/;"    f    file:
check_daemon_running    cp_proc.c    /^int check_daemon_running(const char *pid_file)$/;"    f
check_ppp_interface    cp_ppp.c    /^int check_ppp_interface(char *ppp_dev)$/;"    f
check_ppp_ipaddr    cp_ppp.c    /^int check_ppp_ipaddr(PPPD_INFO  *pppd_info, char *ppp_dev)$/;"    f
check_ppp_stat    cp_ppp.c    /^int check_ppp_stat(PPP_STAT  *ppp_stat, char *ppp_dev)$/;"    f
check_pppd_pid    cp_ppp.c    /^int check_pppd_pid(char *find_key)$/;"    f
clen    cp_string.c    /^    int clen = strlen(cstr);$/;"    l
client_func    cp_sock.h    /^    CP_SOCK_EVENT_CALLBACK   client_func; \/* client data callback function, only server socket use it *\/$/;"    m    struct:_CP_SOCK
client_list    cp_fds.h    /^    struct list_head      client_list;  \/* a list keep all the connect sockets *\/ $/;"    m    struct:_CP_FDS    typeref:struct:_CP_FDS::list_head
close_gsm_dataport    cp_gprs.c    /^void close_gsm_dataport(MODULE_INFO *module)$/;"    f
cmd    cp_logger.c    /^            char cmd[512];$/;"    l
cmd    cp_network.c    /^    char                 cmd[256];$/;"    l
cmd    cp_ppp.c    /^    char       cmd[128];$/;"    l
cmd    cp_proc.c    /^    char                cmd[256];$/;"    l
comport    cp_comport.c    /^    COM_PORT *comport = NULL;$/;"    l
comport    cp_gprs.c    /^    COM_PORT        *comport;$/;"    l
comport    cp_gprs.c    /^    COM_PORT       *comport = NULL;$/;"    l
comport    cp_gprs.h    /^    COM_PORT        *comport[MAX_DATAPORT]; \/* CMUX driver generate CMUX port *\/$/;"    m    struct:__MODULE_INFO
comport    cp_ppp.h    /^    COM_PORT           *comport;$/;"    m    struct:__PPP_CTX
comport    test/comport.c    /^    COM_PORT *comport = NULL;$/;"    l
comport    test/test_hh.c    /^    COM_PORT        *comport = NULL;$/;"    l
comport_close    cp_comport.c    /^void comport_close(COM_PORT * comport)$/;"    f
comport_cnt    cp_gprs.h    /^    int             comport_cnt; \/* GPRS data channel count *\/$/;"    m    struct:__MODULE_INFO
comport_init    cp_comport.c    /^COM_PORT *comport_init(const char *dev_name, int baudrate, const char *settings)$/;"    f
comport_open    cp_comport.c    /^int comport_open(COM_PORT * comport)$/;"    f
comport_recv    cp_comport.c    /^int comport_recv(COM_PORT * comport, char *buf, int buf_size, unsigned long timeout)$/;"    f
comport_send    cp_comport.c    /^int comport_send(COM_PORT * comport, char *buf, int send_bytes)$/;"    f
comport_term    cp_comport.c    /^void comport_term(COM_PORT * comport)$/;"    f
container_of    cp_common.h    25;"    d
container_of    cp_klist.h    29;"    d
cp_add_epoll_event    cp_fds.c    /^int cp_add_epoll_event(CP_SOCK *sock)$/;"    f
cp_array_add    cp_array.c    /^int cp_array_add(CP_ARRAY *array, void *data)$/;"    f
cp_array_count    cp_array.h    28;"    d
cp_array_init    cp_array.c    /^CP_ARRAY *cp_array_init(CP_ARRAY *array, int size)$/;"    f
cp_array_is_empty    cp_array.h    27;"    d
cp_array_is_full    cp_array.h    26;"    d
cp_array_rm_bydata    cp_array.c    /^int cp_array_rm_bydata(CP_ARRAY *array, void *data)$/;"    f
cp_array_rm_byindex    cp_array.c    /^void cp_array_rm_byindex(CP_ARRAY *array, int index)$/;"    f
cp_array_size    cp_array.h    29;"    d
cp_array_term    cp_array.c    /^void cp_array_term(CP_ARRAY *array)$/;"    f
cp_array_travel    cp_array.c    /^void cp_array_travel(CP_ARRAY *array)$/;"    f
cp_cstring_dump    cp_string.c    /^void cp_cstring_dump(char *data, int len)$/;"    f
cp_del_epoll_event    cp_fds.c    /^void cp_del_epoll_event(CP_SOCK *sock)$/;"    f
cp_dequeue    cp_queue.c    /^void *cp_dequeue(CP_QUEUE *queue)$/;"    f
cp_enqueue    cp_queue.c    /^void *cp_enqueue(CP_QUEUE *queue, void *data)$/;"    f
cp_fds_add_sock_registry    cp_fds.c    /^int cp_fds_add_sock_registry(CP_SOCK *sock)$/;"    f
cp_fds_add_sock_task    cp_fds.c    /^int cp_fds_add_sock_task(CP_SOCK *sock)$/;"    f
cp_fds_del_sock_registry    cp_fds.c    /^void cp_fds_del_sock_registry(CP_SOCK *sock)$/;"    f
cp_fds_del_sock_task    cp_fds.c    /^void cp_fds_del_sock_task(CP_SOCK *sock)$/;"    f
cp_fds_destroy_sock    cp_fds.c    /^void cp_fds_destroy_sock(CP_SOCK *sock)$/;"    f
cp_fds_destroy_sock_clear    cp_fds.h    99;"    d
cp_fds_detect_event    cp_fds.c    /^int cp_fds_detect_event(CP_FDS *fds)$/;"    f
cp_fds_init    cp_fds.c    /^CP_FDS *cp_fds_init(CP_FDS *fds, int maxevents, int timeout)$/;"    f
cp_fds_list_sock_task    cp_fds.c    /^void cp_fds_list_sock_task(CP_FDS *fds)$/;"    f
cp_fds_proc_event    cp_fds.c    /^void cp_fds_proc_event(CP_FDS *fds)$/;"    f
cp_fds_setrlimit    cp_fds.c    /^int cp_fds_setrlimit(int maxfd)$/;"    f
cp_fds_sock_dequeue    cp_fds.c    /^void *cp_fds_sock_dequeue(CP_FDS *fds)$/;"    f
cp_fds_sock_enqueue    cp_fds.c    /^void *cp_fds_sock_enqueue(CP_SOCK *sock)$/;"    f
cp_fds_sock_rmqueue    cp_fds.c    /^void *cp_fds_sock_rmqueue(CP_SOCK *sock)$/;"    f
cp_fds_term    cp_fds.c    /^void cp_fds_term(CP_FDS *fds)$/;"    f
cp_fds_term_clear    cp_fds.h    71;"    d
cp_hexdump_string    cp_string.c    /^const char *cp_hexdump_string(const void *data, size_t len)$/;"    f
cp_install_proc_signal    cp_proc.c    /^void cp_install_proc_signal(void)$/;"    f
cp_list_array_for_each    cp_array.c    /^    cp_list_array_for_each(array, i, data)$/;"    f
cp_list_array_for_each    cp_array.c    /^    cp_list_array_for_each(array, i, entry)$/;"    f
cp_list_array_for_each    cp_array.h    31;"    d
cp_list_array_for_each    test/test_array.c    /^    cp_list_array_for_each(array, i, sock)$/;"    f
cp_log    cp_logger.c    /^void cp_log(int level, char *fmt, ...)$/;"    f
cp_log_close    cp_logger.c    /^void cp_log_close(void)$/;"    f
cp_log_default_signal_handler    cp_logger.c    /^static void cp_log_default_signal_handler(int sig)$/;"    f    file:
cp_log_dump    cp_logger.c    /^void cp_log_dump(int level, char *buf, int len)$/;"    f
cp_log_init    cp_logger.c    /^cp_logger *cp_log_init(cp_logger *log, char *filename, int level, int log_size)$/;"    f
cp_log_line    cp_logger.c    /^void cp_log_line(int level, char *file, int line, char *fmt, ...)$/;"    f
cp_log_open    cp_logger.c    /^int cp_log_open(void)$/;"    f
cp_log_raw    cp_logger.c    /^void cp_log_raw(const char *fmt, ...)$/;"    f
cp_log_reopen    cp_logger.c    /^int cp_log_reopen(void)$/;"    f
cp_log_set_time_format    cp_logger.c    /^void cp_log_set_time_format(char *time_format)$/;"    f
cp_log_term    cp_logger.c    /^void cp_log_term(void)$/;"    f
cp_logger    cp_logger.h    /^} cp_logger;$/;"    t    typeref:struct:_cp_logger
cp_mod_epoll_event    cp_fds.c    /^int cp_mod_epoll_event(CP_SOCK *sock, int event)$/;"    f
cp_printout    cp_logger.c    /^static void cp_printout(char *level, char *fmt, va_list argp)$/;"    f    file:
cp_printout_line    cp_logger.c    /^static void cp_printout_line(char *level, char *fmt, char *file, int line, va_list argp)$/;"    f    file:
cp_proc_sighandler    cp_proc.c    /^void cp_proc_sighandler(int sig)$/;"    f
cp_queue_count    cp_queue.h    38;"    d
cp_queue_destroy    cp_queue.c    /^void cp_queue_destroy(CP_QUEUE *queue)$/;"    f
cp_queue_destroy_clear    cp_queue.h    47;"    d
cp_queue_init    cp_queue.c    /^CP_QUEUE *cp_queue_init(CP_QUEUE *queue, int size)$/;"    f
cp_queue_is_empty    cp_queue.h    37;"    d
cp_queue_is_full    cp_queue.h    36;"    d
cp_queue_size    cp_queue.h    39;"    d
cp_rmqueue    cp_queue.c    /^void *cp_rmqueue(CP_QUEUE *queue, void *data)$/;"    f
cp_sock_accept    cp_sock.c    /^int cp_sock_accept(CP_SOCK *serv_sock, CP_SOCK *new_sock)$/;"    f
cp_sock_accept_regist    cp_network.c    /^int cp_sock_accept_regist(CP_SOCK *serv_sock)$/;"    f
cp_sock_close    cp_sock.c    /^int cp_sock_close(CP_SOCK *sock)$/;"    f
cp_sock_connect    cp_sock.c    /^int cp_sock_connect(CP_SOCK *sock, char *raddr, int rport, int lport)$/;"    f
cp_sock_connect_regist    cp_network.c    /^CP_SOCK *cp_sock_connect_regist(CP_FDS *fds, CP_SOCK *sock, char *raddr, int rport, int lport, CP_SOCK_EVENT_CALLBACK service_route)$/;"    f
cp_sock_detect_timeout    cp_fds.c    /^void cp_sock_detect_timeout(CP_FDS *fds)$/;"    f
cp_sock_init    cp_sock.c    /^CP_SOCK *cp_sock_init(CP_SOCK *sock, unsigned int rsize, unsigned int ssize, int keepintvl, int keepcnt)$/;"    f
cp_sock_listen    cp_sock.c    /^int cp_sock_listen(CP_SOCK *sock, char *laddr, int lport, int backlog)$/;"    f
cp_sock_recv    cp_sock.c    /^int cp_sock_recv(CP_SOCK *sock)$/;"    f
cp_sock_send    cp_sock.c    /^int cp_sock_send(CP_SOCK *sock)$/;"    f
cp_sock_server_regist    cp_network.c    /^CP_SOCK *cp_sock_server_regist(CP_FDS *fds, char *addr, int port, int max_client, CP_SOCK_EVENT_CALLBACK service_route, void *data)$/;"    f
cp_sock_set_buffer    cp_sock.c    /^int cp_sock_set_buffer(int sockfd, int rsize, int ssize)$/;"    f
cp_sock_set_idle_timeout    cp_sock.h    /^static void inline cp_sock_set_idle_timeout(CP_SOCK *sock, unsigned long timeout)$/;"    f
cp_sock_set_keepalive    cp_sock.c    /^int cp_sock_set_keepalive(int sockfd, int keepintvl, int keepcnt)$/;"    f
cp_sock_set_msg_timeout    cp_sock.h    /^static void inline cp_sock_set_msg_timeout(CP_SOCK *sock, unsigned long timeout)$/;"    f
cp_sock_set_nonblock    cp_sock.c    /^int cp_sock_set_nonblock(int sockfd)$/;"    f
cp_sock_set_private_data    cp_sock.h    /^static void inline cp_sock_set_private_data(CP_SOCK *sock, void *data, PRIVT_FREE free)$/;"    f
cp_sock_set_reuseaddr    cp_sock.c    /^int cp_sock_set_reuseaddr(int sockfd)$/;"    f
cp_sock_term    cp_sock.c    /^void cp_sock_term(CP_SOCK *sock)$/;"    f
cp_sock_term_all_client    cp_fds.c    /^void cp_sock_term_all_client(CP_FDS *fds)$/;"    f
cp_sock_term_all_server    cp_fds.c    /^void cp_sock_term_all_server(CP_FDS *fds)$/;"    f
cp_sock_term_all_service    cp_network.c    /^void cp_sock_term_all_service(CP_FDS *fds)$/;"    f
cp_sock_term_all_service_clear    cp_network.h    34;"    d
cp_sock_term_all_task    cp_fds.c    /^void cp_sock_term_all_task(CP_FDS *fds)$/;"    f
cp_sock_term_clear    cp_sock.h    170;"    d
cp_sock_term_server    cp_fds.c    /^void cp_sock_term_server(CP_SOCK *serv_sock)$/;"    f
cp_string    cp_string.h    /^} cp_string;$/;"    t    typeref:struct:_cp_string
cp_string_append_char    cp_string.c    /^cp_string *cp_string_append_char(cp_string *str, char ch)$/;"    f
cp_string_cat    cp_string.c    /^cp_string *cp_string_cat(cp_string *str, cp_string *appendum)$/;"    f
cp_string_cat_bin    cp_string.c    /^cp_string *cp_string_cat_bin(cp_string *str, void *bin, int len)$/;"    f
cp_string_clear_data    cp_string.c    /^void cp_string_clear_data(cp_string *str)$/;"    f
cp_string_cmp    cp_string.c    /^int cp_string_cmp(cp_string *s1, cp_string *s2)$/;"    f
cp_string_copy    cp_string.c    /^int cp_string_copy(cp_string *dst, cp_string *src)$/;"    f
cp_string_create    cp_string.c    /^cp_string *cp_string_create(char *data, int len)$/;"    f
cp_string_create_empty    cp_string.c    /^cp_string *cp_string_create_empty(int initial_size)$/;"    f
cp_string_cstrcat    cp_string.c    /^cp_string *cp_string_cstrcat(cp_string *str, char *cstr)$/;"    f
cp_string_cstrcopy    cp_string.c    /^int cp_string_cstrcopy(cp_string *dst, char *string, int len)$/;"    f
cp_string_cstrcpy    cp_string.c    /^cp_string *cp_string_cstrcpy(cp_string *str, char *cstr)$/;"    f
cp_string_cstrdup    cp_string.c    /^cp_string *cp_string_cstrdup(char *src)$/;"    f
cp_string_data    cp_string.c    /^char *cp_string_data(cp_string *s)$/;"    f
cp_string_destroy    cp_string.c    /^void cp_string_destroy(cp_string *str)$/;"    f
cp_string_dump    cp_string.c    /^void cp_string_dump(cp_string *str)$/;"    f
cp_string_dup    cp_string.c    /^cp_string *cp_string_dup(cp_string *src)$/;"    f
cp_string_filter    cp_string.c    /^cp_string *cp_string_filter(cp_string *str, char *letters)$/;"    f
cp_string_flip    cp_string.c    /^void cp_string_flip(cp_string *str)$/;"    f
cp_string_len    cp_string.c    /^int cp_string_len(cp_string *s)$/;"    f
cp_string_move    cp_string.c    /^int cp_string_move(cp_string *dst, cp_string *src)$/;"    f
cp_string_read    cp_string.c    /^cp_string *cp_string_read(int fd, int len)$/;"    f
cp_string_read_file    cp_string.c    /^cp_string *cp_string_read_file(char *filename)$/;"    f
cp_string_tocstr    cp_string.c    /^char *cp_string_tocstr(cp_string *str)$/;"    f
cp_string_write    cp_string.c    /^int cp_string_write(cp_string *str, int fd)$/;"    f
cp_string_write_file    cp_string.c    /^int cp_string_write_file(cp_string *str, char *filename)$/;"    f
cp_time_format    cp_logger.c    /^static char *cp_time_format = DEFAULT_TIME_FORMAT;$/;"    v    file:
cp_travel_queue    cp_queue.c    /^void cp_travel_queue(CP_QUEUE *queue)$/;"    f
cp_vector_add    cp_vector.c    /^void *cp_vector_add(CP_VECTOR *vector, int index, void *item)$/;"    f
cp_vector_count    cp_vector.h    29;"    d
cp_vector_del    cp_vector.c    /^void *cp_vector_del(CP_VECTOR *vector, int index)$/;"    f
cp_vector_destroy    cp_vector.c    /^void cp_vector_destroy(CP_VECTOR *vector)$/;"    f
cp_vector_get    cp_vector.c    /^void *cp_vector_get(CP_VECTOR *vector, int index)$/;"    f
cp_vector_init    cp_vector.c    /^CP_VECTOR *cp_vector_init(int size)$/;"    f
cp_vector_size    cp_vector.h    30;"    d
cstr    cp_string.c    /^    char *cstr = NULL;$/;"    l
ctrl_thread_start    cp_gprs.c    /^void ctrl_thread_start(void *thread_arg)$/;"    f
ctrl_thread_term    cp_gprs.c    /^void ctrl_thread_term(void *thread_arg)$/;"    f
current    cp_time.h    /^    unsigned long current = time_now(); $/;"    l
cval    cp_dictionary.c    /^    char        cval[90] ;$/;"    l
d    cp_dictionary.c    /^    dictionary  *   d ;$/;"    l
d    cp_string.c    /^    unsigned char *d = (unsigned char *)data; $/;"    l
daemonize    cp_proc.c    /^void daemonize(int nochdir, int noclose)$/;"    f
data    cp_array.c    /^    void             *data;$/;"    l
data    cp_array.h    /^    void                   **data;$/;"    m    struct:_CP_ARRAY
data    cp_string.h    /^    char *data;  \/**< internal buffer  *\/$/;"    m    struct:_cp_string
databit    cp_comport.h    /^    unsigned char databit, parity, stopbit, flowctrl, is_connted;$/;"    m    struct:__COM_PORT
date    cp_atcmd.h    /^    char            date[15];$/;"    m    struct:_GPRS_LOCATION
del_char_from_string    cp_string.c    /^char *del_char_from_string(char *str, char delchar)$/;"    f
delay    cp_atcmd.c    /^    unsigned long        delay = 200;$/;"    l
delim    cp_string.c    /^    char        delim[2]={*(fmt+2), '\\0'};$/;"    l
dev    cp_ppp.h    /^    char               dev[10];      \/* PPP dial up device name, such as PPP10  *\/$/;"    m    struct:__PPP_CTX
dev_name    cp_comport.h    /^    char dev_name[DEVNAME_LEN];$/;"    m    struct:__COM_PORT
dev_name    test/comport.c    /^    char *dev_name = NULL;$/;"    l
devname    cp_gprs.c    /^    char                  devname[DEVNAME_LEN];$/;"    l
dict    cp_iniparser.c    /^    dictionary * dict ;$/;"    l
dictionary    cp_dictionary.h    /^} dictionary ;$/;"    t    typeref:struct:_dictionary_
dictionary_del    cp_dictionary.c    /^void dictionary_del(dictionary * d)$/;"    f
dictionary_dump    cp_dictionary.c    /^void dictionary_dump(dictionary * d, FILE * out)$/;"    f
dictionary_get    cp_dictionary.c    /^char * dictionary_get(dictionary * d, const char * key, char * def)$/;"    f
dictionary_hash    cp_dictionary.c    /^unsigned dictionary_hash(const char * key)$/;"    f
dictionary_new    cp_dictionary.c    /^dictionary * dictionary_new(int size)$/;"    f
dictionary_set    cp_dictionary.c    /^int dictionary_set(dictionary * d, const char * key, const char * val)$/;"    f
dictionary_unset    cp_dictionary.c    /^void dictionary_unset(dictionary * d, const char * key)$/;"    f
disp_mode    test/comport.c    /^    unsigned char disp_mode = 0x00;$/;"    l
disp_settings    cp_comport.c    /^void disp_settings(COM_PORT * comport)$/;"    f
dlink    test/swe_tpdud.c    /^    CP_SOCK       *dlink = NULL;$/;"    l
dlink    test/swe_tpdud.c    /^    CP_SOCK       *dlink;  $/;"    l
dlink    test/swe_tpdud.h    /^    CP_SOCK             *dlink;    \/* listen port accept socket *\/$/;"    m    struct:_SWE_TPDU
do_ioctl    test/comport.c    /^int do_ioctl(char *dev_name, int cmd, int arg)$/;"    f
done    cp_proc.c    /^    int                 done; $/;"    l
dose    cp_hal.c    /^    int         dose = 0;$/;"    l
enable    cp_ppp.h    /^    unsigned char      enable;       \/* Enable PPP thread running or not, RFU *\/$/;"    m    struct:__PPP_CTX
encapsulation    cp_gsmmux.h    /^    unsigned int encapsulation;$/;"    m    struct:gsm_config
end    cp_comport.c    /^    char *ptr, *end;$/;"    l
end    cp_string.c    /^    char *end = str;$/;"    l
entry    cp_array.c    /^    void             *entry;$/;"    l
epfd    cp_fds.h    /^    int                   epfd;         \/* the epoll_create() returns file description *\/ $/;"    m    struct:_CP_FDS
error    cp_sock.h    /^    CP_SOCK_EVENT_CALLBACK  error;$/;"    m    struct:_CP_SOCK_CALLBACK
errs    cp_iniparser.c    /^    int  errs=0;$/;"    l
event    cp_gprs.h    /^    unsigned char   event;     \/* Request to set GPRS power REQ_POWER_ON, REQ_POWER_OFF or REQ_POWER_RESET *\/$/;"    m    struct:__MODULE_INFO
event    cp_sock.h    /^    struct epoll_event       event;       \/* epoll_wait returned event *\/$/;"    m    struct:_CP_SOCK    typeref:struct:_CP_SOCK::epoll_event
event_cnt    cp_fds.h    /^    int                   event_cnt;    \/* current socket regist in epoll *\/$/;"    m    struct:_CP_FDS
event_queue    cp_fds.h    /^    CP_QUEUE              *event_queue; \/* a queue keep all these sockets get event happened *\/$/;"    m    struct:_CP_FDS
evts    cp_fds.c    /^    struct epoll_event    evts[CP_MAX_EVENT_ONCE];$/;"    l
exec_system_cmd    cp_proc.c    /^void exec_system_cmd(const char *format, ...)$/;"    f
f    cp_proc.c    /^    FILE *f; $/;"    l
f    cp_string.c    /^        char *i, *f, ch;$/;"    l
f    cp_string.c    /^    char *f;$/;"    l
fStatBuf    cp_proc.c    /^    struct stat fStatBuf; $/;"    l
fStatBuf    cp_proc.c    /^    struct stat fStatBuf;$/;"    l
fail_cnt    cp_gprs.c    /^    static int    fail_cnt = 0;$/;"    l    file:
fail_cnt    cp_ppp.h    /^    unsigned char      fail_cnt;     \/* PPP failure count *\/$/;"    m    struct:__PPP_CTX
fd    cp_comport.h    /^    int fd;$/;"    m    struct:__COM_PORT
fd    cp_hal.c    /^    int         fd = -1;$/;"    l
fd    cp_network.c    /^    int                   fd;           $/;"    l
fd    cp_ppp.c    /^    int                   fd;$/;"    l
fd    cp_ppp.c    /^    int           fd = -1;$/;"    l
fd    cp_proc.c    /^    int fd = -1; $/;"    l
fd    cp_proc.c    /^    int retval, fd; $/;"    l
fd    cp_sock.c    /^    int                      fd = -1;$/;"    l
fd    cp_sock.c    /^    int                 fd = -1;$/;"    l
fd    cp_sock.h    /^    int                      fd;          \/* the socket file description *\/$/;"    m    struct:_CP_SOCK
fd    cp_time.h    /^    int                 rv, fd = -1;$/;"    l
fd    test/comport.c    /^    int fd = -1;$/;"    l
fds    cp_comport.c    /^    fd_set fds;$/;"    l
fds    cp_fds.c    /^    CP_FDS                  *fds;$/;"    l
fds    cp_sock.h    /^    struct _CP_FDS           *fds;        \/* epoll fds contex *\/$/;"    m    struct:_CP_SOCK    typeref:struct:_CP_SOCK::_CP_FDS
fds    test/swe_tpdud.c    /^    CP_FDS         *fds;$/;"    l
fds    test/test_sock_client.c    /^    CP_FDS     *fds;$/;"    l
fds    test/test_sock_server.c    /^    CP_FDS     *fds;$/;"    l
file    cp_logger.h    /^    char               file[FILENAME_LEN];$/;"    m    struct:_cp_logger
file    test/test_logger.c    /^    char    file[FILENAME_LEN];$/;"    l
filemode    cp_logger.c    /^    char *filemode;$/;"    l
first    cp_klist.h    /^    struct hlist_node *first = h->first;$/;"    l
first    cp_klist.h    /^    struct hlist_node *first;$/;"    m    struct:hlist_head    typeref:struct:hlist_head::hlist_node
first    cp_klist.h    /^    struct list_head *first = list->next;$/;"    l
flag    cp_array.h    /^    unsigned char          flag;$/;"    m    struct:_CP_ARRAY
flag    cp_fds.h    /^    unsigned char         flag;         \/* Refer to follow definition  *\/$/;"    m    struct:_CP_FDS
flag    cp_logger.h    /^    unsigned char      flag;  \/* This logger pointer is malloc() or passed by argument *\/$/;"    m    struct:_cp_logger
flag    cp_sock.c    /^    int               flag;$/;"    l
flag    cp_sock.h    /^    unsigned short           flag;        \/* Refer to the follow definition  *\/$/;"    m    struct:_CP_SOCK
flag    test/swe_tpdud.h    /^    unsigned char       flag;$/;"    m    struct:_SWE_TPDU
flowctrl    cp_comport.h    /^    unsigned char databit, parity, stopbit, flowctrl, is_connted;$/;"    m    struct:__COM_PORT
force    cp_sock.c    /^    int        force = 0;$/;"    l
found    cp_iniparser.c    /^    int found=0 ;$/;"    l
foundsec    cp_iniparser.c    /^    int foundsec ;$/;"    l
fp    cp_logger.h    /^    FILE               *fp;$/;"    m    struct:_cp_logger
fp    cp_network.c    /^    FILE                 *fp;$/;"    l
fp    cp_ppp.c    /^    FILE                *fp;$/;"    l
fp    cp_ppp.c    /^    FILE       *fp = NULL;$/;"    l
fp    cp_string.c    /^    FILE *fp = fopen(filename, "rb");$/;"    l
fp    cp_string.c    /^    FILE *fp = fopen(filename, "wb");$/;"    l
fp    test/test_ini.c    /^    FILE         *fp;$/;"    l
frag_size    cp_comport.h    /^    int frag_size;$/;"    m    struct:__COM_PORT
free_gsm_dataport    cp_gprs.c    /^void free_gsm_dataport(char *who, MODULE_INFO *module, COM_PORT  **comport)$/;"    f
front    cp_queue.h    /^    CP_QNODE           *front;$/;"    m    struct:_CP_QUEUE
g_cp_signal    cp_proc.c    /^CP_PROC_SIG     g_cp_signal={0};$/;"    v
g_cp_signal    cp_proc.h    /^extern CP_PROC_SIG     g_cp_signal;$/;"    x
g_ucCtrlZ    test/comport.c    /^unsigned char g_ucCtrlZ;$/;"    v
g_ucProcToken    test/comport.c    /^unsigned char g_ucProcToken = 0x01;$/;"    v
gap    cp_atcmd.c    /^    unsigned long        gap = 300;$/;"    l
get_apn_conf    cp_ppp.c    /^int get_apn_conf(char *ini_name, char *ini_key, APN_ACCOUNT *apn, unsigned char type)$/;"    f
get_current_time    cp_time.h    /^static inline void get_current_time(DATE_TIME * date)$/;"    f
get_daemon_pid    cp_proc.c    /^pid_t get_daemon_pid(const char *pid_file)$/;"    f
get_rtc_time    cp_time.h    /^static inline int get_rtc_time(DATE_TIME *date)$/;"    f
get_sys_time    cp_time.h    94;"    d
gsm_config    cp_gsmmux.h    /^struct gsm_config$/;"    s
gsmport    cp_gprs.h    /^    COM_PORT        *gsmport;  \/* The GSM hardware UART port  *\/$/;"    m    struct:__MODULE_INFO
hal_get_gmtube_dose    cp_hal.c    /^int hal_get_gmtube_dose(void)$/;"    f
hal_get_gprs_power    cp_hal.c    /^int hal_get_gprs_power(void)$/;"    f
hal_get_gps_power    cp_hal.c    /^int hal_get_gps_power(void)$/;"    f
hal_get_zigbee_status    cp_hal.c    /^int hal_get_zigbee_status(void)$/;"    f
hal_reset_zigbee    cp_hal.c    /^int hal_reset_zigbee(void)$/;"    f
hal_set_gmtube    cp_hal.c    /^int hal_set_gmtube(status)$/;"    f
hal_turn_gprs_power    cp_hal.c    /^int hal_turn_gprs_power(int status)$/;"    f
hal_turn_gps_power    cp_hal.c    /^int hal_turn_gps_power(int status)$/;"    f
hal_turn_led_blink    cp_hal.c    /^int hal_turn_led_blink(int led, int mode)$/;"    f
hal_turn_led_off    cp_hal.c    /^int hal_turn_led_off(int led)$/;"    f
hal_turn_led_on    cp_hal.c    /^int hal_turn_led_on(int  led)$/;"    f
hash    cp_dictionary.c    /^    unsigned    hash ;$/;"    l
hash    cp_dictionary.h    /^    unsigned     *  hash ;  \/** List of hash values for keys *\/$/;"    m    struct:_dictionary_
hc    cp_logger.c    /^    char hc[4];$/;"    l
hc    cp_string.c    /^    char hc[4];$/;"    l
hints    cp_sock.c    /^    struct addrinfo     hints, *rp;$/;"    l
hlist_add_after    cp_klist.h    /^static inline void hlist_add_after(struct hlist_node *n,$/;"    f
hlist_add_before    cp_klist.h    /^static inline void hlist_add_before(struct hlist_node *n,$/;"    f
hlist_add_head    cp_klist.h    /^static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)$/;"    f
hlist_del    cp_klist.h    /^static inline void hlist_del(struct hlist_node *n)$/;"    f
hlist_del_init    cp_klist.h    /^static inline void hlist_del_init(struct hlist_node *n)$/;"    f
hlist_empty    cp_klist.h    /^static inline int hlist_empty(const struct hlist_head *h)$/;"    f
hlist_entry    cp_klist.h    660;"    d
hlist_for_each    cp_klist.h    662;"    d
hlist_for_each_entry    cp_klist.h    677;"    d
hlist_for_each_entry_continue    cp_klist.h    689;"    d
hlist_for_each_entry_from    cp_klist.h    701;"    d
hlist_for_each_entry_safe    cp_klist.h    714;"    d
hlist_for_each_safe    cp_klist.h    666;"    d
hlist_head    cp_klist.h    /^struct hlist_head {$/;"    s
hlist_node    cp_klist.h    /^struct hlist_node {$/;"    s
hlist_unhashed    cp_klist.h    /^static inline int hlist_unhashed(const struct hlist_node *h)$/;"    f
hw    cp_gprs.h    /^    HW_INFO         hw;        \/* GPRS Hardware information *\/$/;"    m    struct:__MODULE_INFO
i    cp_array.c    /^    int              i, rv = -3;$/;"    l
i    cp_array.c    /^    int              i;$/;"    l
i    cp_array.c    /^    int        i;$/;"    l
i    cp_atcmd.c    /^        int i = 0;$/;"    l
i    cp_atcmd.c    /^    int         i = 0;$/;"    l
i    cp_dictionary.c    /^    int         i ;$/;"    l
i    cp_dictionary.c    /^    int     i ;$/;"    l
i    cp_fds.c    /^    int                    i;$/;"    l
i    cp_fds.c    /^    int                   i=0, nfds=0;$/;"    l
i    cp_fds.c    /^    int               i;$/;"    l
i    cp_gprs.c    /^    int                   i=0;$/;"    l
i    cp_gprs.c    /^    int                i=0;$/;"    l
i    cp_gprs.c    /^    int            i;$/;"    l
i    cp_gprs.c    /^    int           i, rv = 0;$/;"    l
i    cp_gprs.c    /^    int  i;$/;"    l
i    cp_gprs.c    /^    int i, retval = -1;$/;"    l
i    cp_gsmmux.h    /^    unsigned int i;$/;"    m    struct:gsm_config
i    cp_iniparser.c    /^    int     i ;$/;"    l
i    cp_iniparser.c    /^    int i ;$/;"    l
i    cp_iniparser.c    /^    int i, j ;$/;"    l
i    cp_proc.c    /^    int i; $/;"    l
i    cp_ringbuf.c    /^    int i;$/;"    l
i    cp_string.c    /^        char *i, *f, ch;$/;"    l
i    cp_string.c    /^    char *i;$/;"    l
i    cp_string.c    /^    unsigned int i, left;$/;"    l
i    test/comport.c    /^    int i;$/;"    l
i    test/test_array.c    /^    int i;$/;"    l
i    test/test_hh.c    /^    int             i;$/;"    l
i    test/test_klist.c    /^    int                 i;$/;"    l
i    test/test_queue.c    /^    int i;$/;"    l
i    test/test_string.c    /^    int            i;$/;"    l
i    test/test_vector.c    /^    int i, n;$/;"    l
iCmdLen    cp_atcmd.c    /^    int                  iCmdLen = 0,$/;"    l
iDay    cp_time.h    /^    int iDay;$/;"    m    struct:__DATE_TIME
iDayOfWeek    cp_time.h    /^    int iDayOfWeek;$/;"    m    struct:__DATE_TIME
iHour    cp_time.h    /^    int iHour;$/;"    m    struct:__DATE_TIME
iMinute    cp_time.h    /^    int iMinute;$/;"    m    struct:__DATE_TIME
iMonth    cp_time.h    /^    int iMonth;$/;"    m    struct:__DATE_TIME
iPtr    cp_string.c    /^    int         *iPtr;$/;"    l
iRecvLen    cp_atcmd.c    /^                         iRecvLen = 0,$/;"    l
iRecvSize    cp_atcmd.c    /^                         iRecvSize = 0,$/;"    l
iRet    cp_comport.c    /^    int iRet;$/;"    l
iSecond    cp_time.h    /^    int iSecond;$/;"    m    struct:__DATE_TIME
iSize    cp_atcmd.c    /^                         iSize = 0;$/;"    l
iYear    cp_time.h    /^    int iYear;$/;"    m    struct:__DATE_TIME
idle_timeout    cp_sock.h    /^    unsigned long            idle_timeout;  \/* this is set to the socket idle timeout value, when timeout will disconnect *\/$/;"    m    struct:_CP_SOCK
idx    cp_logger.c    /^    int idx;$/;"    l
idx    cp_string.c    /^    int idx;$/;"    l
idx    cp_string.c    /^    char *idx = str;$/;"    l
iemi    cp_atcmd.h    /^    char            iemi[64];   \/*  AT+CGSN check GPRS module IEMI(International Mobile station Equipment Identity) number *\/$/;"    m    struct:_HARDWARE_INFO
ifr    cp_network.c    /^    struct ifreq          ifr;          $/;"    l
ifr    cp_ppp.c    /^    struct ifreq          ifr;$/;"    l
in    cp_iniparser.c    /^    FILE * in ;$/;"    l
inaddr    cp_sock.c    /^    struct in_addr      inaddr;$/;"    l
index    cp_sock.h    /^    int                      index;       \/* The index member position in the task array *\/$/;"    m    struct:_CP_SOCK
ini    cp_ppp.c    /^    dictionary       *ini ;$/;"    l
ini    test/test_ini.c    /^    dictionary   *ini;$/;"    l
iniparser_dump    cp_iniparser.c    /^void iniparser_dump(dictionary * d, FILE * f)$/;"    f
iniparser_dump_ini    cp_iniparser.c    /^void iniparser_dump_ini(dictionary * d, FILE * f)$/;"    f
iniparser_dumpsection_ini    cp_iniparser.c    /^void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f)$/;"    f
iniparser_find_entry    cp_iniparser.c    /^int iniparser_find_entry($/;"    f
iniparser_freedict    cp_iniparser.c    /^void iniparser_freedict(dictionary * d)$/;"    f
iniparser_getboolean    cp_iniparser.c    /^int iniparser_getboolean(dictionary * d, const char * key, int notfound)$/;"    f
iniparser_getdouble    cp_iniparser.c    /^double iniparser_getdouble(dictionary * d, const char * key, double notfound)$/;"    f
iniparser_getint    cp_iniparser.c    /^int iniparser_getint(dictionary * d, const char * key, int notfound)$/;"    f
iniparser_getlong    cp_iniparser.c    /^int iniparser_getlong(dictionary * d, const char * key, int notfound)$/;"    f
iniparser_getnsec    cp_iniparser.c    /^int iniparser_getnsec(dictionary * d)$/;"    f
iniparser_getseckeys    cp_iniparser.c    /^char ** iniparser_getseckeys(dictionary * d, char * s)$/;"    f
iniparser_getsecname    cp_iniparser.c    /^char * iniparser_getsecname(dictionary * d, int n)$/;"    f
iniparser_getsecnkeys    cp_iniparser.c    /^int iniparser_getsecnkeys(dictionary * d, char * s)$/;"    f
iniparser_getstring    cp_iniparser.c    /^char * iniparser_getstring(dictionary * d, const char * key, char * def)$/;"    f
iniparser_line    cp_iniparser.c    /^static line_status iniparser_line($/;"    f    file:
iniparser_load    cp_iniparser.c    /^dictionary * iniparser_load(const char * ininame)$/;"    f
iniparser_set    cp_iniparser.c    /^int iniparser_set(dictionary * ini, const char * entry, const char * val)$/;"    f
iniparser_unset    cp_iniparser.c    /^void iniparser_unset(dictionary * ini, const char * entry)$/;"    f
init_gsm_module    cp_gprs.c    /^int init_gsm_module(MODULE_INFO *module)$/;"    f
initiator    cp_gsmmux.h    /^    unsigned int initiator;$/;"    m    struct:gsm_config
inspect_network_status    cp_ppp.c    /^int inspect_network_status(PPP_CTX *ppp_ctx)$/;"    f
ipc_dir    cp_proc.c    /^    char ipc_dir[64] = { 0 }; $/;"    l
is_connted    cp_comport.h    /^    unsigned char databit, parity, stopbit, flowctrl, is_connted;$/;"    m    struct:__COM_PORT
item    cp_queue.c    /^    void           *item;$/;"    l
item    cp_queue.h    /^    void               *item;$/;"    m    struct:_CP_QNODE
items    cp_array.h    /^    int                    items;$/;"    m    struct:_CP_ARRAY
items    cp_queue.h    /^    int                items;$/;"    m    struct:_CP_QUEUE
j    cp_iniparser.c    /^    int     j ;$/;"    l
j    cp_iniparser.c    /^    int i, j ;$/;"    l
j    cp_iniparser.c    /^    int j ;$/;"    l
k    cp_gsmmux.h    /^    unsigned int k;$/;"    m    struct:gsm_config
kbhit    cp_comport.c    /^int kbhit()$/;"    f
keepcnt    cp_sock.h    /^    int                      keepcnt;     \/* heartbeat(keepalive) count *\/$/;"    m    struct:_CP_SOCK
keepintvl    cp_sock.h    /^    int                      keepintvl;   \/* heartbeat(keepalive) detect interval *\/$/;"    m    struct:_CP_SOCK
key    cp_dictionary.h    /^    char        **  key ;   \/** List of string keys *\/$/;"    m    struct:_dictionary_
key    cp_iniparser.c    /^    char key     [ASCIILINESZ+1] ;$/;"    l
keym    cp_iniparser.c    /^    char    keym[ASCIILINESZ+1];$/;"    l
keys    cp_iniparser.c    /^    char **keys;$/;"    l
kill_pppd_process    cp_ppp.c    /^int kill_pppd_process(COM_PORT *comport)$/;"    f
l    cp_iniparser.c    /^    static char l[ASCIILINESZ+1];$/;"    l    file:
lPtr    cp_string.c    /^    long        *lPtr;$/;"    l
laddr    cp_sock.h    /^    char                     laddr[16];   \/* local IP address*\/$/;"    m    struct:_CP_SOCK
last    cp_iniparser.c    /^    char * last ;$/;"    l
last    cp_iniparser.c    /^    int  last=0 ;$/;"    l
last    cp_klist.h    /^    struct list_head *last = list->prev;$/;"    l
last_rx_bytes    cp_ppp.c    /^    unsigned long long     last_rx_bytes= ppp_stat->ullRx_Bytes;$/;"    l
last_tx_bytes    cp_ppp.c    /^    unsigned long long     last_tx_bytes= ppp_stat->ullTx_Bytes;$/;"    l
latitude    cp_atcmd.h    /^    char            latitude[15];$/;"    m    struct:_GPRS_LOCATION
lc_key    cp_iniparser.c    /^    char * lc_key ;$/;"    l
ldisc    cp_gsmmux.c    /^    int                    ldisc = N_GSM0710;$/;"    l
ldx    cp_logger.c    /^        int ldx = idx % CHARS_PER_LINE;$/;"    l
left    cp_sock.c    /^    int               rv, left;$/;"    l
left    cp_string.c    /^    int        left;$/;"    l
left    cp_string.c    /^    unsigned int i, left;$/;"    l
left_line    cp_iniparser.c    /^    static char left_line[ASCIILINESZ+1];$/;"    l    file:
len    cp_dictionary.c    /^    int         len ;$/;"    l
len    cp_iniparser.c    /^    int         len, offset ;$/;"    l
len    cp_iniparser.c    /^    int  len ;$/;"    l
len    cp_sock.c    /^    int                 len = sizeof(saddr); $/;"    l
len    cp_sock.c    /^    int len = sizeof (int);$/;"    l
len    cp_sock.c    /^    socklen_t                len = sizeof(saddr);$/;"    l
len    cp_string.c    /^    int len = str->len;$/;"    l
len    cp_string.h    /^    int len;     \/**< size used        *\/$/;"    m    struct:_cp_string
level    cp_logger.h    /^    int                level;$/;"    m    struct:_cp_logger
line    cp_iniparser.c    /^    char        line[ASCIILINESZ+1];$/;"    l
line    cp_iniparser.c    /^    char line    [ASCIILINESZ+1] ;$/;"    l
line_done    cp_logger.c    /^    short line_done = 1;$/;"    l
line_done    cp_string.c    /^    short line_done = 1;$/;"    l
line_status    cp_iniparser.c    /^} line_status ;$/;"    t    typeref:enum:_line_status_    file:
lineno    cp_iniparser.c    /^    int  lineno=0 ;$/;"    l
list_add    cp_klist.h    /^static inline void list_add(struct list_head *new, struct list_head *head)$/;"    f
list_add_tail    cp_klist.h    /^static inline void list_add_tail(struct list_head *new, struct list_head *head)$/;"    f
list_cut_position    cp_klist.h    /^static inline void list_cut_position(struct list_head *list,$/;"    f
list_del    cp_klist.h    /^static inline void list_del(struct list_head *entry)$/;"    f
list_del_init    cp_klist.h    /^static inline void list_del_init(struct list_head *entry)$/;"    f
list_empty    cp_klist.h    /^static inline int list_empty(const struct list_head *head)$/;"    f
list_empty_careful    cp_klist.h    /^static inline int list_empty_careful(const struct list_head *head)$/;"    f
list_entry    cp_klist.h    372;"    d
list_first_entry    cp_klist.h    383;"    d
list_for_each    cp_klist.h    391;"    d
list_for_each_entry    cp_klist.h    444;"    d
list_for_each_entry_continue    cp_klist.h    480;"    d
list_for_each_entry_continue_reverse    cp_klist.h    494;"    d
list_for_each_entry_from    cp_klist.h    507;"    d
list_for_each_entry_reverse    cp_klist.h    455;"    d
list_for_each_entry_safe    cp_klist.h    518;"    d
list_for_each_entry_safe    test/test_klist.c    /^    list_for_each_entry_safe(sock, tsock, head, rlist)$/;"    f
list_for_each_entry_safe_continue    cp_klist.h    534;"    d
list_for_each_entry_safe_from    cp_klist.h    550;"    d
list_for_each_entry_safe_reverse    cp_klist.h    565;"    d
list_for_each_prev    cp_klist.h    413;"    d
list_for_each_prev_safe    cp_klist.h    433;"    d
list_for_each_safe    cp_klist.h    423;"    d
list_head    cp_klist.h    /^struct list_head {$/;"    s
list_is_last    cp_klist.h    /^static inline int list_is_last(const struct list_head *list,$/;"    f
list_is_singular    cp_klist.h    /^static inline int list_is_singular(const struct list_head *head)$/;"    f
list_move    cp_klist.h    /^static inline void list_move(struct list_head *list, struct list_head *head)$/;"    f
list_move_tail    cp_klist.h    /^static inline void list_move_tail(struct list_head *list,$/;"    f
list_prepare_entry    cp_klist.h    468;"    d
list_replace    cp_klist.h    /^static inline void list_replace(struct list_head *old,$/;"    f
list_replace_init    cp_klist.h    /^static inline void list_replace_init(struct list_head *old,$/;"    f
list_splice    cp_klist.h    /^static inline void list_splice(const struct list_head *list,$/;"    f
list_splice_init    cp_klist.h    /^static inline void list_splice_init(struct list_head *list,$/;"    f
list_splice_tail    cp_klist.h    /^static inline void list_splice_tail(struct list_head *list,$/;"    f
list_splice_tail_init    cp_klist.h    /^static inline void list_splice_tail_init(struct list_head *list,$/;"    f
lit    cp_logger.c    /^    char lit[CHARS_PER_LINE + 2];$/;"    l
lit    cp_string.c    /^    char lit[CHARS_PER_LINE + 1];$/;"    l
loc    cp_atcmd.h    /^    GPRS_LOCATION   loc;        \/*  Location *\/$/;"    m    struct:_REGISTER_INFO
local    cp_logger.c    /^    struct tm *local;$/;"    l
lock    cp_gprs.c    /^    static int     lock = 0;$/;"    l    file:
lock    cp_gprs.h    /^    pthread_mutex_t lock;      \/* Module control mutex lock *\/$/;"    m    struct:__MODULE_INFO
log    cp_atcmd.c    /^        char   log[512] = {0};$/;"    l
log_banner    cp_logger.c    /^static void log_banner(char *prefix)$/;"    f    file:
log_dbg    cp_logger.h    102;"    d
log_dbg    cp_logger.h    94;"    d
log_err    cp_logger.h    105;"    d
log_err    cp_logger.h    97;"    d
log_fatal    cp_logger.h    106;"    d
log_fatal    cp_logger.h    98;"    d
log_info    cp_logger.h    101;"    d
log_info    cp_logger.h    93;"    d
log_nrml    cp_logger.h    103;"    d
log_nrml    cp_logger.h    95;"    d
log_rollback_size    cp_logger.c    /^static unsigned long log_rollback_size = LOG_ROLLBACK_NONE;$/;"    v    file:
log_str    cp_logger.c    /^char *log_str[LOG_LEVEL_MAX + 1] = { "", "F", "E", "W", "N", "D", "I", "T", "M" };$/;"    v
log_str    cp_logger.h    /^extern char *log_str[];$/;"    x
log_trace    cp_logger.h    100;"    d
log_trace    cp_logger.h    92;"    d
log_warn    cp_logger.h    104;"    d
log_warn    cp_logger.h    96;"    d
logger    cp_logger.c    /^static cp_logger *logger = NULL;$/;"    v    file:
loglevel    test/swe_tpdud.c    /^    int            loglevel = LOG_LEVEL_NRML;$/;"    l
long_options    test/comport.c    /^    struct option long_options[] = {$/;"    l
long_options    test/swe_tpdud.c    /^    struct option  long_options[] = $/;"    l
long_options    test/test_hal.c    /^    struct option long_options[] = {$/;"    l
longitude    cp_atcmd.h    /^    char            longitude[15];$/;"    m    struct:_GPRS_LOCATION
lost_percent    cp_network.c    /^    int                  lost_percent = 100;$/;"    l
lost_percent    cp_ppp.c    /^    int                    lost_percent;$/;"    l
lport    cp_sock.h    /^    int                      lport;       \/* local port *\/$/;"    m    struct:_CP_SOCK
lport    test/swe_tpdud.h    /^    int                 lport;     \/* dlink  local listen port  *\/$/;"    m    struct:_SWE_TPDU
main    cp_dictionary.c    /^int main(int argc, char *argv[])$/;"    f
main    test/comport.c    /^int main(int argc, char **argv)$/;"    f
main    test/swe_tpdud.c    /^int main (int argc, char **argv)$/;"    f
main    test/test_array.c    /^int main (int argc, char **argv)$/;"    f
main    test/test_hal.c    /^int main (int argc, char **argv)$/;"    f
main    test/test_hh.c    /^int main (int argc, char **argv)$/;"    f
main    test/test_ini.c    /^int main (int argc, char **argv)$/;"    f
main    test/test_klist.c    /^int main (int argc, char **argv)$/;"    f
main    test/test_logger.c    /^int main (int argc, char **argv)$/;"    f
main    test/test_queue.c    /^int main (int argc, char **argv)$/;"    f
main    test/test_sock_client.c    /^int main (int argc, char **argv)$/;"    f
main    test/test_sock_server.c    /^int main (int argc, char **argv)$/;"    f
main    test/test_string.c    /^int main (int argc, char **argv)$/;"    f
main    test/test_vector.c    /^int main (int argc, char **argv)$/;"    f
max_client    cp_sock.h    /^    int                      max_client;  \/* max clients, only listen socket use it*\/$/;"    m    struct:_CP_SOCK
max_event    cp_fds.h    /^    int                   max_event;    \/* Maximum monitor FD number *\/$/;"    m    struct:_CP_FDS
mcc    cp_atcmd.c    /^    char              mcc[5];$/;"    l
mcc_mnc    cp_atcmd.h    /^    char            mcc_mnc[16];\/*   Mobile Country Code, China is 460 *\/$/;"    m    struct:_GPRS_LOCATION
mem    cp_vector.h    /^    void          **mem;$/;"    m    struct:_CP_VECTOR
mem_double    cp_dictionary.c    /^static void * mem_double(void * ptr, int size)$/;"    f    file:
micro_second_sleep    cp_time.h    /^static inline void micro_second_sleep(unsigned long ms)$/;"    f
mnc    cp_atcmd.c    /^    char              mnc[5];$/;"    l
mode    cp_proc.c    /^    int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;$/;"    l
mode    cp_sock.h    /^    int                      mode;        \/* socket work mode: listen, accept, connect *\/$/;"    m    struct:_CP_SOCK
model    cp_atcmd.h    /^    char            model[64];  \/*  AT+CGMM check GPRS module model *\/$/;"    m    struct:_HARDWARE_INFO
module    cp_gprs.c    /^    MODULE_INFO        *module = (MODULE_INFO *)thread_arg;$/;"    l
module    cp_ppp.c    /^    MODULE_INFO         *module = ppp_ctx->module; $/;"    l
module    cp_ppp.c    /^    MODULE_INFO         *module;$/;"    l
module    cp_ppp.h    /^    MODULE_INFO        *module;$/;"    m    struct:__PPP_CTX
mrev    cp_atcmd.h    /^    char            mrev[64];   \/*  AT+CGMR check GPRS module revision *\/$/;"    m    struct:_HARDWARE_INFO
mru    cp_gsmmux.h    /^    unsigned int mru;$/;"    m    struct:gsm_config
msg_time    cp_sock.h    /^    unsigned long            msg_time;      \/* The last time get incoming data in this socket *\/$/;"    m    struct:_CP_SOCK
msg_timeout    cp_sock.h    /^    unsigned long            msg_timeout;   \/* this is set to the socket recv data timeout value,  *\/$/;"    m    struct:_CP_SOCK
mtu    cp_gsmmux.h    /^    unsigned int mtu;$/;"    m    struct:gsm_config
n    cp_dictionary.h    /^    int             n ;     \/** Number of entries in dictionary *\/$/;"    m    struct:_dictionary_
n    test/test_vector.c    /^    int i, n;$/;"    l
n2    cp_gsmmux.h    /^    unsigned int n2;$/;"    m    struct:gsm_config
netaddr    cp_ppp.h    /^    char            netaddr[INET_ADDRSTRLEN];$/;"    m    struct:__PPPD_INFO
network    cp_ppp.h    /^    unsigned char      network;      \/* PPP network status: PPP_FAIL,PPP_BAD,PPP_GOOD *\/$/;"    m    struct:__PPP_CTX
network_ping_test    cp_network.c    /^int network_ping_test(char *from, char *ping_ip)$/;"    f
new_cfg    cp_comport.c    /^    struct termios old_cfg, new_cfg;$/;"    l
new_first    cp_klist.h    /^    struct list_head *new_first = entry->next;$/;"    l
new_sock    cp_network.c    /^    CP_SOCK                *new_sock = NULL;$/;"    l
newptr    cp_dictionary.c    /^    void * newptr ;$/;"    l
next    cp_klist.h    /^    struct hlist_node *next = n->next;$/;"    l
next    cp_klist.h    /^    struct hlist_node *next, **pprev;$/;"    m    struct:hlist_node    typeref:struct:hlist_node::hlist_node
next    cp_klist.h    /^    struct list_head *next = head->next;$/;"    l
next    cp_klist.h    /^    struct list_head *next, *prev;$/;"    m    struct:list_head    typeref:struct:list_head::list_head
next    cp_queue.h    /^    struct _CP_QNODE   *next;$/;"    m    struct:_CP_QNODE    typeref:struct:_CP_QNODE::_CP_QNODE
nfds    cp_fds.c    /^    int                   i=0, nfds=0;$/;"    l
nic_get_ipaddr    cp_network.c    /^int nic_get_ipaddr(char *nic, char *ipaddr)$/;"    f
nic_get_ptpaddr    cp_network.c    /^int nic_get_ptpaddr(char *nic, char *ptpaddr)$/;"    f
nic_network_config    cp_network.c    /^int nic_network_config(char *nic, char *mac, char *ip)$/;"    f
nkeys    cp_iniparser.c    /^    int     seclen, nkeys ;$/;"    l
node    cp_queue.c    /^    CP_QNODE         *node;$/;"    l
node    cp_queue.c    /^    CP_QNODE       *node, *tmp;$/;"    l
node    cp_queue.c    /^    CP_QNODE       *node;$/;"    l
nonblock    cp_comport.c    /^void nonblock()$/;"    f
now    cp_logger.c    /^    struct timeval now;$/;"    l
now    cp_time.h    /^    struct timeval now; $/;"    l
now    cp_time.h    /^    time_t now = time(NULL);$/;"    l
nsec    cp_iniparser.c    /^    int     nsec ;$/;"    l
nsec    cp_iniparser.c    /^    int nsec ;$/;"    l
offset    cp_iniparser.c    /^    int         len, offset ;$/;"    l
offsetof    cp_common.h    22;"    d
offsetof    cp_klist.h    27;"    d
offsetof    cp_klist.h    28;"    d
old_cfg    cp_comport.c    /^    struct termios old_cfg, new_cfg;$/;"    l
old_flags    cp_comport.c    /^    int old_flags;$/;"    l
olen    cp_string.c    /^    int olen = str->len;$/;"    l
open_gsm_dataport    cp_gprs.c    /^int open_gsm_dataport(MODULE_INFO *module)$/;"    f
opt    cp_sock.c    /^    int        opt;$/;"    l
opt    cp_sock.c    /^    int  opt;$/;"    l
opt    cp_sock.c    /^    int opt = 1;$/;"    l
opt    test/comport.c    /^    int opt = 0;$/;"    l
opt    test/swe_tpdud.c    /^    int            opt;$/;"    l
opt    test/test_hal.c    /^    int                   opt;$/;"    l
optlen    cp_sock.c    /^    socklen_t  optlen = sizeof(opt);$/;"    l
opts    cp_sock.c    /^    int opts;$/;"    l
p    cp_string.c    /^        int p = (s1->len > s2->len) ? s2->len : s1->len;$/;"    l
p    test/test_vector.c    /^    CP_SOCK *p = NULL;$/;"    l
parity    cp_comport.h    /^    unsigned char databit, parity, stopbit, flowctrl, is_connted;$/;"    m    struct:__COM_PORT
pcPtr    cp_string.c    /^    char        *pcPtr;$/;"    l
pcRecvPtr    cp_atcmd.c    /^    char                 *pcRecvPtr = NULL; $/;"    l
pcStart    cp_atcmd.c    /^                            *pcStart = NULL,$/;"    l
pcTab    cp_atcmd.c    /^                            *pcTab   = NULL;$/;"    l
pid    cp_ppp.c    /^    int           pid = -1;$/;"    l
pid    cp_ppp.c    /^    int        pid = -1;$/;"    l
pid    cp_ppp.c    /^    pid_t               pid;$/;"    l
pid    cp_ppp.h    /^    pid_t           pid;$/;"    m    struct:__PPPD_INFO
pid    cp_proc.c    /^        char pid[PID_ASCII_SIZE]; $/;"    l
pid    cp_proc.c    /^        pid_t pid = -1; $/;"    l
pid    cp_proc.c    /^    pid_t pid; $/;"    l
pid_ascii    cp_proc.c    /^        char pid_ascii[PID_ASCII_SIZE]; $/;"    l
ping_interval    cp_ppp.h    /^    long               ping_interval;$/;"    m    struct:__PPP_CTX
ping_ip    cp_ppp.h    /^    char               ping_ip[INET_ADDRSTRLEN];$/;"    m    struct:__PPP_CTX
ping_time    cp_ppp.h    /^    unsigned long   ping_time;$/;"    m    struct:__PPPD_INFO
power_off_module    cp_gprs.c    /^int power_off_module(MODULE_INFO *module)$/;"    f
power_on_module    cp_gprs.c    /^int power_on_module(MODULE_INFO *module)$/;"    f
ppp_context_init    cp_ppp.c    /^int ppp_context_init(PPP_CTX *ppp_ctx, MODULE_INFO *module)$/;"    f
ppp_context_term    cp_ppp.c    /^void ppp_context_term(PPP_CTX *ppp_ctx)$/;"    f
ppp_ctx    cp_ppp.c    /^    PPP_CTX             ppp_ctx; $/;"    l
ppp_stat    cp_ppp.c    /^    PPP_STAT               *ppp_stat = &(ppp_ctx->ppp_stat);$/;"    l
ppp_stat    cp_ppp.h    /^    PPP_STAT           ppp_stat;     \/* PPP network statistic *\/$/;"    m    struct:__PPP_CTX
ppp_thread_workbody    cp_ppp.c    /^void *ppp_thread_workbody(void *thread_arg)$/;"    f
pppd_cmd    cp_ppp.c    /^    char                pppd_cmd[PPPD_CMD_LEN];$/;"    l
pppd_info    cp_ppp.c    /^    PPPD_INFO              *pppd_info = &(ppp_ctx->pppd_info);$/;"    l
pppd_info    cp_ppp.h    /^    PPPD_INFO          pppd_info;    \/* pppd process information *\/$/;"    m    struct:__PPP_CTX
pprev    cp_klist.h    /^    struct hlist_node **pprev = n->pprev;$/;"    l
pprev    cp_klist.h    /^    struct hlist_node *next, **pprev;$/;"    m    struct:hlist_node    typeref:struct:hlist_node::
prefetch    cp_klist.h    /^static inline void prefetch(const void *x) {;}$/;"    f
prev    cp_klist.h    /^    struct list_head *next, *prev;$/;"    m    struct:list_head    typeref:struct:list_head::
print_char    cp_logger.c    /^static char *print_char =$/;"    v    file:
print_char    cp_string.c    /^static char *print_char = $/;"    v    file:
print_usage    test/swe_tpdud.c    /^void print_usage(char *progname)$/;"    f
print_usage    test/test_hal.c    /^void print_usage(char *progname)$/;"    f
print_version    test/comport.c    /^void print_version(char *name)$/;"    f
privt    cp_sock.h    /^    void                     *privt;      \/* socket private data *\/$/;"    m    struct:_CP_SOCK
privt_free    cp_sock.h    /^    PRIVT_FREE               privt_free;  \/* private data free function if it's malloc *\/$/;"    m    struct:_CP_SOCK
prn    cp_logger.c    /^    char prn[LINELEN];$/;"    l
prn    cp_string.c    /^    char prn[LINELEN];$/;"    l
proc_uplink_event    test/swe_tpdud.c    /^int proc_uplink_event(CP_SOCK *ulink)$/;"    f
progname    test/comport.c    /^    char *progname = NULL;$/;"    l
progname    test/test_hal.c    /^    char                  *progname=NULL;$/;"    l
ptpaddr    cp_ppp.h    /^    char            ptpaddr[INET_ADDRSTRLEN];$/;"    m    struct:__PPPD_INFO
ptr    cp_atcmd.c    /^    char              *ptr = NULL;$/;"    l
ptr    cp_atcmd.c    /^    char        *ptr = NULL;$/;"    l
ptr    cp_common.h    /^    void *ptr;$/;"    l
ptr    cp_comport.c    /^    char *ptr, *end;$/;"    l
ptr    cp_iniparser.c    /^        char      *ptr = NULL; $/;"    l
ptr    cp_ppp.c    /^    char                *ptr;$/;"    l
ptr    test/comport.c    /^    char *ptr = NULL;$/;"    l
pwd    cp_ppp.h    /^    char            pwd[PWD_LEN];$/;"    m    struct:__APN_ACCOUNT
pwr_status    cp_gprs.h    /^    unsigned char   pwr_status; \/* Current module power status *\/$/;"    m    struct:__MODULE_INFO
queue    test/test_queue.c    /^    CP_QUEUE *queue = NULL;$/;"    l
raddr    cp_sock.h    /^    char                     raddr[16];   \/* remote IP address  *\/$/;"    m    struct:_CP_SOCK
raddr    test/swe_tpdud.h    /^    char                raddr[32]; \/* uplink remote listen port *\/$/;"    m    struct:_SWE_TPDU
rb_clear    cp_ringbuf.c    /^void rb_clear (struct ring_buffer *rb) {$/;"    f
rb_data_size    cp_ringbuf.c    /^int rb_data_size (struct ring_buffer *rb) {$/;"    f
rb_free_size    cp_ringbuf.c    /^int rb_free_size (struct ring_buffer *rb){$/;"    f
rb_init    cp_ringbuf.c    /^void rb_init (struct ring_buffer *ring, u_char* buff, int size) {$/;"    f
rb_peek    cp_ringbuf.c    /^u_char rb_peek(struct ring_buffer* rb, int index) {$/;"    f
rb_read    cp_ringbuf.c    /^int rb_read (struct ring_buffer *rb, u_char * buf, int max) {$/;"    f
rb_write    cp_ringbuf.c    /^rb_write (struct ring_buffer *rb, u_char * buf, int len)$/;"    f
rbuf    cp_sock.c    /^    cp_string         *rbuf;$/;"    l
rbuf    cp_sock.h    /^    cp_string                *rbuf;       \/* receive buffer  *\/$/;"    m    struct:_CP_SOCK
rbuf    test/test_hh.c    /^    unsigned char   rbuf[10];$/;"    l
rc    cp_logger.c    /^    int rc = 0;$/;"    l
rc    cp_logger.c    /^    int rc;$/;"    l
rc    cp_string.c    /^        int rc = $/;"    l
rc    cp_string.c    /^        int rc = memcmp(s1->data, s2->data, p);$/;"    l
rc    cp_string.c    /^    int rc;$/;"    l
rcv    test/test_string.c    /^    cp_string      *rcv;$/;"    l
rd_pointer    cp_ringbuf.h    /^    int rd_pointer;$/;"    m    struct:ring_buffer
read    cp_sock.h    /^    CP_SOCK_EVENT_CALLBACK  read;$/;"    m    struct:_CP_SOCK_CALLBACK
read_len    cp_string.c    /^    int read_len;$/;"    l
ready    cp_gprs.h    /^    unsigned char   ready;     \/* SIM card regist and can work or not *\/$/;"    m    struct:__MODULE_INFO
rear    cp_queue.h    /^    CP_QNODE           *rear;$/;"    m    struct:_CP_QUEUE
record_daemon_pid    cp_proc.c    /^int record_daemon_pid(const char *pid_file)$/;"    f
recv_buf    cp_atcmd.c    /^    char              recv_buf[ATCMD_REPLY_LEN];$/;"    l
recv_buf    cp_atcmd.c    /^    char        recv_buf[ATCMD_REPLY_LEN]; $/;"    l
recv_buf    cp_atcmd.c    /^    char        recv_buf[ATCMD_REPLY_LEN];$/;"    l
recv_size    test/comport.c    /^    int recv_size = 0;$/;"    l
reg    cp_gprs.c    /^    REGISTER_INFO   *reg = &(module->reg);   \/* SIM card Register information  *\/ $/;"    l
reg    cp_gprs.h    /^    REGISTER_INFO   reg;       \/* SIM card register network information *\/$/;"    m    struct:__MODULE_INFO
res    cp_fds.c    /^    struct  rlimit    res;$/;"    l
res    cp_sock.c    /^    struct addrinfo     *res = NULL;$/;"    l
res    cp_string.c    /^    cp_string *res = NULL;$/;"    l
res    cp_string.c    /^    cp_string *res;$/;"    l
result    cp_string.c    /^    char        *result;$/;"    l
ret    cp_iniparser.c    /^    int         ret ;$/;"    l
retVal    cp_proc.c    /^    int retVal = -1; $/;"    l
retval    cp_atcmd.c    /^    int                  retval = -1; $/;"    l
retval    cp_atcmd.c    /^    int               retval;$/;"    l
retval    cp_atcmd.c    /^    int              retval; $/;"    l
retval    cp_atcmd.c    /^    int              retval;$/;"    l
retval    cp_atcmd.c    /^    int         retval = 0; $/;"    l
retval    cp_atcmd.c    /^    int         retval, stat = -1;$/;"    l
retval    cp_atcmd.c    /^    int         retval;$/;"    l
retval    cp_atcmd.c    /^    int         retval=0; $/;"    l
retval    cp_atcmd.c    /^    int    retval;$/;"    l
retval    cp_atcmd.c    /^    int  retval;$/;"    l
retval    cp_comport.c    /^    int retval = -1;$/;"    l
retval    cp_comport.c    /^    int retval = 0;             \/\/ Function return value$/;"    l
retval    cp_comport.c    /^    int retval = 0;$/;"    l
retval    cp_gprs.c    /^    int           retval = 0;$/;"    l
retval    cp_gprs.c    /^    int i, retval = -1;$/;"    l
retval    cp_ppp.c    /^    int                 retval;$/;"    l
retval    cp_ppp.c    /^    int           retval = -1;$/;"    l
retval    cp_proc.c    /^    int        retval = 0;$/;"    l
retval    cp_proc.c    /^    int retval, fd; $/;"    l
retval    test/comport.c    /^    int retval = -1;$/;"    l
retval    test/comport.c    /^    int retval = 0;$/;"    l
ring_buffer    cp_ringbuf.h    /^struct ring_buffer {$/;"    s
rlist    cp_sock.h    /^    struct list_head         rlist;       \/* The list_head member position just for the registry list *\/$/;"    m    struct:_CP_SOCK    typeref:struct:_CP_SOCK::list_head
rp    cp_sock.c    /^    struct addrinfo     hints, *rp;$/;"    l
rport    cp_sock.h    /^    int                      rport;       \/* remote port *\/$/;"    m    struct:_CP_SOCK
rport    test/swe_tpdud.h    /^    int                 rport;     \/* uplink remote IP address  *\/$/;"    m    struct:_SWE_TPDU
rsize    cp_sock.h    /^    int                      rsize;       \/* ioctl() set socket recv buffer size  *\/$/;"    m    struct:_CP_SOCK
rtc_tm    cp_time.h    /^    struct rtc_time     rtc_tm;  $/;"    l
rv    cp_array.c    /^    int              i, rv = -3;$/;"    l
rv    cp_fds.c    /^    int                     rv = 0;$/;"    l
rv    cp_fds.c    /^    int                     rv;$/;"    l
rv    cp_fds.c    /^    int                    rv;$/;"    l
rv    cp_fds.c    /^    int          rv = 0;$/;"    l
rv    cp_gprs.c    /^    int             rv;$/;"    l
rv    cp_gprs.c    /^    int           i, rv = 0;$/;"    l
rv    cp_gprs.c    /^    int           rv = 0;$/;"    l
rv    cp_gprs.c    /^    int           rv;$/;"    l
rv    cp_gprs.c    /^    int     rv = 0;$/;"    l
rv    cp_hal.c    /^    int         rv = 0;$/;"    l
rv    cp_network.c    /^    int                    rv = 0;$/;"    l
rv    cp_network.c    /^    int  rv = 0;$/;"    l
rv    cp_sock.c    /^    int                      rv = 0;$/;"    l
rv    cp_sock.c    /^    int                      rv;$/;"    l
rv    cp_sock.c    /^    int                 rv = 0;$/;"    l
rv    cp_sock.c    /^    int               rv, left;$/;"    l
rv    cp_sock.c    /^    int        rv = 0;$/;"    l
rv    cp_time.h    /^    int                 rv, fd = -1;$/;"    l
rv    test/swe_tpdud.c    /^    int            rv = 0;$/;"    l
rv    test/swe_tpdud.c    /^    int           rv;$/;"    l
rv    test/test_hal.c    /^    int        rv = 0;$/;"    l
rv    test/test_sock_client.c    /^    int      rv;$/;"    l
rv    test/test_sock_server.c    /^    int           rv = 0;$/;"    l
rx_packets    cp_network.c    /^    unsigned long        rx_packets = 0;$/;"    l
saddr    cp_sock.c    /^            struct sockaddr_in    *saddr = (struct sockaddr_in *)rp->ai_addr;$/;"    l
saddr    cp_sock.c    /^    struct sockaddr_in       saddr;$/;"    l
saddr    cp_sock.c    /^    struct sockaddr_in  saddr;$/;"    l
saddr    cp_sock.h    /^    struct sockaddr          saddr;       \/* sockaddr for connect *\/$/;"    m    struct:_CP_SOCK    typeref:struct:_CP_SOCK::sockaddr
save    cp_vector.c    /^    void    *save;$/;"    l
sbuf    cp_sock.h    /^    cp_string                *sbuf;       \/* send buffer *\/$/;"    m    struct:_CP_SOCK
sbuf    test/test_hh.c    /^    unsigned char   sbuf[10]={0x02, 0x48, 0x32, 0x03, 0x20, 0x00, 0x00, 0xF6, 0xBE, 0x03};$/;"    l
seclen    cp_iniparser.c    /^    int     seclen ;$/;"    l
seclen    cp_iniparser.c    /^    int     seclen, nkeys ;$/;"    l
secname    cp_iniparser.c    /^    char *  secname ;$/;"    l
section    cp_iniparser.c    /^    char section [ASCIILINESZ+1] ;$/;"    l
select_apn    cp_ppp.c    /^int select_apn(PPP_CTX *ppp_ctx, char *key)$/;"    f
send    cp_comport.c    /^    int send = 0;$/;"    l
send_atcmd    cp_atcmd.c    /^int send_atcmd(COM_PORT *comport, char *atCmd, char *expect, char *error,$/;"    f
send_atcmd_check_ok    cp_atcmd.c    /^int send_atcmd_check_ok(COM_PORT *comport, char *atcmd, unsigned long timeout)$/;"    f
send_atcmd_check_request    cp_atcmd.c    /^int send_atcmd_check_request(COM_PORT *comport, char *atcmd, unsigned long timeout, char *buf, int buf_len)$/;"    f
send_atcmd_check_value    cp_atcmd.c    /^int send_atcmd_check_value(COM_PORT *comport, char *atcmd, unsigned long timeout, char *buf, int buf_len)$/;"    f
serv_sock    cp_fds.c    /^    CP_SOCK           *sock, *tsock, *serv_sock;$/;"    l
serv_sock    cp_sock.h    /^    struct _CP_SOCK          *serv_sock;  \/* Accept socket used to point to the server socket *\/$/;"    m    struct:_CP_SOCK    typeref:struct:_CP_SOCK::_CP_SOCK
serv_tpdu    test/swe_tpdud.c    /^            SWE_TPDU       *serv_tpdu;$/;"    l
server_list    cp_fds.h    /^    struct list_head      server_list;  \/* a list keep all the listen sockets *\/ $/;"    m    struct:_CP_FDS    typeref:struct:_CP_FDS::list_head
service    cp_sock.c    /^    char                service[20];$/;"    l
service_route    test/test_sock_client.c    /^int service_route(CP_SOCK *sock)$/;"    f
service_route    test/test_sock_server.c    /^int service_route(CP_SOCK *sock)$/;"    f
set_daemon_running    cp_proc.c    /^int set_daemon_running(const char *pid_file)$/;"    f
set_module_event    cp_gprs.c    /^void set_module_event(MODULE_INFO *module, int request)$/;"    f
set_module_event_power    cp_gprs.c    /^int set_module_event_power(MODULE_INFO *module)$/;"    f
set_ppp_disconnect    cp_ppp.c    /^void set_ppp_disconnect(PPP_CTX *ppp_ctx)$/;"    f
set_settings    cp_comport.c    /^void set_settings(COM_PORT * comport, const char *settings)$/;"    f
settings    test/comport.c    /^    char *settings = "8N1N";$/;"    l
sigact    cp_proc.c    /^    struct sigaction sigact, sigign;$/;"    l
sigact    test/comport.c    /^    struct sigaction sigact;$/;"    l
sigign    cp_proc.c    /^    struct sigaction sigact, sigign;$/;"    l
signal    cp_atcmd.c    /^    int         signal = -1;$/;"    l
signal    cp_atcmd.h    /^    int             signal;     \/*  GPRS signal *\/ $/;"    m    struct:_REGISTER_INFO
signal    cp_proc.h    /^    int       signal;$/;"    m    struct:__CP_PROC_SIG
signal_handler    test/comport.c    /^void signal_handler(int i_sig)$/;"    f
sin    cp_network.c    /^    struct sockaddr_in    *sin;         $/;"    l
sin    cp_ppp.c    /^    struct sockaddr_in    *sin;  $/;"    l
size    cp_array.h    /^    int                    size;$/;"    m    struct:_CP_ARRAY
size    cp_dictionary.h    /^    int             size ;  \/** Storage size *\/$/;"    m    struct:_dictionary_
size    cp_logger.h    /^    int                size;$/;"    m    struct:_cp_logger
size    cp_queue.h    /^    int                size;$/;"    m    struct:_CP_QUEUE
size    cp_ringbuf.h    /^    int size;$/;"    m    struct:ring_buffer
size    cp_string.c    /^    int        size;$/;"    l
size    cp_string.h    /^    int size;    \/**< size allocated   *\/$/;"    m    struct:_cp_string
size    cp_vector.h    /^    int           size;$/;"    m    struct:_CP_VECTOR
snd    test/test_string.c    /^    cp_string      *snd;$/;"    l
so_linger    cp_sock.c    /^            struct linger so_linger;$/;"    l
sock    cp_fds.c    /^    CP_SOCK                *sock;$/;"    l
sock    cp_fds.c    /^    CP_SOCK               *sock;$/;"    l
sock    cp_fds.c    /^    CP_SOCK           *sock = NULL, *tsock;$/;"    l
sock    cp_fds.c    /^    CP_SOCK           *sock, *tsock, *serv_sock;$/;"    l
sock    cp_fds.c    /^    CP_SOCK           *sock, *tsock;$/;"    l
sock    cp_fds.c    /^    CP_SOCK           *sock;$/;"    l
sock    cp_fds.c    /^    CP_SOCK    *sock = NULL;$/;"    l
sock    cp_network.c    /^    CP_SOCK   *sock = NULL;$/;"    l
sock    test/swe_tpdud.c    /^    CP_SOCK        *sock;$/;"    l
sock    test/test_array.c    /^    CP_SOCK *sock = NULL;$/;"    l
sock    test/test_klist.c    /^    CP_SOCK             *sock, *tsock;$/;"    l
sock    test/test_queue.c    /^    CP_SOCK *sock = NULL;$/;"    l
sock    test/test_sock_client.c    /^    CP_SOCK    *sock = NULL;$/;"    l
sock    test/test_sock_server.c    /^    CP_SOCK    *sock;$/;"    l
sock_list    test/test_klist.c    /^    struct list_head    sock_list;$/;"    l
sock_poll    cp_sock.c    /^    struct pollfd            sock_poll;$/;"    l
split_string_to_value    cp_string.c    /^int split_string_to_value(char *str, char *fmt, ...)$/;"    f
ssize    cp_sock.h    /^    int                      ssize;       \/* ioctl() set socket send buffer size  *\/$/;"    m    struct:_CP_SOCK
stExcpFds    cp_comport.c    /^    fd_set stReadFds, stExcpFds;$/;"    l
stReadFds    cp_comport.c    /^    fd_set stReadFds, stExcpFds;$/;"    l
stTime    cp_comport.c    /^    struct timeval stTime;$/;"    l
sta    cp_iniparser.c    /^    line_status sta ;$/;"    l
start    cp_atcmd.c    /^    char        *start;$/;"    l
start_ppp_connect    cp_ppp.c    /^int start_ppp_connect(PPP_CTX *ppp_ctx)$/;"    f
start_ppp_dial_cmd    cp_ppp.c    /^int start_ppp_dial_cmd(COM_PORT  *comport, APN_ACCOUNT *apn, char *ppp_dev)$/;"    f
start_thread_ppp    cp_ppp.c    /^int start_thread_ppp(MODULE_INFO *module)$/;"    f
start_time    cp_gprs.c    /^    static unsigned long start_time ;$/;"    l    file:
start_time    cp_ppp.h    /^    unsigned long   start_time;$/;"    m    struct:__PPPD_INFO
stat    cp_atcmd.c    /^    int         retval, stat = -1;$/;"    l
status    cp_atcmd.c    /^    int               status;$/;"    l
status    cp_hal.c    /^    int         status;$/;"    l
status    cp_ppp.h    /^    unsigned char      status;       \/* Current PPP connection status *\/$/;"    m    struct:__PPP_CTX
status    cp_sock.h    /^    unsigned char            status;      \/* current socket status *\/$/;"    m    struct:_CP_SOCK
stop    cp_proc.h    /^    unsigned  stop;     \/* 0: Not term  1: Stop  *\/$/;"    m    struct:__CP_PROC_SIG
stop_ppp_connect    cp_ppp.c    /^int stop_ppp_connect(PPP_CTX *ppp_ctx)$/;"    f
stop_tpdu_service    test/swe_tpdud.c    /^static void stop_tpdu_service(SWE_TPDU *tpdu)$/;"    f    file:
stopbit    cp_comport.h    /^    unsigned char databit, parity, stopbit, flowctrl, is_connted;$/;"    m    struct:__COM_PORT
str    cp_iniparser.c    /^    char    *   str ;$/;"    l
str    cp_ppp.c    /^    char             *str;$/;"    l
str    cp_string.c    /^    cp_string *str = t_malloc(sizeof(cp_string));$/;"    l
str    cp_string.c    /^    cp_string *str;$/;"    l
string    cp_string.c    /^    static char string[1024]; $/;"    l    file:
strlwc    cp_iniparser.c    /^static char * strlwc(const char * s)$/;"    f    file:
strstrip    cp_iniparser.c    /^static char * strstrip(const char * s)$/;"    f    file:
sval    cp_iniparser.c    /^    char * sval ;$/;"    l
t    cp_dictionary.c    /^    char * t ;$/;"    l
t1    cp_gsmmux.h    /^    unsigned int t1;$/;"    m    struct:gsm_config
t2    cp_gsmmux.h    /^    unsigned int t2;$/;"    m    struct:gsm_config
t3    cp_gsmmux.h    /^    unsigned int t3;$/;"    m    struct:gsm_config
t_free    cp_common.h    60;"    d
t_free    cp_common.h    63;"    d
t_malloc    cp_common.h    61;"    d
t_malloc    cp_common.h    64;"    d
task_array    cp_fds.h    /^    CP_ARRAY              *task_array;  \/* an array keep all these pending\/or other special task socket *\/ $/;"    m    struct:_CP_FDS
test_buzzer    test/test_hal.c    /^    int                   test_buzzer = 0;$/;"    l
test_buzzer_hal_api    test/test_hal.c    /^void test_buzzer_hal_api(void)$/;"    f
test_gprs    test/test_hal.c    /^    int                   test_gprs = 0;$/;"    l
test_gprs_hal_api    test/test_hal.c    /^void test_gprs_hal_api(void)$/;"    f
test_led    test/test_hal.c    /^    int                   test_led = 0;$/;"    l
test_led_hal_api    test/test_hal.c    /^void test_led_hal_api(void)$/;"    f
thread_attr    cp_proc.c    /^    pthread_attr_t thread_attr; $/;"    l
thread_id    cp_ppp.h    /^    pthread_t          thread_id;    \/* PPP Thread ID, RFU *\/$/;"    m    struct:__PPP_CTX
thread_start    cp_proc.c    /^int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg)$/;"    f
tid    cp_ppp.c    /^    pthread_t           tid;$/;"    l
time    cp_atcmd.h    /^    char            time[15];$/;"    m    struct:_GPRS_LOCATION
time_elapsed    cp_time.h    /^static inline unsigned long time_elapsed(unsigned long start)$/;"    f
time_now    cp_time.h    /^static inline unsigned long time_now()$/;"    f
timeout    cp_fds.h    /^    int                   timeout;      \/* epoll_wait timeout value  *\/$/;"    m    struct:_CP_FDS
timestr    cp_logger.c    /^    char timestr[256];$/;"    l
tmp    cp_atcmd.c    /^    char        tmp[ATCMD_REPLY_LEN];$/;"    l
tmp    cp_comport.c    /^    long tmp;$/;"    l
tmp    cp_iniparser.c    /^    char tmp     [ASCIILINESZ+1] ;$/;"    l
tmp    cp_ppp.c    /^    char                tmp[64];$/;"    l
tmp    cp_ppp.c    /^    char             tmp[64];$/;"    l
tmp    cp_queue.c    /^    CP_QNODE       *node, *tmp;$/;"    l
tmp    test/test_array.c    /^    CP_SOCK *tmp = NULL;$/;"    l
tmp    test/test_queue.c    /^    CP_SOCK *tmp = NULL;$/;"    l
tnow    cp_time.h    /^    struct tm *tnow = localtime(&now); $/;"    l
total    cp_ringbuf.c    /^    int total;$/;"    l
total    cp_string.c    /^    int total = 0;$/;"    l
tpdu    test/swe_tpdud.c    /^    SWE_TPDU       *tpdu;$/;"    l
tpdu    test/swe_tpdud.c    /^    SWE_TPDU       tpdu = {.lport=TPDUD_PORT, .raddr=HOSTSIM_IP, .rport=HOSTSIM_PORT};$/;"    l
tpdu    test/swe_tpdud.c    /^    SWE_TPDU      *tpdu = NULL; $/;"    l
tpdu_connect_uplink    test/swe_tpdud.c    /^int tpdu_connect_uplink(SWE_TPDU *tpdu)$/;"    f
tpdu_service_route    test/swe_tpdud.c    /^int tpdu_service_route(CP_SOCK *dlink)$/;"    f
travel_list    test/test_klist.c    /^void travel_list(struct list_head *head)$/;"    f
tsock    cp_fds.c    /^    CP_SOCK           *sock = NULL, *tsock;$/;"    l
tsock    cp_fds.c    /^    CP_SOCK           *sock, *tsock, *serv_sock;$/;"    l
tsock    cp_fds.c    /^    CP_SOCK           *sock, *tsock;$/;"    l
tsock    test/test_klist.c    /^    CP_SOCK             *sock, *tsock;$/;"    l
ttystate    cp_comport.c    /^    struct termios ttystate;$/;"    l
tv    cp_comport.c    /^    struct timeval tv;$/;"    l
tx_packets    cp_network.c    /^    unsigned long        tx_packets = 0;$/;"    l
type    cp_atcmd.h    /^    int             type;       \/*  SIM card register type: REG_HOMEWORK,REG_SEARCHING... *\/$/;"    m    struct:_REGISTER_INFO
type    cp_ppp.c    /^    unsigned char       type = APN_2G;$/;"    l
uid    cp_ppp.h    /^    char            uid[UID_LEN];    $/;"    m    struct:__APN_ACCOUNT
ulCollisions    cp_ppp.h    /^    unsigned long ulCollisions;$/;"    m    struct:__PPP_STAT
ulRx_CRC_Errors    cp_ppp.h    /^    unsigned long ulRx_CRC_Errors;  \/\/ recved pkt with crc error$/;"    m    struct:__PPP_STAT
ulRx_Compressed    cp_ppp.h    /^    unsigned long ulRx_Compressed;$/;"    m    struct:__PPP_STAT
ulRx_Dropped    cp_ppp.h    /^    unsigned long ulRx_Dropped; \/\/ no space in linux buffers$/;"    m    struct:__PPP_STAT
ulRx_Errors    cp_ppp.h    /^    unsigned long ulRx_Errors;  \/\/ bad packets received   $/;"    m    struct:__PPP_STAT
ulRx_FIFO_Errors    cp_ppp.h    /^    unsigned long ulRx_FIFO_Errors; \/\/ recv'r fifo overrun    $/;"    m    struct:__PPP_STAT
ulRx_Frame_Errors    cp_ppp.h    /^    unsigned long ulRx_Frame_Errors;    \/\/ recv'd frame alignment error$/;"    m    struct:__PPP_STAT
ulRx_Length_Errors    cp_ppp.h    /^    unsigned long ulRx_Length_Errors;$/;"    m    struct:__PPP_STAT
ulRx_Missed_Errors    cp_ppp.h    /^    unsigned long ulRx_Missed_Errors;   \/\/ receiver missed packet  $/;"    m    struct:__PPP_STAT
ulRx_Multicast    cp_ppp.h    /^    unsigned long ulRx_Multicast;   \/\/ multicast packets received   $/;"    m    struct:__PPP_STAT
ulRx_Over_Errors    cp_ppp.h    /^    unsigned long ulRx_Over_Errors; \/\/ receiver ring buff overflow$/;"    m    struct:__PPP_STAT
ulStartTime    cp_atcmd.c    /^    unsigned long        ulStartTime; $/;"    l
ulTmp    cp_time.h    /^    unsigned long ulTmp;$/;"    l
ulTx_Aborted_Errors    cp_ppp.h    /^    unsigned long ulTx_Aborted_Errors;$/;"    m    struct:__PPP_STAT
ulTx_Carrier_Errors    cp_ppp.h    /^    unsigned long ulTx_Carrier_Errors;$/;"    m    struct:__PPP_STAT
ulTx_Compressed    cp_ppp.h    /^    unsigned long ulTx_Compressed;$/;"    m    struct:__PPP_STAT
ulTx_Dropped    cp_ppp.h    /^    unsigned long ulTx_Dropped; \/\/ no space available in linux$/;"    m    struct:__PPP_STAT
ulTx_Errors    cp_ppp.h    /^    unsigned long ulTx_Errors;  \/\/ packet transmit problems$/;"    m    struct:__PPP_STAT
ulTx_FIFO_Errors    cp_ppp.h    /^    unsigned long ulTx_FIFO_Errors;$/;"    m    struct:__PPP_STAT
ulTx_Heartbeat_Errors    cp_ppp.h    /^    unsigned long ulTx_Heartbeat_Errors;$/;"    m    struct:__PPP_STAT
ulTx_Window_Errors    cp_ppp.h    /^    unsigned long ulTx_Window_Errors;$/;"    m    struct:__PPP_STAT
ulink    test/swe_tpdud.c    /^    CP_SOCK       *ulink;$/;"    l
ulink    test/swe_tpdud.h    /^    CP_SOCK             *ulink;    \/* connect to hostsim socket *\/$/;"    m    struct:_SWE_TPDU
ullRx_Bytes    cp_ppp.h    /^    unsigned long long ullRx_Bytes; \/\/ total bytes received   $/;"    m    struct:__PPP_STAT
ullRx_Packets    cp_ppp.h    /^    unsigned long long ullRx_Packets;   \/\/ total packets received $/;"    m    struct:__PPP_STAT
ullTx_Bytes    cp_ppp.h    /^    unsigned long long ullTx_Bytes; \/\/ total bytes transmitted     $/;"    m    struct:__PPP_STAT
ullTx_Packets    cp_ppp.h    /^    unsigned long long ullTx_Packets;   \/\/ total packets transmitted$/;"    m    struct:__PPP_STAT
unused    cp_gsmmux.h    /^    unsigned int unused[8];   \/* Padding for expansion without breaking stuff *\/$/;"    m    struct:gsm_config
usage    test/comport.c    /^void usage(char *name)$/;"    f
used    cp_comport.h    /^    unsigned char  used;     \/* This comport used or not now *\/$/;"    m    struct:__COM_PORT
used    cp_vector.h    /^    int           used;$/;"    m    struct:_CP_VECTOR
users    cp_gprs.h    /^    int             users;     \/* How many users use the module now  *\/$/;"    m    struct:__MODULE_INFO
v    test/test_vector.c    /^    CP_VECTOR *v = cp_vector_init(1024);$/;"    l
val    cp_dictionary.c    /^    char    *   val ;$/;"    l
val    cp_dictionary.h    /^    char        **  val ;   \/** List of string values *\/$/;"    m    struct:_dictionary_
val    cp_iniparser.c    /^    char val     [ASCIILINESZ+1] ;$/;"    l
vector    cp_vector.c    /^    CP_VECTOR  *vector = NULL;$/;"    l
who    cp_gprs.c    /^    char            *who = "atcmd_check_ready()";$/;"    l
who    cp_gprs.c    /^    char            *who = "atcmd_inspect_status()";$/;"    l
wr_pointer    cp_ringbuf.h    /^    int wr_pointer;$/;"    m    struct:ring_buffer
write    cp_sock.h    /^    CP_SOCK_EVENT_CALLBACK  write;$/;"    m    struct:_CP_SOCK_CALLBACK
xstrdup    cp_dictionary.c    /^static char * xstrdup(const char * s)$/;"    f    file:
program/cp_library/test/comport.c
New file
@@ -0,0 +1,238 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  comport.c
 *    Description:  This file used to do ioctl() on common device or communicate
 *                  with serial port/TTY device.
 *
 *        Version:  1.0.0(10/18/2011~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/18/2011 10:08:05 AM"
 *
 ********************************************************************************/
#include <getopt.h>
#include <libgen.h>
#include <sys/ioctl.h>
#include "cp_comport.h"
#include "cp_common.h"
#include "version.h"
unsigned char g_ucProcToken = 0x01;
unsigned char g_ucCtrlZ;
void print_version(char *name);
void usage(char *name);
int do_ioctl(char *dev_name, int cmd, int arg);
void signal_handler(int i_sig);
int main(int argc, char **argv)
{
    int opt = 0;
    int retval = 0;
    int recv_size = 0;
    int i;
    char *dev_name = NULL;
    int baudrate = 115200;
    char *settings = "8N1N";
    char buf[512];
    unsigned char disp_mode = 0x00;
    struct sigaction sigact;
    struct option long_options[] = {
        {"device", required_argument, NULL, 'd'},
        {"baudrate", required_argument, NULL, 'b'},
        {"settings", required_argument, NULL, 's'},
        {"ioctl", required_argument, NULL, 'i'},
        {"hex", no_argument, NULL, 'x'},
        {"version", no_argument, NULL, 'v'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };
    while ((opt = getopt_long(argc, argv, "d:b:s:ivh", long_options, NULL)) != -1)
    {
        switch (opt)
        {
          case 'd':
              dev_name = optarg;
              break;
          case 'b':
              baudrate = atoi(optarg);
              break;
          case 's':            /* Default settings as 8N1N */
              settings = optarg;
              break;
          case 'i':
              if (5 != argc)
              {
                  usage(argv[0]);
              }
              else
              {
                  do_ioctl(argv[2], atoi(argv[3]), atoi(argv[4]));
              }
              return 0;
          case 'x':            /* Display receive data as Hex mode */
              disp_mode = 0x01;
              break;
          case 'v':            /* version */
              print_version(argv[0]);
              return 0;
          case 'h':            /* help */
              usage(argv[0]);
              return 0;
          default:
              break;
        }                       /* end of "switch(opt)" */
    }
    if (argc < 2)
    {
        usage(argv[0]);
        return 0;
    }
    COM_PORT *comport = NULL;
    if (NULL == (comport = comport_init(dev_name, baudrate, settings)))
    {
        printf("Comport initialize failure.\n");
        return -1;
    }
    if ( (retval=comport_open(comport)) < 0)
    {
        printf("Failed to open %s with baudrate %d, %s. RetCode [%d]\n", dev_name, baudrate,
               settings, retval);
        return -1;
    }
    nonblock();
    /* Process level signal handler */
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigact.sa_handler = signal_handler;
    sigaction(SIGTERM, &sigact, NULL);  /* catch terminate signal */
    sigaction(SIGINT, &sigact, NULL);   /* catch interrupt signal */
    sigaction(SIGSEGV, &sigact, NULL);  /* catch segmentation faults */
    sigaction(SIGTSTP, &sigact, NULL);  /* catch ctrl+Z */
    sigaction(SIGSTOP, &sigact, NULL);  /* catch ctrl+Z */
    while (0x01 == g_ucProcToken)
    {
        recv_size = comport_recv(comport, buf, sizeof(buf) - 1, 10);
        if (recv_size > 0)
        {
            for (i = 0; i < recv_size; i++)
            {
                if (0 == disp_mode)
                    printf("%c", buf[i]);
                else
                    printf("%02X ", buf[i]);
            }
            fflush(stdout);
        }
        if (0 != kbhit())
        {
            retval = fgetc(stdin);
            if (0x0A == retval)
            {
                buf[0] = 0x0D; /* 13 == 0x0D */
            }
            else
            {
                buf[0] = retval;
            }
            comport_send(comport, buf, 1);
        }
        else if (0x00 != g_ucCtrlZ)
        {
            g_ucCtrlZ = 0x00;
            buf[0] = 0x1A;
            comport_send(comport, buf, 1);
        }
    }
    comport_term(comport);
    return 0;
}                               /* ----- End of main() ----- */
void print_version(char *name)
{
    char *progname = NULL;
    char *ptr = NULL;
    ptr = strdup(name);
    progname = basename(ptr);
    printf("%s version: %d.%d.%d Build %04d on %s\n", progname, MAJOR, MINOR, REVER, SVNVER, DATE);
    printf("Copyright (C) 2010 guowenxue <guowenxue@gmail.com>\n");
    t_free(ptr);
    return;
}
void usage(char *name)
{
    char *progname = NULL;
    char *ptr = NULL;
    ptr = strdup(name);
    progname = basename(ptr);
    printf("Usage1: comport -d <device> [-b <baudrate>][-s <settings>] [-x]\n");
    printf("Usage2: comport [-i <driver port> <cmd> <arg>][--help][--version]\n");
    printf(" -d[device  ]  device name\n");
    printf(" -b[baudrate]  device baudrate (115200, 57600, 19200, 9600), default is 115200\n");
    printf(" -s[settings]  device settings as like 8N1N(default setting)\n");
    printf("                 - data bits: 8, 7\n");
    printf("                 - parity: N=None, O=Odd, E=Even, S=Space\n");
    printf("                 - stop bits: 1, 0\n");
    printf("                 - flow control: N=None, H=Hardware, S=Software, B=Both\n");
    printf(" -x[hex     ]  display received data in hex format\n");
    printf(" -i[ioctl   ]  ioctl system call (cmd & arg only support int)\n");
    printf(" -v[version ]  Display the program version\n");
    printf(" -h[help    ]  Display this help information\n");
    print_version(progname);
    t_free(ptr);
    return;
}
int do_ioctl(char *dev_name, int cmd, int arg)
{
    int fd = -1;
    int retval = -1;
    if (((fd = open(dev_name, O_RDWR)) < 0))
    {
        printf("Open device \"%s\" failure: %s\n", dev_name, strerror(errno));
        return -1;
    }
    retval = ioctl(fd, cmd, arg);
    printf("ioctl (%s, %d, %d) returned %d\n", dev_name, cmd, arg, retval);
    close(fd);
    return retval;
}
void signal_handler(int i_sig)
{
    if (SIGTERM == i_sig || SIGINT == i_sig)
    {
        g_ucProcToken = 0x00;
    }
    else if (20 == i_sig)
    {
        g_ucCtrlZ = 0x01;
    }
}
program/cp_library/test/makefile
New file
@@ -0,0 +1,121 @@
#*********************************************************************************
#      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
#                  All rights reserved.
#
#       Filename:  Makefile
#    Description:  This Makefile used to compile all the C source code file in current
#                  folder to respective excutable binary files.
#
#        Version:  1.0.0(10/08/2011~)
#                  Author:  Guo Wenxue <guowenxue@gmail.com>
#      ChangeLog:  1, Release initial version on "11/11/2011 01:29:33 PM"
#
#********************************************************************************/
PWD=$(shell pwd)
LIB_PATH=$(shell dirname ${PWD})
LIB_NAME=$(shell basename ${LIB_PATH})
INSTPATH=/tftp
#ARCH ?= i386
#ARCH?=arm926t
ARCH?=arm920t
#LINK_MODE=STATIC
MODE=PRODUCTION
DEBUG=1
CFLAGS+=-Wall -Werror
#CFLAGS+=-Wno-unused
ifeq ("${MODE}", "PRODUCTION")
    CFLAGS+=-DPRODUCTION_MODE
endif
ifdef DEBUG
    CFLAGS+=-g -DDEBUG
endif
COMPILE_DATE=$(shell date -u +"%Y-%m-%d %H:%M")
VPATH= .
SRCS = $(wildcard ${VPATH}/*.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]")
ifneq (,$(filter i386,$(TMP)))
    CROSS_COMPILE=
else
    CROSS_COMPILE=/opt/buildroot-2012.08/$(ARCH)/usr/bin/arm-linux-
endif
CFLAGS+=-I${LIB_PATH}
LDFLAGS+=-L${LIB_PATH} -l${LIB_NAME}
export CC=${CROSS_COMPILE}gcc
export CXX=${CROSS_COMPILE}g++
export AR=${CROSS_COMPILE}ar
export AS=${CROSS_COMPILE}as
export RANLIB=${CROSS_COMPILE}ranlib
export STRIP=${CROSS_COMPILE}strip
export CFLAGS
export LDFLAGS
export ARCH
export LINK_MODE
LDFLAGS+=-lpthread
ifeq ("${LINK_MODE}", "STATIC")
    CFLAGS+=--static
    LDFLAGS+=-static
else
    LDFLAGS+=-ldl
endif
SRCFILES = $(wildcard *.c)
BINARIES=$(SRCFILES:%.c=%)
all: entry version binaries install
entry:
    @echo " ";
    @echo " =========================================================";
    @echo " **        Compile \"${BINARIES}\" for ${ARCH}         ";
    @echo " =========================================================";
version:
    @echo "/* Generated by makefile, don't Edit it by hand */" > version.h
    @echo "#define DATE \"$(COMPILE_DATE)\"" >> version.h
    @echo "#define MAJOR 1" >>version.h
    @echo "#define MINOR 0" >>version.h
    @echo "#define REVER 0" >>version.h
    @if [ -f .svn/entries ] ; then \
        echo "#define SVNVER `sed -n -e 11p .svn/entries`" >>version.h; \
    else \
        echo "#define SVNVER 0" >>version.h; \
    fi;
    @echo "" >> version.h
    @echo '#define version(progname) printf("%s Version %d.%d.%d Build @%05d (%s)\n", progname, MAJOR, MINOR, REVER,SVNVER, DATE)'  >> version.h
    @echo '#define copyright() printf("Copyright:  (C) 2012 Guo Wenxue<Email:guowenxue@gmail.com\n")' >>version.h
    @echo '#define banner(progname) {version(progname); copyright(); printf("\n");}' >>version.h
    @echo "" >> version.h
binaries:  ${BINARIES}
    @echo " Compile over"
%:  %.c
    $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
tag:
    @ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R .
    @cscope -Rbq
install:
    @cp $(BINARIES) ${INSTPATH}
clean:
    @rm -f version.h
    @rm -f *.o *.lo $(BINARIES)
    @rm -rf *.gdb *.a *.so *.elf*
    @rm -f *.log
distclean: clean
    @rm -f  tags cscope*
.PHONY: clean entry
program/cp_library/test/sample.ini
New file
@@ -0,0 +1,11 @@
[section1]
key1                           = 15
key2                           = hello
[section2]
key1                           = 30
key2                           = world
program/cp_library/test/swe_tpdud.c
New file
@@ -0,0 +1,360 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  tpdud.c
 *    Description:  This file
 *
 *        Version:  1.0.0(10/30/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/30/2012 01:15:18 PM"
 *
 ********************************************************************************/
#include <unistd.h>
#include <getopt.h>
#include <libgen.h>
#include "cp_common.h"
#include "cp_network.h"
#include "cp_logger.h"
#include "cp_proc.h"
#include "cp_time.h"
#include "swe_tpdud.h"
#include "version.h"
static void stop_tpdu_service(SWE_TPDU *tpdu)
{
    if(!tpdu)
        return ;
    log_dbg("release tpdu contex [%p]\n", tpdu);
    if( tpdu->dlink )
    {
        log_nrml("stop tpdu service for downlink socket [%p:%d]\n", tpdu->dlink, tpdu->dlink->fd);
        cp_fds_destroy_sock_clear(tpdu->dlink);
        tpdu->dlink = NULL;
    }
    if( tpdu->ulink )
    {
        log_nrml("stop tpdu service for uplink socket [%p:%d]\n", tpdu->ulink, tpdu->ulink->fd);
        cp_fds_destroy_sock_clear(tpdu->ulink);
        tpdu->ulink = NULL;
    }
    t_free(tpdu);
}
int proc_uplink_event(CP_SOCK *ulink)
{
    int           rv;
    CP_SOCK       *dlink = NULL;
    SWE_TPDU      *tpdu = NULL;
    if(!ulink || !(tpdu=ulink->privt) || !(dlink=tpdu->dlink))
    {
        log_err("tpdu address:[%p] ulink address:[%p] dlink address:[%p]\n", tpdu, ulink, dlink);
        return -1;
    }
    if(ulink->status == SOCK_STAT_DISCONNECT)
    {
        goto stop_service;
    }
    if(ulink->event.events & CP_SOCK_EVENT_READ)
    {
        rv = cp_sock_recv(ulink);
        if( 0==rv )
        {
            log_warn("Socket [%d %s:%d] remote socket [%s:%d] disconnect, remove it now\n",
                    ulink->fd, ulink->laddr, ulink->lport, ulink->raddr, ulink->rport);
            goto stop_service;
        }
        else if(rv > 0)
        {
            log_nrml("Socket [%d %s:%d] receive %d bytes data:\n", ulink->fd, ulink->laddr, ulink->lport, rv);
            cp_log_dump(LOG_LEVEL_DEBUG, ulink->rbuf->data, ulink->rbuf->len);
            if(ulink->rbuf->len > 0)
            {
                cp_string_move(dlink->sbuf, ulink->rbuf);
                cp_sock_send(dlink);
            }
        }
        else
        {
            log_err("Socket [%d %s:%d] receive data failed: %s\n", ulink->fd, ulink->laddr, ulink->lport, strerror(errno));
        }
    }
    else if(ulink->event.events & CP_SOCK_EVENT_IDLE_TIMEOUT)
    {
        log_warn("uplink socket [%d] is idle and to-do something here\n");
    }
    else if(ulink->event.events & CP_SOCK_EVENT_MSG_TIMEOUT)
    {
        log_warn("uplink socket [%d] message is timeout and to-do something here\n");
    }
    return 0;
stop_service:
    stop_tpdu_service(tpdu);
    return 0;
}
/* Connect to hostsim */
int tpdu_connect_uplink(SWE_TPDU *tpdu)
{
    CP_SOCK       *ulink;
    CP_SOCK       *dlink;
    if(!tpdu || !(dlink=tpdu->dlink))
    {
        log_err("tpdu address [%p] dlink address [%p]\n", tpdu, dlink);
        return -1;
    }
    ulink = tpdu->ulink;
    ulink=cp_sock_connect_regist(dlink->fds, ulink, tpdu->raddr, tpdu->rport, 0, proc_uplink_event);
    if( !ulink ) /* connect failure */
    {
        /* the uplink connect failure or connect already, then we should
         * remove the downlink socket from task list  */
        log_err("connect to remote [%s:%d] failure\n", tpdu->raddr, tpdu->rport);
        tpdu->ulink = NULL;
        return -1;
    }
    else /* connecting in progress */
    {
        ulink->privt = tpdu;
        tpdu->ulink = ulink;
        log_info("connect to remote [%s:%d] in progress\n", tpdu->raddr, tpdu->rport);
        cp_fds_add_sock_task(dlink);
        dlink->event.events = 0;  /* clear the events flag */
    }
    return 0;
}
int tpdu_service_route(CP_SOCK *dlink)
{
    int            rv = 0;
    SWE_TPDU       *tpdu;
    if( !dlink )
        return -1;
    tpdu = dlink->privt;
    /* If it's first data incoming from the dlink, then we should
     * malloc a TPDU work context now and save it */
    if( !tpdu )
    {
        if( !(tpdu=t_malloc(sizeof(*tpdu))) )
        {
            log_err("Malloc TPDU work contex failure\n");
            goto stop_service;
        }
        else
        {
            SWE_TPDU       *serv_tpdu;
            log_info("malloc TPDU work contex [%p]\n", tpdu);
            serv_tpdu = dlink->serv_sock->privt;
            dlink->privt = tpdu;
            tpdu->dlink = dlink;
            strcpy(tpdu->raddr, serv_tpdu->raddr);
            tpdu->rport = serv_tpdu->rport;
        }
    }
    log_dbg("Process socket [%d %s:%d] with event [%d]\n", dlink->fd, dlink->laddr, dlink->lport, dlink->event.events);
    /* If there is data incoming from this socket, now we receive the data */
    if(dlink->event.events & CP_SOCK_EVENT_READ)
    {
        rv = cp_sock_recv(dlink);
        if( rv == 0 )
        {
            log_warn("Socket [%d %s:%d] remote socket [%s:%d] disconnect, remove it now\n",
                    dlink->fd, dlink->laddr, dlink->lport, dlink->raddr, dlink->rport);
            goto stop_service;
        }
        else if( rv < 0)
        {
            log_err("Socket [%d %s:%d] receive data failed: %s\n", dlink->fd, dlink->laddr, dlink->lport, strerror(errno));
            goto stop_service;
        }
        /* Receive data OK */
        log_nrml("Socket [%d %s:%d] receive %d bytes data:\n", dlink->fd, dlink->laddr, dlink->lport, rv);
        cp_log_dump(LOG_LEVEL_DEBUG, dlink->rbuf->data, dlink->rbuf->len);
    }
    else if(dlink->event.events & CP_SOCK_EVENT_HUP)
    {
        log_warn("socket [%d] remote already disconnect\n", dlink->fd);
        dlink->status = SOCK_STAT_DISCONNECT;
        goto stop_service;
    }
    else if(dlink->event.events & CP_SOCK_EVENT_IDLE_TIMEOUT)
    {
        log_warn("socket [%d] is idle and to-do something here\n");
    }
    else if(dlink->event.events & CP_SOCK_EVENT_MSG_TIMEOUT)
    {
        log_warn("socket [%d] message is timeout and to-do something here\n");
    }
    /* If we have receive some data already, now we need do TPDU parser to
     * get the remote server address and port */
    if( dlink->rbuf->len > 0)
    {
        SWE_TPDU    *arg = dlink->serv_sock->privt;
        /* To-Do: parser downlink data here and get the uplink IP address and port */
        tpdu->rport = arg->rport;
        strncpy(tpdu->raddr, arg->raddr, sizeof(tpdu->raddr));
    }
    /* If not connect to the remote host or it's still connecting, then we do it again  */
    if( !tpdu->ulink || (tpdu->ulink->status==SOCK_STAT_CONNECTING))
    {
        log_nrml("tpdu dlink: %p\n", tpdu->dlink);
        if( tpdu_connect_uplink(tpdu) < 0 )
            goto stop_service;
    }
    /* If connect to the remote host already, now we send the data to the remote host  */
    if( !tpdu->ulink || (tpdu->ulink->status==SOCK_STAT_CONNECTED))
    {
        log_dbg("connect to remote [%s:%d] ok and send %d bytes data\n", tpdu->raddr, tpdu->rport, dlink->rbuf->len);
        cp_fds_del_sock_task(dlink);
        if(dlink->rbuf->len > 0)
        {
            cp_string_move(tpdu->ulink->sbuf, dlink->rbuf);
            cp_sock_send(tpdu->ulink);  /* send the data to the remote host  */
            return 0;
        }
    }
    return 0;
stop_service:
    stop_tpdu_service(tpdu);
    tpdu = NULL;
    return 0;
}
void print_usage(char *progname)
{
    version(progname);
    printf("Usage: %s [OPTION]...\n", progname);
    printf(" %s is a handle program to create a tunnel between an incoming and outgoing FD\n", progname);
    printf("\nMandatory arguments to long options are mandatory for short options too:\n");
    printf(" -l[loglevel]  To configure the logger level [0(DIS)...8(MAX)], default 4[NRML]\n");
    printf(" -p[port    ]  To configure the listening port, default [%d]\n", TPDUD_PORT);
    printf(" -i[RemoteIP]  To configure the remote/outgoing IP, default [%s]\n", HOSTSIM_IP);
    printf(" -o[outgoing]  To configure the remote/outgoing Port, default [%d]\n", HOSTSIM_PORT);
    printf(" -h[help    ]  Display this help information\n");
    printf(" -v[version ]  Display the program version\n");
    printf("\n");
    return ;
}
/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    CP_FDS         *fds;
    CP_SOCK        *sock;
    SWE_TPDU       tpdu = {.lport=TPDUD_PORT, .raddr=HOSTSIM_IP, .rport=HOSTSIM_PORT};
    int            opt;
    int            loglevel = LOG_LEVEL_NRML;
    struct option  long_options[] =
    {
        {"loglevel", required_argument, NULL, 'l'},
        {"port", required_argument, NULL, 'p'},
        {"host", required_argument, NULL, 'i'},
        {"outgoing", required_argument, NULL, 'o'},
        {"version", no_argument, NULL, 'v'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };
    while ((opt = getopt_long(argc, argv, "l:p:i:o:vh", long_options, NULL)) != -1)
    {
        switch (opt)
        {
            case 'l':
                loglevel = atoi(optarg);
                break;
            case 'p':
                tpdu.lport = atoi(optarg);
                break;
            case 'i':
                strncpy(tpdu.raddr, optarg, sizeof(tpdu.raddr));
                break;
            case 'o':
                tpdu.rport = atoi(optarg);
                break;
            case 'v':
                version(basename(argv[0]));
                return EXIT_SUCCESS;
            case 'h':
                print_usage(basename(argv[0]));
                return EXIT_SUCCESS;
            default:
                break;
        }
    }
    //if (!cp_log_init(NULL, "tpdud.log", LOG_LEVEL_MAX, LOG_ROLLBACK_NONE) || cp_log_open())
    //if (!cp_log_init(NULL, "tpdud.log", loglevel, LOG_ROLLBACK_SIZE) || cp_log_open())
    if (!cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_MAX, LOG_ROLLBACK_NONE) || cp_log_open())
    //if (!cp_log_init(NULL, DBG_LOG_FILE, loglevel, LOG_ROLLBACK_NONE) || cp_log_open())
        goto cleanup;
    cp_install_proc_signal();
    if( !(fds=cp_fds_init(NULL, CP_DEF_MAX_EVENTS, CP_DEF_FDS_TIMEOUT)) )
        goto cleanup;
    if( !(sock=cp_sock_server_regist(fds, NULL, tpdu.lport, 0, tpdu_service_route, (void *)&tpdu)) )
        goto cleanup;
    while( !g_cp_signal.stop )
    {
        cp_fds_detect_event(fds);
        cp_fds_proc_event(fds);
        cp_sock_detect_timeout(fds);
        micro_second_sleep(10);
    }
cleanup:
    cp_sock_term_all_service_clear(fds);
    cp_log_term();
    return 0;
} /* ----- End of main() ----- */
program/cp_library/test/swe_tpdud.h
New file
@@ -0,0 +1,42 @@
/********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  tpdud.h
 *    Description:  This head file
 *
 *        Version:  1.0.0(11/19/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/19/2012 11:21:05 AM"
 *
 ********************************************************************************/
#ifndef __SWE_TPDUD_H
#define __SWE_TPDUD_H
#include <cp_sock.h>
#define HOSTSIM_PORT          9002
#define HOSTSIM_IP            "192.168.3.6"
#define TPDUD_PORT            8000
#define UPLINK_ADDR           HOSTSIM_IP
#define UPLINK_PORT           HOSTSIM_PORT
#define FLAG_TPDU_INIT        (1<<0)
#define FLAG_TPDU_STOP        (1<<7)
typedef struct _SWE_TPDU
{
    unsigned char       flag;
    char                raddr[32]; /* uplink remote listen port */
    int                 lport;     /* dlink  local listen port  */
    int                 rport;     /* uplink remote IP address  */
    CP_SOCK             *dlink;    /* listen port accept socket */
    CP_SOCK             *ulink;    /* connect to hostsim socket */
} SWE_TPDU;
#endif
program/cp_library/test/test_array.c
New file
@@ -0,0 +1,82 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  test_array.c
 *    Description:  This file used to test the array library
 *
 *        Version:  1.0.0(08/14/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "08/14/2012 05:17:03 PM"
 *
 ********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cp_array.h"
#include "cp_sock.h"
#include "cp_logger.h"
#define MAX_ITEMS  10
/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    int i;
    CP_SOCK *sock = NULL;
    CP_SOCK *tmp = NULL;
    CP_ARRAY *array = NULL;
    if (!cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_MAX, LOG_ROLLBACK_NONE) || cp_log_open())
        return 0;
    if( !(array=cp_array_init(NULL, MAX_ITEMS)) )
        return -1;
    for (i=0; i<MAX_ITEMS; i++)
    {
        sock = cp_sock_init(NULL, 1024, 1024, 10, 30);
        if( cp_array_add(array, sock)<0 )
        {
            cp_sock_term(sock);
        }
        else
        {
            if(i==3)
            {
                tmp = sock;
            }
        }
    }
    printf("Array usage %d/%d \n", cp_array_count(array), cp_array_size(array));
    cp_array_travel(array);
    if( !cp_array_rm_bydata(array, tmp) )
    {
        printf("remove and terminate sock [%p] from array\n", tmp);
        cp_sock_term(tmp);
    }
    cp_array_travel(array);
    cp_list_array_for_each(array, i, sock)
    {
        cp_sock_term(sock);
    }
    cp_array_term(array);
    cp_log_term();
    return 0;
} /* ----- End of main() ----- */
program/cp_library/test/test_hal.c
New file
@@ -0,0 +1,210 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  test_hal.c
 *    Description:  This file
 *
 *        Version:  1.0.0(12/05/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "12/05/2012 04:52:59 PM"
 *
 ********************************************************************************/
#include <libgen.h>
#include <getopt.h>
#include "cp_hal.h"
#define  HAL_LIBRARY_TEST
void test_led_hal_api(void)
{
    printf("+------------------------------------+\n");
    printf("|          Test LED HAL API          |\n");
    printf("+------------------------------------+\n");
    printf("Turn all LED off\n");
    hal_turn_led_off(LED_ALL);
    sleep(2);
    printf("Turn LED blink one by one\n");
    hal_turn_led_blink(LED_SYS, MODE_FAST);
    hal_turn_led_blink(LED_SIM1, MODE_FAST);
    hal_turn_led_blink(LED_SIM2, MODE_FAST);
    hal_turn_led_blink(LED_WIFI, MODE_FAST);
    hal_turn_led_blink(LED_ETH, MODE_FAST);
    sleep(4);
    printf("Turn LED off one by one\n");
    hal_turn_led_off(LED_SYS);
    hal_turn_led_off(LED_SIM1);
    hal_turn_led_off(LED_SIM2);
    hal_turn_led_off(LED_WIFI);
    hal_turn_led_off(LED_ETH);
    sleep(4);
    printf("Turn LED on one by one\n");
    hal_turn_led_on(LED_SYS);
    hal_turn_led_on(LED_SIM1);
    hal_turn_led_on(LED_SIM2);
    hal_turn_led_on(LED_WIFI);
    hal_turn_led_on(LED_ETH);
    sleep(4);
    printf("Turn all LED off\n");
    hal_turn_led_off(LED_ALL);
    sleep(2);
    printf("Turn all LED blink\n");
    hal_turn_led_blink(LED_ALL, MODE_SLOW);
    sleep(4);
    printf("Turn all LED on\n");
    hal_turn_led_on(LED_ALL);
    sleep(4);
    hal_turn_led_off(LED_ALL);
}
void test_buzzer_hal_api(void)
{
    printf("+------------------------------------+\n");
    printf("|         Test Buzzer HAL API        |\n");
    printf("+------------------------------------+\n");
    printf("Turn buzzer on\n");
    hal_turn_buzzer_on();
    sleep(2);
    printf("Turn buzzer off\n");
    hal_turn_buzzer_off();
    sleep(2);
    printf("Turn buzzer beep for 5 times\n");
    hal_turn_buzzer_beep(3);
    sleep(4);
    printf("Turn buzzer off\n");
    hal_turn_buzzer_off();
    sleep(3);
    printf("Turn buzzer beep infinitely\n");
    hal_turn_buzzer_beep(0);
    sleep(5);
    printf("Turn buzzer off\n");
    hal_turn_buzzer_off();
}
void test_gprs_hal_api(void)
{
    int        rv = 0;
    printf("+------------------------------------+\n");
    printf("|         Test GPRS HAL API          |\n");
    printf("+------------------------------------+\n");
    hal_poweron_gprs(SIM_NONE);
    rv = hal_check_simdoor(SIM_ALL);
    printf("Check all SIM card present status: 0x%02x\n", rv);
    rv = hal_check_simdoor(SIM1);
    printf("Check SIM1 card present status: 0x%02x\n", rv);
    rv = hal_check_simdoor(SIM2);
    printf("Check SIM2 card present status: 0x%02x\n", rv);
    printf("Get current working SIM card: 0x%02x\n", hal_get_worksim());
    hal_set_worksim(SIM2);
    printf("Set current working SIM to SIM2\n");
    printf("Get current working SIM card: 0x%02x\n", hal_get_worksim());
    hal_set_worksim(SIM1);
    printf("Set current working SIM to SIM1\n");
    printf("Get current working SIM card: 0x%02x\n", hal_get_worksim());
    hal_poweroff_gprs();
}
void print_usage(char *progname)
{
    printf("Usage: %s [OPTION]...\n", progname);
    printf("\nMandatory arguments to long options are mandatory for short options too:\n");
    printf(" -l[led     ]  Test LED HAL API\n");
    printf(" -b[buzzer  ]  Test Buzzer HAL API\n");
    printf(" -g[gprs    ]  Test GPRS HAL API\n");
    printf(" -h[help    ]  Display this help information\n");
}
#ifdef HAL_LIBRARY_TEST
/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    int                   opt;
    char                  *progname=NULL;
    int                   test_led = 0;
    int                   test_gprs = 0;
    int                   test_buzzer = 0;
    struct option long_options[] = {
        {"led", no_argument, NULL, 'l'},
        {"buzzer", no_argument, NULL, 'b'},
        {"gprs", no_argument, NULL, 'g'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };
    progname = basename(argv[0]);
    while ((opt = getopt_long(argc, argv, "bghl", long_options, NULL)) != -1)
    {
        switch(opt)
        {
            case 'b':
                test_buzzer = 1;
                break;
            case 'l':
                test_led = 1;
                break;
            case 'g':
                test_gprs = 1;
                break;
            case 'h':
                print_usage(progname);
            default:
                break;
        }
    }
    if(!test_buzzer && !test_led && !test_gprs)
        print_usage(progname);
    if(test_buzzer)
        test_buzzer_hal_api();
    if(test_led)
        test_led_hal_api();
    if(test_gprs)
        test_gprs_hal_api();
    return 0;
} /* ----- End of main() ----- */
#endif /*  HAL_LIBRARY_TEST */
program/cp_library/test/test_hh.c
New file
@@ -0,0 +1,85 @@
/*********************************************************************************
 *      Copyright:  (C) 2013 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  test_hh.c
 *    Description:  This file
 *
 *        Version:  1.0.0(01/28/2013~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "01/28/2013 03:35:36 PM"
 *
 ********************************************************************************/
#include <libgen.h>
#include "cp_comport.h"
#define HH_DATAPORT     "/dev/ttySSHHR"
/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    int             i;
    COM_PORT        *comport = NULL;
    unsigned char   sbuf[10]={0x02, 0x48, 0x32, 0x03, 0x20, 0x00, 0x00, 0xF6, 0xBE, 0x03};
    unsigned char   rbuf[10];
#if 0
    char            *HH_DATAPORT = NULL;
    if(argc != 2)
    {
        printf("Usage: %s [device name]\n", basename(argv[0]));
        return 0;
    }
    HH_DATAPORT = argv[1];
#endif
    if( !(comport=comport_init(HH_DATAPORT, 115200, "8N1N")) )
    {
        printf("Initialise comport %s failure\n", HH_DATAPORT);
        return -1;
    }
    if(comport_open(comport)<0)
    {
        printf("Open comport %s failure\n", HH_DATAPORT);
        return -1;
    }
    if(comport_send(comport, (char *)sbuf, sizeof(sbuf)) < 0)
    {
        printf("Send 10 bytes data to %s failure\n", HH_DATAPORT);
        return -1;
    }
    printf("Send %d bytes data to %s:\n>>", sizeof(sbuf), HH_DATAPORT);
    for(i=0; i<10; i++)
    {
        printf("%02x ", sbuf[i]);
    }
    printf("\n");
    memset(rbuf, 0, sizeof(rbuf));
    if((i=comport_recv(comport, (char *)rbuf, sizeof(rbuf), 5000)) < 0)
    {
        printf("Receive 10 bytes data to %s failure\n", HH_DATAPORT);
        return -1;
    }
    printf("Receive %d bytes data from %s:\n<<", i, HH_DATAPORT);
    for(i=0; i<10; i++)
    {
        printf("%02x ", rbuf[i]);
    }
    printf("\n");
    comport_term(comport);
    return 0;
} /* ----- End of main() ----- */
program/cp_library/test/test_ini.c
New file
@@ -0,0 +1,48 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  test_ini.c
 *    Description:  This file
 *
 *        Version:  1.0.0(12/18/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "12/18/2012 10:54:09 AM"
 *
 ********************************************************************************/
#include "cp_iniparser.h"
#define INI_CONF   "sample.ini"
/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    dictionary   *ini;
    FILE         *fp;
    ini=iniparser_load(INI_CONF);
    fp=fopen(INI_CONF, "w+");
    iniparser_set(ini, "section1:key1", "30");
    iniparser_dump(ini, stderr);
    iniparser_dump_ini(ini, fp);
    iniparser_freedict(ini);
    return 0;
} /* ----- End of main() ----- */
program/cp_library/test/test_klist.c
New file
@@ -0,0 +1,79 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  test_klist.c
 *    Description:  This file is for test kernel space double linked list.
 *
 *        Version:  1.0.0(11/12/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/12/2012 04:26:39 PM"
 *
 ********************************************************************************/
#include "cp_klist.h"
#include "cp_sock.h"
//#define LIST_REVERSE
void travel_list(struct list_head *head)
{
    CP_SOCK             *sock, *tsock;
    if( (sock=cp_sock_init(NULL, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) )
    {
        list_add_tail(&sock->rlist, head);
        printf("Add new socket %p to sock_list \n", sock);
    }
    /* Use list_for_each_entry to travel the socket list, we can not remove the node in it */
    list_for_each_entry_safe(sock, tsock, head, rlist)
    {
        printf("Travel2 socket list on socket %p\n", sock);
    }
}
/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    int                 i;
    struct list_head    sock_list;
    CP_SOCK             *sock, *tsock;
    INIT_LIST_HEAD(&sock_list);
    for(i=0; i<10; i++)
    {
        if( (sock=cp_sock_init(NULL, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) )
        {
            list_add_tail(&sock->rlist, &sock_list);
            printf("Add socket %p to sock_list \n", sock);
        }
    }
    /* Use list_for_each_entry to travel the socket list, we can not remove the node in it */
    list_for_each_entry(sock, &sock_list, rlist)
    {
        printf("Travel socket list on socket %p\n", sock);
    }
    travel_list(&sock_list);
    /* Use list_for_each_entry_safe to travel the socket list and destroy the socket */
    list_for_each_entry_safe(sock, tsock, &sock_list, rlist)
    {
        list_del(&sock->rlist);
        cp_sock_term(sock);
        printf("Remove and destroy socket %p from socket list\n", sock);
    }
    return 0;
} /* ----- End of main() ----- */
program/cp_library/test/test_logger.c
New file
@@ -0,0 +1,58 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  test_logger.c
 *    Description:  This is the linux logger system test code.
 *
 *        Version:  1.0.0(08/08/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "08/08/2012 06:51:40 PM"
 *
 ********************************************************************************/
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <libgen.h>
#include "cp_logger.h"
/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    char    buf[30]="Hello World!\n";
    char    file[FILENAME_LEN];
    snprintf(file, FILENAME_LEN, "%s.log", basename(argv[0]) );
    //if (! cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_NRML, LOG_ROLLBACK_NONE) )
    //if (! cp_log_init(NULL, DEFAULT_LOGFILE, LOG_LEVEL_MAX, LOG_ROLLBACK_SIZE) )
    if(! cp_log_init(NULL, file, LOG_LEVEL_MAX, 12) || cp_log_open() )
        return 0;
    while(1)
    {
        log_info("1connection.\n");
        log_dbg("2connection.\n");
        log_nrml("3connection.\n");
        log_warn("4connection.\n");
        log_err("5connection.\n");
        log_fatal("6connection.\n");
        cp_log_dump(LOG_LEVEL_DEBUG, buf, 30);
        sleep(1);
    }
    cp_log_term();
    return 0;
} /* ----- End of main() ----- */
program/cp_library/test/test_queue.c
New file
@@ -0,0 +1,84 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  test_queue.c
 *    Description:  This file used to test the queue library
 *
 *        Version:  1.0.0(08/14/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "08/14/2012 05:17:03 PM"
 *
 ********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cp_queue.h"
#include "cp_sock.h"
#define MAX_ITEMS  10
/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    int i;
    CP_SOCK *sock = NULL;
    CP_SOCK *tmp = NULL;
    CP_QUEUE *queue = NULL;
    queue = cp_queue_init(NULL, MAX_ITEMS);
    //for (i=0; i<MAX_ITEMS; i++)
    for (i=0; i<MAX_ITEMS+10; i++)
    //for (i=0; i<MAX_ITEMS-3; i++)
    {
        sock = cp_sock_init(NULL, 1024, 1024, 10, 30);
        if( NULL==cp_enqueue(queue, sock) )
        {
            cp_sock_term(sock);
        }
        else
        {
            if(i==3)
            {
                tmp = sock;
            }
            printf("enqueue sock %p\n", sock);
        }
    }
    printf("queue usage %d/%d \n", cp_queue_count(queue), cp_queue_size(queue));
    cp_travel_queue(queue);
    if( cp_rmqueue(queue, tmp) )
    {
        printf("remove and terminate sock [%p] from queue\n", tmp);
        cp_sock_term(tmp);
    }
    cp_travel_queue(queue);
    while(!cp_queue_is_empty(queue))
    {
        if( (sock=cp_dequeue(queue)) )
        {
            printf("Terminate socket: %p\n", sock);
            cp_sock_term(sock);
        }
    }
    cp_queue_destroy(queue);
    return 0;
} /* ----- End of main() ----- */
program/cp_library/test/test_sock_client.c
New file
@@ -0,0 +1,110 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  test_client_sock.c
 *    Description:  This file
 *
 *        Version:  1.0.0(10/30/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/30/2012 01:15:18 PM"
 *
 ********************************************************************************/
#include "cp_network.h"
#include "cp_logger.h"
#include "cp_proc.h"
#include "cp_time.h"
//#define SERV_ADDR              "192.168.1.175"
#define SERV_ADDR              "192.168.1.78"
//#define SERV_ADDR              "kkernel.oicp.net"
#define SERV_PORT              8880
int service_route(CP_SOCK *sock)
{
    int      rv;
    if( !sock )
        return -1;
    printf("Client socket [%d] get event: %d\n", sock->fd, sock->event.events);
    if(sock->event.events & EPOLLIN)
    {
        rv = cp_sock_recv(sock);
        if(!rv)
        {
            log_nrml("Socket [%d %s:%d] remote socket [%s:%d] disconnect, remove it now\n",
                    sock->fd, sock->laddr, sock->lport, sock->raddr, sock->rport);
            cp_fds_destroy_sock(sock);
            g_cp_signal.stop = 1;
            return 0;
        }
        else if(rv > 0)
        {
            log_nrml("Socket [%d %s:%d] receive [%d] bytes data:\n", sock->fd, sock->laddr, sock->lport, sock->rbuf->len);
            cp_log_dump(LOG_LEVEL_DEBUG, sock->rbuf->data, sock->rbuf->len);
            cp_string_clear_data(sock->rbuf);
        }
    }
    return 0;
}
/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    CP_FDS     *fds;
    CP_SOCK    *sock = NULL;
    if ( !cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_NRML, LOG_ROLLBACK_NONE) || cp_log_open() )
    //if ( !cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_MAX, LOG_ROLLBACK_NONE) || cp_log_open() )
        return -1;
    cp_install_proc_signal();
    if( !(fds=cp_fds_init(NULL, CP_DEF_MAX_EVENTS, CP_DEF_FDS_TIMEOUT)) )
        return -2;
    while( !g_cp_signal.stop )
    {
        sock = cp_sock_connect_regist(fds, sock, SERV_ADDR, SERV_PORT, 0, service_route);
        if( sock && sock->status==SOCK_STAT_CONNECTING)
        {
            /* Connect is in progress */
            sleep(1);
            continue;
        }
        else if(!sock || sock->status!=SOCK_STAT_CONNECTED)
        {
            break;
        }
        cp_string_cstrcpy(sock->sbuf, "Hello World!\n");
        printf("Send buffer data: %s", cp_string_data(sock->sbuf));
        cp_sock_send(sock);
        cp_fds_detect_event(fds);
        cp_fds_proc_event(fds);
        micro_second_sleep(100);
    }
    cp_sock_term_all_service_clear(fds);
    cp_log_term();
    return 0;
} /* ----- End of main() ----- */
program/cp_library/test/test_sock_server.c
New file
@@ -0,0 +1,98 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  test_sock_server.c
 *    Description:  This file
 *
 *        Version:  1.0.0(10/30/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/30/2012 01:15:18 PM"
 *
 ********************************************************************************/
#include "cp_network.h"
#include "cp_logger.h"
#include "cp_proc.h"
#include "cp_time.h"
#define SERV_PORT1            8880
#define SERV_PORT2            8881
#define DOMAIN                "kkernel.oicp.net"
#define IPADDR                "192.168.1.78"
int service_route(CP_SOCK *sock)
{
    int           rv = 0;
    log_nrml("Process socket [%d %s:%d] get event [%d]\n", sock->fd, sock->laddr, sock->lport, sock->event.events);
    if(sock->event.events & EPOLLIN)
    {
        rv = cp_sock_recv(sock);
        if(0==rv)
        {
            log_nrml("Socket [%d %s:%d] remote socket [%s:%d] disconnect, remove it now\n",
                    sock->fd, sock->laddr, sock->lport, sock->raddr, sock->rport);
            cp_fds_destroy_sock(sock);
            return 0;
        }
        else if(rv > 0)
        {
            log_nrml("Socket[%d] recv buffer %d bytes data:\n", sock->fd, sock->rbuf->len);
            //cp_log_dump(LOG_LEVEL_NRML, sock->rbuf->data, sock->rbuf->len);
            cp_string_move(sock->sbuf, sock->rbuf);
            log_nrml("Socket[%d] send buffer %d bytes data:\n", sock->fd, sock->sbuf->len);
            cp_sock_send(sock);
            cp_string_clear_data(sock->sbuf);
        }
    }
    return 0;
}
/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    CP_FDS     *fds;
    CP_SOCK    *sock;
    //if (!cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_NRML, LOG_ROLLBACK_NONE) || cp_log_open())
    if (!cp_log_init(NULL, DBG_LOG_FILE, LOG_LEVEL_MAX, LOG_ROLLBACK_NONE) || cp_log_open())
        goto cleanup;
    cp_install_proc_signal();
    if( !(fds=cp_fds_init(NULL, CP_DEF_MAX_EVENTS, CP_DEF_FDS_TIMEOUT)) )
        goto cleanup;
    if( !(sock=cp_sock_server_regist(fds, NULL, SERV_PORT1, 0, service_route, NULL)) )
        goto cleanup;
    if( !(sock=cp_sock_server_regist(fds, NULL, SERV_PORT2, 0, service_route, NULL)) )
        goto cleanup;
    while( !g_cp_signal.stop )
    {
        cp_fds_detect_event(fds);
        cp_fds_proc_event(fds);
        micro_second_sleep(10);
    }
cleanup:
    cp_sock_term_all_service_clear(fds);
    cp_log_term();
    return 0;
} /* ----- End of main() ----- */
program/cp_library/test/test_string.c
New file
@@ -0,0 +1,77 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  test_string.c
 *    Description:  This file
 *
 *        Version:  1.0.0(11/27/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "11/27/2012 01:28:39 PM"
 *
 ********************************************************************************/
#include <cp_string.h>
/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    int            i;
    cp_string      *rcv;
    cp_string      *snd;
    rcv = cp_string_create_empty(64);
    snd = cp_string_create_empty(64);
    printf("=======================\n");
    printf("Test cp_string_copy \n");
    printf("=======================\n");
    cp_string_clear_data(rcv);
    cp_string_cstrcpy(rcv, "Hello world!");
    printf("Receive buffer data:\n");
    cp_string_dump(rcv);
    for(i=0; i<20; i++)
    {
        if( cp_string_copy(snd, rcv) > 0)
        {
            printf("[%d] Send buffer data:\n", i);
            cp_string_dump(snd);
        }
    }
    printf("\n=======================\n");
    printf("Test cp_string_move \n");
    printf("=======================\n");
    cp_string_clear_data(snd);
    cp_string_clear_data(rcv);
    for(i=0; i<20; i++)
    {
        cp_string_cstrcpy(rcv, "Hello world!");
        //printf("Set new receive buffer data [%d] bytes:\n", cp_string_len(rcv));
        cp_string_dump(rcv);
        if( cp_string_move(snd, rcv) > 0)
        {
            printf("[%d] Send buffer [%d] bytes data:\n", i, cp_string_len(snd));
            cp_string_dump(snd);
            printf("[%d] receive buffer [%d] bytes data:\n", i, cp_string_len(rcv));
            cp_string_dump(rcv);
        }
    }
    cp_string_destroy(rcv);
    cp_string_destroy(snd);
    return 0;
} /* ----- End of main() ----- */
program/cp_library/test/test_vector.c
New file
@@ -0,0 +1,67 @@
/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  test_vector.c
 *    Description:  This file used to test the vector library
 *
 *        Version:  1.0.0(08/14/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "08/14/2012 05:17:03 PM"
 *
 ********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cp_vector.h"
#include "cp_sock.h"
/********************************************************************************
 *  Description:
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/
int main (int argc, char **argv)
{
    int i, n;
    CP_SOCK *p = NULL;
    CP_VECTOR *v = cp_vector_init(1024);
    for (i = 0; i < 10; i++)
    {
        p = cp_sock_init(NULL, 1024, 1024, 10, 30);
        cp_vector_add(v, i, p);
    }
    n = cp_vector_count(v);
    for (i = 0; i < n; i++)
    {
        p = cp_vector_get(v, i);
        printf("%d: %p\n", i, p);
    }
    p = cp_sock_init(NULL, 1024, 1024, 10, 30);
    cp_vector_add(v, 28, p);
    printf("Set 28: %p\n", p);
    for (i=0; i <cp_vector_size(v); i++)
    {
        p = cp_vector_get(v, i);
        if(p)
        {
            printf("Terminate socket %i: %p\n", i, p);
            cp_sock_term(p);
        }
    }
    cp_vector_destroy(v);
    return 0;
} /* ----- End of main() ----- */
program/fwed/etc/default_apn.conf
New file
@@ -0,0 +1,741 @@
[202-01]  carrier='Cosmote Wireless Internet' apn='internet' uid='' pwd=''
[202-05]  carrier='Vf Mobile Internet' apn='internet.vodafone.gr' uid='' pwd=''
[202-10]  carrier='Wind Internet' apn='gint.b-online.gr' uid='' pwd=''
[204-04]  carrier='Vodafone NL' apn='live.vodafone.com' uid='vodafone' pwd='vodafone'
[204-08]  carrier='KPN Internet' apn='portalmmm.nl' uid='' pwd=''
[204-12]  carrier='Telfort Internet' apn='internet' uid='' pwd=''
[204-16]  carrier='T-Mobile Internet' apn='internet' uid='' pwd=''
[204-20]  carrier='Rabo Mobiel' apn='rabo.plus' uid='' pwd=''
[206-01]  carrier='Proximus Internet' apn='internet.proximus.be' uid='' pwd=''
[206-01]  carrier='Telenet Internet' apn='telenetwap.be' uid='' pwd=''
[206-05]  carrier='Telenet' apn='telenetwap.be' uid='' pwd=''
[206-10]  carrier='Mobistar' apn='mworld.be' uid='mobistar' pwd='mobistar'
[206-20]  carrier='Base' apn='gprs.base.be' uid='base' pwd='base'
[208-01]  carrier='Orange World' apn='orange' uid='orange' pwd='orange'
[208-01]  carrier='Orange Entreprise' apn='orange-mib' uid='orange' pwd='orange'
[208-01]  carrier='Orange Internet' apn='orange.fr' uid='orange' pwd='orange'
[208-01]  carrier='Orange Internet Entreprise' apn='internet-entreprise' uid='orange' pwd='orange'
[208-10]  carrier='SFR webphone' apn='sl2sfr' uid='' pwd=''
[208-10]  carrier='SFR Mobile' apn='wapsfr' uid='' pwd=''
[208-10]  carrier='NRJWEB' apn='fnetnrj' uid='' pwd=''
[208-01]  carrier='VM WAP' apn='ofnew.fr' uid='orange' pwd='orange'
[208-01]  carrier='Tele2 WAP' apn='ofnew.fr' uid='orange' pwd='orange'
[208-01]  carrier='Carrefour WAP' apn='ofnew.fr' uid='orange' pwd='orange'
[208-10]  carrier='Auchan WAP' apn='wap65' uid='' pwd=''
[208-01]  carrier='NRJWEB' apn='ofnew.fr' uid='orange' pwd='orange'
[208-10]  carrier='WAP Simplicime' apn='wapdebitel' uid='' pwd=''
[208-10]  carrier='WAP LeclercMobile' apn='wap66' uid='' pwd=''
[208-10]  carrier='Coriolis WAP' apn='wapcoriolis' uid='' pwd=''
[208-10]  carrier='Keyyo Mobile Internet' apn='internet68' uid='' pwd=''
[208-10]  carrier='WEB La Poste Mobile' apn='wapdebitel' uid='' pwd=''
[214-01]  carrier='Internet movil' apn='airtelwap.es' uid='wap@wap' pwd='wap125'
[214-03]  carrier='Orange Internet Móvil' apn='orangeworld' uid='orange' pwd='orange'
[214-03]  carrier='Orange Internet PC' apn='internet' uid='orange' pwd='orange'
[214-04]  carrier='Yoigo Navegador' apn='internet' uid='' pwd=''
[214-06]  carrier='INTERNET GPRS' apn='airtelnet.es' uid='vodafone' pwd='vodafone'
[214-06]  carrier='Euskaltel Internet' apn='internet.euskaltel.mobi' uid='CLIENTE' pwd='EUSKALTEL'
[214-06]  carrier='Internet R' apn='internet.mundo-r.com' uid='' pwd=''
[214-06]  carrier='TeleCable Internet' apn='internet.telecable.es' uid='telecable' pwd='telecable'
[214-07]  carrier='Movistar' apn='telefonica.es' uid='telefonica' pwd='telefonica'
[214-07]  carrier='Conexión compartida' apn='movistar.es' uid='MOVISTAR' pwd='MOVISTAR'
[214-08]  carrier='Euskaltel Internet' apn='internet.euskaltel.mobi' uid='CLIENTE' pwd='EUSKALTEL'
[214-16]  carrier='TeleCable Internet' apn='internet.telecable.es' uid='telecable' pwd='telecable'
[216-01]  carrier='Telenor Online' apn='online' uid='' pwd=''
[216-30]  carrier='Web' apn='wnw' uid='' pwd=''
[216-70]  carrier='VF internet' apn='internet.vodafone.net' uid='' pwd=''
[216-70]  carrier='VMAX Internet' apn='vitamax.internet.vodafone.net' uid='' pwd=''
[218-03]  carrier='HT Eronet' apn='wap.eronet.ba' uid='' pwd=''
[218-05]  carrier='m:tel' apn='3g1' uid='' pwd=''
[218-90]  carrier='Bh Mobile' apn='active.bhmobile.ba' uid='' pwd=''
[219-01]  carrier='T-Mobile' apn='web.htgprs' uid='' pwd=''
[219-02]  carrier='Tele2' apn='internet.tele2.hr' uid='' pwd=''
[219-10]  carrier='Broadband' apn='data.vip.hr' uid='38591' pwd='38591'
[220-01]  carrier='Telenor WAP' apn='internet' uid='telenor' pwd='gprs'
[220-02]  carrier='Telenor MNE internet' apn='internet' uid='gprs' pwd='gprs'
[220-03]  carrier='mt:s wap' apn='gprswap' uid='mts' pwd='64'
[220-04]  carrier='T-Mobile Internet' apn='tmcg-wnw' uid='38267' pwd='38267'
[220-05]  carrier='Vip GPRS' apn='vipmobile' uid='vipmobile' pwd='vipmobile'
[222-01]  carrier='TIM WAP' apn='wap.tim.it' uid='WAPTIM' pwd='WAPTIM'
[222-01]  carrier='TIM WEB' apn='ibox.tim.it' uid='' pwd=''
[222-10]  carrier='Vodafone Internet' apn='mobile.vodafone.it' uid='' pwd=''
[222-10]  carrier='Vodafone WEB' apn='web.omnitel.it' uid='' pwd=''
[222-88]  carrier='WIND WEB' apn='internet.wind' uid='' pwd=''
[222-88]  carrier='WIND BIZ WEB' apn='internet.wind.biz' uid='' pwd=''
[222-99]  carrier='3' apn='tre.it' uid='' pwd=''
[222-99]  carrier='Fastweb WEB' apn=' apn.fastweb.it' uid='' pwd=''
[226-01]  carrier='Vodafone live!' apn='live.vodafone.com' uid='live' pwd='vodafone'
[226-01]  carrier='Vodafone live! PRE' apn='live.pre.vodafone.com' uid='live' pwd='vodafone'
[226-03]  carrier='Cosmote Internet' apn='internet' uid='' pwd=''
[226-03]  carrier='web'n'walk' apn='wnw' uid='wnw' pwd='wnw'
[226-06]  carrier='web'n'walk' apn='wnw' uid='wnw' pwd='wnw'
[226-10]  carrier='Orange WAP' apn='wap' uid='' pwd=''
[226-10]  carrier='Orange Internet' apn='net' uid='' pwd=''
[228-01]  carrier='Swisscom Services' apn='gprs.swisscom.ch' uid='' pwd=''
[228-02]  carrier='Sunrise live' apn='internet' uid='' pwd=''
[228-03]  carrier='Orange Internet' apn='internet' uid='' pwd=''
[230-01]  carrier='T-Mobile CZ' apn='internet.t-mobile.cz' uid='wap' pwd='wap'
[230-02]  carrier='O2 internet' apn='internet' uid='' pwd=''
[230-03]  carrier='GPRS Web' apn='internet' uid='' pwd=''
[231-01]  carrier='Orange SK' apn='internet' uid='' pwd=''
[231-01]  carrier='Orange World' apn='orangewap' uid='wap' pwd='wap'
[231-02]  carrier='T-Mobile internet' apn='internet' uid='' pwd=''
[231-06]  carrier='O2 internet' apn='o2internet' uid='' pwd=''
[232-01]  carrier='A1' apn='a1.net' uid='ppp@a1plus.at' pwd='ppp'
[232-01]  carrier='aonMobil' apn='aon.at' uid='mobil@aon.at' pwd='ppp'
[232-03]  carrier='T-Mobile Internet' apn='gprsinternet' uid='t-mobile' pwd='tm'
[232-05]  carrier='Orange Smartphone' apn='orange.smartphone' uid='web' pwd='web'
[232-07]  carrier='tele.ring web' apn='web' uid='web@telering.at' pwd='web'
[232-10]  carrier='Planet3' apn='drei.at' uid='' pwd=''
[232-11]  carrier='data.bob' apn='bob.at' uid='data@bob.at' pwd='ppp'
[232-12]  carrier='YESSS! GPRS' apn='web.yesss.at' uid='' pwd=''
[234-01]  carrier='UBIQUISYS' apn='internet' uid='' pwd=''
[234-02]  carrier='O2 MOBILE WEB' apn='mobile.o2.co.uk' uid='O2web' pwd='O2web'
[234-10]  carrier='O2 Mobile Web' apn='mobile.o2.co.uk' uid='o2web' pwd='password'
[234-10]  carrier='O2 PREPAY' apn='payandgo.o2.co.uk' uid='payandgo' pwd='password'
[234-10]  carrier='TESCO' apn='prepay.tesco-mobile.com' uid='tescowap' pwd='password'
[234-11]  carrier='O2 MOBILE WEB' apn='mobile.o2.co.uk' uid='O2web' pwd='O2web'
[234-11]  carrier='O2 MOBILE WEB' apn='mobile.o2.co.uk' uid='O2web' pwd='O2web'
[234-15]  carrier='Vodafone UK' apn='wap.vodafone.co.uk' uid='wap' pwd='wap'
[234-15]  carrier='Vodafone UK Prepay' apn='pp.vodafone.co.uk' uid='wap' pwd='wap'
[234-20]  carrier='3' apn='three.co.uk' uid='' pwd=''
[234-30]  carrier='T-Mobile UK' apn='general.t-mobile.uk' uid='t-mobile' pwd='tm'
[234-30]  carrier='Virgin Media' apn='goto.virginmobile.uk' uid='user' pwd=''
[234-31]  carrier='T-Mobile Internet' apn='general.t-mobile.uk' uid='t-mobile' pwd='tm'
[234-31]  carrier='T-Mobile Picture Message' apn='general.t-mobile.uk' uid='t-mobile' pwd='tm'
[234-32]  carrier='T-Mobile Internet' apn='general.t-mobile.uk' uid='t-mobile' pwd='tm'
[234-32]  carrier='T-Mobile Picture Message' apn='general.t-mobile.uk' uid='t-mobile' pwd='tm'
[234-33]  carrier='Orange Internet' apn='orangeinternet' uid='' pwd=''
[234-33]  carrier='Consumer Broadband' apn='consumerbroadband' uid='' pwd=''
[234-34]  carrier='Orange internet' apn='orangeinternet' uid='' pwd=''
[234-50]  carrier='pepperWEB (Jersey)' apn='pepper' uid='' pwd=''
[234-55]  carrier='C&W Guernsey Internet' apn='internet' uid='' pwd=''
[234-58]  carrier='3G HSDPA' apn='3gpronto' uid='' pwd=''
[234-58]  carrier='Manx Telecom Contract WEB' apn='web.manxpronto.net' uid='gprs' pwd='gprs'
[234-86]  carrier='Orange internet' apn='orangeinternet' uid='' pwd=''
[238-01]  carrier='TDC' apn='internet' uid='' pwd=''
[238-01]  carrier='TDC Song WAP' apn='internet.no' uid='' pwd=''
[238-01]  carrier='TDC WAP' apn='wap' uid='' pwd=''
[238-01]  carrier='Telmore Wap' apn='wap' uid='' pwd=''
[238-02]  carrier='Telenor Internet' apn='Internet' uid='' pwd=''
[238-06]  carrier='3' apn='data.tre.dk' uid='' pwd=''
[238-20]  carrier='Internet' apn='websp' uid='' pwd=''
[238-20]  carrier='Telia Internet' apn='www.internet.mtelia.dk' uid='' pwd=''
[238-77]  carrier='Telenor Internet' apn='Internet' uid='' pwd=''
[240-01]  carrier='Telia SE WAP' apn='online.telia.se' uid='' pwd=''
[240-17]  carrier='Halebop Internet' apn='halebop.telia.se' uid='' pwd=''
[240-02]  carrier='3' apn='data.tre.se' uid='' pwd=''
[240-04]  carrier='Telenor Mobilsurf' apn='services.telenor.se' uid='' pwd=''
[240-06]  carrier='Telenor Mobilsurf' apn='services.telenor.se' uid='' pwd=''
[240-07]  carrier='Tele2' apn='internet.tele2.no' uid='' pwd=''
[240-07]  carrier='Tele2' apn='internet.tele2.se' uid='' pwd=''
[240-08]  carrier='Telenor Mobilsurf' apn='services.telenor.se' uid='' pwd=''
[240-09]  carrier='TelenorMobilsurf' apn='services.telenor.se' uid='' pwd=''
[240-10]  carrier='Spring data' apn='data.springmobil.se' uid='' pwd=''
[242-01]  carrier='Ventelo Internett' apn='internet.ventelo.no' uid='' pwd=''
[242-01]  carrier='Telenor' apn='telenor' uid='' pwd=''
[242-02]  carrier='NetCom Internett' apn='wap' uid='' pwd=''
[242-04]  carrier='Tele2 Internett' apn='internet.tele2.no' uid='' pwd=''
[242-05]  carrier='NwN Internet' apn='internet' uid='' pwd=''
[244-03]  carrier='DNA Internet' apn='internet' uid='' pwd=''
[244-04]  carrier='DNA Internet' apn='internet' uid='' pwd=''
[244-05]  carrier='Elisa Internet' apn='internet' uid='' pwd=''
[244-10]  carrier='TDC Internet' apn='internet.song.fi' uid='song@internet' pwd='songnet'
[244-12]  carrier='DNA Pro Internet' apn='dnapro.fi' uid='' pwd=''
[244-12]  carrier='TDC Internet Finland' apn='inet.tdc.fi' uid='' pwd=''
[244-13]  carrier='DNA Internet' apn='internet' uid='' pwd=''
[244-21]  carrier='Saunalahti Internet' apn='internet.saunalahti' uid='' pwd=''
[244-91]  carrier='SONERA Internet' apn='internet' uid='' pwd=''
[246-01]  carrier='Omnitel Internet' apn='omnitel' uid='omni' pwd='omni'
[246-02]  carrier='Bite LT WAP' apn='wap' uid='' pwd=''
[246-03]  carrier='Tele2 Internet LT' apn='internet.tele2.lt' uid='wap' pwd='wap'
[247-01]  carrier='LMT Internet' apn='internet.lmt.lv' uid='' pwd=''
[247-02]  carrier='Tele2 LV Internet' apn='internet.tele2.lv' uid='wap' pwd='wap'
[247-05]  carrier='Bite LV Internet' apn='internet' uid='' pwd=''
[247-05]  carrier='Bite LV WAP' apn='wap' uid='' pwd=''
[248-01]  carrier='EMT Internet' apn='internet.emt.ee' uid='' pwd=''
[248-01]  carrier='EMT WAP' apn='wap.emt.ee' uid='' pwd=''
[248-02]  carrier='Elisa Internet' apn='internet' uid='' pwd=''
[248-02]  carrier='Elisa WAP' apn='wap' uid='' pwd=''
[248-03]  carrier='Tele2 Internet' apn='internet.tele2.ee' uid='' pwd=''
[250-01]  carrier='MTS Internet' apn='internet.mts.ru' uid='mts' pwd='mts'
[250-02]  carrier='Megafon Internet' apn='internet' uid='gdata' pwd='gdata'
[250-99]  carrier='Beeline Internet' apn='internet.beeline.ru' uid='beeline' pwd='beeline'
[250-20]  carrier='TELE2 Internet' apn='internet.tele2.ru' uid='' pwd=''
[255-01]  carrier='MTS-internet' apn='internet' uid='' pwd=''
[255-02]  carrier='Beeline-internet' apn='internet.beeline.ua' uid='' pwd=''
[255-03]  carrier='Kyivstar Internet' apn='www.kyivstar.net' uid='' pwd=''
[255-06]  carrier='life:) internet' apn='internet' uid='' pwd=''
[255-07]  carrier='Utel Internet' apn='3g.utel.ua' uid='' pwd=''
[260-01]  carrier='Plus Internet' apn='internet' uid='' pwd=''
[260-02]  carrier='T-mobile.pl' apn='internet' uid='' pwd=''
[260-02]  carrier='heyahinternet' apn='heyah.pl' uid='' pwd=''
[260-03]  carrier='Internet' apn='Internet' uid='internet' pwd='internet'
[260-06]  carrier='P4 Internet' apn='internet' uid='' pwd=''
[262-01]  carrier='T-Mobile Internet' apn='internet.t-mobile' uid='t-mobile' pwd='tm'
[262-02]  carrier='Vodafone DE' apn='web.vodafone.de' uid='' pwd=''
[262-03]  carrier='E-Plus Web GPRS' apn='internet.eplus.de' uid='eplus' pwd='internet'
[262-07]  carrier='o2' apn='internet' uid='' pwd=''
[262-07]  carrier='o2 Internet Prepaid' apn='pinternet.interkom.de' uid='' pwd=''
[268-01]  carrier='Vodafone Net2' apn='net2.vodafone.pt' uid='vodafone' pwd='vodafone'
[268-03]  carrier='Optimus Internet' apn='umts' uid='' pwd=''
[268-06]  carrier='tmn internet' apn='internet' uid='' pwd=''
[270-01]  carrier='LUXGSM WAP' apn='wap.pt.lu' uid='wap' pwd='wap'
[270-77]  carrier='Tango WAP' apn='internet' uid='tango' pwd='tango'
[270-99]  carrier='Vox Mobile' apn='vox.lu' uid='' pwd=''
[272-01]  carrier='Vodafone IE' apn='live.vodafone.com' uid='' pwd=''
[272-02]  carrier='O2 Ireland' apn='internet' uid='' pwd=''
[272-03]  carrier='Meteor Data' apn='data.mymeteor.ie' uid='' pwd=''
[272-05]  carrier='3' apn='3ireland.ie' uid='' pwd=''
[272-11]  carrier='Tesco' apn='tescomobile.liffeytelecom.com' uid='' pwd=''
[274-01]  carrier='Siminn Internet' apn='internet' uid='' pwd=''
[274-02]  carrier='Vodafone Internet' apn='gprs.is' uid='' pwd=''
[274-11]  carrier='Net Nova' apn='net.nova.is' uid='' pwd=''
[278-01]  carrier='Vodafone MT' apn='internet' uid='internet' pwd='internet'
[280-01]  carrier='CYTA' apn='cytamobile' uid='user' pwd='pass'
[280-10]  carrier='MTN Wap' apn='wap' uid='wap' pwd='wap'
[284-01]  carrier='M-Tel' apn='wap-gprs.mtel.bg' uid='' pwd=''
[284-03]  carrier='Vivacom WAP' apn='wap.vivacom.bg' uid='wap' pwd='wap'
[284-05]  carrier='GPRS GLOBUL' apn='globul' uid='' pwd=''
[286-01]  carrier='Turkcell Internet' apn='internet' uid='gprs' pwd='gprs'
[286-02]  carrier='Vodafone Internet' apn='internet' uid='vodafone' pwd='vodafone'
[286-03]  carrier='Avea Internet' apn='internet' uid='wap' pwd='wap'
[290-01]  carrier='Tele Internet' apn='internet' uid='' pwd=''
[293-40]  carrier='Vodafone live!' apn='internet.simobil.si' uid='simobil' pwd='internet'
[293-41]  carrier='Planet' apn='internet' uid='mobitel' pwd='internet'
[294-01]  carrier='T-Mobile MK Internet' apn='internet' uid='internet' pwd='t-mobile'
[294-02]  carrier='Cosmofon' apn='Internet' uid='Internet' pwd='Internet'
[294-03]  carrier='Internet' apn='vipoperator' uid='vipoperator' pwd='vipoperator'
[297-02]  carrier='T-Mobile Internet' apn='tmcg-wnw' uid='38267' pwd='38267'
[302-220] carrier='TELUS' apn='sp.telus.com' uid='' pwd=''
[302-320] carrier='MOWAP' apn='wap.davewireless.com' uid='' pwd=''
[302-370] carrier='Fido Internet' apn='fido-core-appl1.apn' uid='' pwd=''
[302-370] carrier='Fido Tethering' apn='isp.fido.apn' uid='' pwd=''
[302-720] carrier='Chatr Internet' apn='chatrweb.apn' uid='' pwd=''
[302-490] carrier='Wind CA' apn='internet.windmobile.ca' uid='' pwd=''
[302-500] carrier='Videotron' apn='media.videotron' uid='' pwd=''
[302-610] carrier='Bell Internet' apn='pda.bell.ca' uid='' pwd=''
[302-720] carrier='Rogers Tethering' apn='isp.apn' uid='' pwd=''
[302-720] carrier='Rogers' apn='rogers-core-appl1.apn' uid='' pwd=''
[302-780] carrier='SaskTel' apn='pda.stm.sk.ca' uid='' pwd=''
[310-30]  carrier='Internet' apn='private.centennialwireless.com' uid='privuser' pwd='priv'
[310-90]  carrier='Internet' apn='isp' uid='' pwd=''
[310-100] carrier='PLATWEB' apn='plateauweb' uid='' pwd=''
[310-160] carrier='T-Mobile US 160' apn='epc.tmobile.com' uid='' pwd=''
[310-170] carrier='DataConnect' apn='isp.cingular' uid='' pwd=''
[310-200] carrier='T-Mobile US 200' apn='epc.tmobile.com' uid='' pwd=''
[310-210] carrier='T-Mobile US 210' apn='epc.tmobile.com' uid='' pwd=''
[310-220] carrier='T-Mobile US 220' apn='epc.tmobile.com' uid='' pwd=''
[310-230] carrier='T-Mobile US 230' apn='epc.tmobile.com' uid='' pwd=''
[310-240] carrier='T-Mobile US 240' apn='epc.tmobile.com' uid='' pwd=''
[310-250] carrier='T-Mobile US 250' apn='epc.tmobile.com' uid='' pwd=''
[310-260] carrier='T-Mobile US' apn='epc.tmobile.com' uid='' pwd=''
[310-270] carrier='T-Mobile US 270' apn='epc.tmobile.com' uid='' pwd=''
[310-310] carrier='T-Mobile US 310' apn='epc.tmobile.com' uid='' pwd=''
[310-380] carrier='Cingular 380 ATT' apn='proxy' uid='' pwd=''
[310-410] carrier='Cingular 410' apn='wap.cingular' uid='WAP@CINGULARGPRS.COM' pwd='CINGULAR1'
[310-470] carrier='DataConnect' apn='isp.cingular' uid='' pwd=''
[310-470] carrier='MediaNet' apn='wap.cingular' uid='WAP@CINGULARGPRS.COM' pwd='CINGULAR1'
[310-480] carrier='DataConnect' apn='isp.cingular' uid='' pwd=''
[310-480] carrier='MediaNet' apn='wap.cingular' uid='WAP@CINGULARGPRS.COM' pwd='CINGULAR1'
[310-490] carrier='T-Mobile US 490' apn='epc.tmobile.com' uid='' pwd=''
[310-490] carrier='GoodCall Picture Message' apn='good.call' uid='' pwd=''
[310-580] carrier='T-Mobile US 580' apn='epc.tmobile.com' uid='' pwd=''
[310-610] carrier='EpicINT' apn='internet.epictouch' uid='' pwd=''
[310-660] carrier='T-Mobile US 660' apn='epc.tmobile.com' uid='' pwd=''
[310-770] carrier='WEB 2' apn='i2.iwireless.com' uid='' pwd=''
[310-770] carrier='Picture Messaging' apn='wap1.iwireless.com' uid='' pwd=''
[310-770] carrier='PIAPicture Messaging' apn='wap9.iwireless.com' uid='' pwd=''
[310-800] carrier='T-Mobile US 800' apn='epc.tmobile.com' uid='' pwd=''
[310-840] carrier='Internet' apn='isp' uid='' pwd=''
[310-910] carrier='WOW_WAP' apn='wap.firstcellular.com' uid='' pwd=''
[311-210] carrier='Farmers GPRS' apn='internet.farmerswireless.com' uid='' pwd=''
[330-110] carrier='INTERNET CLARO' apn='internet.claropr.com' uid='' pwd=''
[334-20]  carrier='Internet' apn='internet.itelcel.com' uid='webgprs' pwd='webgprs2002'
[334-03]  carrier='movistar Internet' apn='internet.movistar.mx' uid='movistar' pwd='movistar'
[334-30]  carrier='movistar Internet' apn='internet.movistar.mx' uid='movistar' pwd='movistar'
[334-50]  carrier='Iusacell Internet' apn='web.iusacellgsm.mx' uid='Iusacellgsm' pwd='Iusacellgsm'
[338-50]  carrier='INTERNET Digicel' apn='web.digiceljamaica.com' uid='' pwd=''
[338-18]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[338-70]  carrier='Claro Web' apn='internet.ideasclaro.com.jm' uid='' pwd=''
[338-180] carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[340-01]  carrier='Orange World Caraïbe' apn='orangewap' uid='orange' pwd='wap'
[340-20]  carrier='Digicel FR' apn='wap.digicelfr.com' uid='wap' pwd='wap'
[342-60]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[344-92]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[346-14]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[348-17]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[352-11]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[354-86]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[356-11]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[358-11]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[360-11]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[363-02]  carrier='INTERNET Aruba' apn='web.digicelaruba.com' uid='' pwd=''
[363-20]  carrier='INTERNET Aruba' apn='web.digicelaruba.com' uid='' pwd=''
[365-84]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[366-11]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[368-01]  carrier='Internet' apn='internet' uid='' pwd=''
[370-01]  carrier='Orange net' apn='orangenet.com.do' uid='' pwd=''
[370-02]  carrier='INTERNET CLARO' apn='internet.ideasclaro.com.do' uid='' pwd=''
[370-04]  carrier='Viva Edge' apn='edge.viva.net.do' uid='viva' pwd='viva'
[374-12]  carrier='Bmobile internet' apn='internet' uid='' pwd=''
[374-120] carrier='Bmobile internet' apn='internet' uid='' pwd=''
[374-121] carrier='Bmobile internet' apn='internet' uid='' pwd=''
[374-122] carrier='Bmobile internet' apn='internet' uid='' pwd=''
[374-123] carrier='Bmobile internet' apn='internet' uid='' pwd=''
[374-124] carrier='Bmobile internet' apn='internet' uid='' pwd=''
[374-125] carrier='Bmobile internet' apn='internet' uid='' pwd=''
[374-126] carrier='Bmobile internet' apn='internet' uid='' pwd=''
[374-127] carrier='Bmobile internet' apn='internet' uid='' pwd=''
[374-128] carrier='Bmobile internet' apn='internet' uid='' pwd=''
[374-129] carrier='Bmobile internet' apn='internet' uid='' pwd=''
[374-13]  carrier='INTERNET Trinidad' apn='web.digiceltt.com' uid='' pwd=''
[374-130] carrier='INTERNET Trinidad' apn='web.digiceltt.com' uid='' pwd=''
[376-35]  carrier='Lime Internet Postpaid' apn='internet' uid='' pwd=''
[401-01]  carrier='Beeline Internet' apn='internet.beeline.kz' uid='@internet.beeline' pwd='beeline'
[401-02]  carrier='Kcell Internet' apn='internet' uid='' pwd=''
[401-77]  carrier='Tele2 Internet' apn='internet' uid='' pwd=''
[404-01]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-02]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-03]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-04]  carrier='IDEA' apn='internet' uid='' pwd=''
[404-05]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-07]  carrier='IDEA' apn='internet' uid='' pwd=''
[404-09]  carrier='Reliance RTel' apn='SMARTNET' uid='' pwd=''
[404-10]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-11]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-12]  carrier='IDEA' apn='internet' uid='' pwd=''
[404-13]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-14]  carrier='IDEA Punjab' apn='spicegprs' uid='' pwd=''
[404-15]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-16]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-17]  carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd=''
[404-18]  carrier='Reliance RTel' apn='SMARTNET' uid='' pwd=''
[404-19]  carrier='IDEA' apn='internet' uid='' pwd=''
[404-20]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-21]  carrier='Loop Mobile' apn='www' uid='' pwd=''
[404-22]  carrier='IDEA' apn='internet' uid='' pwd=''
[404-24]  carrier='IDEA' apn='internet' uid='' pwd=''
[404-25]  carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd=''
[404-27]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-28]  carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd=''
[404-29]  carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd=''
[404-30]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-31]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-33]  carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd=''
[404-34]  carrier='Cellone_North' apn='bsnlnet' uid='' pwd=''
[404-35]  carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd=''
[404-36]  carrier='Reliance RTel' apn='SMARTNET' uid='' pwd=''
[404-37]  carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd=''
[404-38]  carrier='CellOne_Kolkata' apn='bsnlnet' uid='' pwd=''
[404-40]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-41]  carrier='AIRCEL TN' apn='aircelgprs.po' uid='' pwd=''
[404-42]  carrier='AIRCEL TN' apn='aircelgprs.po' uid='' pwd=''
[404-43]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-44]  carrier='IDEA Karnataka' apn='simplyinternet' uid='' pwd=''
[404-45]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-46]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-49]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-50]  carrier='Reliance RTel' apn='SMARTNET' uid='' pwd=''
[404-51]  carrier='Cellone_North' apn='bsnlnet' uid='' pwd=''
[404-52]  carrier='Reliance RTel' apn='SMARTNET' uid='' pwd=''
[404-53]  carrier='Cellone_North' apn='bsnlnet' uid='' pwd=''
[404-54]  carrier='Cellone_North' apn='bsnlnet' uid='' pwd=''
[404-55]  carrier='Cellone_North' apn='bsnlnet' uid='' pwd=''
[404-56]  carrier='IDEA' apn='internet' uid='' pwd=''
[404-57]  carrier='Cellone_West' apn='bsnlnet' uid='' pwd=''
[404-58]  carrier='Cellone_West' apn='bsnlnet' uid='' pwd=''
[404-59]  carrier='Cellone_North' apn='bsnlnet' uid='' pwd=''
[404-60]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-62]  carrier='Cellone_North' apn='bsnlnet' uid='' pwd=''
[404-64]  carrier='CellOne_South' apn='bsnlnet' uid='' pwd=''
[404-66]  carrier='Cellone_West' apn='bsnlnet' uid='' pwd=''
[404-67]  carrier='Reliance RTel' apn='SMARTNET' uid='' pwd=''
[404-68]  carrier='Dolphin_Delhi' apn='gprsmtnldel' uid='mtnl' pwd='mtnl123'
[404-68]  carrier='Dolphin_Delhi_3G' apn='mtnl3g' uid='mtnl' pwd='mtnl123'
[404-69]  carrier='Dolphin_Mumbai' apn='gprsmtnlmum' uid='mtnl' pwd='mtnl123'
[404-69]  carrier='Dolphin_Mumbai_3G' apn='mtnl3g' uid='mtnl' pwd='mtnl123'
[404-70]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-71]  carrier='CellOne_South' apn='bsnlnet' uid='' pwd=''
[404-72]  carrier='CellOne_South' apn='bsnlnet' uid='' pwd=''
[404-73]  carrier='CellOne_South' apn='bsnlnet' uid='' pwd=''
[404-74]  carrier='CellOne_Kolkata' apn='bsnlnet' uid='' pwd=''
[404-75]  carrier='CellOne_Kolkata' apn='bsnlnet' uid='' pwd=''
[404-76]  carrier='CellOne_Kolkata' apn='bsnlnet' uid='' pwd=''
[404-77]  carrier='CellOne_Kolkata' apn='bsnlnet' uid='' pwd=''
[404-78]  carrier='IDEA' apn='internet' uid='' pwd=''
[404-79]  carrier='CellOne_South' apn='bsnlnet' uid='' pwd=''
[404-80]  carrier='CellOne_South' apn='bsnlnet' uid='' pwd=''
[404-81]  carrier='CellOne_Kolkata' apn='bsnlnet' uid='' pwd=''
[404-82]  carrier='IDEA' apn='internet' uid='' pwd=''
[404-83]  carrier='Reliance RTel' apn='SMARTNET' uid='' pwd=''
[404-84]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-85]  carrier='Reliance RTel' apn='SMARTNET' uid='' pwd=''
[404-86]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-87]  carrier='IDEA' apn='internet' uid='' pwd=''
[404-88]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[404-89]  carrier='IDEA' apn='internet' uid='' pwd=''
[404-90]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-91]  carrier='AIRCEL NE' apn='aircelwebpost' uid='' pwd=''
[404-92]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-93]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-94]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-95]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-96]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-97]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[404-98]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[405-01]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-03]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-04]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-05]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-06]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-07]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-08]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-09]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-10]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-11]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-12]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-13]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-14]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-15]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-17]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-18]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-19]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-20]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-21]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-22]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-23]  carrier='Reliance RCOM' apn='rcomnet' uid='' pwd=''
[405-25]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-26]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-27]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-28]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-29]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-30]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-31]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-32]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-33]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-34]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-35]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-36]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-37]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-38]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-39]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-40]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-41]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-42]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-43]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-44]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-45]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-46]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-47]  carrier='TataDOCOMO' apn='TATA.DOCOMO.INTERNET' uid='' pwd=''
[405-51]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[405-52]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[405-53]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[405-54]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[405-55]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[405-56]  carrier='Airtel' apn='airtelgprs.com' uid='' pwd=''
[405-66]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[405-67]  carrier='Vodafone Connect' apn='www' uid='' pwd=''
[405-70]  carrier='IDEA' apn='internet' uid='' pwd=''
[405-750] carrier='Vodafone Connect' apn='jkgprs' uid='' pwd=''
[405-750] carrier='VodafoneLive!' apn='vodafonelivejk' uid='' pwd=''
[405-751] carrier='Vodafone Connect' apn='www' uid='' pwd=''
[405-752] carrier='Vodafone Connect' apn='www' uid='' pwd=''
[405-753] carrier='Vodafone Connect' apn='www' uid='' pwd=''
[405-754] carrier='Vodafone Connect' apn='www' uid='' pwd=''
[405-755] carrier='Vodafone Connect' apn='www' uid='' pwd=''
[405-756] carrier='Vodafone Connect' apn='www' uid='' pwd=''
[405-799] carrier='IDEA' apn='internet' uid='' pwd=''
[405-800] carrier='AIRCEL ROI' apn='aircelgprs' uid='' pwd=''
[405-801] carrier='AIRCEL South' apn='aircelgprs' uid='' pwd=''
[405-802] carrier='AIRCEL Central' apn='aircelgprs' uid='' pwd=''
[405-803] carrier='AIRCEL South' apn='aircelgprs' uid='' pwd=''
[405-804] carrier='AIRCEL ROI' apn='aircelgprs' uid='' pwd=''
[405-805] carrier='AIRCEL ROI' apn='aircelgprs' uid='' pwd=''
[405-806] carrier='AIRCEL Central' apn='aircelgprs' uid='' pwd=''
[405-807] carrier='AIRCEL Central' apn='aircelgprs' uid='' pwd=''
[405-808] carrier='AIRCEL Central' apn='aircelgprs' uid='' pwd=''
[405-809] carrier='AIRCEL South' apn='aircelgprs' uid='' pwd=''
[405-810] carrier='AIRCEL ROI' apn='aircelgprs' uid='' pwd=''
[405-811] carrier='AIRCEL ROI' apn='aircelgprs' uid='' pwd=''
[405-812] carrier='AIRCEL Central' apn='aircelgprs' uid='' pwd=''
[405-813] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-814] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-815] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-816] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-817] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-818] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-819] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-820] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-821] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-822] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-823] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-824] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-825] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-826] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-827] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-828] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-829] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-830] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-831] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-832] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-833] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-834] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-835] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-836] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-837] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-838] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-839] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-840] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-841] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-842] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-843] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[405-844] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-845] carrier='IDEA' apn='internet' uid='' pwd=''
[405-846] carrier='IDEA' apn='internet' uid='' pwd=''
[405-847] carrier='IDEA' apn='internet' uid='' pwd=''
[405-848] carrier='IDEA' apn='internet' uid='' pwd=''
[405-849] carrier='IDEA' apn='internet' uid='' pwd=''
[405-850] carrier='IDEA' apn='internet' uid='' pwd=''
[405-851] carrier='IDEA' apn='internet' uid='' pwd=''
[405-852] carrier='IDEA' apn='internet' uid='' pwd=''
[405-853] carrier='IDEA' apn='internet' uid='' pwd=''
[405-875] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-876] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-877] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-878] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-879] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-880] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-881] carrier='STEL' apn='gprs.stel.in' uid='' pwd=''
[405-882] carrier='STEL' apn='gprs.stel.in' uid='' pwd=''
[405-883] carrier='STEL' apn='gprs.stel.in' uid='' pwd=''
[405-884] carrier='STEL' apn='gprs.stel.in' uid='' pwd=''
[405-885] carrier='STEL' apn='gprs.stel.in' uid='' pwd=''
[405-886] carrier='STEL' apn='gprs.stel.in' uid='' pwd=''
[405-908] carrier='IDEA' apn='internet' uid='' pwd=''
[405-909] carrier='IDEA' apn='internet' uid='' pwd=''
[405-910] carrier='IDEA' apn='internet' uid='' pwd=''
[405-911] carrier='IDEA' apn='internet' uid='' pwd=''
[405-925] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-926] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-927] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-928] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-929] carrier='Uninor GPRS' apn='uninor' uid='' pwd=''
[405-932] carrier='Videocon' apn='vinternet.com' uid='' pwd=''
[410-01]  carrier='Mobilink WAP GPRS' apn='connect.mobilinkworld.com' uid='Mobilink' pwd='Mobilink'
[410-03]  carrier='Ufone WAP' apn='Ufone.internet' uid='' pwd=''
[410-04]  carrier='ZONG WAP' apn='zonginternet' uid='' pwd=''
[410-06]  carrier='Telenor WAP' apn='internet' uid='' pwd=''
[410-07]  carrier='Warid WAP' apn='Wap.warid' uid='' pwd=''
[415-01]  carrier='Alfa Internet' apn='internet.mic1.com.lb' uid='mic1' pwd='mic1'
[415-03]  carrier='MTC Touch GPRS' apn='gprs.mtctouch.com.lb' uid='' pwd=''
[416-01]  carrier='Zain JO Internet Postpaid' apn='internet' uid='' pwd=''
[416-01]  carrier='Zain JO Internet Prepaid' apn='internetpre' uid='zain' pwd='zain'
[416-03]  carrier='umniahinternet Postpaid' apn='internet' uid='' pwd=''
[416-03]  carrier='umniah Prepaid' apn='net' uid='' pwd=''
[416-77]  carrier='Orange Internet' apn='net.orange.jo' uid='net' pwd='net'
[419-02]  carrier='ZAIN MI' apn='pps' uid='pps' pwd='pps'
[419-03]  carrier='INTERNET ACTION' apn='action.wataniya.com' uid='' pwd=''
[419-04]  carrier='VIVA Internet' apn='VIVA' uid='' pwd=''
[420-01]  carrier='JAWALNet' apn='jawalnet.com.sa' uid='' pwd=''
[420-03]  carrier='mobily Net Prepaid' apn='web2' uid='' pwd=''
[420-03]  carrier='mobily Net Postpaid' apn='web1' uid='' pwd=''
[420-04]  carrier='zain-gprs' apn='zain' uid='' pwd=''
[422-02]  carrier='Oman Mobile Internet' apn='taif' uid='taif' pwd='taif'
[422-03]  carrier='Nawras GPRS' apn='isp.nawras.com.om' uid='' pwd=''
[424-02]  carrier='DATA Package' apn='etisalat.ae' uid='' pwd=''
[424-03]  carrier='du' apn='du' uid='' pwd=''
[425-01]  carrier='3G Portal' apn='uwap.orange.co.il' uid='' pwd=''
[425-01]  carrier='Internet 3G' apn='modem.orange.net.il' uid='' pwd=''
[425-02]  carrier='Cellcom Internet' apn='Sphone' uid='' pwd=''
[425-03]  carrier='Sphone Pelephone' apn='sphone.pelephone.net.il' uid='pcl@3g' pwd='pcl'
[426-01]  carrier='Internet' apn='internet.batelco.com' uid='' pwd=''
[426-02]  carrier='Zain Internet' apn='connect.mobilinkworld.com' uid='Mobilink' pwd='Mobilink'
[426-04]  carrier='VIVAGPRS' apn='viva.bh' uid='' pwd=''
[427-01]  carrier='Qtel GPRS' apn='gprs.qtel' uid='gprs' pwd='gprs'
[427-02]  carrier='VFQ Mobile Internet' apn='web.vodafone.com.qa' uid='' pwd=''
[440-10]  carrier='sp???' apn='spmode.ne.jp' uid='' pwd=''
[440-10]  carrier='mopera U(?????????)' apn='mpr2.bizho.net' uid='' pwd=''
[440-10]  carrier='mopera U??' apn='0120.mopera.net' uid='' pwd=''
[450-05]  carrier='SK Telecom (Roaming)' apn='roaming.sktelecom.com' uid='' pwd=''
[450-05]  carrier='SK Telecom' apn='web.sktelecom.com' uid='' pwd=''
[450-08]  carrier='KT-HSDPA' apn='alwayson-r6.ktfwing.com' uid='' pwd=''
[452-04]  carrier='Viettel Email' apn='v-internet' uid='' pwd=''
[452-05]  carrier='Vietnamobile Email' apn='internet' uid='' pwd=''
[452-07]  carrier='BEELINE Email' apn='internet' uid='' pwd=''
[452-08]  carrier='EVNTelecom Email' apn='e-internet' uid='' pwd=''
[454-00]  carrier='CSL Data' apn='hkcsl' uid='' pwd=''
[454-02]  carrier='CSL Data' apn='hkcsl' uid='' pwd=''
[454-03]  carrier='3' apn='mobile.three.com.hk' uid='' pwd=''
[454-04]  carrier='3-DB-GPRS' apn='web-g.three.com.hk' uid='' pwd=''
[454-06]  carrier='SmarTone HK' apn='SmarTone' uid='' pwd=''
[454-10]  carrier='CSL Data' apn='hkcsl' uid='' pwd=''
[454-12]  carrier='CMHK GPRS' apn='peoples.net' uid='' pwd=''
[454-16]  carrier='PCCW_GPRS' apn='pccwdata' uid='' pwd=''
[454-18]  carrier='CSL Data' apn='hkcsl' uid='' pwd=''
[454-19]  carrier='PCCW 3G' apn='pccw' uid='' pwd=''
[455-00]  carrier='SmarTone MAC' apn='smartgprs' uid='' pwd=''
[455-01]  carrier='CTM' apn='ctm-mobile' uid='' pwd=''
[455-03]  carrier='3 Macau' apn='web-g.three.com.hk' uid='hutchison' pwd='1234'
[455-04]  carrier='CTM' apn='ctm-mobile' uid='' pwd=''
[460-00]  carrier='China Mobile' apn='cmnet' uid='' pwd=''
[460-01]  carrier='China Unicom' 3g_apn='3gnet' 3g_uid='' 3g_pwd='' apn='uninet' uid='' pwd=''
[460-02]  carrier='China Mobile' apn='cmnet' uid='' pwd=''
[460-03]  carrier='China Telecom' apn='ctnet' uid='' pwd=''
[460-07]  carrier='China Mobile' apn='cmnet' uid='' pwd=''
[466-01]  carrier='????(Far EasTone) (Internet)' apn='internet' uid='' pwd=''
[466-88]  carrier='????(KGT-Online) (Internet)' apn='internet' uid='' pwd=''
[466-89]  carrier='????(VIBO)' apn='vibo' uid='' pwd=''
[466-92]  carrier='????(Chunghwa) (Internet)' apn='internet' uid='' pwd=''
[466-92]  carrier='????(Chunghwa)' apn='emome' uid='' pwd=''
[466-93]  carrier='?????(TW Mobile) (Internet)' apn='internet' uid='' pwd=''
[466-93]  carrier='?????(TW Mobile) (twm)' apn='TWM' uid='' pwd=''
[466-97]  carrier='?????(TW Mobile) (Internet)' apn='internet' uid='' pwd=''
[466-97]  carrier='?????(TW Mobile) (twm)' apn='TWM' uid='' pwd=''
[466-99]  carrier='?????(TW Mobile) (Internet)' apn='internet' uid='' pwd=''
[466-99]  carrier='?????(TW Mobile) (twm)' apn='TWM' uid='' pwd=''
[502-12]  carrier='Maxis 3G Internet' 3g_apn='unet' 3g_uid='maxis' 3g_pwd='wap' apn='net' uid='maxis' pwd='wap'
[502-16]  carrier='DiGi Internet' 3g_apn='diginet' 3g_uid='' 3g_pwd='' apn='diginet' uid='' pwd=''
[502-18]  carrier='U Mobile Internet' 3g_apn='my3g' 3g_uid='' 3g_pwd='' apn='my3g' uid='' pwd=''
[502-19]  carrier='Celcom 3G Internet' 3g_apn='celcom3g' 3g_uid='' 3g_pwd='' apn='celcom.net.my' uid='' pwd=''
[505-01]  carrier='Telstra Internet' apn='telstra.wap' uid='' pwd=''
[505-02]  carrier='Optus Yes Internet' apn='yesinternet' uid='' pwd=''
[505-03]  carrier='Vodafone live!' apn='live.vodafone.com' uid='' pwd=''
[505-06]  carrier='Planet 3' apn='3services' uid='' pwd=''
[505-07]  carrier='VF AU PXT' apn='live.vodafone.com' uid='' pwd=''
[505-07]  carrier='VF Internet' apn='vfinternet.au' uid='' pwd=''
[505-11]  carrier='Telstra Internet' apn='Telstra.wap' uid='' pwd=''
[505-12]  carrier='3Internet' apn='3netaccess' uid='' pwd=''
[505-12]  carrier='3' apn='3services' uid='' pwd=''
[505-71]  carrier='Telstra Internet' apn='Telstra.wap' uid='' pwd=''
[505-72]  carrier='Telstra Internet' apn='Telstra.wap' uid='' pwd=''
[505-88]  carrier='VF AU PXT' apn='live.vodafone.com' uid='' pwd=''
[505-88]  carrier='VF Internet' apn='vfinternet.au' uid='' pwd=''
[505-90]  carrier='Optus Internet' apn='internet' uid='' pwd=''
[510-01]  carrier='ISAT BB INTERNET' apn='indosat3g' uid='indosat' pwd='indosat'
[510-01]  carrier='ISAT WAP' apn='indosatgprs' uid='indosat' pwd='indosat'
[510-08]  carrier='AXISinternet' apn='AXIS' uid='AXIS' pwd='123456'
[510-10]  carrier='Telkomsel GPRS WEB' apn='internet' uid='wap' pwd='wap123'
[510-11]  carrier='XL GPRS' apn='www.xlgprs.net' uid='xlgprs' pwd='proxl'
[510-11]  carrier='XL Unlimited' apn='xlunlimited' uid='' pwd=''
[510-21]  carrier='ISAT M3 INTERNET' apn='indosatgprs' uid='indosat' pwd='indosat'
[510-89]  carrier='3 GPRS' apn='3gprs' uid='3gprs' pwd='3gprs'
[515-02]  carrier='myGlobe Internet Postpaid' apn='internet.globe.com.ph' uid='' pwd=''
[515-02]  carrier='myGlobe Internet Prepaid' apn='http.globe.com.ph' uid='' pwd=''
[515-03]  carrier='Smart Internet' apn='internet' uid='' pwd=''
[515-05]  carrier='SUN INTERNET' apn='minternet' uid='' pwd=''
[515-18]  carrier='RED INTERNET' apn='redinternet' uid='' pwd=''
[520-01]  carrier='AIS Internet' apn='internet' uid='' pwd=''
[520-18]  carrier='DTAC Internet' apn='www.dtac.co.th' uid='' pwd=''
[520-99]  carrier='True GPRS Inet' apn='internet' uid='TRUE' pwd='TRUE'
[525-01]  carrier='IDEAS E-mail' apn='e-ideas' uid='' pwd=''
[525-02]  carrier='IDEAS E-mail' apn='e-ideas' uid='' pwd=''
[525-03]  carrier='M1 E-mail' apn='sunsurf' uid='65' pwd=''
[525-05]  carrier='StarHub' apn='internet' uid='' pwd=''
[525-05]  carrier='Gee!' apn='shwap' uid='star' pwd='hub'
[525-05]  carrier='StarHub E-mail' apn='shwap' uid='' pwd=''
[530-01]  carrier='VFNZ PXT' apn='live.vodafone.com' uid='' pwd=''
[530-01]  carrier='VFNZ Internet' apn='www.vodafone.net.nz' uid='' pwd=''
[530-05]  carrier='TelecomDefault' apn='wap.telecom.co.nz' uid='' pwd=''
[530-24]  carrier='2degrees Internet' apn='internet' uid='' pwd=''
[602-01]  carrier='Mobinil Web' apn='MobinilWeb' uid='' pwd=''
[602-02]  carrier='VF internet' apn='internet.vodafone.net' uid='internet' pwd='internet'
[602-03]  carrier='Etisalat internet' apn='Etisalat' uid='' pwd=''
[605-01]  carrier='weborange' apn='weborange' uid='' pwd=''
[605-02]  carrier='mobinet' apn='gprs.tn' uid='gprs' pwd='gprs'
[605-03]  carrier='internet Tunisiana' apn='internet.tunisiana.com' uid='internet' pwd='internet'
[621-20]  carrier='Zain Mobile Internet' apn='internet.ng.Zain.com' uid='' pwd=''
[621-30]  carrier='MTN GPRS' apn='web.gprs.mtnnigeria.net' uid='web' pwd='web'
[621-50]  carrier='glo direct' apn='glosecure' uid='gprs' pwd='gprs'
[621-60]  carrier='Etisalat Internet' apn='etisalat' uid='' pwd=''
[639-02]  carrier='SafaricomBrowse' apn='Safaricom' uid='saf' pwd='data'
[639-03]  carrier='Zain WAP' apn='wap.ke.celtel.com' uid='wap' pwd='wap'
[639-07]  carrier='Orange Internet' apn='wap.orange.co.ke' uid='' pwd=''
[640-04]  carrier='Vodacom WAP' apn='Wap' uid='' pwd=''
[647-00]  carrier='Orange World re' apn='orangerun' uid='orange' pwd='orange'
[647-10]  carrier='GPRS SRR' apn='wapsfr' uid='wap' pwd='wap'
[651-01]  carrier='VCL Internet GPRS' apn='internet' uid='' pwd=''
[655-01]  carrier='Vodacom' apn='internet' uid='' pwd=''
[655-02]  carrier='8.ta internet' apn='internet' uid='' pwd=''
[655-07]  carrier='Smartdata' apn='internet' uid='' pwd=''
[655-07]  carrier='virgin_internet' apn='vdata' uid='' pwd=''
[655-10]  carrier='MTN Data' apn='myMTN' uid='mtn' pwd=''
[704-01]  carrier='INTERNET CLARO' apn='internet.ideasclaro' uid='' pwd=''
[704-02]  carrier='BROADBAND TIGO' apn='broadband.tigo.gt' uid='' pwd=''
[704-03]  carrier='Internet GT' apn='internet.movistar.gt' uid='movistargt' pwd='movistargt'
[704-30]  carrier='Internet GT' apn='internet.movistar.gt' uid='movistargt' pwd='movistargt'
[706-01]  carrier='INTERNET CLARO' apn='internet.ideasclaro' uid='' pwd=''
[706-02]  carrier='El Salvaldor Digicel' apn='web.digicelsv.com' uid='' pwd=''
[706-03]  carrier='BROADBAND TIGO' apn='broadband.tigo.sv' uid='' pwd=''
[706-04]  carrier='Internet SV' apn='internet.movistar.sv' uid='movistarsv' pwd='movistarsv'
[706-40]  carrier='Internet SV' apn='internet.movistar.sv' uid='movistarsv' pwd='movistarsv'
[708-01]  carrier='Internet Claro' apn='web.megatel.hn' uid='webmegatel' pwd='webmegatel'
[708-02]  carrier='INTERNET TIGO' apn='internet.tigo.hn' uid='' pwd=''
[708-20]  carrier='INTERNET TIGO' apn='internet.tigo.hn' uid='' pwd=''
[710-21]  carrier='INTERNET' apn='web.emovil' uid='webemovil' pwd='webemovil'
[710-300] carrier='Internet GPRS' apn='internet.movistar.ni' uid='movistarni' pwd='movistarni'
[710-730] carrier='INTERNET' apn='web.emovil' uid='webemovil' pwd='webemovil'
[712-01]  carrier='Kolbi' apn='kolbi3g' uid='' pwd=''
[712-01]  carrier='Multimedia' apn='kolbi3g' uid='' pwd=''
[712-02]  carrier='Kolbi' apn='kolbi3g' uid='' pwd=''
[712-02]  carrier='Multimedia' apn='kolbi3g' uid='' pwd=''
[712-03]  carrier='INTERNET CLARO' apn='internet.ideasclaro' uid='' pwd=''
[712-04]  carrier='movistar INTERNET' apn='internet.movistar.cr' uid='movistarcr' pwd='movistarcr'
[714-01]  carrier='Wap' apn=' apn01.cwpanama.com.pa' uid='' pwd=''
[714-01]  carrier='Mms' apn=' apn02.cwpanama.com.pa' uid='' pwd=''
[714-20]  carrier='movistar INTERNET' apn='internet.movistar.pa' uid='movistarpa' pwd='movistarpa'
[714-03]  carrier='WEB Claro' apn='web.claro.com.pa' uid='CLAROWEB' pwd='CLAROWEB'
[714-04]  carrier='INTERNET Panama' apn='web.digicelpanama.com' uid='' pwd=''
[716-06]  carrier='movistar Internet' apn='movistar.pe' uid='movistar@datos' pwd='movistar'
[716-10]  carrier='CLARO DATOS' apn='claro.pe' uid='claro' pwd='claro'
[722-07]  carrier='Movistar Emoción' apn='wap.gprs.unifon.com.ar' uid='wap' pwd='wap'
[722-31]  carrier='Claro AR' apn='igprs.claro.com.ar' uid='ctigprs' pwd='ctigprs999'
[722-310] carrier='Claro AR' apn='igprs.claro.com.ar' uid='ctigprs' pwd='ctigprs999'
[722-34]  carrier='Personal Datos' apn='datos.personal.com' uid='gprs' pwd='adgj'
[722-341] carrier='Personal Datos' apn='datos.personal.com' uid='gprs' pwd='adgj'
[724-02]  carrier='TIM Connect' apn='timbrasil.br' uid='tim' pwd='tim'
[724-03]  carrier='TIM Connect' apn='timbrasil.br' uid='tim' pwd='tim'
[724-04]  carrier='TIM Connect' apn='timbrasil.br' uid='tim' pwd='tim'
[724-05]  carrier='Java Session' apn='java.claro.com.br' uid='claro' pwd='claro'
[724-06]  carrier='Vivo Internet' apn='zap.vivo.com.br' uid='vivo' pwd='vivo'
[724-07]  carrier='SCTL GPRS' apn='sercomtel.com.br' uid='sercomtel' pwd='sercomtel'
[724-10]  carrier='Vivo Internet' apn='zap.vivo.com.br' uid='vivo' pwd='vivo'
[724-11]  carrier='Vivo Internet' apn='zap.vivo.com.br' uid='vivo' pwd='vivo'
[724-16]  carrier='BrT Modem' apn='brt.br' uid='brt' pwd='brt'
[724-19]  carrier='TelemigC GPRS' apn='gprs.telemigcelular.com.br' uid='celular' pwd='celular'
[724-23]  carrier='Vivo Internet' apn='zap.vivo.com.br' uid='vivo' pwd='vivo'
[724-24]  carrier='AmazôniaC GPRS' apn='gprs.amazoniacelular.com.br' uid='celular' pwd='celular'
[724-31]  carrier='OI GPRS' apn='gprs.oi.com.br' uid='' pwd=''
[730-01]  carrier='Internet Movil' apn='bam.entelpcs.cl' uid='entelpcs' pwd='entelpcs'
[730-10]  carrier='Internet Movil' apn='bam.entelpcs.cl' uid='entelpcs' pwd='entelpcs'
[730-02]  carrier='NEM' apn='wap.tmovil.cl' uid='wap' pwd='wap'
[730-03]  carrier='BAM Claro' apn='bam.clarochile.cl' uid='clarochile' pwd='clarochile'
[730-07]  carrier='web' apn='web.gtdmovil.cl' uid='webgtd' pwd='webgtd'
[730-08]  carrier='Internet' apn='movil.vtr.com' uid='vtrmovil' pwd='vtrmovil'
[730-08]  carrier='Wap' apn='wap.vtr.com' uid='' pwd=''
[730-08]  carrier='Bam' apn='bam.vtr.com' uid='vtr' pwd='vtr'
[730-10]  carrier='Internet Movil' apn='bam.entelpcs.cl' uid='entelpcs' pwd='entelpcs'
[732-101] carrier='WEB Comcel 3GSM' apn='internet.comcel.com.co' uid='COMCELWEB' pwd='COMCELWEB'
[732-103] carrier='TIGO WEB' apn='web.colombiamovil.com.co' uid='' pwd=''
[732-111] carrier='TIGO WEB' apn='web.colombiamovil.com.co' uid='' pwd=''
[732-123] carrier='movistar INTERNET' apn='internet.movistar.com.co' uid='movistar' pwd='movistar'
[734-01]  carrier='Digitel GSM' apn='gprsweb.digitel.ve' uid='' pwd=''
[734-02]  carrier='Digitel GSM' apn='gprsweb.digitel.ve' uid='' pwd=''
[734-03]  carrier='Digitel GSM' apn='gprsweb.digitel.ve' uid='' pwd=''
[734-04]  carrier='movistar INTERNET' apn='internet.movistar.ve' uid='' pwd=''
[734-04]  carrier='movistar WAP' apn='wap.movistar.ve' uid='' pwd=''
[734-06]  carrier='MODEM' apn='int.movilnet.com.ve' uid='' pwd=''
[736-01]  carrier='VIVA3G' apn='internet.nuevatel.com' uid='' pwd=''
[736-02]  carrier='ENTEL WAP GPRS' apn='wap.movil.com.bo' uid='' pwd=''
[736-03]  carrier='WAPTIGO' apn='wap.tigo.bo' uid='' pwd=''
[740-00]  carrier='movistar INTERNET' apn='internet.movistar.com.ec' uid='movistar' pwd='movistar'
[740-01]  carrier='Claro Internet' apn='internet.porta.com.ec' uid='' pwd=''
[740-10]  carrier='Claro Internet' apn='internet.porta.com.ec' uid='' pwd=''
[740-02]  carrier='ALEGRO 3G' apn='internet3gsp.alegro.net.ec' uid='' pwd=''
[744-01]  carrier='VOX INTERNET' apn='vox.internet' uid='' pwd=''
[744-02]  carrier='Claro PY' apn='igprs.claro.com.py' uid='ctigprs' pwd='ctigprs999'
[744-04]  carrier='TIGO PY' apn='internet.tigo.py' uid='' pwd=''
[744-05]  carrier='Personal Datos Py' apn='internet' uid='personal' pwd='personal'
[748-01]  carrier='wapANCEL' apn='wap' uid='' pwd=''
[748-01]  carrier='gprsANCEL' apn='gprs.ancel' uid='' pwd=''
[748-07]  carrier='Movistar Emoción' apn='webapn.movistar.com.uy' uid='movistar' pwd='movistar'
[748-10]  carrier='Claro UY' apn='igprs.claro.com.uy' uid='ctigprs' pwd='ctigprs999'
program/fwed/fwe_entry.c
New file
@@ -0,0 +1,96 @@
/*********************************************************************************
 *      Copyright:  (C) Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  fw_entry.c
 *    Description:  This is the FWE(FL2440 Worker Engine) applets(such as gsmd,
 *                  gpsd, zigbeed) main entry point function.
 *
 *        Version:  1.0.0(01/13/2013~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "01/13/2013 02:40:36 PM"
 *
 ********************************************************************************/
#include "fwe_entry.h"
#include "gsmd.h"
#include "gpsd.h"
#include "zigd.h"
FWE_APPLET applets_list[] =
{
    {"gsmd", gsmd_main},
    {"gpsd", gpsd_main},
    {"zigd", zigd_main},
    {0, 0}
};
static void entry_usage(void);
static void print_applist(void);
int main(int argc, char **argv)
{
    FWE_APPLET      *app = NULL;
    const char       *applet_name = NULL;
    int              ind = 0;
    applet_name = basename(argv[0]);
    /* Run command like "FWE gsmd"  */
    if( !strncmp(applet_name, FWE_ENTRY_NAME, 4) )
    {
        if(argv[1] && argv[1][0]!='-')
        {
            applet_name = basename(argv[1]);
            ind = 1;
        }
        else
        {
            entry_usage();
            return 0;
        }
    }
    for(app=(FWE_APPLET *)&applets_list; app->name; app++)
    {
        if(!strcmp (app->name, applet_name) && app->main)
        {
            return app->main(argc-ind, argv+ind);
        }
    }
    printf("%s: applet not found\n\n", applet_name);
    print_applist();
    return 0;
}
static void print_applist(void)
{
    FWE_APPLET       *app;
    printf("Currently defined applets:\n");
    for(app=(FWE_APPLET *)&applets_list; app->name; app++)
    {
        printf("%s ", app->name);
    }
    printf("\n");
}
/* Just print the help information  */
static void entry_usage(void)
{
    banner(FWE_ENTRY_NAME);
    printf("Usage: %s [applet] [arguments]...\n", FWE_ENTRY_NAME);
    printf("   or: applet [arguments]...\n");
    printf("\n\t%s is a multi-call binary that combines many FL2440 Work Engine(FWE) applets\n", FWE_ENTRY_NAME);
    printf("\tinto a single executable. We can create a symbolic link to %s for each applet\n",FWE_ENTRY_NAME);
    printf("\tlike busybox work.\n\n");
    print_applist();
    printf("\n");
    return ;
}
program/fwed/fwe_entry.h
New file
@@ -0,0 +1,39 @@
/********************************************************************************
 *      Copyright:  (C) 2013 Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  fwe_entry.h
 *    Description:  This head file
 *
 *        Version:  1.0.0(01/13/2013~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "01/13/2013 02:53:41 PM"
 *
 ********************************************************************************/
#ifndef __FWE_ENTRY_H_
#define __FWE_ENTRY_H_
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include <pthread.h>
#include "version.h"
#define FWE_ENTRY_NAME "fwed"
typedef int (APPLET_MAIN)(int argc, char **argv);
typedef struct __FWE_APPLET
{
    char             *name;
    APPLET_MAIN      *main;
} FWE_APPLET;
#endif /* end of __FWE_ENTRY_H_  */
program/fwed/gpsd/gpsd.c
New file
@@ -0,0 +1,211 @@
/*********************************************************************************
 *      Copyright:  (C) Guo Wenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  gpsd.c
 *    Description:  This is the RWME(Radiation Monitor Works Engine) gpsd applet entry point
 *
 *        Version:  1.0.0(01/13/2013~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "01/13/2013 02:40:36 PM"
 *
 ********************************************************************************/
#include "gpsd.h"
#include "cp_hal.h"
#include "cp_time.h"
static void usage_gpsd(const char *progname)
{
    banner(progname);
    printf("Usage: %s [OPTION]...\n", progname);
    printf(" %s is a daemon program running on the device to locate the device\n", progname);
    printf("\nMandatory arguments to long options are mandatory for short options too:\n");
    printf(" -d[debug   ]  Running in debug mode\n");
    printf(" -l[level   ]  Set the log level as [0..%d]\n", LOG_LEVEL_MAX-1);
    printf(" -h[help    ]  Display this help information\n");
    printf(" -v[version ]  Display the program version\n");
    return;
}
int init_gpsd_context(GPSD_CONTEX *gps)
{
    log_info("Initialize gpsd context.\n");
    gps->pwr_status = POWER_OFF;
    nmea_zero_INFO(&(gps->info));
    /*  Initialize the GPS dataport pointer */
    gps->comport = comport_init(GPS_DATAPORT, 9600, "8N1N");
    if(NULL == gps->comport)
    {
        log_err("Initialise GPS data port %s on 9600 with 8N1N failure\n", GPS_DATAPORT);
        return -1;
    }
    if( comport_open(gps->comport) < 0)
    {
        log_err("Open GPS data port %s on 9600 with 8N1N failure\n", GPS_DATAPORT);
        return -2;
    }
    log_dbg("Open GPS data port %s on 9600 with 8N1N successfully\n", GPS_DATAPORT);
    return 0;
}
void term_gpsd_context(GPSD_CONTEX *gps)
{
    comport_term(gps->comport);
#if 0
    if( ON== hal_get_gps_power())
    {
        hal_turn_gps_power(OFF);
    }
#endif
    return ;
}
int start_gpsd_service(GPSD_CONTEX *gps)
{
    int            len;
    char           buf[1024];
    while( !g_cp_signal.stop )
    {
        if( OFF== (gps->pwr_status=hal_get_gps_power()) )
        {
            hal_turn_gps_power(ON);
            continue;
        }
        memset(buf, 0, sizeof(buf));
        if( (len=comport_recv(gps->comport, buf, sizeof(buf), 3000)) > 0)
        {
            /* Data sample:
             * $GPGGA,081803.000,3029.9100,N,11423.2012,E,1,05,1.6,38.7,M,-13.7,M,,0000*4C
             * $GPGSA,A,3,18,24,21,22,15,,,,,,,,3.1,1.6,2.7*3A
             * $GPRMC,081803.000,A,3029.9100,N,11423.2012,E,1.14,126.38,210113,,,A*62
             */
            nmea_parse(buf, len, &(gps->info));
            log_nrml("GPS get UTC time: %d-%d-%d %d:%d:%d.%d\n", gps->info.utc.year+1900, gps->info.utc.mon+1, gps->info.utc.day,
                    gps->info.utc.hour+8, gps->info.utc.min, gps->info.utc.sec, gps->info.utc.hsec);
            log_nrml("GPS Sig[%d] Latitude:[%f] Longitude:[%f]\n", gps->info.sig, gps->info.lat, gps->info.lon);
        }
        micro_second_sleep(100);
    }
    return 0;
}
int gpsd_main(int argc, char **argv)
{
    int            opt;
    int            rv = 0;
    int            debug = 0;
    char           pid_file[64] = { 0 }; /* The file used to record the PID */
    const char     *progname=NULL;
    char           *log_file = GPSD_DEF_LOG_FILE;
    int            log_level = GPSD_DEF_LOG_LEVEL;
    cp_logger      *logger = NULL;
    GPSD_CONTEX    gpsd_ctx;
    struct option long_options[] = {
        {"debug", no_argument, NULL, 'd'},
        {"level", required_argument, NULL, 'l'},
        {"version", no_argument, NULL, 'v'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };
    progname = basename(argv[0]);
    /* Parser the command line parameters */
    while ((opt = getopt_long(argc, argv, "dl:vh", long_options, NULL)) != -1)
    {
        switch (opt)
        {
            case 'd': /* Set debug running */
                debug = 1;
                log_file = DBG_LOG_FILE;
                break;
            case 'l': /* Set the log level */
                log_level = atoi(optarg);
                break;
            case 'v':  /* Get software version */
                banner(progname); /* Defined in version.h */
                return EXIT_SUCCESS;
            case 'h':  /* Get help information */
                usage_gpsd(progname);
                return 0;
            default:
                break;
        } /*  end of "switch(opt)" */
    }
    if( !debug )
    {
        snprintf(pid_file, sizeof(pid_file), "%s/%s.pid", PID_FILE_PATH, progname);
        if( check_daemon_running(pid_file) )
        {
            printf("Programe already running, exit now.\n");
            return -1;
        }
    }
    if ( !(logger=cp_log_init(NULL, log_file, log_level, GPSD_LOG_FILE_SIZE)) )
    {
        printf("Logger initialize failure with file: %s\n", logger->file);
        return -1;
    }
    if ( cp_log_open() )
    {
        printf("Logger initialize failure with file: %s\n", logger->file);
        return -1;
    }
    if( !debug )
    {
        if( set_daemon_running(pid_file) )
        {
            log_fatal("Set program \"%s\" running as daemon failure.\n", progname);
            goto CleanUp;
        }
    }
    cp_install_proc_signal();
    if( init_gpsd_context(&gpsd_ctx) < 0 )
    {
        log_fatal("Initialise gpsd work context failure, rv=%d\n", rv);
        goto CleanUp;
    }
    /*  Start the GPS thread to locate the device */
    if( (rv=start_gpsd_service(&gpsd_ctx)) < 0)
    {
        log_fatal("Start PPP thread failure, rv=%d\n", rv);
        goto CleanUp;
    }
CleanUp:
    log_nrml("Terminate program \"%s\".\n", progname);
    term_gpsd_context(&gpsd_ctx);
    unlink(pid_file);
    cp_log_term();
    return rv;
}
program/fwed/gpsd/gpsd.h
New file
@@ -0,0 +1,52 @@
/********************************************************************************
 *      Copyright:  (C) guowenxue<guowenxue@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  gpsd.h
 *    Description:  This is the rmwe(Radiation Moniter Worker Engine) gpsd applet head file
 *
 *        Version:  1.0.0(02/02/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "02/02/2012 11:33:33 AM"
 *
 ********************************************************************************/
#ifndef __GPSD_H_
#define __GPSD_H_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <signal.h>
#include "cp_comport.h"
#include "cp_logger.h"
#include "cp_proc.h"
#include "nmea_info.h"
#include "version.h"
#ifndef PID_FILE_PATH
#define PID_FILE_PATH         "/var/run/"
#endif
#define GPSD_DEF_LOG_FILE     "/logs/gpsd.log"
#define GPSD_DEF_LOG_LEVEL    LOG_LEVEL_NRML
#define GPSD_LOG_FILE_SIZE    12  /* Unit KiByte */
#define GPS_DATAPORT          "/dev/ttyS4"
#define POWER_OFF             0
#define POWER_ON              1
typedef struct __GPSD_CONTEX
{
    unsigned char     pwr_status;
    nmeaINFO          info;
    COM_PORT          *comport;
} GPSD_CONTEX;
extern int gpsd_main(int argc, char **argv);
#endif /* End of __GPSD_H_ */
program/fwed/gpsd/makefile
New file
@@ -0,0 +1,95 @@
#*********************************************************************************
#      Copyright:  (C) Guo Wenxue<guowenxue@gmail.com>
#                  All rights reserved.
#
#       Filename:  Makefile
#    Description:  This is the common subdir Makefile which to compile all the C
#                  source code to object files and then generate the shared or
#                  static library named lib$(FOLDER_NAME).a orlib $(FOLDER_NAME).so,
#                  which depends on the variable $LINK_MODE.
#
#        Version:  1.0.0(01/13/2013~)
#                  Author:  Guo Wenxue <guowenxue@gmail.com>
#      ChangeLog:  1, Release initial version on "Sun Jan 13 14:44:36 CST 2013"
#
#********************************************************************************/
PWD=$(shell pwd)
#If wanna compile in the subdir, not called by top makefile, uncomment it
ifneq (${TOP_COMPILE}, YES)
LOCAL_COMPILE=YES
endif
LIBNAME=$(shell basename ${PWD})
STALIB=lib${LIBNAME}.a
DYNLIB=lib${LIBNAME}.so
VPATH= .
SRCS = $(wildcard ${VPATH}/*.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
#======================================================
#  ---> Doesn't call by top makefile, compile by local
#======================================================
ifeq (${LOCAL_COMPILE}, YES)
#ARCH?=arm926t
ARCH?=i386
CFLAGS+=-fPIC
TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]")
ifneq (,$(filter i386,$(TMP)))
    CROSS_COMPILE=
else
    CROSS_COMPILE=/opt/xtools/arm920t/bin/arm-linux-
endif
PRJDIR?=$(shell dirname ${PWD})
CFLAGS+=-I${PRJDIR}
CC = ${CROSS_COMPILE}gcc
AR = ${CROSS_COMPILE}ar
endif #End local compile
ifeq ("${LINK_MODE}", "STATIC")
    LIBS = ${STALIB}
else
    LIBS=${DYNLIB}
endif
all: entry ${LIBS} install
entry:
    @echo " ";
    @echo " =========================================================";
    @echo " **     Compile subdir ${LIBNAME} for ${ARCH}             ";
    @echo " =========================================================";
#$(LD) -g --relocatable $(OBJS) -o lib${LIBNAME}.o
${STALIB}:    $(OBJS)
    $(AR) -rcu $@ $(OBJS)
${DYNLIB}:   $(OBJS)
    $(CC) -fPIC -shared -o $@ $(OBJS)
%.o : %.c
    $(CC) -c $< $(CFLAGS)
tag:
    @ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R .
    @cscope -Rbq
install:
    @if [ ! -z "${LIBS_PATH}" ] ; then \
        mkdir -p ${LIBS_PATH} ; \
        cp ${LIBS} ${LIBS_PATH}; \
    fi;
clean:
    @rm -f *.o
    @rm -rf *.gdb *.a *.so
distclean: clean
    @rm -f  tags cscope*
.PHONY: clean entry
program/fwed/gpsd/nmea_info.c
New file
@@ -0,0 +1,195 @@
/*
 *
 * NMEA library
 * URL: http://nmea.sourceforge.net
 * Author: Tim (xtimor@gmail.com)
 * Licence: http://www.gnu.org/licenses/lgpl.html
 * $Id: sentence.c 17 2008-03-11 11:56:11Z xtimor $
 *
 */
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include "nmea_parse.h"
#include "nmea_info.h"
#include "cp_logger.h"
void nmea_zero_GPGGA(nmeaGPGGA *pack)
{
    memset(pack, 0, sizeof(nmeaGPGGA));
    nmea_time_now(&pack->utc);
    pack->ns = 'N';
    pack->ew = 'E';
    pack->elv_units = 'M';
    pack->diff_units = 'M';
}
void nmea_zero_GPGSA(nmeaGPGSA *pack)
{
    memset(pack, 0, sizeof(nmeaGPGSA));
    pack->fix_mode = 'A';
    pack->fix_type = NMEA_FIX_BAD;
}
void nmea_zero_GPGSV(nmeaGPGSV *pack)
{
    memset(pack, 0, sizeof(nmeaGPGSV));
}
void nmea_zero_GPRMC(nmeaGPRMC *pack)
{
    memset(pack, 0, sizeof(nmeaGPRMC));
    nmea_time_now(&pack->utc);
    pack->status = 'V';
    pack->ns = 'N';
    pack->ew = 'E';
    pack->declin_ew = 'E';
}
void nmea_zero_GPVTG(nmeaGPVTG *pack)
{
    memset(pack, 0, sizeof(nmeaGPVTG));
    pack->dir_t = 'T';
    pack->dec_m = 'M';
    pack->spn_n = 'N';
    pack->spk_k = 'K';
}
void nmea_zero_INFO(nmeaINFO *info)
{
    memset(info, 0, sizeof(nmeaINFO));
    nmea_time_now(&info->utc);
    info->sig = NMEA_SIG_BAD;
    info->fix = NMEA_FIX_BAD;
}
void nmea_time_now(nmeaTIME *stm)
{
    time_t lt;
    struct tm *tt;
    time(&lt);
    tt = gmtime(&lt);
    stm->year = tt->tm_year;
    stm->mon = tt->tm_mon;
    stm->day = tt->tm_mday;
    stm->hour = tt->tm_hour;
    stm->min = tt->tm_min;
    stm->sec = tt->tm_sec;
    stm->hsec = 0;
}
/* buf sample: "$GPRMC,134325.000,A,3029.8871,N,11423.1932,E,0.26,258.74,210113,,,A*"  */
int nmea_parse_line(char *buf, int buf_sz, nmeaINFO *info)
{
    int       type;
    void      *pack;
    type = nmea_pack_type(buf+1, buf_sz); /* Skip '$' */
    switch (type)
    {
        case GPGGA:
            if( !(pack = malloc(sizeof(nmeaGPGGA))) )
            {
                goto mem_fail;
            }
            if( nmea_parse_GPGGA(buf, buf_sz, (nmeaGPGGA *)pack) )
            {
                nmea_GPGGA2info(pack, info);
            }
            free(pack);
            break;
        case GPGSA:
            if( !(pack = malloc(sizeof(nmeaGPGSA))) )
            {
                goto mem_fail;
            }
            if( nmea_parse_GPGSA(buf, buf_sz, (nmeaGPGSA *)pack) )
            {
                nmea_GPGSA2info(pack, info);
            }
            free(pack);
            break;
        case GPGSV:
            if( !(pack = malloc(sizeof(nmeaGPGSV))) )
            {
                goto mem_fail;
            }
            if( nmea_parse_GPGSV(buf, buf_sz, (nmeaGPGSV *)pack) )
            {
                nmea_GPGSV2info(pack, info);
            }
            free(pack);
            break;
        case GPRMC:
            if( !(pack = malloc(sizeof(nmeaGPRMC))) )
            {
                goto mem_fail;
            }
            if( nmea_parse_GPRMC(buf, buf_sz, (nmeaGPRMC *)pack) )
            {
                nmea_GPRMC2info(pack, info);
            }
            free(pack);
            break;
        case GPVTG:
            if( !(pack = malloc(sizeof(nmeaGPVTG))) )
            {
                goto mem_fail;
            }
            if( nmea_parse_GPVTG(buf, buf_sz, (nmeaGPVTG *)pack) )
            {
                nmea_GPVTG2info(pack, info);
            }
            free(pack);
            break;
        default:
            break;
    }
    return 0;
mem_fail:
    log_err("Insufficient memory!\n");
    return -1;
}
int nmea_parse(char *data, int len, nmeaINFO *info)
{
    int       line_len, nbytes;
    char      line[512];
    while(len > 0)
    {
        memset(line, 0, sizeof(line));
        nbytes = nmea_get_item_line(data, len, line, &line_len);
        /* Not a integrated line */
        if( line_len< 0 )
            break;
        if( line_len > 0 )
        {
            nmea_parse_line(line, line_len, info);
        }
        data += nbytes;
        len -= nbytes;
    }
    return 0;
}
program/fwed/gpsd/nmea_info.h
New file
@@ -0,0 +1,234 @@
/*
 *
 * NMEA library
 * URL: http://nmea.sourceforge.net
 * Author: Tim (xtimor@gmail.com)
 * Licence: http://www.gnu.org/licenses/lgpl.html
 * $Id: sentence.h 17 2008-03-11 11:56:11Z xtimor $
 *
 */
/*! \file */
#ifndef __NMEA_INFO_H__
#define __NMEA_INFO_H__
#define NMEA_SIG_BAD        (0)
#define NMEA_SIG_LOW        (1)
#define NMEA_SIG_MID        (2)
#define NMEA_SIG_HIGH       (3)
#define NMEA_FIX_BAD        (1)
#define NMEA_FIX_2D         (2)
#define NMEA_FIX_3D         (3)
#define NMEA_MAXSAT         (12)
#define NMEA_SATINPACK      (4)
#define NMEA_NSATPACKS      (NMEA_MAXSAT / NMEA_SATINPACK)
#define NMEA_DEF_LAT        (5001.2621)
#define NMEA_DEF_LON        (3613.0595)
#ifdef  __cplusplus
extern "C" {
#endif
/**
 * Date and time data
 * @see nmea_time_now
 */
typedef struct _nmeaTIME
{
    int     year;       /**< Years since 1900 */
    int     mon;        /**< Months since January - [0,11] */
    int     day;        /**< Day of the month - [1,31] */
    int     hour;       /**< Hours since midnight - [0,23] */
    int     min;        /**< Minutes after the hour - [0,59] */
    int     sec;        /**< Seconds after the minute - [0,59] */
    int     hsec;       /**< Hundredth part of second - [0,99] */
} nmeaTIME;
/**
 * Position data in fractional degrees or radians
 */
typedef struct _nmeaPOS
{
    double lat;         /**< Latitude */
    double lon;         /**< Longitude */
} nmeaPOS;
/**
 * Information about satellite
 * @see nmeaSATINFO
 * @see nmeaGPGSV
 */
typedef struct _nmeaSATELLITE
{
    int     id;         /**< Satellite PRN number */
    int     in_use;     /**< Used in position fix */
    int     elv;        /**< Elevation in degrees, 90 maximum */
    int     azimuth;    /**< Azimuth, degrees from true north, 000 to 359 */
    int     sig;        /**< Signal, 00-99 dB */
} nmeaSATELLITE;
/**
 * Information about all satellites in view
 * @see nmeaINFO
 * @see nmeaGPGSV
 */
typedef struct _nmeaSATINFO
{
    int     inuse;      /**< Number of satellites in use (not those in view) */
    int     inview;     /**< Total number of satellites in view */
    nmeaSATELLITE sat[NMEA_MAXSAT]; /**< Satellites information */
} nmeaSATINFO;
/**
 * Summary GPS information from all parsed packets,
 * used also for generating NMEA stream
 * @see nmea_parse
 * @see nmea_GPGGA2info,  nmea_...2info
 */
typedef struct _nmeaINFO
{
    int     smask;      /**< Mask specifying types of packages from which data have been obtained */
    nmeaTIME utc;       /**< UTC of position */
    int     sig;        /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */
    int     fix;        /**< Operating mode, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */
    double  PDOP;       /**< Position Dilution Of Precision */
    double  HDOP;       /**< Horizontal Dilution Of Precision */
    double  VDOP;       /**< Vertical Dilution Of Precision */
    double  lat;        /**< Latitude in NDEG - +/-[degree][min].[sec/60] */
    double  lon;        /**< Longitude in NDEG - +/-[degree][min].[sec/60] */
    double  elv;        /**< Antenna altitude above/below mean sea level (geoid) in meters */
    double  speed;      /**< Speed over the ground in kilometers/hour */
    double  direction;  /**< Track angle in degrees True */
    double  declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */
    nmeaSATINFO satinfo; /**< Satellites information */
} nmeaINFO;
/**
 * NMEA packets type which parsed and generated by library
 */
enum nmeaPACKTYPE
{
    GPNON   = 0x0000,   /**< Unknown packet type. */
    GPGGA   = 0x0001,   /**< GGA - Essential fix data which provide 3D location and accuracy data. */
    GPGSA   = 0x0002,   /**< GSA - GPS receiver operating mode, SVs used for navigation, and DOP values. */
    GPGSV   = 0x0004,   /**< GSV - Number of SVs in view, PRN numbers, elevation, azimuth & SNR values. */
    GPRMC   = 0x0008,   /**< RMC - Recommended Minimum Specific GPS/TRANSIT Data. */
    GPVTG   = 0x0010    /**< VTG - Actual track made good and speed over ground. */
};
/**
 * GGA packet information structure (Global Positioning System Fix Data)
 */
typedef struct _nmeaGPGGA
{
    nmeaTIME utc;       /**< UTC of position (just time) */
    double  lat;        /**< Latitude in NDEG - [degree][min].[sec/60] */
    char    ns;         /**< [N]orth or [S]outh */
    double  lon;        /**< Longitude in NDEG - [degree][min].[sec/60] */
    char    ew;         /**< [E]ast or [W]est */
    int     sig;        /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */
    int     satinuse;   /**< Number of satellites in use (not those in view) */
    double  HDOP;       /**< Horizontal dilution of precision */
    double  elv;        /**< Antenna altitude above/below mean sea level (geoid) */
    char    elv_units;  /**< [M]eters (Antenna height unit) */
    double  diff;       /**< Geoidal separation (Diff. between WGS-84 earth ellipsoid and mean sea level. '-' = geoid is below WGS-84 ellipsoid) */
    char    diff_units; /**< [M]eters (Units of geoidal separation) */
    double  dgps_age;   /**< Time in seconds since last DGPS update */
    int     dgps_sid;   /**< DGPS station ID number */
} nmeaGPGGA;
/**
 * GSA packet information structure (Satellite status)
 */
typedef struct _nmeaGPGSA
{
    char    fix_mode;   /**< Mode (M = Manual, forced to operate in 2D or 3D; A = Automatic, 3D/2D) */
    int     fix_type;   /**< Type, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */
    int     sat_prn[NMEA_MAXSAT]; /**< PRNs of satellites used in position fix (null for unused fields) */
    double  PDOP;       /**< Dilution of precision */
    double  HDOP;       /**< Horizontal dilution of precision */
    double  VDOP;       /**< Vertical dilution of precision */
} nmeaGPGSA;
/**
 * GSV packet information structure (Satellites in view)
 */
typedef struct _nmeaGPGSV
{
    int     pack_count; /**< Total number of messages of this type in this cycle */
    int     pack_index; /**< Message number */
    int     sat_count;  /**< Total number of satellites in view */
    nmeaSATELLITE sat_data[NMEA_SATINPACK];
} nmeaGPGSV;
/**
 * RMC packet information structure (Recommended Minimum sentence C)
 */
typedef struct _nmeaGPRMC
{
    nmeaTIME utc;       /**< UTC of position */
    char    status;     /**< Status (A = active or V = void) */
    double  lat;        /**< Latitude in NDEG - [degree][min].[sec/60] */
    char    ns;         /**< [N]orth or [S]outh */
    double  lon;        /**< Longitude in NDEG - [degree][min].[sec/60] */
    char    ew;         /**< [E]ast or [W]est */
    double  speed;      /**< Speed over the ground in knots */
    double  direction;  /**< Track angle in degrees True */
    double  declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */
    char    declin_ew;  /**< [E]ast or [W]est */
    char    mode;       /**< Mode indicator of fix type (A = autonomous, D = differential, E = estimated, N = not valid, S = simulator) */
} nmeaGPRMC;
/**
 * VTG packet information structure (Track made good and ground speed)
 */
typedef struct _nmeaGPVTG
{
    double  dir;        /**< True track made good (degrees) */
    char    dir_t;      /**< Fixed text 'T' indicates that track made good is relative to true north */
    double  dec;        /**< Magnetic track made good */
    char    dec_m;      /**< Fixed text 'M' */
    double  spn;        /**< Ground speed, knots */
    char    spn_n;      /**< Fixed text 'N' indicates that speed over ground is in knots */
    double  spk;        /**< Ground speed, kilometers per hour */
    char    spk_k;      /**< Fixed text 'K' indicates that speed over ground is in kilometers/hour */
} nmeaGPVTG;
void nmea_zero_INFO(nmeaINFO *info);
void nmea_zero_GPGGA(nmeaGPGGA *pack);
void nmea_zero_GPGSA(nmeaGPGSA *pack);
void nmea_zero_GPGSV(nmeaGPGSV *pack);
void nmea_zero_GPRMC(nmeaGPRMC *pack);
void nmea_zero_GPVTG(nmeaGPVTG *pack);
void nmea_time_now(nmeaTIME *t);
int nmea_parse(char *buf, int len, nmeaINFO *info);
#ifdef  __cplusplus
}
#endif
#endif /* __NMEA_INFO_H__ */
program/fwed/gpsd/nmea_parse.c
New file
@@ -0,0 +1,681 @@
/*
 *
 * NMEA library
 * URL: http://nmea.sourceforge.net
 * Author: Tim (xtimor@gmail.com)
 * Licence: http://www.gnu.org/licenses/lgpl.html
 * $Id: context.c 17 2008-03-11 11:56:11Z xtimor $
 *
 */
#include "nmea_parse.h"
#include "cp_logger.h"
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#define NMEA_TOKS_COMPARE   (1)
#define NMEA_TOKS_PERCENT   (2)
#define NMEA_TOKS_WIDTH     (3)
#define NMEA_TOKS_TYPE      (4)
/**
 * \brief Convert string to number
 */
int nmea_atoi(const char *str, int str_sz, int radix)
{
    char *tmp_ptr;
    char buff[NMEA_CONVSTR_BUF];
    int res = 0;
    if(str_sz < NMEA_CONVSTR_BUF)
    {
        memcpy(&buff[0], str, str_sz);
        buff[str_sz] = '\0';
        res = strtol(&buff[0], &tmp_ptr, radix);
    }
    return res;
}
/**
 * \brief Convert string to fraction number
 */
double nmea_atof(const char *str, int str_sz)
{
    char *tmp_ptr;
    char buff[NMEA_CONVSTR_BUF];
    double res = 0;
    if(str_sz < NMEA_CONVSTR_BUF)
    {
        memcpy(&buff[0], str, str_sz);
        buff[str_sz] = '\0';
        res = strtod(&buff[0], &tmp_ptr);
    }
    return res;
}
/**
 * \brief Analyse string (specificate for NMEA sentences)
 */
int nmea_scanf(const char *buff, int buff_sz, const char *format, ...)
{
    const char *beg_tok;
    const char *end_buf = buff + buff_sz;
    va_list arg_ptr;
    int tok_type = NMEA_TOKS_COMPARE;
    int width = 0;
    const char *beg_fmt = 0;
    int snum = 0, unum = 0;
    int tok_count = 0;
    void *parg_target;
    va_start(arg_ptr, format);
    for(; *format && buff < end_buf; ++format)
    {
        switch(tok_type)
        {
        case NMEA_TOKS_COMPARE:
            if('%' == *format)
                tok_type = NMEA_TOKS_PERCENT;
            else if(*buff++ != *format)
                goto fail;
            break;
        case NMEA_TOKS_PERCENT:
            width = 0;
            beg_fmt = format;
            tok_type = NMEA_TOKS_WIDTH;
        case NMEA_TOKS_WIDTH:
            if(isdigit(*format))
                break;
            {
                tok_type = NMEA_TOKS_TYPE;
                if(format > beg_fmt)
                    width = nmea_atoi(beg_fmt, (int)(format - beg_fmt), 10);
            }
        case NMEA_TOKS_TYPE:
            beg_tok = buff;
            if(!width && ('c' == *format || 'C' == *format) && *buff != format[1])
                width = 1;
            if(width)
            {
                if(buff + width <= end_buf)
                    buff += width;
                else
                    goto fail;
            }
            else
            {
                if(!format[1] || (0 == (buff = (char *)memchr(buff, format[1], end_buf - buff))))
                    buff = end_buf;
            }
            if(buff > end_buf)
                goto fail;
            tok_type = NMEA_TOKS_COMPARE;
            tok_count++;
            parg_target = 0; width = (int)(buff - beg_tok);
            switch(*format)
            {
            case 'c':
            case 'C':
                parg_target = (void *)va_arg(arg_ptr, char *);
                if(width && 0 != (parg_target))
                    *((char *)parg_target) = *beg_tok;
                break;
            case 's':
            case 'S':
                parg_target = (void *)va_arg(arg_ptr, char *);
                if(width && 0 != (parg_target))
                {
                    memcpy(parg_target, beg_tok, width);
                    ((char *)parg_target)[width] = '\0';
                }
                break;
            case 'f':
            case 'g':
            case 'G':
            case 'e':
            case 'E':
                parg_target = (void *)va_arg(arg_ptr, double *);
                if(width && 0 != (parg_target))
                    *((double *)parg_target) = nmea_atof(beg_tok, width);
                break;
            };
            if(parg_target)
                break;
            if(0 == (parg_target = (void *)va_arg(arg_ptr, int *)))
                break;
            if(!width)
                break;
            switch(*format)
            {
            case 'd':
            case 'i':
                snum = nmea_atoi(beg_tok, width, 10);
                memcpy(parg_target, &snum, sizeof(int));
                break;
            case 'u':
                unum = nmea_atoi(beg_tok, width, 10);
                memcpy(parg_target, &unum, sizeof(unsigned int));
                break;
            case 'x':
            case 'X':
                unum = nmea_atoi(beg_tok, width, 16);
                memcpy(parg_target, &unum, sizeof(unsigned int));
                break;
            case 'o':
                unum = nmea_atoi(beg_tok, width, 8);
                memcpy(parg_target, &unum, sizeof(unsigned int));
                break;
            default:
                goto fail;
            };
            break;
        };
    }
fail:
    va_end(arg_ptr);
    return tok_count;
}
int nmea_parse_time(const char *buff, int buff_sz, nmeaTIME *res)
{
    int success = 0;
    switch(buff_sz)
    {
    case sizeof("hhmmss") - 1:
        success = (3 == nmea_scanf(buff, buff_sz,
            "%2d%2d%2d", &(res->hour), &(res->min), &(res->sec)
            ));
        break;
    case sizeof("hhmmss.s") - 1:
    case sizeof("hhmmss.ss") - 1:
    case sizeof("hhmmss.sss") - 1:
        success = (4 == nmea_scanf(buff, buff_sz,
            "%2d%2d%2d.%d", &(res->hour), &(res->min), &(res->sec), &(res->hsec)
            ));
        break;
    default:
        log_err("Parse of time error (format error)!\n");
        success = 0;
        break;
    }
    return (success?0:-1);
}
/**
 * \brief Define packet type by header (nmeaPACKTYPE).
 * @param buff a constant character pointer of packet buffer.
 * @param buff_sz buffer size.
 * @return The defined packet type
 * @see nmeaPACKTYPE
 */
int nmea_pack_type(const char *buff, int buff_sz)
{
    static const char *pheads[] = {
        "GPGGA",
        "GPGSA",
        "GPGSV",
        "GPRMC",
        "GPVTG",
    };
    assert(buff);
    if(buff_sz < 5)
        return GPNON;
    else if(0 == memcmp(buff, pheads[0], 5))
        return GPGGA;
    else if(0 == memcmp(buff, pheads[1], 5))
        return GPGSA;
    else if(0 == memcmp(buff, pheads[2], 5))
        return GPGSV;
    else if(0 == memcmp(buff, pheads[3], 5))
        return GPRMC;
    else if(0 == memcmp(buff, pheads[4], 5))
        return GPVTG;
    return GPNON;
}
/**
 * \brief Get the first line in buffer and check control sum (CRC).
 * @param buff a constant character pointer of packets buffer.
 * @param buff_sz buffer size.
 * @param line pointer output for a line in the packet
 * @param line_len a integer pointer for return the line length (must be defined).
 * @return already read bytes to a line end from buff.
 */
int nmea_get_item_line(const char *buff, int buff_sz, char *line, int *line_len)
{
    static const int tail_sz = 3 /* *[CRC] */ + 2 /* \r\n */;
    char  *start, *star;
    int nread = 0;
    *line_len = -1;
    /* Data sample:
     * $GPGGA,081803.000,3029.9100,N,11423.2012,E,1,05,1.6,38.7,M,-13.7,M,,0000*4C
     * $GPGSA,A,3,18,24,21,22,15,,,,,,,,3.1,1.6,2.7*3A
     * $GPRMC,081803.000,A,3029.9100,N,11423.2012,E,1.14,126.38,210113,,,A*62
     */
    start = strchr(buff, '$');
    if(!start)
    {
        /* Can not find the line start flag '$', means can not find an integrated line */
        return buff_sz;
    }
    star = strchr(start, '*');
    if(!star)
    {
        /* Can not find the line CRC start flag '*', means can not find an integrated line */
        return buff_sz;
    }
    *line_len = star - start + 1; /* include '*' */
    strncpy(line, start, *line_len);
    nread = (star-buff) + tail_sz ;
    return nread>buff_sz ? buff_sz : nread;
}
/**
 * \brief Find tail of packet ("\r\n") in buffer and check control sum (CRC).
 * @param buff a constant character pointer of packets buffer.
 * @param buff_sz buffer size.
 * @param res_crc a integer pointer for return CRC of packet (must be defined).
 * @return Number of bytes to packet tail.
 */
int nmea_find_tail(const char *buff, int buff_sz, int *res_crc)
{
    static const int tail_sz = 3 /* *[CRC] */ + 2 /* \r\n */;
    const char *end_buff = buff + buff_sz;
    int nread = 0;
    int crc = 0;
    assert(buff && res_crc);
    *res_crc = -1;
    for(;buff < end_buff; ++buff, ++nread)
    {
        if(('$' == *buff) && nread)
        {
            buff = 0;
            break;
        }
        else if('*' == *buff)
        {
            if(buff + tail_sz <= end_buff && '\r' == buff[3] && '\n' == buff[4])
            {
                *res_crc = nmea_atoi(buff + 1, 2, 16);
                nread = buff_sz - (int)(end_buff - (buff + tail_sz));
                if(*res_crc != crc)
                {
                    *res_crc = -1;
                    buff = 0;
                }
            }
            break;
        }
        else if(nread)
            crc ^= (int)*buff;
    }
    if(*res_crc < 0 && buff)
        nread = 0;
    return nread;
}
/**
 * \brief Parse GGA packet from buffer.
 * @param buff a constant character pointer of packet buffer.
 * @param buff_sz buffer size.
 * @param pack a pointer of packet which will filled by function.
 * @return 1 (true) - if parsed successfully or 0 (false) - if fail.
 */
int nmea_parse_GPGGA(const char *buff, int buff_sz, nmeaGPGGA *pack)
{
    char time_buff[NMEA_TIMEPARSE_BUF];
    assert(buff && pack);
    memset(pack, 0, sizeof(nmeaGPGGA));
    log_dbg("parse_GPGGA: %s\n", buff);
    if(14 != nmea_scanf(buff, buff_sz,
        "$GPGGA,%s,%f,%C,%f,%C,%d,%d,%f,%f,%C,%f,%C,%f,%d*",
        &(time_buff[0]),
        &(pack->lat), &(pack->ns), &(pack->lon), &(pack->ew),
        &(pack->sig), &(pack->satinuse), &(pack->HDOP), &(pack->elv), &(pack->elv_units),
        &(pack->diff), &(pack->diff_units), &(pack->dgps_age), &(pack->dgps_sid)))
    {
        log_err("GPGGA parse error!\n");
        return 0;
    }
    if(0 != nmea_parse_time(&time_buff[0], (int)strlen(&time_buff[0]), &(pack->utc)))
    {
        log_err("GPGGA time parse error!\n");
        return 0;
    }
    return 1;
}
/**
 * \brief Parse GSA packet from buffer.
 * @param buff a constant character pointer of packet buffer.
 * @param buff_sz buffer size.
 * @param pack a pointer of packet which will filled by function.
 * @return 1 (true) - if parsed successfully or 0 (false) - if fail.
 */
int nmea_parse_GPGSA(const char *buff, int buff_sz, nmeaGPGSA *pack)
{
    assert(buff && pack);
    memset(pack, 0, sizeof(nmeaGPGSA));
    log_dbg("parse_GPGSA: %s\n", buff);
    if(17 != nmea_scanf(buff, buff_sz,
        "$GPGSA,%C,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f,%f*",
        &(pack->fix_mode), &(pack->fix_type),
        &(pack->sat_prn[0]), &(pack->sat_prn[1]), &(pack->sat_prn[2]), &(pack->sat_prn[3]), &(pack->sat_prn[4]), &(pack->sat_prn[5]),
        &(pack->sat_prn[6]), &(pack->sat_prn[7]), &(pack->sat_prn[8]), &(pack->sat_prn[9]), &(pack->sat_prn[10]), &(pack->sat_prn[11]),
        &(pack->PDOP), &(pack->HDOP), &(pack->VDOP)))
    {
        log_err("GPGSA parse error!\n");
        return 0;
    }
    return 1;
}
/**
 * \brief Parse GSV packet from buffer.
 * @param buff a constant character pointer of packet buffer.
 * @param buff_sz buffer size.
 * @param pack a pointer of packet which will filled by function.
 * @return 1 (true) - if parsed successfully or 0 (false) - if fail.
 */
int nmea_parse_GPGSV(const char *buff, int buff_sz, nmeaGPGSV *pack)
{
    int nsen, nsat;
    assert(buff && pack);
    memset(pack, 0, sizeof(nmeaGPGSV));
    log_dbg("parse_GPGSV: %s\n", buff);
    nsen = nmea_scanf(buff, buff_sz,
        "$GPGSV,%d,%d,%d,"
        "%d,%d,%d,%d,"
        "%d,%d,%d,%d,"
        "%d,%d,%d,%d,"
        "%d,%d,%d,%d*",
        &(pack->pack_count), &(pack->pack_index), &(pack->sat_count),
        &(pack->sat_data[0].id), &(pack->sat_data[0].elv), &(pack->sat_data[0].azimuth), &(pack->sat_data[0].sig),
        &(pack->sat_data[1].id), &(pack->sat_data[1].elv), &(pack->sat_data[1].azimuth), &(pack->sat_data[1].sig),
        &(pack->sat_data[2].id), &(pack->sat_data[2].elv), &(pack->sat_data[2].azimuth), &(pack->sat_data[2].sig),
        &(pack->sat_data[3].id), &(pack->sat_data[3].elv), &(pack->sat_data[3].azimuth), &(pack->sat_data[3].sig));
    nsat = (pack->pack_index - 1) * NMEA_SATINPACK;
    nsat = (nsat + NMEA_SATINPACK > pack->sat_count)?pack->sat_count - nsat:NMEA_SATINPACK;
    nsat = nsat * 4 + 3 /* first three sentence`s */;
    if(nsen < nsat || nsen > (NMEA_SATINPACK * 4 + 3))
    {
        log_err("GPGSV parse error!\n");
        return 0;
    }
    return 1;
}
/**
 * \brief Parse RMC packet from buffer.
 * @param buff a constant character pointer of packet buffer.
 * @param buff_sz buffer size.
 * @param pack a pointer of packet which will filled by function.
 * @return 1 (true) - if parsed successfully or 0 (false) - if fail.
 */
int nmea_parse_GPRMC(const char *buff, int buff_sz, nmeaGPRMC *pack)
{
    int nsen;
    char time_buff[NMEA_TIMEPARSE_BUF];
    assert(buff && pack);
    memset(pack, 0, sizeof(nmeaGPRMC));
    log_dbg("parse_GPGRMC: %s\n", buff);
    nsen = nmea_scanf(buff, buff_sz,
        "$GPRMC,%s,%C,%f,%C,%f,%C,%f,%f,%2d%2d%2d,%f,%C,%C*",
        &(time_buff[0]),
        &(pack->status), &(pack->lat), &(pack->ns), &(pack->lon), &(pack->ew),
        &(pack->speed), &(pack->direction),
        &(pack->utc.day), &(pack->utc.mon), &(pack->utc.year),
        &(pack->declination), &(pack->declin_ew), &(pack->mode));
    if(nsen != 13 && nsen != 14)
    {
        log_err("GPRMC parse error!\n");
        return 0;
    }
    if(0 != nmea_parse_time(&time_buff[0], (int)strlen(&time_buff[0]), &(pack->utc)))
    {
        log_err("GPRMC time parse error!\n");
        return 0;
    }
    if(pack->utc.year < 90)
        pack->utc.year += 100;
    pack->utc.mon -= 1;
    return 1;
}
/**
 * \brief Parse VTG packet from buffer.
 * @param buff a constant character pointer of packet buffer.
 * @param buff_sz buffer size.
 * @param pack a pointer of packet which will filled by function.
 * @return 1 (true) - if parsed successfully or 0 (false) - if fail.
 */
int nmea_parse_GPVTG(const char *buff, int buff_sz, nmeaGPVTG *pack)
{
    assert(buff && pack);
    memset(pack, 0, sizeof(nmeaGPVTG));
    log_dbg("parse_GPVTG: %s\n", buff);
    if(8 != nmea_scanf(buff, buff_sz,
        "$GPVTG,%f,%C,%f,%C,%f,%C,%f,%C*",
        &(pack->dir), &(pack->dir_t),
        &(pack->dec), &(pack->dec_m),
        &(pack->spn), &(pack->spn_n),
        &(pack->spk), &(pack->spk_k)))
    {
        log_err("GPVTG parse error!\n");
        return 0;
    }
    if( pack->dir_t != 'T' ||
        pack->dec_m != 'M' ||
        pack->spn_n != 'N' ||
        pack->spk_k != 'K')
    {
        log_err("GPVTG parse error (format error)!\n");
        return 0;
    }
    return 1;
}
/**
 * \brief Fill nmeaINFO structure by GGA packet data.
 * @param pack a pointer of packet structure.
 * @param info a pointer of summary information structure.
 */
void nmea_GPGGA2info(nmeaGPGGA *pack, nmeaINFO *info)
{
    assert(pack && info);
    info->utc.hour = pack->utc.hour;
    info->utc.min = pack->utc.min;
    info->utc.sec = pack->utc.sec;
    info->utc.hsec = pack->utc.hsec;
    info->sig = pack->sig;
    info->HDOP = pack->HDOP;
    info->elv = pack->elv;
    info->lat = ((pack->ns == 'N')?pack->lat:-(pack->lat));
    info->lon = ((pack->ew == 'E')?pack->lon:-(pack->lon));
    info->smask |= GPGGA;
}
/**
 * \brief Fill nmeaINFO structure by GSA packet data.
 * @param pack a pointer of packet structure.
 * @param info a pointer of summary information structure.
 */
void nmea_GPGSA2info(nmeaGPGSA *pack, nmeaINFO *info)
{
    int i, j, nuse = 0;
    assert(pack && info);
    info->fix = pack->fix_type;
    info->PDOP = pack->PDOP;
    info->HDOP = pack->HDOP;
    info->VDOP = pack->VDOP;
    for(i = 0; i < NMEA_MAXSAT; ++i)
    {
        for(j = 0; j < info->satinfo.inview; ++j)
        {
            if(pack->sat_prn[i] && pack->sat_prn[i] == info->satinfo.sat[j].id)
            {
                info->satinfo.sat[j].in_use = 1;
                nuse++;
            }
        }
    }
    info->satinfo.inuse = nuse;
    info->smask |= GPGSA;
}
/**
 * \brief Fill nmeaINFO structure by GSV packet data.
 * @param pack a pointer of packet structure.
 * @param info a pointer of summary information structure.
 */
void nmea_GPGSV2info(nmeaGPGSV *pack, nmeaINFO *info)
{
    int isat, isi, nsat;
    assert(pack && info);
    if(pack->pack_index > pack->pack_count ||
        pack->pack_index * NMEA_SATINPACK > NMEA_MAXSAT)
        return;
    if(pack->pack_index < 1)
        pack->pack_index = 1;
    info->satinfo.inview = pack->sat_count;
    nsat = (pack->pack_index - 1) * NMEA_SATINPACK;
    nsat = (nsat + NMEA_SATINPACK > pack->sat_count)?pack->sat_count - nsat:NMEA_SATINPACK;
    for(isat = 0; isat < nsat; ++isat)
    {
        isi = (pack->pack_index - 1) * NMEA_SATINPACK + isat;
        info->satinfo.sat[isi].id = pack->sat_data[isat].id;
        info->satinfo.sat[isi].elv = pack->sat_data[isat].elv;
        info->satinfo.sat[isi].azimuth = pack->sat_data[isat].azimuth;
        info->satinfo.sat[isi].sig = pack->sat_data[isat].sig;
    }
    info->smask |= GPGSV;
}
/**
 * \brief Fill nmeaINFO structure by RMC packet data.
 * @param pack a pointer of packet structure.
 * @param info a pointer of summary information structure.
 */
void nmea_GPRMC2info(nmeaGPRMC *pack, nmeaINFO *info)
{
    assert(pack && info);
    if('A' == pack->status)
    {
        if(NMEA_SIG_BAD == info->sig)
            info->sig = NMEA_SIG_MID;
        if(NMEA_FIX_BAD == info->fix)
            info->fix = NMEA_FIX_2D;
    }
    else if('V' == pack->status)
    {
        info->sig = NMEA_SIG_BAD;
        info->fix = NMEA_FIX_BAD;
    }
    info->utc = pack->utc;
    info->lat = ((pack->ns == 'N')?pack->lat:-(pack->lat));
    info->lon = ((pack->ew == 'E')?pack->lon:-(pack->lon));
    info->speed = pack->speed * NMEA_TUD_KNOTS;
    info->direction = pack->direction;
    info->smask |= GPRMC;
}
/**
 * \brief Fill nmeaINFO structure by VTG packet data.
 * @param pack a pointer of packet structure.
 * @param info a pointer of summary information structure.
 */
void nmea_GPVTG2info(nmeaGPVTG *pack, nmeaINFO *info)
{
    assert(pack && info);
    info->direction = pack->dir;
    info->declination = pack->dec;
    info->speed = pack->spk;
    info->smask |= GPVTG;
}
Diff truncated after the above file
program/fwed/gpsd/nmea_parse.h program/fwed/gsmd/gsmd.c program/fwed/gsmd/gsmd.h program/fwed/gsmd/makefile program/fwed/makefile program/fwed/zigd/makefile program/fwed/zigd/zigd.c program/fwed/zigd/zigd.h program/serial2socket/thread_mode/cp_comport.c program/serial2socket/thread_mode/cp_comport.h program/serial2socket/thread_mode/cp_logger.c program/serial2socket/thread_mode/cp_logger.h program/serial2socket/thread_mode/cp_proc.c program/serial2socket/thread_mode/cp_proc.h program/serial2socket/thread_mode/cp_socket.c program/serial2socket/thread_mode/cp_socket.h program/serial2socket/thread_mode/makefile program/serial2socket/thread_mode/sp2sck.c program/serial2socket/thread_mode/sp2sck.h program/sqlite/build.sh program/sqlite/makefile program/sqlite/test_sqlite.c program/unp/makefile program/unp/socket_client.c program/unp/socket_server_select.c program/unp/socket_server_thread.c program/unp/test.sh