I'm trying to take the output from usb-devices and parsing it to assign it to a simple struct. However, I just can't get fscanf to properly read the values from the output. Here's the function in question:
struct Devices* getDevices() {
int pipes[2];
pid_t pid;
if (pipe(pipes)==-1)
die("Failed to create pipe");
if ((pid = fork()) == -1)
die("Could not fork process");
if(pid == 0) {
dup2 (pipes[1], STDOUT_FILENO);
close(pipes[0]);
close(pipes[1]);
execl("/bin/usb-devices", "usb-devices", (char *)0);
}
else {
close(pipes[1]);
wait(NULL);
}
FILE *rawList = fdopen(pipes[0],"r");
if (rawList == NULL)
die("Failed to open file");
fpos_t pos;
int pos_init = 0;
struct Devices *deviceList = malloc(sizeof(struct Devices));
if(!deviceList) die ("Memory error");
int i;
int conn;
int iBus = -1;
int iPort = -1;
for (i = 0; !feof(rawList); i++) {
if (pos_init) fsetpos(rawList, &pos);
conn = fscanf(rawList, "T: Bus=%d Lev=%*d Prnt=%*d Port=%d Cnt=%*d Dev#= %*d Spd=%*d MxCh= %*d",
&iBus, &iPort);
if (!conn) {
printf("bus%d port%d num %i", iBus, iPort, i);
deviceList->devNum[i].set = 1;
deviceList->devNum[i].bus = iBus;
deviceList->devNum[i].port = iPort;
fgetpos (rawList,&pos);
pos_init = 1;
}
}
fclose(rawList);
return deviceList;
}
Quickly explaining what's supposed to be happening. I'm creating a pipe so I can grap the output of the command I'm running, then after it runs I try to put it in a stream named rawList through fdopen. Then, I malloc a chunk of memory for the struct I will be assigning the values I get to.
Then, in a for loop it should check for the lines starting with "T:" which contain the data I want, and then it should take the integers that the output of usb-devices gives me and assign it to the struct per device. Finally, it should be saving the point it stopped reading to so it can keep reading from there to find the next line I'm looking for.
The printf is there to try and figure out what's going on. It ends up printing "-1" which is the value assigned before the for loop, which tells me fscanf isn't assigning any values to my variables. "i" just counts on until the program segfaults and ends up quitting. I'm not sure whether the value is meaningful, but Valgrind consistently tells me there are 77408 errors from 5 contexts (main is simply running this function, the only other things in the code are the struct declarations, the die function and main itself).
When the process finally quits, Valgrind gives me this:
==11278== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==11278== Access not within mapped region at address 0x55F0040
==11278== at 0x108C7A: getDevices (usbDeviceList.c:77)
==11278== by 0x108D4C: main (usbDeviceList.c:103)
Line 77 is this one
deviceList->devNum[i].set = 1;
The last value of "i" that gets printed is 15644.
Any and all help is appreciated, I've asked around and no one seems to have the slightest clue as to what's happening. I'll list the SO resources I used to write this:
easy way to parse a text file?
Update:
As per request, here's the structs:
struct deviceData {
int set;
int bus;
int port;
char manufacturer[MAX_LENGTH_U];
char product[MAX_LENGTH_U];
};
struct Devices {
struct deviceData devNum[MAX_DEVICES_U];
};