I am trying to open the utmp file in Linux and read the contents into an array of utmp structures. After that I display the ut_user and ut_type from each structure in the array. I have this working when I open the file with File *file and use the fopen() and fread() functions but when I try to do the same task with just a file descriptor int file and the open() and read() functions I get address locations when trying to access members of the utmp structure.
So in the below program you can see I commented out three lines of code which together I could use to successfully perform the task of reading the utmp file into an array of utmp structures and print out two of their members values. But when I try doing the exact same thing with the three lines of code (denoted "new way") in place of the old way that worked I get a bunch of address locations rather than the values of ut_user and ut_id.
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <utmp.h>
void utmpprint(struct utmp *log) {
printf("\n ut_user: %s \n ut_type: %ld \n", log->ut_user, log->ut_type);
}
int main() {
int logsize = 10;
//FILE *file; //Working way
int file; //New way
struct utmp log[logsize];
int i = 0;
//file = fopen("/var/run/utmp", "rb"); //Working way
file = open("/var/run/utmp", O_RDONLY); //New way
if( file < 0 ) { //New way
printf("Failed to open");
return(0);
}
if (file) {
//fread(&log, sizeof(struct utmp), logsize, file); //Working way
read(file, &log, logsize); //New way
for(i = 0; i < logsize; i++) {
utmpprint(&log[i]);
}
close(file); //New way
} else {
return(0);
}
return(0);
}
Here is some of the output for the working way:

And here is the output for the new way that is not working:

I have tried looking online for more information on this matter but I can't seem to find anything that uses the file descriptor and not File. I also tried changing around some of the pointers and references but that did not improve any of the results.
I am very new to C and I think I am probably using the read() function incorrectly in this case because I am passing a simple buffer into the read function when I think I should be somehow passing it the utmp structure array.
You are not reading enough data from the file.
read(file, &log, logsize);
should be:
read(file, &log, sizeof(log));
// or
read(file, &log, logsize * sizeof (struct utmp));
Also, in both cases, you should check the return value to see how many bytes were actually read.
Even though you could manipulate data from the utmp file by using the open() system call or functions derived from open(), it is impractical.
You could include the "utmp.h" header in your project and use predefined functions and data structures.
Here you can find the utmp.h file documentation.
Below is some code to print the ut_user and ut_type using the utmp.h data structures and functions.
#include <utmp.h>
#include <stdio.h>
#include <string.h>
int main()
{
struct utmp* data;
char aux[50];
data = getutent();
//getutent() populates the data structure with information
while(data != NULL )
{
/*make sure to use strncpy
*because most data fiels in the utmp struct
*have ___nonstring___ atribute */
strncpy(aux, data->ut_user, 32);
aux[32] = '\0';
printf("ut_user: %s\n", aux);
printf("ut_type: %hi\n\n", data->ut_type);
data = getutent();
}
return 0;
}
The output of the code is:
ut_user: reboot
ut_type: 2
ut_user: alc
ut_type: 7
ut_user: runlevel
ut_type: 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With