How to make the c code compiled? - c

Here is a sample c code related to stat.h. bits/stat.h that mentioned "Never include <bits/stat.h> directly; use <sys/stat.h> instead.". However struct stat is defined in bits/stat.h, and int __xstat (...) is defined in sys/stat.h. The code won't compile with any one of headers or even both of them. How to make it copiled while only changing the #include ... without changing any one of the functions?
#include <stdio.h>
#include <bits/stat.h>
#include <sys/stat.h>
int stat_1(char *filename, struct stat *stat_buf)
{
return __xstat(1, filename, stat_buf); // extern int __xstat (...) defined in sys/stat.h
}
char * test(const char *filename) {
char *result;
stat stat_buf; // struct stat defined in bits/stat.h
printf("DO something here");
if ( stat_1(filename, &sbuf) == -1 ) {
printf("DO something here");
}
return result;
}
int main() {
const char *fileName = "file.txt";
test(fileName);
return 0;
}

You should be calling stat see https://linux.die.net/man/2/stat. Not __xstat.
Interacting with names that start with __ is almost always a sign you are doing something wrong. They are under the hood implementation things

For stat and its associated struct, you should likely be includeing:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

Related

using struct variable from .h file in .c

shm_fileuploader.c:
#include "sharedMemory.h"
struct filesharing_struct temp()
{
printf("Enter the name of the file. ");
scanf("%s", &fname);
}
sharedMemory.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
//void* get();
const int SIZE = 40960;
const char *name = "obaloch_filesharing";
struct filesharing_struct{
char flag;
int size;
char content;
char fname[50];
};
//struct filesharing_struct temp;
I am getting an error saying "error: ‘fname’ undeclared" and im not sure why since fname is declared in my header file. Is there anyway i can use fname in the from the .h file in the .c file?
You need to declare a variable whose type is the structure, and scan into its fname member.
Then you can return the structure from the function, to satisfy the return type.
struct filesharing_struct temp()
{
struct filesharing_struct temp;
printf("Enter the name of the file. ");
scanf("%s", &temp.fname);
return temp;
}

Can't store values on a struct defined in a library

In main:
#include stdio.h
#include stdlib.h
#include string.h
#include dictionary.h
int main( int argc, char ** argv ){
dictionary_t dictionary = NULL;
dictionary->entries = 1;
return 0;
}
//In header
#ifndef DICTIONARY_H
#define DICTIONARY_H
struct dictionary_s{
char * name;
llist_t content;
int entries;
};
typedef struct dictionary_s* dictionary_t;
#endif
//It compiles but shows Segmentation Fault (Core dump) in the console screen.
I have tried almost everything I can think of and checked several posts, but I've been unable to solve this problem.
In main:
#include stdio.h
#include stdlib.h
#include string.h
#include dictionary.h
int main( int argc, char ** argv ){
//dictionary_t dictionary = NULL;//This was your old line that leads to a null pointer voilation..
dictionary_t dictionary = (dictionary_t *) malloc(sizeof(dictionary_t));
if( NULL == dictionary){
//malloc failed, what do you wanna do now?
printf("Malloc failed\n");
//exit(-1);
while(1){} //just spin forever so you can see the error i suppose?
}
dictionary->entries = 1;
return 0;
}
Here is a malloc example, the stack example is similar but different.
https://en.wikibooks.org/wiki/C_Programming/stdlib.h/malloc

Why my C function works well, but got something wrong in PHP-Extension?

I need to call a .so shared library in PHP, so I write C code using "dlopen" and "dlsym" to do this, and it works.
sample.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
typedef int (*libfunc) (char *msg, int msglen);
int
sfunc(char *msg, int msglen);
sample.c:
#include "sample.h"
int
sfunc(char *msg, int msglen)
{
void *lib;
libfunc lib_func;
int result;
...
lib = dlopen(THE_LIB_PATH, RTLD_NOW);
lib_func = (libfunc) dlsym(lib, THE_LIB_FUNC);
...
result = lib_func(msg, msglen); // return 0 if success
...
dlclose(lib);
return result;
}
It always return 0.
And then I write a PHP extension as a wrapper, it takes PHP arguments and calls the C code before.
php_sample.c:
...
#include "sample.h"
...
PHP_FUNCTION(s_func)
{
char *msg;
long msglen;
int result;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &msg, &msglen) == FAILURE) {
RETURN_NULL();
}
result = sfunc(msg, (int) msglen);
RETURN_LONG(result);
}
Then I added the extension(compiled to .so) to PHP and test the PHP function:
php -r "echo s_func("somestring");"
The call always failed, just return something not zero.
Why? Is there any difference?
Note: I tested this on one other computer and it works. So is there any problems about environments or something?

Variable in struct corrupted when storing value using library function

I'm trying the write a service that pings the watchdog device using the linux watchdog driver.
In the function named 'LoadConfigurationFile' I pass a pointer to a struct that is defined above. That function then gets a string and stores it at the address of the variable in the struct with a library call(libconfig).
However when I access the variable 'printf("%s\n", options.devicepath);return 1;' instead of printing the contents of configuration file as expected: "/dev/watchdog", the program displays "�/watchdog".
#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <linux/types.h>
#include <linux/watchdog.h>
#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <libconfig.h>
struct cfgoptions {
const char* devicepath;
};
struct cfgoptions options;
char *confile = "/etc/watchdogd.cfg";
int LoadConfigurationFile(struct cfgoptions *s);
int main(int argc, char *argv[])
{
struct cfgoptions *st_ptr;
st_ptr = &options;
if (LoadConfigurationFile(st_ptr) < 0)
/*exit(EXIT_FAILURE);*/
/**/
printf("%s\n", options.devicepath);return 1;
/**/
int LoadConfigurationFile(struct cfgoptions *s)
{
config_t cfg;
config_init(&cfg);
if (!config_read_file(&cfg, confile) && config_error_file(&cfg) == NULL)
{
fprintf(stderr, "daemon: cannot open configuration file: %s\n", config_error_file(&cfg));
config_destroy(&cfg);
return -1;
} else if (!config_read_file(&cfg, confile)) {
fprintf(stderr, "daemon:%s:%d: %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg);
config_destroy(&cfg);
return -1;
}
if (!config_lookup_string(&cfg, "watchdog-device", &s->devicepath))
s->devicepath = "/dev/watchdog";
config_destroy(&cfg);
return 0;
}
/etc/watchdogd.cfg:
watchdog-device = "/dev/watchdog"
int config_setting_lookup_string(const config_setting_t *setting,
const char *name, const char **value)
{
config_setting_t *member = config_setting_get_member(setting, name);
if(! member)
return(CONFIG_FALSE);
if(config_setting_type(member) != CONFIG_TYPE_STRING)
return(CONFIG_FALSE);
*value = config_setting_get_string(member);
return(CONFIG_TRUE);
}
config_setting_t *config_setting_get_member(const config_setting_t *setting,
const char *name)
{
if(setting->type != CONFIG_TYPE_GROUP)
return(NULL);
return(__config_list_search(setting->value.list, name, NULL));
}
const char *config_setting_get_string(const config_setting_t *setting)
{
return((setting->type == CONFIG_TYPE_STRING) ? setting->value.sval : NULL);
}
the problem is you're calling config_destroy. That loses all your data allocated during lookups..
— Function: void config_destroy (config_t * config)
These functions initialize and destroy the configuration object config.
config_init() initializes the config_t structure pointed to by config as a new, empty configuration.
config_destroy() destroys the configuration config, deallocating all memory associated with the configuration, but does not attempt to deallocate the config_t structure itself.
Pretty sure on this.
Try getting rid of that line and see what happens.
More: When libconfig allocates memory for the pointers you pass in, it has to keep the memory references around somewhere so it can clean them up later. That's what the cfg object is. It's just a big record keeping object for everything the library has allocated. When you destroy it, the library must free all allocated memory or else it will be leaked forever.

Passing command line arguments through a C setuid wrapper to another script

I have the following c setuid wrapper:
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
main( int argc, char ** argv ) {
struct passwd *pwd;
char user[] = "cvmfs-test";
pwd = getpwnam(user);
setuid(pwd->pw_uid);
system(argv[1]);
}
I can call my perl script with ./cwrapper perlscript.pl.
I would like to do ./cwrapper perlscript.pl --option1 --option2 --option3 and elaborate all arguments inside the perl script with GetOptions. How should I change my wrapper?
There is also a nice solution which does not need any allocation, is able to deal with arbitrary long commands and does not imply running useless processes because it does not use system. Moreover with the following solution you get the exit code of the spawned process for free.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#define SETUIDUSER "foobar"
int main(int argc, char **argv) {
struct passwd *pwd;
char user[] = SETUIDUSER;
pwd = getpwnam(user);
// success test needed here
setuid(pwd->pw_uid);
// success test needed here
if (argc < 2)
return 1;
execvp(argv[1], &argv[1]);
return 42;
}
Here is a version dealing with a variable number of arguments. Please note that your syscalls should be tested to ensure everything is going OK.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#define CMDMAXLGTH 4096
#define SETUIDUSER "testuser"
int main( int argc, char ** argv ) {
struct passwd *pwd;
char user[] = SETUIDUSER;
char buf[CMDMAXLGTH];
char *p = buf;
int i = 1;
pwd = getpwnam(user);
// success test needed here
setuid(pwd->pw_uid);
// success test needed here
memset (buf, 0, sizeof(buf));
while (argv[i]) {
p += sprintf(p, " %s", argv[i++]);
}
system(buf);
return 0;
}
You should use sprintf to build a character string with your options, then pass this string to system:
char command [100];
sprintf (command, "./cwrapper %s --%s --%s --%s", program_name,option1,option2,
option3);
system(command);
Update: this approach assumes a fixed number of arguments, and looking back at your question, I see that may not be the case.
Ignore the argv[0] because is the name of the c program and use all the other. You can calculate (strlen) the required memory to assemble a new string, malloc() the memory for the new string and then build your new string by concatenating all the argv (strcat). Or for a fixed length approach, follow #dan1111 answer.

Resources