I'm trying to compile some example C code with GCC/MinGW on Windows 7. The example code includes some local header files which ultimately include stdio.h, and I get this error when I try to compile:
c:\mingw\include\stdio.h:345:12: error: expected '=', ',', ';', 'asm' or '__attribute__' before '__mingw__snprintf'
extern int __mingw_stdio_redirect__(snprintf)(char*, size_t, const char*, ...);
This is a weird one to me. How could there possibly be errors in stdio.h?
regarding:
if (i == 0)
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return 0;
}
pcap_freealldevs(alldevs);
since the variable i is initialized to 0 and never modified, this if() statement will always be true. One result is the call to: pcap_freealldev() will never be called.
the scope of variables should be limited as much as reasonable.
Code should never depend on the OS to clean up after itself. suggest
#include <stdio.h>
#include <stdlib.h>
#include "pcap.h"
int main( void )
{
pcap_if_t *alldevs = NULL;
char errbuf[PCAP_ERRBUF_SIZE];
/* Retrieve the device list from the local machine */
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /* auth is not needed */, &alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs_ex: %s\n", errbuf);
exit(1);
}
/* Print the list */
for( pcap_if_t *d = alldevs; d != NULL; d= d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else
printf(" (No description available)\n");
}
if ( ! alldevs )
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
}
/* We don't need any more the device list. Free it */
pcap_freealldevs(alldevs);
}
Related
I'm trying to write C code to parse a config file using libconfig
The config file contains a simple element and a group. A group is composed of multiple settings, each has a unique name. ref
Config file :
host_name = "HOST";
device_settings:
{
rcu1:
{
product_id = 0x0001;
vendor_id = 0x0217;
},
rcu2:
{
product_id = 0x0001;
vendor_id = 0x0218;
}
}
I want to parse all RCUs data and store it in a data structre (the storing part is not a problem for now).
So I'm using the simple steps of :
Store the group in a config_setting_t * called section.
get length of section in a varaible called len
Iterrate len time to read RCUs data.
The problem is when i want to read RCU data i get a seg fault.
Code :
#include <libconfig.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
config_t cfg;
config_setting_t *root;
config_setting_t *section;
config_setting_t *elem;
int d, len;
config_init(&cfg);
if (config_read_file(&cfg,"./config.cfg") != CONFIG_TRUE) {
printf("[%s:%d] %s \n", config_error_file(&cfg),
config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg);
return -1;
}
if ((root = config_root_setting(&cfg)) == NULL) {
printf ("[%s:%d] %s \n", config_error_file(&cfg),
config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg);
return -1;
}
/* Device settings */
if ((section = config_setting_get_member(root, "device_settings")) != NULL)
{
len = config_setting_length(section);
printf("len = %d \n",len);
}
int i;
const char* device_id;
config_setting_t *device = NULL;
printf("device_settings %s a group \n",config_setting_is_group(section)?"is":"isn't");
for(i=0;i<len;i++) {
printf("iteration i = %d \n",i);
//device
if(device = config_setting_get_elem(section, i) != NULL) {
/*device id*/
if ((d = config_setting_lookup_string(device, "device_id",&device_id) != CONFIG_FALSE)) /*seg fault here*/
{
// Do stuff
}
}
}
return 0;
}
Something strange I noticed is when I compile the code i get this warning :
parse.c: In function ‘main’: parse.c:46:14: warning: assignment to
‘config_setting_t *’ {aka ‘struct config_setting_t *’} from ‘int’
makes pointer from integer without a cast [-Wint-conversion]
if(device = config_setting_get_elem(section, i) != NULL) {
GDB output :
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7da78a0 in config_setting_get_member () from
/lib/x86_64-linux-gnu/libconfig.so.9
ref to config_setting_get_elem(..)
I can not find what wrong Im doing. Everything looks correct to me.
Can someone see why the seg fault is happening?
if (device = config_setting_get_elem(section, i) != NULL)
needs to be
if ((device = config_setting_get_elem(section, i)) != NULL)
Because != has higher precedence than =.
I was working on my game and decided to use eclipse as my compiler. I had to compile it for both platforms: x86 and x64. The trouble started there. There are many dependency files in the system path.
And every time I had to change them in order to change the platform. So, I've created a line to set up my configurations faster and without affect the path itself.
This is the line to add into the path that I've created:
%DRIVE%\mingw\mingw%PLATFORM%\bin;%DRIVE%\Dropbox\Machine\Windows\C\Place\bin\x%PLATFORM%;%DRIVE%\Dropbox\Machine\Windows\C\PLUGIN\x%PLATFORM%\bin;
As you guys can see there are two variables there: %DRIVE% and %PLATFORM%.
I wish to change them with a file that I try to create in c.
Here is the code
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
char *strremove(char *str, const char *sub) {
char *p, *q, *r;
if ((q = r = strstr(str, sub)) != NULL) {
size_t len = strlen(sub);
while ((r = strstr(p = r + len, sub)) != NULL) {
while (p < r)
*q++ = *p++;
}
while ((*q++ = *p++) != '\0')
continue;
}
return str;
}
#ifndef HAVE_SETENV
int setenv(const char * variable,const char * value) {
if(!variable || !value)return(0);
int len = strlen(variable)+1+strlen(value)+1;
char * EnvString = calloc(len,sizeof(char));
sprintf(EnvString, "%s=%s", variable, value);
if (!_putenv(EnvString)) {
return (1);
}
if(EnvString)free(EnvString);
return (0);
}
#endif
void change_platform(int argc,char ** argv) {
char * variable = "PLATFORM",* value = "86";
if(argc > 1){
value = argv[1];
}
if (setenv(variable, value)) {
printf("\n environmental variable successfully written");
printf("\n value of the environmental variable written is %s",
getenv(variable));
} else {
printf("\n error in writing the environmental variable");
}
}
int main(int argc, char ** argv) {
change_platform(argc,argv);
getch();
return 0;
}
My code shows the right result inside the program, but when I go and check the system environment itself, nothing changes. Am I doing something wrong.
Detail: I thought it was because of mingw which isn't native from Windows, then I've created I file in Visual c++ too, but it did not work either.
Please remember it affects only the environment of the current process
getenv, _wgetenv
int main( void )
{
char *libvar;
// Get the value of the LIB environment variable.
libvar = getenv( "LIB" ); // C4996
// Note: getenv is deprecated; consider using getenv_s instead
if( libvar != NULL )
printf( "Original LIB variable is: %s\n", libvar );
// Attempt to change path. Note that this only affects the environment
// variable of the current process. The command processor's
// environment is not changed.
_putenv( "LIB=c:\\mylib;c:\\yourlib" ); // C4996
// Note: _putenv is deprecated; consider using putenv_s instead
// Get new value.
libvar = getenv( "LIB" ); // C4996
if( libvar != NULL )
printf( "New LIB variable is: %s\n", libvar );
}
I want to stop the execution of my C code after I detected an NaN and send the error message to MATLAB using mexWarnMsgTxt.
The C code is executed from MATLAB over mex file. I tried to use abort() and exit() which indeed kill the c program but also MATLAB (I guess because it is the calling process here.)
#include "mex.h"
#include "matrix.h"
for (int i = 0; i <= 5; i++)
{
if (mxIsFinite(out[i])) {
}
else if (mxIsInf(out[i])) {
char *err_msg = malloc(max_len_err_msg);
snprintf(err_msg, max_len_err_msg, "Inf detected in file %s at line %d", __FILE__, __LINE__);
mexWarnMsgTxt(err_msg);
abort();
//free(err_msg);
//abort(1);
/* NOTE: Test for NaN is here for illustration only. If a double
* is not finite and is not infinity, then it is a NaN */
}
else if (mxIsNaN(out[i])) {
char *err_msg = malloc(max_len_err_msg);
snprintf(err_msg, max_len_err_msg, "NaN detected in file %s at line %d", __FILE__, __LINE__);
mexWarnMsgTxt(err_msg);
abort();
//free(err_msg);
}
}
I just want my mexFunction to stop but not to terminate Matlab.
mex functions are normal C functions so, to leave the function early, just use return.
If you function allocated resources that need to be cleaned up manually, the established idiom in C is to use a goto cleanup; (this is one of the few, if not the only, acceptable and generally accepted uses of goto):
void mexFunction(
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]
) {
for (int i = 0; i <= 5; i++) {
if (mxIsInf(out[i])) {
char *err_msg = malloc(max_len_err_msg);
snprintf(err_msg, max_len_err_msg, "Inf detected in file %s at line %d", __FILE__, __LINE__);
mexWarnMsgTxt(err_msg);
free(err_msg);
goto cleanup;
} else if (mxIsNaN(out[i])) {
char *err_msg = malloc(max_len_err_msg);
snprintf(err_msg, max_len_err_msg, "NaN detected in file %s at line %d", __FILE__, __LINE__);
mexWarnMsgTxt(err_msg);
free(err_msg);
goto cleanup;
}
…
}
cleanup:
// Perform cleanup here.
}
(Note that in this code the err_msg cleanup is performed in its own scope rather than with the global cleanup.)
But in the case where no cleanup is to be performed, the goto statements are unnecessary and can be replaced by return.
My current solution is to define a global variable abort_flag in C, set it to 1 if the error occured and based on that break all my loops and return from the functions.
Kind of "manual" but works:
int abort_flag = 0;
// to use in other file insert into header: extern int abort_flag;
// in the NaN case (see above)
abort_flag = 1;
// in the loops
if (abort_flag==1) { break; };
// in the functions
if (abort_flag==1) { return; };
I have seen posts like this on StackOverflow which talk about using uname() to get the current Kernel version number (stored in utsname.release). However that returns a string.
Is there a way to return the or check the Kernel version as a numerical value so that one can simply use if (version >= min_req_ver) { ... } ?
The only method I have seen is to include linux/version.h and check LINUX_VERSION_CODE however in CentOS for example, this version number is not updated when one runs a newer Kernel than the default. The uname() function however does report the correct current Kernel version across Linux distros (on the ones I have tested) including in scenario such as using CentOS with a newer Kernel.
Use below function to get Kernel, Major, Minor and Patch version and compare individual version.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <sys/utsname.h>
int main(void) {
struct utsname buffer;
char *p;
long ver[16];
int i=0;
errno = 0;
if (uname(&buffer) != 0) {
perror("uname");
exit(EXIT_FAILURE);
}
printf("system name = %s\n", buffer.sysname);
printf("node name = %s\n", buffer.nodename);
printf("release = %s\n", buffer.release);
printf("version = %s\n", buffer.version);
printf("machine = %s\n", buffer.machine);
#ifdef _GNU_SOURCE
printf("domain name = %s\n", buffer.domainname);
#endif
p = buffer.release;
while (*p) {
if (isdigit(*p)) {
ver[i] = strtol(p, &p, 10);
i++;
} else {
p++;
}
}
printf("Kernel %d Major %d Minor %d Patch %d\n", ver[0], ver[1], ver[2], ver[3]);
return EXIT_SUCCESS;
}
I will go ahead and say this is a homework assignment for an intro to Linux class. I would not be posting it without extensive attempts on my own, and seeing as I am a distance student this semester, I cannot make it to campus for tutoring. I need some help finding out what the issue is.
Essentially the assignment asks us to make a program that serves the same basic function as the pwd command in POSIX, to show the absolute path for the current directory. We are to use three functions along with main. We are not to use the getcwd command as well. I'll list them and their purpose
inum_to_filename: Accepts three arguments (inode number to translate, a pointer to a buffer where the name is written, and the size of the buffer). Returns nothing. It is to:
Open the current directory,
Read the first directory entry,
If the inode of the current directory matches the one passed in, copy name to buffer and return.
Otherwise read the next directory entry and repeat the previous step.
filename_to_inum: Accepts one argument (a char * representing the filename). It returns the corresponding inode number. It is to:
Read the information from the files inode into a structure in memory.
If there is any problem, display the appropriate error.
Return the inode number from the structure.
display_path: Accepts one argument (inode from the current working directory). It returns nothing. It is to:
Create an array of characters to use as a buffer for the name of the directory.
Get the inode for the parent directory using filename_to_inode.
If the parent inode is equal to the current inode, we have reached root and can return.
Otherwise, change to the parent directory and use inum_to_filename to find the name for the inode that was passed into the function. Use the buffer from step 1 to store it.
Recursively call display_path to display the absolute path.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
void inum_to_filename (int inode_arg, char *pathBuffer, int size_arg) {
DIR *dir_ptr = opendir(".");
struct dirent *dirent_ptr = readdir(dir_ptr);
int counter = 0;
while (counter != 1) {
if (inode_arg == dirent_ptr->d_ino) {
strcat(pathBuffer, "/");
strcat(pathBuffer, dirent_ptr->d_name);
counter = counter + 1;
return;
} else {
dirent_ptr = readdir(dir_ptr);
}
}
closedir(dir_ptr);
}
int filename_to_inum (char *src) {
int res = 0;
struct stat info;
int result = stat(src, &info);
if (result != 0) {
fprintf(stderr, "Cannot stat ");
perror(src);
exit(EXIT_FAILURE);
} else {
res = info.st_ino;
}
return res;
}
void display_path (int ino_src) {
int bufSize = 4096;
char pathBuffer[bufSize];
int ino_prnt = filename_to_inum("..");
if (ino_src == ino_prnt) {
//print for test
inum_to_filename(ino_src, pathBuffer, bufSize);
printf("%s", pathBuffer);
return;
} else {
//print for test
chdir("..");
inum_to_filename(ino_src, pathBuffer, bufSize);
display_path(ino_prnt);
printf("%s", pathBuffer);
}
}
int main (int argc, char *argv[]) {
int c_ino = filename_to_inum(".");
display_path(c_ino);
printf("\n");
}
As of right now it is displaying "/./MyName" with MyName being my personal named directory on the server. It is the directory I am running the program from. When using pwd I return "/home/MyName". I'm not really sure what my next step to getting the absolute path correct is.
The code is mostly set up to print one name at a time in the correct order, so the primary problem is the use of strcat() rather than strcpy(). Also, detecting when you're in the root directory at the start is important; if you don't, you can end up with /. or something similar (depending on exactly how you coordinate the printing) when the current directory is the root directory.
This version of your code has:
Squished the loop in inum_to_filename(), but also added error reporting. Remember, a process can be run in a directory which it does not have permission to get to (it requires a setuid program, usually — although permissions could be changed after the program is launched). In that case, it may fail to open .. (or .).
Lost variable count; it wasn't serving a useful purpose. Using the assign-and-test idiom allows the code to contain a single call to readdir().
Use strcpy() instead of strcat().
Use type ino_t to store inode numbers. Use size_t for sizes.
Reduce number of intermediate variables in filename_to_inum().
Note that the code in the if (ino_src == ino_prnt) statement body is for the root directory; in the absence of the testing print, it would do nothing.
Note that the printing in the else part is a major part of the operations, not just test printing.
Error check chdir("..");
Detect root in main().
Observe that this code is not directly suitable for rewriting into a function because it changes the process's current directory to / when it succeeds.
Revised code:
#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
static void inum_to_filename(ino_t inode_arg, char *pathBuffer, size_t size_arg)
{
assert(size_arg > 0);
DIR *dir_ptr = opendir(".");
if (dir_ptr == 0)
{
fprintf(stderr, "Failed to open directory '.' (%d: %s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
struct dirent *dirent_ptr;
while ((dirent_ptr = readdir(dir_ptr)) != 0)
{
if (inode_arg == dirent_ptr->d_ino)
{
if (strlen(dirent_ptr->d_name) >= size_arg)
{
fprintf(stderr, "File name %s too long (%zu vs %zu max)\n",
dirent_ptr->d_name, strlen(dirent_ptr->d_name), size_arg);
exit(EXIT_FAILURE);
}
strcpy(pathBuffer, dirent_ptr->d_name);
break;
}
}
closedir(dir_ptr);
}
static ino_t filename_to_inum(char *src)
{
struct stat info;
if (stat(src, &info) != 0)
{
fprintf(stderr, "Cannot stat ");
perror(src);
exit(EXIT_FAILURE);
}
return info.st_ino;
}
static void display_path(ino_t ino_src)
{
size_t bufSize = 4096;
char pathBuffer[bufSize];
ino_t ino_prnt = filename_to_inum("..");
if (ino_src == ino_prnt)
{
// print for test
inum_to_filename(ino_src, pathBuffer, bufSize);
printf("%s", "(root): /\n");
}
else
{
// print for real
if (chdir("..") != 0)
{
fprintf(stderr, "Failed to chdir to .. (%d: %s)\n",
errno, strerror(errno));
}
inum_to_filename(ino_src, pathBuffer, bufSize);
display_path(ino_prnt);
printf("/%s", pathBuffer);
}
}
int main(void)
{
ino_t c_ino = filename_to_inum(".");
ino_t r_ino = filename_to_inum("/");
if (r_ino == c_ino)
putchar('/');
else
display_path(c_ino);
printf("\n");
}
There are undoubtedly other ways to fix this.
Caveat: this is giving me some grief when working in /Volumes/CRUZER/Sub-Directory which is a memory stick. It fails to find the inode (1, which is surprising) when scanning /Volumes, and I've not worked out why. One of my programs — a getpwd implementation — is working fine; another is having a different problem. I expect I'll get to the bottom of it all. Testing on Mac OS X 10.10.5 with GCC 5.1.0.
this is really nice assignment :).
I read and tried your code, and it is almost correct. There were two small issues which were causing the incorrect behaviour.
First issue
When display_path reaches the root folder you don't need to call inum_to_filename and print the name of the folder because you have already printed the first folder of the path in the previous iteration. This prevents your code from showing a "./" in the beginning of the path.
That is, the if condition becomes:
if (ino_src == ino_prnt) {
return;
} else {
chdir("..");
inum_to_filename(ino_src, pathBuffer, bufSize);
display_path(ino_prnt);
printf("%s", pathBuffer);
}
Second Issue:
You're not initializing propertly the buffer where you save the name of the directory. This causes random values to be displayed. To solve this issue you can just set the initial value of the buffer to zero by using memset.
void inum_to_filename (int inode_arg, char *pathBuffer, int size_arg) {
DIR *dir_ptr = opendir(".");
struct dirent *dirent_ptr = readdir(dir_ptr);
int counter = 0;
memset(pathBuffer, 0, size_arg);
while (counter != 1) {
...
}
closedir(dir_ptr);
}
Full code working :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
void inum_to_filename (int inode_arg, char *pathBuffer, int size_arg) {
DIR *dir_ptr = opendir(".");
struct dirent *dirent_ptr = readdir(dir_ptr);
int counter = 0;
memset(pathBuffer, 0, size_arg);
while (counter != 1) {
if (inode_arg == dirent_ptr->d_ino) {
strcat(pathBuffer, "/");
strcat(pathBuffer, dirent_ptr->d_name);
counter = counter + 1;
return;
} else {
dirent_ptr = readdir(dir_ptr);
}
}
closedir(dir_ptr);
}
int filename_to_inum (char *src) {
int res = 0;
struct stat info;
int result = stat(src, &info);
if (result != 0) {
fprintf(stderr, "Cannot stat ");
perror(src);
exit(EXIT_FAILURE);
} else {
res = info.st_ino;
}
return res;
}
/*
- Create an array of characters to use as a buffer for the name of the directory.
- Get the inode for the parent directory using filename_to_inode.
- If the parent inode is equal to the current inode, we have reached root and can return.
- Otherwise, change to the parent directory and use inum_to_filename to find the name for
the inode that was passed into the function. Use the buffer from step 1 to store it.
- Recursively call display_path to display the absolute path.
*/
void display_path (int ino_src) {
int bufSize = 4096;
char pathBuffer[bufSize];
int ino_prnt = filename_to_inum("..");
if (ino_src == ino_prnt) {
return;
} else {
chdir("..");
inum_to_filename(ino_src, pathBuffer, bufSize);
display_path(ino_prnt);
printf("%s", pathBuffer);
}
}
int main (int argc, char *argv[]) {
int c_ino = filename_to_inum(".");
display_path(c_ino);
printf("\n");
}
Output :
ubuntu#ubuntu-VirtualBox:~/dev$ vi pwd.c
ubuntu#ubuntu-VirtualBox:~/dev$ gcc pwd.c
ubuntu#ubuntu-VirtualBox:~/dev$ ./a.out
/home/ubuntu/dev
ubuntu#ubuntu-VirtualBox:~/dev$ pwd
/home/ubuntu/dev
ubuntu#ubuntu-VirtualBox:~/dev$