C starter question

R

rudra

Hello friends, i am not a c-programmer. I generally do things using
fortran. but I need it to retrive the machine info. I write two code:
/***********************************************
uname
***********************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int operating_system(char *sys){
FILE *stream;
char *sysptr;
int bit;
sysptr = &sys[0];
sys[0] = 0x0;
stream=popen("/bin/uname -snm","r");
fread(sysptr,1,32,stream);
pclose(stream);
//printf("bit=%s\n",sysptr);
return bit;
}

and

/***********************************************
nisdomainname
***********************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int operating_sys(char *nis ){
FILE *stream;
char *sysptr;
int bit;
sysptr = &nis[0];
nis[6] = 0x0;
stream=popen("/bin/nisdomainname","r");
fread(sysptr,1,15,stream);
pclose(stream);
//printf("bit=%s\n",sysptr);
return bit;
}

which is called by fortran (f03-C interoperability). But when i am
trying to merge the code, as
/***********************************************
This code returns the machine bit
to the program bitinit
***********************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int operating_system(char *sys){
FILE *stream,*stream2;
char *sysptr,*nisptr, *nis;
int bit;
sysptr = &sys[0];
sys[6] = 0x0;
nisptr = &nis[0];
nis[0] = 0x0;
stream=popen("/bin/uname -m","r");
stream2=popen("/bin/nisdomainname","r");
fread(sysptr,1,4,stream);
pclose(stream);
printf("bit=%s\n",sysptr);
return bit;
}

and trying to run, i am getting error:
Program received signal SIGSEGV, Segmentation fault.
0x08049e72 in operating_system (sys=0x80b1d6c " ") at machine.c:15
warning: Source file is more recent than executable.
15 nis[0] = 0x0;
which i am not getting why. can you people show me where i am going
wrong?i know it is a silly mistake, but being a beginner, i request
your little time.
thanks
 
W

Wolfgang Draxinger

rudra said:
Hello friends, i am not a c-programmer. I generally do things using
fortran. but I need it to retrive the machine info. I write two code:
/***********************************************
uname
***********************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int operating_system(char *sys){
FILE *stream;
char *sysptr;
int bit;

You lack to check if the pointer sys is not null. Being not null isn't
sufficient for a pointer to be valid in terms of proper allocation, but
invalid pointers usually are marked by being set null, so that calling a
function with a null pointer can raise an error. So add a

if( !sys ) {
big_fat_error();
}
sysptr = &sys[0];

You could as well write

sysptr = sys;
sys[0] = 0x0;

This has no endeffect as
stream=popen("/bin/uname -snm","r");
fread(sysptr,1,32,stream);

fread will overwrite it through sysptr.
pclose(stream);
//printf("bit=%s\n",sysptr);
return bit;
}

Furthermore, there's no way you can be sure, that sys points to a largely
enough allocated memory region. The style you're coding in is error prone
and vulnerable. Either allocate everyhing within the function in question,
or add a parameter to the function, telling the size of the buffer.
Personally I prefer to allocate on demand.

#define BLOCK_LENGTH 100
char * get_operating_system() {
FILE *fil;
char *output = 0;
size_t output_length = 0;
size_t output_read = 0;

fil = popen("uname -snm", "r");
if( !fil ) {
perror("error calling uname: ");
return 0;
}

while( !feof(fil) ) {
if( output_read + BLOCK_LENGTH + 1 > output_length )
output = remalloc(output, output_length += BLOCK_LENGTH);
if( !output ) {
perror("error allocating memory: ");
break;
}
output_read += fread(fil, BLOCK_LENGTH, 1, output + output_read);
if( ferror() ) {
fprintf(stderr, "error reading from uname stdout\n");
break;
}
}

pclose(fil);

return output;
}

The pointer returned by get_operating_system must be freed with free.

In this code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int operating_system(char *sys){
FILE *stream,*stream2;
char *sysptr,*nisptr, *nis;
int bit;
sysptr = &sys[0];
sys[6] = 0x0;
nisptr = &nis[0];
nis[0] = 0x0;
stream=popen("/bin/uname -m","r");
stream2=popen("/bin/nisdomainname","r");
fread(sysptr,1,4,stream);
pclose(stream);

Then, what's that supposed to mean:
printf("bit=%s\n",sysptr);
return bit;
}

bit will contain just garbage, as it nowhere properly initialized and gets
no value assigned.
and trying to run, i am getting error:
Program received signal SIGSEGV, Segmentation fault.
0x08049e72 in operating_system (sys=0x80b1d6c " ") at machine.c:15
warning: Source file is more recent than executable.
15 nis[0] = 0x0;
which i am not getting why. can you people show me where i am going
wrong?i know it is a silly mistake, but being a beginner, i request
your little time.

Obviously you're not allocating any or too few memory. Frankly, doesn't
Fortran provide means to get the output of a programm from stdout? Would be
easier for you.


HTH

Wolfgang
 
W

Wolfgang Draxinger

Wolfgang Draxinger wrote:

I forgot ine important thing, to make this thing practicable usable:
#define BLOCK_LENGTH 100
char * get_operating_system() {
FILE *fil;
char *output = 0;
size_t output_length = 0;
size_t output_read = 0;

fil = popen("uname -snm", "r");
if( !fil ) {
perror("error calling uname: ");
return 0;
}

while( !feof(fil) ) {
if( output_read + BLOCK_LENGTH + 1 > output_length )
output = remalloc(output, output_length += BLOCK_LENGTH);
if( !output ) {
perror("error allocating memory: ");
break;
}
output_read += fread(fil, BLOCK_LENGTH, 1, output +
output_read); if( ferror() ) {
fprintf(stderr, "error reading from uname
stdout\n"); break;
}
}
/* fill the rest of the output buffer with 0 bytes.
one would be sufficient, but it looks cleaner
when checked in a debugger or similiar. */
if( output &&
output_length > 0 &&
output_read > 0 ) {
memset(output + output_read, 0, output_length - output_read);
}
pclose(fil);

return output;
}

Wolfgang
 
A

Antoninus Twink

int operating_system(char *sys){
FILE *stream;
char *sysptr;
int bit;
sysptr = &sys[0];
sys[0] = 0x0;
stream=popen("/bin/uname -snm","r");
fread(sysptr,1,32,stream);

I have no idea what you're trying to achieve with sysptr and setting
sys[0] to zero... you may want to read Steve Summit's FAQ section on
arrays and pointers.

As a general rule, calling external programs and reading their output
through a pipe is fine in scripting languages like shell or Perl, but
it's not the best way to do things in C. Instead, using library calls is
the normal way of doing things. Consider this alternative to your
function:

#include <string.h>
#include <errno.h>
#include <sys/utsname.h>

int operating_system(char *s, size_t n)
{
int ret;
struct utsname buf;
if((ret = uname(&buf)) == 0) {
if(strlen(buf.sysname) < n)
strcpy(s, buf.sysname);
else {
ret = -1;
errno = ERANGE;
}
}
return ret;
}

Note that besides not relying on calling /bin/uname, this version also
handles errors and lets the caller specify how big a buffer is being
passed.
 
A

Antoninus Twink

output = remalloc(output, output_length += BLOCK_LENGTH);
if( !output ) {
perror("error allocating memory: ");
break;
}

There's no standard function called remalloc(). Replacing it with
realloc() gives you a memory leak if the allocation fails, since you
don't save the previous value of output.
 
K

Kenny McCormack

There's no standard function called remalloc(). Replacing it with
realloc() gives you a memory leak if the allocation fails, since you
don't save the previous value of output.

It appears that the latest incarnation of "Antoninus Twink" is as a Kiki-clone.

Well done.
 
A

Antoninus Twink

It appears that the latest incarnation of "Antoninus Twink" is as a
Kiki-clone.

Well done.

Hehe, just trying to fill Han's boots in beating the regs at their own
game...
 
W

Wolfgang Draxinger

Antoninus said:
There's no standard function called remalloc(). Replacing it with
realloc()

Which is waht I meant, typo.
gives you a memory leak if the allocation fails, since you don't save the
previous value of output.

Err yes. I got to used to using the Boehm GC, so I missed that. Thanks. But
preferrably a memory leak, than a buffer overrun.

Personally I think GC should become the main method of memory management,
everything else is just too error prone.

Here the completely revised and corrected version:

#define BLOCK_LENGTH 100
char * get_operating_system() {
FILE *fil;
char *output = 0;
size_t output_length = 0;
size_t output_read = 0;

fil = popen("uname -snm", "r");
if( !fil ) {
perror("error calling uname: ");
return 0;
}

while( !feof(fil) ) {
if( output_read + BLOCK_LENGTH + 1 > output_length )
char * o_new =
realloc(output,
output_length += BLOCK_LENGTH);
if( !o_new ) {
perror("error allocating memory: ");
break;
}
output = o_new;
output_read += fread(fil, BLOCK_LENGTH, 1, output +
output_read); if( ferror() ) {
fprintf(stderr, "error reading from uname
stdout\n"); break;
}
}
if( output &&
output_length > 0 &&
output_read > 0 ) {
memset(output + output_read, 0,
output_length - output_read);
}


pclose(fil);

return output;
}

BTW: I go with Antonius' other post, that the OP should use the library
function uname. However I thought, showing him an proper version of his
original approach might be instructional.


Wolfgang
 
R

rudra

On Jun 14, 4:24 pm, Wolfgang Draxinger <[email protected]>
wrote:
Frankly, doesn't
Fortran provide means to get the output of a programm from stdout? Would be
easier for you.

HTH

Wolfgang

Thanks for all your reply.
As for WD, fortran do provide a way to get output from stdout, but no
std. conforming way for call system info like nisdomain or uname!
 
R

rudra

Which is waht I meant, typo.


Err yes. I got to used to using the Boehm GC, so I missed that. Thanks. But
preferrably a memory leak, than a buffer overrun.

Personally I think GC should become the main method of memory management,
everything else is just too error prone.

Here the completely revised and corrected version:

#define BLOCK_LENGTH 100
char * get_operating_system() {
        FILE *fil;
        char *output = 0;
        size_t output_length = 0;
        size_t output_read = 0;

        fil = popen("uname -snm", "r");
        if( !fil ) {
                perror("error calling uname: ");
                return 0;
        }

        while( !feof(fil) ) {
                if( output_read + BLOCK_LENGTH + 1 > output_length )
                char * o_new =
                        realloc(output,
                                output_length += BLOCK_LENGTH);
                if( !o_new ) {
                        perror("error allocating memory: ");
                        break;
                }
                output = o_new;
                output_read += fread(fil, BLOCK_LENGTH, 1, output +
                output_read); if( ferror() ) {
                        fprintf(stderr, "error reading from uname
                        stdout\n"); break;
                }
        }
        if( output &&
            output_length > 0 &&
            output_read > 0 ) {
                memset(output + output_read, 0,
                       output_length - output_read);
        }

        pclose(fil);

        return output;

}

BTW: I go with Antonius' other post, that the OP should use the library
function uname. However I thought, showing him an proper version of his
original approach might be instructional.

Wolfgang

hello friends,
thanks for your support. but while compiling, i am getting error:
$ gcc -c cor.c
cor.c: In function ‘get_operating_system’:
cor.c:3: error: ‘FILE’ undeclared (first use in this function)
cor.c:3: error: (Each undeclared identifier is reported only once
cor.c:3: error: for each function it appears in.)
cor.c:3: error: ‘fil’ undeclared (first use in this function)
cor.c:5: error: ‘size_t’ undeclared (first use in this function)
cor.c:5: error: expected ‘;’ before ‘output_length’
cor.c:6: error: expected ‘;’ before ‘output_read’
cor.c:15: error: ‘output_read’ undeclared (first use in this function)
cor.c:15: error: ‘output_length’ undeclared (first use in this
function)
cor.c:16: error: expected expression before ‘char’
cor.c:19: error: ‘o_new’ undeclared (first use in this function)
cor.c:26: warning: incompatible implicit declaration of built-in
function ‘fprintf’
cor.c:26: error: ‘stderr’ undeclared (first use in this function)
cor.c:26:41: warning: missing terminating " character
cor.c:26: error: missing terminating " character
cor.c:27: error: stray ‘\’ in program
cor.c:27: error: ‘stdout’ undeclared (first use in this function)
cor.c:27: error: expected ‘)’ before ‘n’
cor.c:27:33: warning: missing terminating " character
cor.c:27: error: missing terminating " character
cor.c:28: error: expected ‘;’ before ‘}’ token
cor.c:33: warning: incompatible implicit declaration of built-in
function ‘memset’


where cor.c is the function you provided. can you check this further?
 
R

rudra

hello friends,
thanks for your support. but while compiling, i am getting error:
$ gcc -c cor.c
cor.c: In function ‘get_operating_system’:
cor.c:3: error: ‘FILE’ undeclared (first use in this function)
cor.c:3: error: (Each undeclared identifier is reported only once
cor.c:3: error: for each function it appears in.)
cor.c:3: error: ‘fil’ undeclared (first use in this function)
cor.c:5: error: ‘size_t’ undeclared (first use in this function)
cor.c:5: error: expected ‘;’ before ‘output_length’
cor.c:6: error: expected ‘;’ before ‘output_read’
cor.c:15: error: ‘output_read’ undeclared (first use in this function)
cor.c:15: error: ‘output_length’ undeclared (first use in this
function)
cor.c:16: error: expected expression before ‘char’
cor.c:19: error: ‘o_new’ undeclared (first use in this function)
cor.c:26: warning: incompatible implicit declaration of built-in
function ‘fprintf’
cor.c:26: error: ‘stderr’ undeclared (first use in this function)
cor.c:26:41: warning: missing terminating " character
cor.c:26: error: missing terminating " character
cor.c:27: error: stray ‘\’ in program
cor.c:27: error: ‘stdout’ undeclared (first use in this function)
cor.c:27: error: expected ‘)’ before ‘n’
cor.c:27:33: warning: missing terminating " character
cor.c:27: error: missing terminating " character
cor.c:28: error: expected ‘;’ before ‘}’ token
cor.c:33: warning: incompatible implicit declaration of built-in
function ‘memset’

where cor.c is the function you provided. can you check this further?

to be complete, let me give the function once again:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define BLOCK_LENGTH 100
char * get_operating_system() {
FILE *fil;
char *output = 0;
size_t output_length = 0;
size_t output_read = 0;

fil = popen("uname -snm", "r");
if( !fil ) {
perror("error calling uname: ");
return 0;
}

while( !feof(fil) ) {
if( output_read + BLOCK_LENGTH + 1 > output_length )
char * o_new =
realloc(output,
output_length += BLOCK_LENGTH);
if( !o_new ) {
perror("error allocating memory: ");
break;
}
output = o_new;
output_read += fread(fil, BLOCK_LENGTH, 1, output +
output_read); if( ferror() ) {
fprintf(stderr, "error reading from uname
stdout\n"); break;
}
}
if( output &&
output_length > 0 &&
output_read > 0 ) {
memset(output + output_read, 0,
output_length - output_read);
}

pclose(fil);

return output;

}

looking for your help
 
A

Antoninus Twink

Some of the error messages suggest that your stdio.h is broken. You need
string.h for memset. The only real errors that jumped out at me are:
if( output_read + BLOCK_LENGTH + 1 > output_length )
char * o_new =
realloc(output,
output_length += BLOCK_LENGTH);
if( !o_new ) {
perror("error allocating memory: ");
break;
}
output = o_new;

This part needs to be in a block controlled by the if.
output_read += fread(fil, BLOCK_LENGTH, 1, output +
output_read);

The order of the parameters is completely wrong: try
fread(output + output_read, 1, BLOCK_LENGTH, fil);
if( ferror() ) {

You need to supply a FILE* to ferror().
 
U

user1

Wolfgang said:
Obviously you're not allocating any or too few memory. Frankly, doesn't
Fortran provide means to get the output of a programm from stdout? Would be
easier for you.


HTH

Wolfgang

Yes, it seems overly complex. Although not standard, most Fortran
compilers have some sort of routine for system calls. Redirect the
output to a temp file and read it.

character*80 rec1
call system('/bin/uname -snm > /tmp/uname.out')
open(11,file='/tmp/uname.out')
read(11,'(a)') rec1
write(6,*) rec1
close(11)
end
 
R

rudra

Yes, it seems overly complex. Although not standard, most Fortran
compilers have some sort of routine for system calls. Redirect the
output to a temp file and read it.

        character*80 rec1
        call system('/bin/uname -snm > /tmp/uname.out')
        open(11,file='/tmp/uname.out')
        read(11,'(a)') rec1
        write(6,*) rec1
        close(11)
        end

true enough, but the point is, as you said,"most Fortran compilers"!!
system is not in fortran std!! and i am a bit afraid i ll be pushing
my luck too far using this command
 
U

user1

rudra said:
true enough, but the point is, as you said,"most Fortran compilers"!!
system is not in fortran std!! and i am a bit afraid i ll be pushing
my luck too far using this command

Your mixed Fortran / C approach hardly seems any more portable ...
 
B

Ben Bacarisse

rudra said:
On Jun 15, 10:46 am, rudra <[email protected]> wrote:

to be complete, let me give the function once again:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

This is line 3. I think the error messages apply to something else.
Probably what you originally posted which lacked the headers.
#define BLOCK_LENGTH 100
char * get_operating_system() {
FILE *fil;
char *output = 0;
size_t output_length = 0;
size_t output_read = 0;

fil = popen("uname -snm", "r");
if( !fil ) {
perror("error calling uname: ");
return 0;
}

while( !feof(fil) ) {
if( output_read + BLOCK_LENGTH + 1 > output_length ) {
char * o_new =
realloc(output,
output_length += BLOCK_LENGTH);
if( !o_new ) {
perror("error allocating memory: ");
break;
}
output = o_new;
}

The missing block was in the original.
 
U

user1

rudra said:
can you plz check chapter 15 of fortran standard?

Chapter 15 of which fortran standard ?

I must say that I do not understand why you are worried about using an
extension supplied by virtually every Fortran compiler, while at the
same time you seem not to be worried about invoking system utilities
(/bin/uname or /bin/nisdomainname) that may not exist on all systems.
 
R

rudra

Chapter 15 of which fortran standard ?
The current fortran ...fortran 2003
I must say that I do not understand why you are worried about using an
extension supplied by virtually every Fortran compiler, while at the
same time you seem not to be worried about invoking system utilities
(/bin/uname or /bin/nisdomainname) that may not exist on all systems.

Because, i am interested in Linux system, not in other OS, and all
Linux system has these utility, but not all compiler use system in
same way(as in ifort, it may be function, or subroutine)

But more then anything else, i was looking for a simple solution of
the post....which i am yet to get....is there anyone to help me on
this issue?
 
U

user1

rudra said:
The current fortran ...fortran 2003

Because, i am interested in Linux system, not in other OS, and all
Linux system has these utility, but not all compiler use system in
same way(as in ifort, it may be function, or subroutine)

But more then anything else, i was looking for a simple solution of
the post....which i am yet to get....is there anyone to help me on
this issue?

OK, so you are only wanting to do it on Linux, so it does not need to be
portable at all. The simplest solution is do it all in Fortran. On my
Linux machine, I have verified that call system('uname >somefile.out')
works with f2c+gcc, g77, g95 , gfortran, ifort, and the Sun Studio
Fortran compiler.

What compiler for Linux you have encountered where it does not work ?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top