0

I have a simple function to get the MAC address on a linux machine (assuming eth0 exists. I'll write more later on).

Side Question: Is there an interface universal across ALL Linux distros? Other than lo?

C Function:

char* getmac(){
        FILE *mf;
        mf = fopen("/sys/class/net/eth0/address", "r");
        if(!mf) exit(-1);
        char *mac;
        fgets(mac, 18, mf);
        printf("%2\n", mac);
        return mac;
}

Now, this prints out the MAC perfectly. However, when I return it, I get a totally different value.

char *m;
m = getmac();
printf("%s\n", m);

yields a completely different, mostly unreadable string. The first 2 characters are ALWAYS correct, after that, it's unreadable...


This worked like a charm:

char* getmac(){
        FILE *mf;
        mf = fopen("/sys/class/net/eth0/address", "r");
        if(!mf) exit(-1);
        char *mac;
        mac = calloc(18, sizeof(char));
        if(!mac) exit(-1);
        fgets(mac, 18, mf);
        printf("%s\n", mac);
        return mac;
}

Thanks for the answers!! Also, free'd later on.

3
  • 1
    char *mac; is uninitialised. It points to nothing. Commented Feb 12, 2014 at 22:51
  • Don't write "answered" into the title, accept the relevant answer and the question gets marked as answered, the answerer gets additional point and the question disappears from the unanswered questions section. Commented Feb 12, 2014 at 23:05
  • My apologies. At the time, the time threshold of accepting an answer had not yet passed. Thank you for the tip! Commented Feb 13, 2014 at 1:20

3 Answers 3

2
    char *mac;
    fgets(mac, 18, mf);

You need to assign memory to mac first, perhaps with malloc.


As jia103 points out in the comments, one way to structure your code could be:

char* getmac(char *buf, size_t size);

Then the caller can more freely decide how the contents are stored (perhaps the client isn't all that interested in malloc and would much prefer an array on the stack).

Sign up to request clarification or add additional context in comments.

1 Comment

malloc and free are great, but if you have control of the method, consider taking in a buffer provided by the client. Then, the client is responsible for both the allocation and the deallocation, and is less likely to forget to free.
1

You never allocated memory for mac. Malloc it:

char * mac = malloc(18);

(char mac[18] wouldn't work since you want to return the string from the function, so it needs to live beyond the scope of getmac)

Don't forget to free it!

Alternatively, make it the caller's responsibility:

void getmac(char mac[18]){

Note that this requires you to pass an array of exactly 18 chars, i.e. not one that was malloced or isn't exactly 18 elements. So, call it with this:

char mac[18];
getmac(mac);

To allow a bit more freedom declare it with this:

void getmac(char * mac)

And make sure the caller always allocates enough memory.

As the other answers note you could also pass a size parameter, but since you know that you need a buffer of exactly 18 characters this seems a bit redundant to me. A size parameter does become important when you work with strings of variable length.

3 Comments

Will update :) Worked like a charm with calloc (string terminates at \x00 which is initialized by calloc).
malloc/calloc and free are great, but if you have control of the method, consider taking in a buffer provided by the client. Then, the client is responsible for both the allocation and the deallocation, and is less likely to forget to free.
@jia103 Added malloc-less alternatives
0

You're writing to memory you're not supposed to. You never initialized mac to any usable memory, so it's writing to whatever memory location it initially had. You'd catch this immediately if you have a habit of initializing your variables, but I can't remember if C allows this:

FILE* mf = NULL;
char* mac = NULL;

The reason this should get caught is because your program will fail when you try to call fgets() and pass it NULL for mac.

What you should do is provide a storage area in which to write the data so that you can get it when it comes back out.

void getmac(char* buffer,
            int   bufsize)
{
   ...
}

Then, you can call it as follows:

const int BUFSIZE = 1024;
char m[BUFSIZE] = {0};
getmac(m, BUFSIZE);
printf("%s\n", m);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.