LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-23-2009, 01:21 PM   #1
stuffradio
LQ Newbie
 
Registered: Sep 2005
Posts: 10

Rep: Reputation: 0
Libc arrays


Hi,

I'm using this code:
Code:
/*
 * Based on:
 * http://www.gnu.org/software/libc/manual/html_mono/libc.html#Server%20Example
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <syslog.h>
#include <stdarg.h>
#include <time.h>

#define PORT             1730   /* default port to listen on */
#define MAXMSG          10240
#define MAX_QUEUED_CONNS    5
#define MAX_SOCK_IDLE      10   /* minutes */
#define SECS_PER_MIN       60

/*
 * Global vars.
 */
static const char  gVersion[] = "@(#) tcpechoserver v1.4 " __DATE__;

const char         gScaryMsg[] =
    "\r\n\r\n                             OK\r\n"
    "      Your IP address has been logged: ";

const char         gDiscMsg[] = "\r\nDisconnecting due to inactivity\r\n";

char               gHostNameBuf[512];
struct sockaddr_in gServerName;
int                gMaxFd;
int                gNumberClients;
int                gDebug;
int                gTcpListenSock;
int                gUdpSock;
time_t             gMaxSockIdle = MAX_SOCK_IDLE * SECS_PER_MIN;
time_t             gSockTime[FD_SETSIZE];
fd_set             gActive_fd_set;

#ifdef __CYGWIN__
/* Set default log file name for Cygwin build. */
char               gLogFilename[FILENAME_MAX] = { "C:/TEMP/tcpecho.log" };
#define SYSLOG   mySyslog
/* ------------------------------------------------
 *                                       mySyslog
 * ------------------------------------------------
 */
static void mySyslog (int level, const char *fmt, ...)
{
    static FILE    *logFile = NULL;
    va_list         ap;
    char            buf[1024];
    time_t          logTime;

    if (logFile == NULL)
    {
        logFile = fopen (gLogFilename, "a");
    }

    if (logFile != NULL)
    {
        va_start (ap, fmt);
        vsnprintf (buf, sizeof buf, fmt, ap);
        va_end (ap);

        logTime = time (NULL);
        fprintf (logFile, "%24.24s: %s\n", ctime (&logTime), buf);
        fflush (logFile);
    }
}
#else
#define SYSLOG   syslog
#endif

/* ------------------------------------------------
 *                               getRemoteHostname
 * ------------------------------------------------
 */
const char * getRemoteHostname (struct sockaddr_in sin)
{
    struct hostent *hp;

    hp = gethostbyaddr ((char *) &sin.sin_addr,
                        sizeof sin.sin_addr, AF_INET);
    if (hp)
    {
        /*
         * We found a corresponding hostname, format the string one way...
         */
        snprintf (gHostNameBuf, sizeof gHostNameBuf, "%s [%s]", hp->h_name,
                  inet_ntoa (sin.sin_addr));
    }
    else
    {
        /*
         * This host not in the host tables or Domain Name Server.
         */
        snprintf (gHostNameBuf, sizeof gHostNameBuf, "[%s]",
                  inet_ntoa (sin.sin_addr));
    }

    return gHostNameBuf;
}

/* ------------------------------------------------
 *                                    bindToPort 
 * ------------------------------------------------
 */
int bindToPort (int sockStyle)
{
    int             sock;
    int             opt;

    /* Create the socket. */
    sock = socket (PF_INET, sockStyle, 0);
    if (sock < 0)
    {
        SYSLOG (LOG_USER, "socket failed");
        exit (EXIT_FAILURE);
    }

    /*
     * Set the "REUSEADDR" option on this socket. This will allow us to
     * bind() to it EVEN if there already connections in progress on this
     * port number. Otherwise, we would get an "Address already in use"
     * error.
     */
    if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
    {
      SYSLOG (LOG_USER, "setsockopt failed");
      exit (EXIT_FAILURE);
    }

    if (bind (sock, (struct sockaddr *) &gServerName, sizeof gServerName) < 0)
    {
        SYSLOG (LOG_USER, "bind failed");
        exit (EXIT_FAILURE);
    }

    return sock;
}

/* ------------------------------------------------
 *                                    closeSock
 * ------------------------------------------------
 */
void closeSock (int sock)
{
    SYSLOG (LOG_USER, "connection %d: disconnecting.", sock);
    close (sock);
    FD_CLR (sock, &gActive_fd_set);
    gNumberClients--;
}

/* ------------------------------------------------
 *                                 echoTcp
 * ------------------------------------------------
 */
int echoTcp (int sock)
{
    int             nbytes;
    char            buffer[MAXMSG];
    char            *message="OK\n\r";

    nbytes = read (sock, buffer, MAXMSG);
    if (nbytes > 0)
    {
        /* Echo data read and log the time. */
        write (sock, message, nbytes);
        gSockTime[sock] = time(NULL);
        return nbytes;
    }
    else
    {
        /* End-of-file or error. */
        closeSock (sock);
        return -1;
    }
}

/* ------------------------------------------------
 *                               echoUdp
 * ------------------------------------------------
 */
void echoUdp (int sock)
{
    int                nbytes;
    int                size;
    struct sockaddr_in sin;
    char               buffer[MAXMSG];

    sin.sin_family      = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port        = gServerName.sin_port;
    size                = sizeof sin;

    nbytes = recvfrom (sock, buffer, MAXMSG, 0,
                       (struct sockaddr *) &sin, &size);
    if (nbytes < 0)
    {
        SYSLOG (LOG_USER, "recfrom failed");
        return;
    }

    /* Log the message. */
    if (gDebug)
    {
        SYSLOG (LOG_USER, "Rcvd UDP (%d bytes) from: [%s]  Port: %d",
                nbytes, inet_ntoa (sin.sin_addr), ntohs(sin.sin_port));
    }

    /*
     * If the source port is 0, we can't send the message back.
     */
    if ( ntohs(sin.sin_port) != 0 )
    {
        /* Echo the message back to the sender. */
        nbytes = sendto (sock, buffer, nbytes, 0,
                         (struct sockaddr *) &sin, size);
        if (nbytes < 0)
        {
            SYSLOG (LOG_USER, "sendto failed");
            return;
        }
    }
}

/* ------------------------------------------------
 *                               checkIdleSockets
 * ------------------------------------------------
 */
void checkIdleSockets ( void )
{
    int         sock;
    time_t      currentTime = time(NULL);

    //if (gDebug) SYSLOG(LOG_USER, "checkIdleSockets");

    /*
     * Check for an active socket that has been idle
     * for longer than gMaxSockIdle seconds.
     */
    for (sock = 0; sock <= gMaxFd; ++sock)
    {
        if (FD_ISSET (sock, &gActive_fd_set)  &&
            ((currentTime - gSockTime[sock]) > gMaxSockIdle ) &&
            (sock != gTcpListenSock) &&
            (sock != gUdpSock))
        {
            write (sock, gDiscMsg, sizeof gDiscMsg);
            closeSock (sock);
        }
    }
}

/* ------------------------------------------------
 *                                  acceptNewSock
 * ------------------------------------------------
 */
void acceptNewSock ( void )
{
    struct sockaddr_in clientName;
    int                acceptSock;
    int                size;
    char               buffer[MAXMSG];

    /* Accept new connection request on original socket. */
    size = sizeof clientName;
    acceptSock = accept (gTcpListenSock,
                         (struct sockaddr *) &clientName,
                         &size);
    if (acceptSock < 0)
    {
        SYSLOG (LOG_USER, "accept failed");
        exit (EXIT_FAILURE);
    }

    SYSLOG (LOG_USER,
            "connection %d from %s, port %hu.",
            acceptSock,
            getRemoteHostname (clientName),
            ntohs (clientName.sin_port));

    snprintf(buffer, sizeof buffer, "%s%s\r\n\r\n",
             gScaryMsg, gHostNameBuf);
    write (acceptSock, buffer, strlen(buffer));

    /*
     * Add newly accepted socket to the active set.
     */
    FD_SET (acceptSock, &gActive_fd_set);
    gMaxFd = MAX(gMaxFd, acceptSock);

    gSockTime[acceptSock] = time(NULL);
    gNumberClients++;
}

/* ------------------------------------------------
 *                                  processSockets 
 * ------------------------------------------------
 */
void processSockets (fd_set   *pRead_fd_set)
{
    int                activeSock;

    /* Service all the sockets with input pending. */
    for (activeSock = 0; activeSock <= gMaxFd; ++activeSock)
    {
        if (FD_ISSET (activeSock, pRead_fd_set))
        {
            if (activeSock == gTcpListenSock)
            {
                /*
                 * Accept a connection for a TCP socket.
                 */
                acceptNewSock ();
            }
            else if (activeSock == gUdpSock)
            {
                /*
                 * Echo data arriving on the UDP socket.
                 */
                echoUdp (activeSock);
            }
            else
            {
                /*
                 * Echo data arriving on a connected TCP socket.
                 */
                echoTcp (activeSock);

            }           /* if (activeSock == gTcpListenSock)        */
        }               /* if (FD_ISSET (activeSock, pRead_fd_set)) */
    }                   /* for (activeSock = 0; ...)                */

}

/* ------------------------------------------------
 *                                        mainLoop 
 * ------------------------------------------------
 */
void mainLoop (void)
{
    int             selectResult;
    fd_set          read_fd_set;
    struct timeval  selectTimeout;
    struct timeval *pSelectTimeout;

    /* Create the tcp socket and set it up to accept connections. */
    gTcpListenSock = bindToPort (SOCK_STREAM);
    if (listen (gTcpListenSock, MAX_QUEUED_CONNS) < 0)
    {
        SYSLOG (LOG_USER, "listen failed");
        exit (EXIT_FAILURE);
    }

    gUdpSock = bindToPort (SOCK_DGRAM);

    /* Initialize the set of active sockets. */
    FD_ZERO (&gActive_fd_set);
    FD_SET (gTcpListenSock, &gActive_fd_set);
    FD_SET (gUdpSock,       &gActive_fd_set);

    gMaxFd = MAX(gTcpListenSock, gUdpSock);
    gNumberClients = 0;

    while (1)
    {
        if ((gMaxSockIdle > 0) && (gNumberClients > 0))
        {
           /*
            * If there are any clients connected, we'll have
            * select timeout every so often so that we can
            * check for idle sockets and close them if they
            * have been idle too long.
            */
           selectTimeout.tv_usec =  0;
           selectTimeout.tv_sec  = 61;
           pSelectTimeout = &selectTimeout;
        }
        else
        {
            /*
             * If there are no clients, or the timeout is disabled,
             * we let select block until there is activity on the
             * listen socket.
             */
            pSelectTimeout = NULL;
        }

        read_fd_set = gActive_fd_set;

        /* Block until input arrives on one or more active sockets. */
        selectResult = select (gMaxFd+1, &read_fd_set, NULL, NULL, pSelectTimeout);

        if (selectResult < 0)
        {
            SYSLOG (LOG_USER, "select failed");
            exit (EXIT_FAILURE);
        }

        if (selectResult > 0)
        {
            processSockets (&read_fd_set);
        }

        if ((gMaxSockIdle > 0) && (selectResult >= 0))
        {
            /*
             * Data received or select timed out.
             */
            checkIdleSockets ();
        }
    }                           /* while (1)    */

    /* not reached */
}

/* ------------------------------------------------
 *                                          usage
 * ------------------------------------------------
 */
void usage (const char *progname)
{
    fprintf (stderr, "%s\n", gVersion);
#ifdef __CYGWIN__
    fprintf (stderr, "\nusage: %s [-adhlpt]\n", progname);
#else
    fprintf (stderr, "\nusage: %s [-adhpt]\n", progname);
#endif
    fprintf (stderr, "      -a <inetaddr>   set local address for bind\n");
    fprintf (stderr, "      -d              enable debug logging\n");
    fprintf (stderr, "      -h              print this help\n");
#ifdef __CYGWIN__
    fprintf (stderr, "      -l <logfile>    log to file <logfile> (default: %s)\n",
             gLogFilename);
#endif
    fprintf (stderr, "      -p #            set port for bind (default: %d)\n", PORT);
    fprintf (stderr, "      -t #            "
                     "set idle socket timeout in minutes (default: %d)\n"
                     "                      zero disables timeout\n\n",
                     MAX_SOCK_IDLE);
}

/* ------------------------------------------------
 *                                          main
 * ------------------------------------------------
 */
int main (int argc, char *argv[])
{
    char            ch;
    char           *progname;
    int             i;
    char            cmdLine[256];
    int             cmdIdx;

    /*
     * Trim path from program name.
     */
    progname = rindex (argv[0], '/');
    if (progname == NULL)
    {
        progname = argv[0];
    }
    else
    {
        progname++;
    }

    /* Set default socket name. */
    gServerName.sin_family      = AF_INET;
    gServerName.sin_port        = htons (PORT);
    gServerName.sin_addr.s_addr = htonl (INADDR_ANY);

    // Log the exact command line used to start the program.
    cmdIdx = 0;
    cmdIdx += sprintf(&cmdLine[cmdIdx], "# %s", progname);
    for (i=1; i<argc; i++)
    {
        cmdIdx += sprintf(&cmdLine[cmdIdx], " %s", argv[i]);
    }

    /*
     * Process cmd line options.
     */
#ifdef __CYGWIN__
    while ((ch = getopt (argc, argv, ":dhl:a:p:t:")) != -1)
#else
    while ((ch = getopt (argc, argv, ":dha:p:t:")) != -1)
#endif
    {
        switch (ch)
        {
        case 'h':
            usage (progname);
            exit (0);
            break;

        case 'd':
            gDebug = 1;
            break;

        case 'a':
            if (strcmp (optarg, "localhost") == 0)
            {
                gServerName.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
            }
            else
            {
                gServerName.sin_addr.s_addr = inet_addr (optarg);
                if (gServerName.sin_addr.s_addr == htonl (INADDR_NONE))
                {
                    fprintf (stderr, "Bad bind address: %s\n", optarg);
                    exit (-1);
                }
            }
            break;

        case 'p':
            {
                uint16_t        port = atoi (optarg);

                if (port < 1024)
                {
                    fprintf (stderr, "Can't bind to privileged port: %hu\n",
                             port);
                    exit (-1);
                }
                gServerName.sin_port = htons (port);
            }
            break;

        case 't':
            gMaxSockIdle = atoi (optarg) * SECS_PER_MIN;
            if (gMaxSockIdle < 0)
            {
                fprintf (stderr, "Error: invalid timeout value\n");
                exit (-1);
            }
            break;

#ifdef __CYGWIN__
        case 'l':
            strncpy (gLogFilename, optarg, sizeof gLogFilename);
            break;
#endif

        default:
            fprintf (stderr, "\nUnknown option");
            usage (progname);
            exit (-1);
            break;
        }
    }

    /*
     * Close all open file descriptors.
     */
    close (STDIN_FILENO);
    close (STDOUT_FILENO);
    close (STDERR_FILENO);

    /*
     * Fork to detach from shell.
     */
    if (fork () != 0)
    {
        exit (0);               /* parent exits */
    }

    SYSLOG (LOG_USER, cmdLine);
    SYSLOG (LOG_USER, "%s : port %hu",
            gVersion, ntohs (gServerName.sin_port));
    if (gDebug)
    {
        SYSLOG (LOG_USER, "Timeout = %d secs; local addr = %s", gMaxSockIdle,
                inet_ntoa (gServerName.sin_addr));
    }

    mainLoop ();                /* does not return */

    exit (0);
}
Basically, as soon as a socket is accepted... I want to take the message that gets sent to the socket server. With the message (I believe it's in an array right?) I want to somehow explode the array like you can with PHP's explode and separate the values by a comma.

The first comma will be the password (I will check via a database against a table of IDs to see if it's in there). If it is in there, the program will insert the rest of the values in to another table and output OK.

Does anyone know how I could go about taking the array and separating it using something similar to PHP's explode function using commas?

Example: explode(",", $string);

Thanks!
 
Old 07-23-2009, 02:08 PM   #2
bannock
LQ Newbie
 
Registered: Jun 2009
Location: Toronto
Distribution: Ubuntu, Fedora
Posts: 24

Rep: Reputation: 18
If you have to use C, take a look at strtok examples.
If you can use Boost, then use boost::split. Otherwise maybe std::istream_iterator ?
 
  


Reply

Tags
array



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Arrays of Structures to Arrays of Classes knobby67 Programming 1 01-01-2008 01:39 PM
Question about outputing arrays with pointers, then just arrays... RHLinuxGUY Programming 1 04-12-2006 05:40 AM
libc.so.6(GLIBC_2.3), libc.so.6(GLIBC_2.3.2) needed for Linux 7.3.1 vivek_thampy Linux - Software 1 08-09-2004 04:12 PM
libc.so verse libc.so.5 markstevens Linux - Software 4 06-19-2003 11:41 AM
libc.so.6 bash Linux - Distributions 2 08-09-2002 07:39 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:42 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration