How to iterate through a char ** variable - c

I'm running a small rpc program/ using an rpc framework that takes a char[] from the client file and sends it to the server that enumerates the integers in the string.
I have a file client.c that takes user input and passes it to an external function in a header file.
#include <rpc/rpc.h>
#include "getNumInt.h"
int main(int argc, char **argv){
CLIENT *cli;
char *server;
server = argv[1];
cli = clnt_create(server, GETNUMINT, GNUMINT, "tcp"); //creates a client handle
/*does some check for whether the client connected*/
char command[256];
int *numInt;
fgets(command, 256, stdin);
numInt = enumints_1(&command, cli); //segfaults here according to backtrace
return(0);
}
The function enumints_1 is defined in my server stub server.c as:
int *enumints_1(msg, req)
char **msg; struct svc_req *req;{
printf(*msg);
static int numDigits = 0;
char msgcopy[256];
strcpy(msgcopy, *msg);
int i = 0;
for(i; i<strlen(msgcopy); i++){
if(msgcopy[i] >= '0' && msgcopy[i] <='9'){
numDigits++;
}
}
return(&numDigits);
}
My main issue is how I iterate through the char **msg as that is likely why my program is segfaulting.
command is just a string taken from user input and then passed by reference to the enumints_1 function.
Since it is a pointer to a point I assumed that I could just strcpy or memcpy to copy the string to a char array, but that doesn't work.
also my .x file:
struct intStringPair{
int numInts;
char msg[256];
};
program GETNUMINT{
version GNUMINT{
int ENUMINTS(string) = 1; //string considered char * the rpc generated file makes it so enumints_1 then has to take char **
int WRITEMESSAGE(intStringPair) = 2;
} = 1;
}= 0x20000001;

Like #user3386109 said:
command is not a pointer. So &command is not a pointer-to-a-pointer
so assigning &command to msg is not valid (and my compiler doesn't even compile it)
When I compile this code:
// my set up code
#include <stdio.h>
#include <string.h>
struct svc_req {};
typedef struct svc_req CLIENT;
struct svc_req *clnt_create(const char *, int, int, const char*) {return 0;}
int GETNUMINT=0, GNUMINT=0;
// your code verbatim
int *enumints_1(char **msg, struct svc_req *req){
printf(*msg);
static int numDigits = 0;
char msgcopy[256];
strcpy(msgcopy, *msg);
int i = 0;
for(i; i<strlen(msgcopy); i++){
if(msgcopy[i] >= '0' && msgcopy[i] <='9'){
numDigits++;
}
}
return(&numDigits);
}
int main(int argc, char **argv){
CLIENT *cli;
char *server;
server = argv[1];
cli = clnt_create(server, GETNUMINT, GNUMINT, "tcp"); //creates a client handle
/*does some check for whether the client connected*/
char command[256];
int *numInt;
fgets(command, 256, stdin);
numInt = enumints_1(&command, cli); //segfaults here according to backtrace
return(0);
}
The compiler says:
<source>: In function 'int main(int, char**)':
<source>:34:25: error: cannot convert 'char (*)[256]' to 'char**'
numInt = enumints_1(&command, cli); //segfaults here according to backtrace
^~~~~~~~
<source>:10:24: note: initializing argument 1 of 'int* enumints_1(char**, svc_req*)'
int *enumints_1(char **msg, struct svc_req *req){
~~~~~~~^~~
Compiler returned: 1
What you can do instead is make a pointer to the array and then pass the address of that:
// my set up code
#include <stdio.h>
#include <string.h>
struct svc_req {};
typedef struct svc_req CLIENT;
struct svc_req *clnt_create(const char *, int, int, const char*) {return 0;}
int GETNUMINT=0, GNUMINT=0;
// your code verbatim
int *enumints_1(char **msg, struct svc_req *req){
printf(*msg);
static int numDigits = 0;
char msgcopy[256];
strcpy(msgcopy, *msg);
int i = 0;
for(i; i<strlen(msgcopy); i++){
if(msgcopy[i] >= '0' && msgcopy[i] <='9'){
numDigits++;
}
}
return(&numDigits);
}
int main(int argc, char **argv){
CLIENT *cli;
char *server;
server = argv[1];
cli = clnt_create(server, GETNUMINT, GNUMINT, "tcp"); //creates a client handle
/*does some check for whether the client connected*/
char command[256], *command_pointer=command;
int *numInt;
fgets(command, 256, stdin);
numInt = enumints_1(&command_pointer, cli); //segfaults here according to backtrace
return(0);
}

Related

how to Organize a program into header and c files

I am required to organize the following c code into header (s) and c file (s). However, im unable to do so myself.
The code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 256
#define PROGRAMMES_SIZE 2
#define DELIMETER ","
struct programme
{
char name[32];
char code[8];
int credits;
};
struct programme parseProgramme(char *);
struct programme createProgramme(char[], char[], int);
void printProgramme(struct programme);
void updateProgrammeName(struct programme *, char[]);
int main()
{
char buffer[BUFFER_SIZE];
struct programme programmes[PROGRAMMES_SIZE];
FILE *input = fopen("input", "r");
if (input == NULL)
exit(1);
int i;
for (i = 0; i < PROGRAMMES_SIZE; i++)
{
fgets(buffer, BUFFER_SIZE, input);
programmes[i] = parseProgramme(buffer);
}
for (i = 0; i < PROGRAMMES_SIZE; i++)
printProgramme(programmes[i]);
fclose(input);
return 0;
}
struct programme parseProgramme(char *buffer)
{
char name[32];
char code[8];
int credits;
// parse name
strcpy(name, strtok(buffer, DELIMETER));
// parse code
strcpy(code, strtok(NULL, DELIMETER));
// parse credits
credits = atoi(strtok(NULL, DELIMETER));
return createProgramme(name, code, credits);
}
struct programme createProgramme(char name[], char code[], int credits)
{
struct programme programme;
strcpy(programme.name, name);
strcpy(programme.code, code);
programme.credits = credits;
return programme;
}
void printProgramme(struct programme programme)
{
puts(programme.name);
puts(programme.code);
printf("%d\n", programme.credits);
}
void updateProgrammeName(struct programme *programme, char name[])
{
strcpy(programme->name, name);
}
Please be noted that its not required to update any of the following definitions or implementations of the code listed above, stated by my collage professor. Just to organize them accordingly, any help is apricated!.
There is no strict need to create a separate header file here, because there is no code re-use.
However, if some of the code were to be reused in other files, then it would start to make sense. So let's say we want to move some functionality to a library.
Then it would make sense to split up the functions to a separate file, and create a header file which would also be roughly representing the API.
So let's skip some code and look at main.c:
int main()
{
char buffer[BUFFER_SIZE];
struct programme programmes[PROGRAMMES_SIZE];
FILE *input = fopen("input", "r");
if (input == NULL)
exit(1);
int i;
for (i = 0; i < PROGRAMMES_SIZE; i++)
{
fgets(buffer, BUFFER_SIZE, input);
programmes[i] = parseProgramme(buffer);
}
for (i = 0; i < PROGRAMMES_SIZE; i++)
printProgramme(programmes[i]);
fclose(input);
return 0;
}
And obviously the functions would be in e.g. program.c:
struct programme parseProgramme(char *buffer)
{
char name[32];
char code[8];
int credits;
// parse name
strcpy(name, strtok(buffer, DELIMETER));
// parse code
strcpy(code, strtok(NULL, DELIMETER));
// parse credits
credits = atoi(strtok(NULL, DELIMETER));
return createProgramme(name, code, credits);
}
struct programme createProgramme(char name[], char code[], int credits)
{
struct programme programme;
strcpy(programme.name, name);
strcpy(programme.code, code);
programme.credits = credits;
return programme;
}
void printProgramme(struct programme programme)
{
puts(programme.name);
puts(programme.code);
printf("%d\n", programme.credits);
}
void updateProgrammeName(struct programme *programme, char name[])
{
strcpy(programme->name, name);
}
Now we can easily see, that PROGRAMMES_SIZE and BUFFER_SIZE are not used in the functions, and should be defined in main.c.
On the other hand, DELIMETER is only used in the functions, so it should be defined at the top in program.c.
We can move the struct and function definitions to program.h. It's good practice to prevent recursive inclusion, we could use some simple ifndef for that:
#ifndef PROGRAM_H
#define PROGRAM_H
struct programme
{
char name[32];
char code[8];
int credits;
};
struct programme parseProgramme(char *);
struct programme createProgramme(char[], char[], int);
void printProgramme(struct programme);
void updateProgrammeName(struct programme *, char[]);
#endif /* PROGRAM_H */
Finally, you should look which standard library functions are used in either .c file and add the necessary #include at the top of main.c and program.c. For example, main.c uses fgets and program.c uses puts. So both should #include <stdio.h>.
I'll leave the rest for you as an exercise.

Pass String array and indexes using Struct to a thread in C

I am trying to pass a string array and indexes from where to start end searching in the array, I am unable to solve it from the last two days. I am sending to the pthread_create a struct data thread_data, here i am able to send the int and long data, but not the string array, can someone help me, how to pass these.
struct data{
int tid;
unsigned long start;
unsigned long end;
char * word;
char * str;
};
struct data thread_data[NUM_THREADS];
void *searchString(void *passeddata)
{
struct data *t_data;
int tid1;
char * str[3];
t_data=(struct data *) passeddata;
tid1=t_data->tid;
str=t_data->str;
.....
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
...
char work[]={"First Line","Second line","Third line"};
...
while(fgets(arr[index],120, fp)!=NULL){
index=index+1;
thread_data[index].tid=index;
thread_data[index].str=work;
...
rc=pthread_create(&threads[index],NULL,searchString,(void *)&thread_data[index]);
...
}
pthread_exit(NULL);
}
To hold the multiple strings you need 2D array.
const char *work[]={"First Line","Second line","Third line", "Fourth Line"};
You need to use pointer to pointer in struct data to hold the above array.
struct data{
.....
const char **str;
size_t lenOfStr;
};
And pass the length of array explicitly to thread function from main function.
Your sample code may look like below.
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
struct data{
int tid;
unsigned long start;
unsigned long end;
char * word;
const char **str;
size_t lenOfStr;
};
struct data thread_data[3];
void *searchString(void *passeddata)
{
struct data *t_data;
int tid1;
const char **str = NULL;
t_data=(struct data *) passeddata;
tid1=t_data->tid;
str=t_data->str;
int i = 0;
for (i = 0;i<t_data->lenOfStr;i++)
printf("%s\n", str[i]);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
const char *work[]={"First Line","Second line","Third line", "Fourth Line"};
int index = 0;
pthread_t threadid=0;
thread_data[index].tid=index;
thread_data[index].str=work;
thread_data[index].lenOfStr = sizeof(work)/sizeof(*work); // Calculate the size of work here
int rc=pthread_create(&threadid,NULL,searchString,&thread_data[index]);
pthread_exit(NULL);
}

passing an array of structs from a function to the main program

I have a data file of about 2500 lines. Each line contains 5 parameters. I declare a strut out side of a routine.
typedef struct data
{
char date[9];
char time[3];
float price;
float NAV;
float percent_change;
} _data ;
void readfile(int *j, struct data *input);
void readfile(int *j,struct data *input)
I set aside memory to read each line of the file into an array of structs.
input = calloc(days_of_data,sizeof(*input));
for (i = 0; i< days_of_data; i++)
input[i] = *(_data*)calloc(1,sizeof(_data));
and read the file.
while(fgets(line, 75, fp) != NULL)
{
date = strtok(line,",");
strcpy(input[i].date,date);
time = strtok(NULL,",");
strcpy(input[i].time, time);
price = strtok(NULL,",");
input[i].price = atof(price);
NAV = strtok(NULL,",");
input[i].NAV = atof(NAV);
percent_change = strtok(NULL,",");
input[i].percent_change = atof(percent_change);
i--;
}
This works. Now I want to sent the structure to the main program.
int main(int argc, const char * argv[]) {
struct data *input;
readfile(&j, input);
printf("%f\n",input[0].percent_change);
}
This compiles but crashes on the print statement.
You will have to use return value
struct data * readfile(int *j) {
struct data *input;
/* read the data */
return input;
}
int main(int argc, const char * argv[]) {
struct data *input;
input = readfile(&j);
printf("%f\n",input[0].percent_change);
}
or pointer
void readfile(int *j, struct data **input_out) {
struct data *input;
/* read the data */
*input_out = input;
}
int main(int argc, const char * argv[]) {
struct data *input;
readfile(&j, &input);
printf("%f\n",input[0].percent_change);
}
to pass the data to the caller.

PAM module error (passing argument 1 of ‘snprintf’ discards ‘const’)

I have my PAM module:
I try to compile it, using string:
gcc -fPIC -DPIC -shared -rdynamic -o pam_test.so pam_test.c
But I have errors:
pam_test.c: In function ‘pam_sm_authenticate’:
pam_test.c:74:9: warning: passing argument 1 of ‘snprintf’ discards ‘const’ qualifier from pointer target type [enabled by default]
snprintf(msg[0].msg,60,"Second Password:%d:%d:%d:%d:",x1,x2,x3,x4);
^
In file included from pam_test.c:10:0:
/usr/include/stdio.h:386:12: note: expected ‘char * __restrict__’ but argument is of type ‘const char *’
extern int snprintf (char *__restrict __s, size_t __maxlen,
module code:
#include <security/pam_modules.h>
#include <stdarg.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#define PAM_SM_AUTH
#define MAX_V 30
PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv)
{
unsigned int ctrl;
int retval;
const char *name, *p;
char *right;
int x1,x2,x3,x4,y;
time_t mytime;
struct tm *mytm;
mytime=time(0);
mytm=localtime(&mytime);
srandom(mytime);
x1=random()%MAX_V;
x2=random()%MAX_V;
x3=random()%MAX_V;
x4=random()%MAX_V;
retval = pam_get_user(pamh, &name, "login: ");
{
struct pam_conv *conv;
struct pam_message *pmsg[3],msg[3];
struct pam_response *response;
retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
pmsg[0] = &msg[0];
msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
msg[0].msg=malloc(100);
snprintf(msg[0].msg,60,"Second Password:%d:%d:%d:%d:",x1,x2,x3,x4);
retval = conv->conv(1, ( const struct pam_message ** ) pmsg
, &response, conv->appdata_ptr);
y=2*x1*mytm->tm_mday+x3*mytm->tm_hour;
right=malloc(100);
snprintf(right,20,"%d",y);
if (!(strcmp(right,response->resp))){
return PAM_SUCCESS;
}else{
return PAM_AUTH_ERR;
}
}
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags
,int argc, const char **argv)
{
unsigned int ctrl;
int retval;
retval = PAM_SUCCESS;
}
#ifdef PAM_STATIC
struct pam_module _pam_unix_auth_modstruct = {
"pam_test",
pam_sm_authenticate,
pam_sm_setcred,
NULL,
NULL,
NULL,
NULL,
};
#endif
The problem here is that in struct pam_message, the msg field is declared as const char*; that is, a pointer to an immutable string. So you're not supposed to overwrite it with snprintf.
A simple workaround is to write the string before inserting a pointer to it into msg:
char *s = malloc(100);
snprintf(s, 100, "Second Password:%d:%d:%d:%d:",x1,x2,x3,x4);
msg[0].msg = s;
Note: You should check the return value of snprintf. If the value returned is more than 100, then the string was truncated.

Passing character pointers from client to server in RPCGen

I am trying to send character pointers from rpc client to server in rpcgen for which below are the server and client programs
RPC program for RPC gen
struct clientinput {
char * optype;
char * word;
};
program DICTIONARY_PROG {
version DICTIONARY_VERS {
int USEDICTIONARY(clientinput) = 1;
} = 1;
} = 0x23451113;
RPC Server
#include "dictionary.h"
int *
usedictionary_1_svc(clientinput *argp, struct svc_req *rqstp)
{
static int result;
char *optype = (char*)malloc (10);
char *word = (char*)malloc (10);
char *a = argp->optype;
char *b = argp->word;
printf("Optype is %s\n", a);
printf("Word is %s\n", b);
printf("The optype is %s\n", strcpy(optype, argp->optype));
printf("The word is %s\n", strcpy(word, argp->word));
/*
* insert server code here
*/
return &result;
}
RPC Client
#include "dictionary.h"
void
dictionary_prog_1(char *host, char *optype, char *word)
{
CLIENT *clnt;
int *result_1;
clientinput usedictionary_1_arg;
//strcpy(usedictionary_1_arg.optype, optype);
//strcpy(usedictionary_1_arg.word, word);
usedictionary_1_arg.optype = optype;
usedictionary_1_arg.word = word;
printf("Optype input is %s\n",usedictionary_1_arg.optype);
printf("Word input is %s \n",usedictionary_1_arg.word);
#ifndef DEBUG
clnt = clnt_create (host, DICTIONARY_PROG, DICTIONARY_VERS, "udp");
if (clnt == NULL) {
clnt_pcreateerror (host);
exit (1);
}
#endif /* DEBUG */
result_1 = usedictionary_1(&usedictionary_1_arg, clnt);
if (result_1 == (int *) NULL) {
clnt_perror (clnt, "call failed");
}
#ifndef DEBUG
clnt_destroy (clnt);
#endif /* DEBUG */
}
int
main (int argc, char *argv[])
{
char *host, *optype, *word;
if (argc < 2) {
printf ("usage: %s server_host\n", argv[0]);
exit (1);
}
host = argv[1];
optype = argv[2];
word = argv[3];
dictionary_prog_1 (host,optype,word);
exit (0);
}
Here is the output on the server side
Optyep is a
Word is e
The optype is a
The word is e
The problem i encounter here is that only first character of the character pointers which I have passed from server to client gets printed. I have tried possible combinations of using character pointers and could not find the reason. So can someone please help me figure out the reason for this?
From looking at the documentation, RPCGen needs some help to distinguish between single character argument and actual array of characters since all parameters are passed as pointers. To let it know that you want an array of character, aka string, you need to use the string keyword in your struct declaration like so:
struct clientinput {
string optype<>;
string word<>;
};
This answer explains it as well and this blog post has a similar example to what you want to accomplish.

Resources