How do I copy or rewind *argv[]

I'm working on my own pow function and I need to make a copy of *argv[] but
I think that I am having trouble with the size of *argv[] and the size of any array that I
make. The code below isn't working for me. and I want to accept any number no
matter the size with pow -f 2 2. I was working out the input issues but I need an
array that will copy *argv[] so that I can iterate through *argv[]. Or I need a function
that will rewind *argv[].

    char *arg[3];
     for(i=1; 1<4; i++)
     {
         if(i< argc)
             arg = argv;
     }

Here is one of the reasons I need to rewind or copy *argv[], also this isn't
homework or anything. I am using this for my pow function and atoi doesn't check
whether or not the string itself is a number or not.

    for(;*argv[1] && !isspace(*argv[1]);*argv[1]++)

Simply capturing the pointer in argv doesn't make a copy of the string that argv points to.

Also, you've picked up on the fact that argv[1] is the first command line parameter, but you're going to possibly cause a segment fault with your code because your target array is zero based. Your assignment should be something like this with the definition of your array:

arg[i-1] = strdup( argv );  /* make a copy of the string */

If you must index into a string (any string, not just argv[x]), it is wise to allocate a character pointer and advance that along so that you never lose the pointer to the head of the string.

   char *sp;           /* pointer into string */

   for( sp = argv[1];  isspace( *sp ); sp++ );  /* CAUTION! empty body */
   
   /* *sp will point to first non-whitespace character in the string or the end of string (0) */

Hope this helps.

You don't have to if you don't want to but I am still confused at how to fix the for loop.
Is there anything else I could search for other the isspace to tell the for loop when to
stop. Because the only problem I am seeing other then not accepting appropriate input
is having to change argv and I still don't understand what the fix did. You posted use the
code below but I don't understand what it does. could you iterate? Also what exactly
do I have to match that will tell me when the end of an argument has been reach. I tried
to print the last argument with printf and all did was print something empty. God only I
can't tell if the end of the argument is '\0' '\n' or anything of that nature. Basically if I enter
"pow eric justin allan" what will *argv[1]+4 equal? Will it be '\n'.? Also what should i equal,
in the code below.

argd[i-1]

Here's a small programme that will search through all command line parameters and print each out. It will also scan each parameter and print whether or not it contains all digits (leading whitespace is discarded such that " 123" is considered all digits. It should illustrate how to know when to stop processing command line arguments.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* return true if string contains all digits
   skips leading whitespace if skip_lws is !0
*/
int all_digits( const char *buf, int skip_lws  )
{
    const char  *sp;            /* pointer into buffer */
    int     all_dig = 1;    /* state of string */

    sp = buf;
    if( skip_lws )      /* skip leading whitespace when asked*/
        for( ; *sp && isspace( *sp ); sp++ );

    if( ! *sp )
        return 0;       /* empty string -- return false (no digits) */

    for( ; *sp; sp++ )      /* for each character until \0 */
        if( ! isdigit( *sp ) )  /* return false on first non-digit found */
            return 0;

    return 1;       /* if we finish the loop, we saw all digits */
}

int main (int argc, const char **argv)
{
    int i;

    fprintf( stderr, "there are %d arguments on the command line\n", argc-1 );

    for( i = 1; i < argc; i++ )         /* for each argument */
    {
        fprintf( stderr, "parameter %d = %s\n", i, argv );
        if( all_digits( argv, 1 ) )
            fprintf( stderr, "\targument is all digits\n" );
        else
            fprintf( stderr, "\targument is NOT all digits\n" );
    }

    return 0;
}

Arguments from the command line are zero terminated. From the example above the statement for( ; *sp; sp++ ) will stop when the character pointed to by sp is zero. It is the same as using:

for( ; *sp != 0; sp++ ) 

So, to answer your question about what *argv[1]+4 will equal when argv[1] is "eric" -- it should be zero.

I'm not sure what you are asking here.

Do you mind if I ask you another question?

It's a network question. The code below doesn't work. Do you have any idea how
to receive data about the connecting networks?

accept(simpleSocket, (struct sockaddr *)&dest, NULL);

---------- Post updated at 09:13 PM ---------- Previous update was at 09:13 PM ----------

I wanna thank you for the code above also.

Are you getting an error from the accept? It would also help to see how you initialise simpleSocket and any messages that the process that is trying to connect to your programme is reporting.

Accepting a file descriptor: Bad file descriptor
Select failed: Bad file descriptor

struct sockaddr_in serv;
struct sockaddr_in dest;
if ((simpleSocket=socket(AF_INET, SOCK_STREAM,0)) == -1)
if (bind(simpleSocket,(struct sockaddr *)&serv,sizeof(serv)) == -1)
if (listen(simpleSocket, 1000) == -1) 
if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1)
if (FD_ISSET(i, &read_fds))
newfd = accept(simpleSocket, (struct sockaddr *)&dest, NULL);

I thought that if I used a different struct with the accept that the network data would
be part of the (struct sockaddr_in dest). I also have couple more questions to ask
about network programming. Is there a way to receive from a network without stopping
a loop.

Your problem is your third argument to accept(). Accept() wants the length of the structure (dest) in your case. You must pass a pointer to the length, so declare it first:

 socklen_t dlen;

Then assign and pass it:

dlen = sizeof( dest );
if( (newfd = accept( simpleSocket, (struct sockaddr *)&dest, &dlen )) < 0 )
       fprintf( stderr, "accept failed: %s\n", strerror( errno ) );

If you mean is there a way to test for data ready on any socket without blocking, yes. You can set a timeout on the select. If you set the value to zero, then the select call should return immediately and indicate which file descriptors are ready for non-blocking read. Have a very close look at the select() manual page.

Thanks for this coding.

I used select with a time out value of 0 and I have a send command in my loop to see if
the data will be sent. I still have to send a return to the server before it will send data
the way I want it to. I'll post the whole loop because that might be the problem. Thanks much.

    for(;;)
    {
        read_fds = master;
        int i;
        if (select(fdmax+1, &read_fds, NULL, NULL, 0) == -1)
        {
            nonfatal("Select failed");
        }
        for(i = 0; i <= fdmax; i++)
        {            
            if (FD_ISSET(i, &read_fds)) // We got a connection
            {
                if (i == simpleSocket) {
                    // handle new connections
                    newfd = accept(simpleSocket, (struct sockaddr *)&inco, &clilen);

                    if (newfd == -1)
                    {
                        nonfatal("Accepting a file descriptor");
                    }
                    else 
                    {
                        FD_SET(newfd, &master); // add to master set
                        if (newfd > fdmax)      // keep track of the max
                        {
                            fdmax = newfd;
                        }
                        printf("New connection from %s on socket %d\n", inet_ntoa(inco.sin_addr), newfd);
                        const char welcome_message[] =
                        {
                            "Welcome: \r\n"
                            "Mud welcome goes here\r\n"
                        };
                        send(newfd, welcome_message, sizeof (welcome_message), 0);
                    }
                }
            }/* END FD_ISSET(i, &read_fds)*/            
        }/* for(i = 0; i <= fdmax; i++) */
                        int j;
                        if(ii<9000)    {ii++;}
                        sprintf(jog, "%d", ii);
                        for(j = 0; j <= fdmax; j++) {
                            // send to everyone!
                            if (FD_ISSET(j, &master)) {
                                    if (send(j, jog, sizeof jog, 0) == -1) {
                                        perror("send");
                                    }
                            }
                    }
    }/* END for(;;).*/

Your select() statement is still not right. The last parameter is supposed to be a pointer to a timeval structure. Passing 0 (interpret as NULL in this case) indicates no timeout and the select will block until there is data for one of the filedescriptors.

Read the man page for select() -- it has a good example of how to use the timeout and illustrates the layout of the timevalue struct.

Could you show me a proper select call?

Sure.

    struct timeval  delay;

    delay.tv_sec = 10;   /* seconds to delay */
    delay.tv_usec = 0;   /* micro seconds to delay */
    select( simpleSocket+1, &readfds, NULL, NULL, &delay)

Thank you very much.
My last question is, do you have any suggested methods of receiving data that you could post? I
have read that I can use something similar to "if(FD_ISSET(i, &read_fds) && i != simpleSocket)"
but do you know of any other methods you would recommend. It works so awesome
at the moment.

---------- Post updated at 06:31 AM ---------- Previous update was at 06:29 AM ----------

Also if anyone wants me to post the entire server, which as of right now is just a main statement
with a couple of functions, I will be glad to. It works great and I would be glad to explain parts of
it to anyone.

---------- Post updated at 05:43 PM ---------- Previous update was at 06:31 AM ----------

Is there any chance you could show me how to check the write_fds set for write block after running
it through the select function?

Typically I maintain a list of structures where each represents a session. For each pass through the "select loop" I set the readfd corresponding to each connected session and call select(). When select returns, I loop across each session structure to see if the select indicated data ready and read the data if it's there. Similar to what you are doing.

A potential issue is that the data received may not be complete, or it may have multiple complete "things." If, for instance, your application is expecting zero terminated strings as a "thing" the data read may contain multiple things with one partial thing at the end. You will have to write code that saves the partial thing and joins it with the first part of the next data read from that session. Not difficult, just tedious.

Checking to see if a write() will block is nearly the same as checking for data ready. Set the fd list for each session you want to write to and then invoke select(). Test the write fd list for each fd, and any that is set can be written to without blocking.

Similarly to piecing back together partial buffers when reading, if you don't want the write to block, you'll need to save the data to be sent in a queue, and manage sending it at some future time when the session isn't blocking. Again, not difficult, but tedious to implement.

Getting your hands dirty with this level of socket programming is good experience, but if you're looking for something that might handle this layer of the communications for you, check out 0MQ (Zero-MQ):

The Intelligent Transport Layer - zeromq

Thank you so very much. Here is a link you might enjoy. I really liked looking it over.
select_tut(2): synchronous I/O multiplexing - Linux man page

1 Like