Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   C++ (http://www.programmingforums.org/forum15.html)
-   -   new unix problem: signals and write() calls (http://www.programmingforums.org/showthread.php?t=12186)

Ghosty Dec 14th, 2006 8:05 PM

new unix problem: signals and write() calls
 
The following code will print prime numbers and output them to a file specified by the user. Also, it will call the alarm() based on values passed on the command line. The SIGALRM and the SIGUSR1 will cause the program to print the last prime number generated. I'm having problems doing my write(). It should be the most straightforward function but I'm really tired and I can't seem to figure it out. There's also a bug with the way I implemented my command line arguments to call the alarm() but I'm not requesting help with that. I just haven't gotten to fixing it yet.

Thanks in advance. Sorry for how ugly the code is.
:

#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <list>
#include <algorithm>
#include <fcntl.h>

using namespace std;

void generatePrimesFile(int*, char*);
void usr1_handler(int);
void alarm_handler(int);
list<int> alarm_values;

//I don't like globals but we can't pass the handler functions anything
int currentPrime = 1;

int main(int argc, char *argv[]) {
        if(argc < 2){
                cerr << "Usage: Lab6 <file to be written> <optional time>" << endl;
                return 1;
        }
        char * name = argv[1];
        int * cp_ptr = &currentPrime;

    // Setup the signal handlers
    struct sigaction usr1Act;
        struct sigaction alarmAct;
    usr1Act.sa_handler = usr1_handler;
        sigemptyset( &usr1Act.sa_mask );
        usr1Act.sa_flags = SA_RESTART;
       
        alarmAct.sa_handler = alarm_handler;
        sigemptyset( &alarmAct.sa_mask);
        alarmAct.sa_flags = SA_RESTART;
       
    if( sigaction( SIGUSR1 , &usr1Act, NULL ) == -1 ) {
                //syserr("sigaction");
            perror( "sigaction" );
            exit( 1 );
        }

        if( sigaction( SIGALRM, &alarmAct, NULL) == -1 ) {
                perror( "sigaction alarm");
                exit(1);
        }
        //fill alarm values list
        alarm_values.clear();
        for(int i= 2; i < argc; i++){
                alarm_values.push_back(i);
        }
        //sort it
        alarm_values.unique();
        alarm_values.sort();
        //set the alarm to the lowest value in the list
        alarm( alarm_values.front() );
       
        generatePrimesFile(cp_ptr, name);
}

void usr1_handler(int signo){
        cout << "Current Prime: " << currentPrime << endl;
}

void alarm_handler(int signo) {
        cout << "Current Prime: " << currentPrime << endl;
        if(!alarm_values.empty()){
                int temp = alarm_values.front();
                alarm_values.pop_front();
                alarm( alarm_values.front() - temp );
        }
}
 
void generatePrimesFile(int * currentPrime, char* name) {
                const int BIGNUMBER = 65534;
                bool isPrime=true;
               
                int fd;
                if( (fd = open(name, O_WRONLY|O_APPEND|O_CREAT, 0700)) == -1){
                        perror("open");
                        exit(1);
                }

                for ( int i = 0; i < BIGNUMBER; i++) {
                                for ( int j = 2; j < BIGNUMBER; j++) {
                                                if ( i!=j && i % j == 0 ) {
                                                  isPrime=false;
                                                  break;
                                                }
                                }
                                if (isPrime) {
                                        *currentPrime = i;
                                        int buff[] = {i};
                                        write(fd, buff, 2);
                                        sleep(1);
                                }
                                isPrime=true;
                }
}


Game_Ender Dec 14th, 2006 8:15 PM

Did you even look up the prototype of write?
:

ssize_t write(int fildes, const void *buf, size_t nbyte);
You need a char buffer, not an int one. After you have done that use itoa to turn the number into a character. Then just call write with that buffer.

Ghosty Dec 14th, 2006 9:43 PM

Well that certainly explains why I wasn't getting readable files. But I included <stdlib.h> and itoa() is reported as undefined. Does Gcc not support it?

Edit: A little googling made me aware of sprintf(). I'm going to try that.
Edit2: sprintf works for my purposes.

Ghosty Dec 15th, 2006 12:16 AM

This code works for the most part. I don't know how to format the output though. Ideally, I'd like the output file to look similar to this:

:

1
2
3
5
7
11
13
and so on with primes


Thanks in advance and again sorry for the mess.

:

#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <list>
#include <algorithm>
#include <fcntl.h>
#include <cstdio>
#include <signal.h>

using namespace std;

void generatePrimesFile(int*, char*);
void usr1_handler(int);
void alarm_handler(int);

//I don't like globals but we can't pass the handler functions anything
int currentPrime = 1;
list<int> alarm_values;

int main(int argc, char *argv[]) {
        if(argc < 2){
                cerr << "Usage: Lab6 <file to be written> <optional time>" << endl;
                return 1;
        }
        char * name = argv[1];
        int * cp_ptr = &currentPrime;

    // Setup the signal handlers
    struct sigaction usr1Act;
        struct sigaction alarmAct;
    usr1Act.sa_handler = usr1_handler;
        sigemptyset( &usr1Act.sa_mask );
        usr1Act.sa_flags = SA_RESTART;
       
        alarmAct.sa_handler = alarm_handler;
        sigemptyset( &alarmAct.sa_mask);
        alarmAct.sa_flags = SA_RESTART;
       
    if( sigaction( SIGUSR1 , &usr1Act, NULL ) == -1 ) {
                //syserr("sigaction");
            perror( "sigaction" );
            exit( 1 );
        }

        if( sigaction( SIGALRM, &alarmAct, NULL) == -1 ) {
                perror( "sigaction alarm");
                exit(1);
        }
        //fill alarm values list
        alarm_values.clear();
        for(int i= 2; i < argc; i++){
                alarm_values.push_back(atoi(argv[i]));
        }
        //sort it
        alarm_values.unique();
        alarm_values.sort();
        //set the alarm to the lowest value in the list
        alarm( alarm_values.front() );
       
        generatePrimesFile(cp_ptr, name);
}

void usr1_handler(int signo){
        cout << "Current Prime: " << currentPrime << endl;
}

void alarm_handler(int signo) {
        cout << "Current Prime: " << currentPrime << endl;
        if(!alarm_values.empty()){
                int temp = alarm_values.front();
                alarm_values.pop_front();
                alarm( alarm_values.front() - temp );
        }
}
 
void generatePrimesFile(int * currentPrime, char* name) {
                const int BIGNUMBER = 2000;
                bool isPrime=true;
               
                int fd;
                if( (fd = open(name, O_WRONLY|O_APPEND|O_CREAT|O_TRUNC, 0700)) == -1){
                        perror("open");
                        exit(1);
                }

                for ( int i = 0; i < BIGNUMBER; i++) {
                                for ( int j = 2; j < BIGNUMBER; j++) {
                                                if ( i!=j && i % j == 0 ) {
                                                  isPrime=false;
                                                  break;
                                                }
                                }
                                if (isPrime) {
                                        *currentPrime = i;
                                        char buff[500];
                                        int n = sprintf( buff, "%d", i );
                                        buff[n+1] += '\0';             
                                        write(fd, buff, n+1);
                                        sleep(1);
                                }
                                isPrime=true;
                }
}


DaWei Dec 15th, 2006 7:11 AM

You need to be more than aware of sprintf; you need to read its docs (and possibly follow the link to printf). If you want a newline after the number, consider using "%d\n".

Ghosty Dec 15th, 2006 2:59 PM

You are indeed right DaWei. I was in a rush to fix the code and didn't bother reading up on sprintf. I have the code working however.

Thanks for the help GE.

lectricpharaoh Dec 15th, 2006 10:48 PM

Quote:

Originally Posted by Ghosty
Well that certainly explains why I wasn't getting readable files. But I included <stdlib.h> and itoa() is reported as undefined. Does Gcc not support it?

There is no itoa() in standard C (or C++). It's a compiler-specific function present in some compilers.
Quote:

Originally Posted by Ghosty
Edit: A little googling made me aware of sprintf(). I'm going to try that.

Yes, that would be my suggestion. As DaWei mentioned, you need to be 'more than aware' of it. There is also a risk of buffer overflows; however, since the source is a value with a defined and known range, it's relatively trivial to ensure that the destination string is allocated with sufficient size. The various minimums and maximums for integer values are stored in <limits.h>; you can use these values at run time to allocate a defined buffer size, or (preferably) at compile time via conditional compilation to set a symbolic constant to the appropriate size. Don't forget the terminating zero.

An alternative that avoids all of these allocation size issues would be to use stringstreams. This lets you use the stream I/O syntax you're already familiar with. Info to get you started can be found here.

Ghosty Dec 18th, 2006 12:21 AM

Quote:

Originally Posted by lectricpharaoh (Post 121241)
An alternative that avoids all of these allocation size issues would be to use stringstreams. This lets you use the stream I/O syntax you're already familiar with. Info to get you started can be found here.

Thanks for the link. I'm definitely going to read up on string streams.


All times are GMT -5. The time now is 1:35 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC