I'm not able to pass a callback function with a new argument i added in c - c

I don't know how to pass a variable into a callback to do some stuff (print json output) inside this function.
In sample code there is no other functions i need to pass but with sqlite3 I think I have to do this in the callback, tell me if i'm doing wrong.
The callback is called in sendhosts() function in my code.
I get this error :
In function ‘sendhosts’:
sample.c:85:48: error: too few arguments to function ‘callback’
rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback(req), 0, &zErrMsg);
Original code is :
#include <stdio.h>
#include <sqlite3.h>
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main(int argc, char **argv){
sqlite3 *db;
char *zErrMsg = 0;
int rc;
if( argc!=3 ){
fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
return(1);
}
rc = sqlite3_open(argv[1], &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return(1);
}
rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
return 0;
}
My code is :
#include <sys/types.h> /* size_t, ssize_t */
#include <stdarg.h> /* va_list */
#include <stddef.h> /* NULL */
#include <stdint.h> /* int64_t */
#include <stdlib.h>
#include <string.h> /* memset */
#include <stdio.h>
#include <kcgi.h>
#include <kcgihtml.h>
#include <sqlite3.h>
enum page {
PAGE_HOSTS,
PAGE__MAX
};
enum key {
KEY_INTEGER,
KEY_FILE,
KEY_PAGECOUNT,
KEY_PAGESIZE,
KEY__MAX
};
struct tstrct {
struct khtmlreq req;
struct kreq *r;
};
typedef void (*disp)(struct kreq *);
static void sendhosts(struct kreq *);
static const disp disps[PAGE__MAX] = {
sendhosts, /* PAGE_SENDDATA */
};
static const struct kvalid keys[KEY__MAX] = {
{ kvalid_int, "integer" }, /* KEY_INTEGER */
{ NULL, "file" }, /* KEY_FILE */
{ kvalid_uint, "count" }, /* KEY_PAGECOUNT */
{ kvalid_uint, "size" }, /* KEY_PAGESIZE */
};
static const char *const pages[PAGE__MAX] = {
"sendhosts" /* PAGE_SENDDATA */
};
static void
resp_open(struct kreq *req, enum khttp http)
{
enum kmime mime;
if (KMIME__MAX == (mime = req->mime))
mime = KMIME_APP_OCTET_STREAM;
khttp_head(req, kresps[KRESP_STATUS],
"%s", khttps[http]);
khttp_head(req, kresps[KRESP_CONTENT_TYPE],
"%s", kmimetypes[mime]);
khttp_body(req);
}
static int callback(struct kreq *req, int argc, char **argv, char **azColName){
char *page;
struct khtmlreq r;
resp_open(req, KHTTP_200);
khtml_open(&r, req, 0);
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
struct khtmlreq r;
khtml_puts(&r, "OK");
}
khtml_close(&r);
free(page);
}
static void
sendhosts(struct kreq *req)
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("/var/www/MaSSH/databases/massh.db", &db);
if(rc){
sqlite3_close(db);
}
rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback(req), 0, &zErrMsg);
if(rc!= SQLITE_OK){
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
}
int
main(void)
{
struct kreq r;
enum kcgi_err er;
/* Set up our main HTTP context. */
er = khttp_parse(&r, keys, KEY__MAX,
pages, PAGE__MAX, PAGE_HOSTS);
if (KCGI_OK != er)
return(EXIT_FAILURE);
/*
* Accept only GET, POST, and OPTIONS.
* Restrict to text/html and a valid page.
* If all of our parameters are valid, use a dispatch array to
* send us to the page handlers.
*/
if (KMETHOD_OPTIONS == r.method) {
khttp_head(&r, kresps[KRESP_ALLOW],
"OPTIONS GET POST");
resp_open(&r, KHTTP_200);
} else if (KMETHOD_GET != r.method &&
KMETHOD_POST != r.method) {
resp_open(&r, KHTTP_405);
} else if (PAGE__MAX == r.page ||
KMIME_TEXT_HTML != r.mime) {
resp_open(&r, KHTTP_404);
} else
(*disps[r.page])(&r);
khttp_free(&r);
return(EXIT_SUCCESS);
}

Your callback's signature
static int callback(struct kreq *req, int argc, char **argv, char **azColName)
is wrong. It should be
static int callback(void *ptr, int argc, char **argv, char **azColName) {
struct kreq *req = (struct kreq *)ptr;
The callback's signature should exactly match the function pointer's format, which, for sqlite3_exec, is int (*callback)(void *, int, char **, char **).
And this
rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback(req), 0, &zErrMsg);
should be
rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback, req, &zErrMsg);
callback(req) calls callback, which is not what you want; you're trying to pass a function pointer to a function, which is done with just the function's name.

Related

Message queues: Bad file descriptor in notification

I've created a table of mq file descriptors and I'm trying to pass numbers from stdin by one of them.
I'm using notification using threads and when a number occures in one of the queues it should print for example "Number: 1 from queue: 3".
Here's my code:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <mqueue.h>
#define MAX_LENGTH 20
#define ERR(source) (\
fprintf(stderr, "%s:%d\n", __FILE__, __LINE__),\
perror(source),\
kill(0, SIGKILL),\
exit(EXIT_FAILURE)\
)
static void not_func(union sigval sv) {
mqd_t queue;
uint8_t number;
unsigned msg_prio;
queue = *((mqd_t*)sv.sival_ptr);
static struct sigevent not;
not.sigev_notify = SIGEV_THREAD;
not.sigev_notify_function = not_func;
not.sigev_value.sival_ptr = &queue;
if(mq_notify(queue, &not)<0) ERR("mq_notify");
for(;;) {
if(mq_receive(queue, (char*)&number, 1, &msg_prio)<1) {
if(errno == EAGAIN) break;
else ERR("mq_receive");
printf("Number: %d from queue: %d", number, msg_prio);
}
}
}
void get_queue_name(int nr, char *str) {
snprintf(str, MAX_LENGTH, "/queue%d", nr);
}
mqd_t create_message_queue(int nr) {
mqd_t queue;
char name[MAX_LENGTH] = "";
get_queue_name(nr, name);
struct mq_attr attr;
attr.mq_maxmsg = 10;
attr.mq_msgsize = 1;
if((queue = TEMP_FAILURE_RETRY(mq_open(name, O_RDWR|O_NONBLOCK|O_CREAT, 0600, &attr))) == (mqd_t)-1) ERR("mq open in");
static struct sigevent not;
not.sigev_notify = SIGEV_THREAD;
not.sigev_notify_function = not_func;
not.sigev_value.sival_ptr = &queue;
if(mq_notify(queue, &not)<0) ERR("mq_notify");
return queue;
}
void delete_message_queue(mqd_t queue, int nr) {
char name[MAX_LENGTH] = "";
get_queue_name(nr, name);
mq_close(queue);
if(mq_unlink(name)) ERR("mq_unlink");
}
void usage(void) {
fprintf(stderr, "USAGE: mqueue n\n");
fprintf(stderr, "100 > n > 0 - number of children\n");
exit(EXIT_FAILURE);
}
int main(int argc, char **argv) {
int n, i;
char strnumber[MAX_LENGTH];
int number;
mqd_t *queues;
srand(time(NULL));
if(argc != 2) usage();
n = atoi(argv[1]);
if(n<=0 || n>=100) usage();
queues = (mqd_t*)malloc(sizeof(mqd_t) * n);
if(queues == NULL) ERR("malloc");
for(i = 0; i < n; i++) {
queues[i] = create_message_queue(i+1);
}
while(fgets(strnumber, MAX_LENGTH, stdin)!=NULL) {
number = (uint8_t)atoi(strnumber);
if(number<=0) continue;
int randomQueue = rand()%n;
if(TEMP_FAILURE_RETRY(mq_send(queues[randomQueue], (const char *)&number, 1, (unsigned)randomQueue))) ERR("mq_send");
}
for(i = 0; i < n; i++) {
delete_message_queue(queues[i], i+1);
}
free(queues);
return EXIT_SUCCESS;
}
When I execute my code nothing happens:
or I have such an error:
You pass a pointer to queue (which is a local variable) to the thread (via not.sigev_value.sival_ptr) which runs after that variable goes out of scope. So it gets a dangling pointer.
Either pass the descriptor by value (if it fits in sigval; it should), or store it on the heap (with new/malloc) and pass that pointer.

Get all output from sqlite3 in C

I have a table with 2 entry :
id hostname ip port
1 Raspberry pi 192.168.1.49 22
2 Test 127.0.0.1 22
In my code i get only the first entry with sqlite3.
I have :
{"id": "1", "hostname": "Raspberry pi", "ip": "192.168.1.49", "port": "22"}
Where is the second entry ?
I tried with printf and get the same problem it's not json issue.
There is the code :
#include <stdarg.h> /* va_list */
#include <stddef.h> /* NULL */
#include <stdint.h> /* int64_t */
#include <stdlib.h>
#include <string.h> /* memset */
#include <stdio.h>
#include <sqlite3.h>
#include <kcgi.h>
#include <kcgihtml.h>
#include <kcgijson.h>
static int callback(void *ptr, int argc, char **argv, char **azColName) {
struct kjsonreq *req = (struct kjsonreq *)ptr;
struct khtmlreq r;
int i;
for(i=0; i<argc; i++){
kjson_putstringp(req, azColName[i], argv[i] ? argv[i] : "NULL");
}
}
int
main(void)
{
struct kreq r;
struct kjsonreq req;
const char *page = "index";
if (khttp_parse(&r, NULL, 0, &page, 1, 0) != KCGI_OK)
return EXIT_FAILURE;
khttp_head(&r, kresps[KRESP_STATUS],
"%s", khttps[KHTTP_200]);
khttp_head(&r, kresps[KRESP_CONTENT_TYPE],
"%s", kmimetypes[r.mime]);
khttp_body(&r);
kjson_open(&req, &r);
kjson_obj_open(&req);
sqlite3 *db;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("/var/www/MaSSH/databases/massh.db", &db);
if(rc){
sqlite3_close(db);
}
rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback, &req, &zErrMsg);
if(rc!= SQLITE_OK){
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
kjson_obj_close(&req);
kjson_close(&req);
khttp_free(&r);
return EXIT_SUCCESS;
}
#include <sys/types.h> /* size_t, ssize_t */
#include <stdarg.h> /* va_list */
#include <stddef.h> /* NULL */
#include <stdint.h> /* int64_t */
#include <stdlib.h>
#include <string.h> /* memset */
#include <stdio.h>
#include <sqlite3.h>
#include <kcgi.h>
#include <kcgihtml.h>
#include <kcgijson.h>
int
main(void)
{
struct kreq r;
struct kjsonreq req;
const char *page = "index";
if (khttp_parse(&r, NULL, 0, &page, 1, 0) != KCGI_OK)
return EXIT_FAILURE;
khttp_head(&r, kresps[KRESP_STATUS],
"%s", khttps[KHTTP_200]);
khttp_head(&r, kresps[KRESP_CONTENT_TYPE],
"%s", kmimetypes[r.mime]);
khttp_body(&r);
kjson_open(&req, &r);
kjson_obj_open(&req);
sqlite3 *db;
sqlite3_stmt *res;
int rc;
rc = sqlite3_open("/var/www/MaSSH/databases/massh.db", &db);
if(rc){
sqlite3_close(db);
}
rc = sqlite3_prepare_v2(db, "SELECT * FROM hosts;", -1, &res, 0);
while((rc = sqlite3_step(res)) == SQLITE_ROW){
kjson_objp_open(&req, "host");
kjson_putstringp(&req, "id", sqlite3_column_text(res,0));
kjson_putstringp(&req, "hostname", sqlite3_column_text(res,1));
kjson_putstringp(&req, "ip", sqlite3_column_text(res,2));
kjson_putstringp(&req, "port", sqlite3_column_text(res,3));
kjson_obj_close(&req);
}
sqlite3_close(db);
kjson_obj_close(&req);
kjson_close(&req);
khttp_free(&r);
return EXIT_SUCCESS;
}

Unable to initialize an array of structs

I'm trying to initialize array cells of type struct using memset.
The program successfully compiles, however Valgrind is not happy with something related to memseting those cells.
The commented-out code doesn't work either.
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define MAX_DATA 512
#define MAX_ROWS 100
struct Address {
int id;
int set;
char name[MAX_DATA];
char email[MAX_DATA];
};
struct Database{
struct Address rows[MAX_ROWS];
};
struct Connection{
FILE* file;
struct Database* db;
};
void die(const char* message)
{
if(errno){
perror(message);
}else{
printf("ERROR: %s\n", message);
}
exit(1);
}
void Database_load(struct Connection* conn)
{
int rc = fread(conn->db, sizeof(struct Database), 1, conn->file);
if (rc != 1)
{
die("Failed to load database.");
}
}
struct Connection* Database_open(const char* filename, char mode)
{
struct Connection* conn = malloc(sizeof(struct Connection));
if (!conn)
{
die("Memory error");
}
if (mode == 'c')
{
conn->file = fopen(filename, "w");
}
else
{
conn->file = fopen(filename, "r+");
if(conn->file) {
Database_load(conn);
}
}
if(!conn->file) die("Failed to open file");
return conn;
}
void Database_create(struct Connection* conn)
{
int i = 0;
for(i = 0; i < MAX_ROWS; i++) {
//struct Address addr = {.id = i, .set = 0};
//conn->db->rows[i] = addr;
memset(&(conn->db->rows[i]), 0, sizeof(struct Address));
conn->db->rows[i].id = i;
}
}
int main(int argc, char* argv[])
{
if(argc < 3) die("USAGE: ex17 <dbfile> <action> [action params]");
char* filename = argv[1];
char action = argv[2][0];
struct Connection* conn = Database_open(filename, action);
int id = 0;
if(argc > 3) id = atoi(argv[3]);
if(id >= MAX_ROWS) die("There's not that many records.");
Database_create(conn);
return 0;
}
related Valgrind error -
==16227== Conditional jump or move depends on uninitialised value(s)
==16227== at 0x4C3009C: memset (vg_replace_strmem.c:1224)
==16227== by 0x400BA8: Database_create (ex17.c:108)
==16227== by 0x400EE1: main (ex17.c:174)
Your code never initializes conn->db
You need something like:
conn->db = malloc(sizeof(struct Database));
if (!conn->db)
{
die("Memory error");
}
inside the Database_open function

dbus c program - send(with reply) and receive using method_call

I'm new to D-Bus. I want a c program to send and receive data using the dbus_message_new_method_call function. I have tried the following programs from the link How to reply a D-Bus message but I'm getting error in the server.c side like "the name client.signal.Object was not provided by any .service files"
"server.c"
/* server.c */
#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
static DBusHandlerResult
filter_func(DBusConnection *connection, DBusMessage *message, void *usr_data)
{
DBusMessage *reply;
dbus_bool_t handled = false;
char *word = NULL;
DBusError dberr;
dbus_error_init(&dberr);
dbus_message_get_args(message, &dberr, DBUS_TYPE_STRING, &word, DBUS_TYPE_INVALID);
printf("receive message: %s\n", word);
handled = true;
reply = dbus_message_new_method_return(message);
char * reply_content;
printf("\nEnter your Reply Msg : ");
scanf("%s",reply_content);
dbus_message_append_args(reply, DBUS_TYPE_STRING, &reply_content, DBUS_TYPE_INVALID);
dbus_connection_send(connection, reply, NULL);
dbus_connection_flush(connection);
dbus_message_unref(reply);
return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
}
int main(int argc, char *argv[])
{
DBusError dberr;
DBusConnection *dbconn;
dbus_error_init(&dberr);
dbconn = dbus_bus_get(DBUS_BUS_SESSION, &dberr);
if (!dbus_connection_add_filter(dbconn, filter_func, NULL, NULL))
{
return -1;
}
dbus_bus_add_match(dbconn, "type='method_call',interface='client.signal.Type'", &dberr);
while(dbus_connection_read_write_dispatch(dbconn, -1))
{
/* loop */
}
return 0;
}
here client.c
#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
static DBusHandlerResult
filter_func(DBusConnection *connection, DBusMessage *message, void *usr_data)
{
dbus_bool_t handled = false;
char *word = NULL;
DBusError dberr;
dbus_error_init(&dberr);
dbus_message_get_args(message, &dberr, DBUS_TYPE_STRING, &word, DBUS_TYPE_INVALID);
printf("receive message %s\n", word);
handled = true;
return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
}
int db_send(DBusConnection *dbconn)
{
DBusMessage *dbmsg;
char *word = (char *)malloc(sizeof(char));
int i;
dbmsg = dbus_message_new_method_call("client.signal.Object","/client/signal/Object", "client.signal.Type", "Test");
scanf("%s", word);
if (!dbus_message_append_args(dbmsg, DBUS_TYPE_STRING, &word, DBUS_TYPE_INVALID))
{
return -1;
}
if (!dbus_connection_send(dbconn, dbmsg, NULL))
{
return -1;
}
dbus_connection_flush(dbconn);
printf("send message %s\n", word);
dbus_message_unref(dbmsg);
return 0;
}
int main(int argc, char *argv[])
{
DBusError dberr;
DBusConnection *dbconn;
dbus_error_init(&dberr);
dbconn = dbus_bus_get(DBUS_BUS_SESSION, &dberr);
if (!dbus_connection_add_filter(dbconn, filter_func, NULL, NULL))
{
return -1;
}
db_send(dbconn);
while(dbus_connection_read_write_dispatch(dbconn, -1))
{
db_send(dbconn);
}
dbus_connection_unref(dbconn);
return 0;
}
Please help me to fix.
Have a look here: http://www.freedesktop.org/wiki/IntroductionToDBus/
From what it looks like you need to write a file "*.service" that describes the service.
(Quoted from the website)
# (Lines starting with hash marks are comments)
# Fixed section header (do not change):
[D-BUS Service]
Names=com.bigmoneybank.Deposits;com.bigmoneybank.Withdrawals
Exec=/usr/local/bin/bankcounter
This is what I found within 5 minutes of Googleing.

fuse changes chown to?

i m trying to modify fuse example to mount any directory. I want to mount /home/nikhil in tmp.
i ran it as,
$ ./ni /home/nikhil tmp
It mounts tmp folder, but cannot access it.
$ls -ltr tmp
ls: cannot access tmp: Operation not permitted
$ ls -ltr
ls: cannot access delete: Operation not permitted
total 11716
d????????? ? ? ? ? ? delete
My code is
#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#define MAX 100
char *rootpath;
static void ni_fullpath(char fpath[MAX], const char *path){
strcpy(fpath, rootpath);
strncat(fpath, path, MAX);
}
static int ni_getattr(const char *path, struct stat *stbuf)
{
int res = 0;
char fpath[MAX];
memset(stbuf, 0, sizeof(struct stat));
ni_fullpath(fpath, path);
res = lstat(fpath, stbuf);
return res;
}
static int ni_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
(void) offset;
(void) fi;
// i didnt understand this
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
ni_fullpath(fpath, path);
filler(buf, fpath + 1, NULL, 0);
return 0;
}
static int ni_open(const char *path, struct fuse_file_info *fi)
{
int fd;
char fpath[MAX];
ni_fullpath(fpath, path);
if ((fi->flags & 3) != O_RDONLY)
return -EACCES;
fd = open(fpath, fi->flags);
return fd;
}
static int ni_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
return pread(fi->fh, buf, size, offset);
}
static struct fuse_operations ni_oper = {
.getattr = ni_getattr,
.readdir = ni_readdir,
.open = ni_open,
.read = ni_read,
};
void ni_usage(){
fprintf(stderr, "usage ni rootDir mountPoint");
abort();
}
int main(int argc, char *argv[])
{
printf("%s %s \n", argv[1], argv[2]);
rootpath = realpath(argv[1], NULL);
argv[1] = argv[2];
argc--;
return fuse_main(argc, argv, &ni_oper, NULL);
}
Can anybody help what i m doing wrong ?
I m using ubuntu 1104 64 bit.
How about using uninitialized var fpath instead of path?
static int ni_getattr(const char *path, struct stat *stbuf)
{
int res = 0;
char fpath[MAX];
memset(stbuf, 0, sizeof(struct stat));
res = lstat(fpath, stbuf);
return res;
}
You probably missed ni_fullpath(fpath, path);
And as far as I understand the 0 should be returned in open callback if success, so it should look like:
....
fd = open(fpath, fi->flags);
if (fd < 0)
return -errno;
fi->fh = fd;
return 0;
}
List operation should uses readdir callback, and in your case it has very limited application. It'd be better to start code on the basis of fusexmp. Check how readdir is implemented there.

Resources