Need help using the strsep function in c - c

int main(int argc, char *argv[])
{
char *line, buffer[1024];
char *token, *setValue, *pointer;
FILE *fp = fopen("file", "r");
if(fp == NULL)
{
printf("File was unable to be opened.\n");
}
fgets(buffer,1024,fp);
printf("%s\n", buffer);
while(fgets(buffer,1024,fp) != NULL)
{
strcpy(token, strsep(&buffer, ","));
printf("%s\n", token);
}
return 0;
}
I'm having a bit of trouble understanding how strsep works.. I've looked up tutorials for it, but when I try different methods, it keeps just not being able to compile.. It'd be appreciated if someone helped me understand the syntax and the way it works. Thank you.
**EDIT: 'Buffer' contains "I,was,in,the,school"
****EDIT x2: I'm trying to parse a csv file, and using the basic 'Buffer' I created on my desktop as an example. I want to separate the different words by the respective comma.

regarding:
strcpy(token, strsep(&buffer, ","));
the variable token is ONLY a pointer, it has not been set to point to any memory that the application owns. Therefore, it will contain what ever trash was on the stack at the location of the variable.
The result is undefined behavior and it can lead to a seg fault event.
Suggest declare token as
char token[ 1024 ];
so it is large enough to hold a maximum length string (I.E. the length of buffer[]
as it the above wasn't bad enough:
the posted code is missing the statement: #include <string.h> so as to expose the prototype for the function strsep() so the compiler will make the assumption that the parameters and returned value are int rather than their actual types.
The posted code is also missing the statement: #include <stdio.h> so the parameter and return types for the functions: fopen(), fgets(), printf()and even the struct type forFILEare assumed to beint` rather than their actual types.

Related

correct way to filter execve environment

I'm trying to write a LD_PRELOADable library that prevents processes from removing itself from this variable (to make sure children inherit it).
So far I sucessfully wrapped putenv,setenv and clearenv, but execve gives me issues.
My code so far:
int (*real_execve)(const char *filename, char *const argv[], char *const envp[]);
int execve(const char *filename, char *const argv[], char *const envp[]){
real_execve = dlsym(RTLD_NEXT,"execve");
char *path = getenv("LD_PRELOAD");
fprintf(stderr, "INTERCEPTED execve, env:\n");
int i;
for(i=0;envp[i]!=NULL;i++);
char *nenvp[i+1];
nenvp[i]=NULL;
for(i=0;envp[i]!=NULL;i++){
char *string = envp[i];
char *buf = malloc((strlen(string)+1)*sizeof(char));
strcpy(buf,string);
char *name = strtok(buf,"=");
char *value = strtok(NULL,"=");
if(0==strcmp(name,"LD_PRELOAD")){
fprintf(stderr," FIXING '%s'\n",string);
char * nstring = malloc((strlen(name)+strlen(path)+strlen(value)+3)*sizeof(char));
strcpy(nstring,name);
strcat(nstring,"=");
strcat(nstring,path);
strcat(nstring,":");
strcat(nstring,value);
nenvp[i]=nstring;
fprintf(stderr," TO '%s'\n",nenvp[i]);
free(string);
}else{
nenvp[i]=envp[i];
fprintf(stderr," LEFT '%s'\n",nenvp[i]);
}
free(buf);
}
fprintf(stderr, " CALLING %s\n", filename);
return real_execve(filename,argv,nenvp);
}
I'm encountering 2 issues:
it logs things like:
FIXING 'LD_PRELOAD=/usr/$LIB/libstdc++.so.6 /usr/$LIB/libgcc_s.so.1 /usr/$LIB/libxcb.so.1'
TO 'LD_PRELOAD=/usr/$LIB/libstdc++.so.6 /usr/$LIB/libgcc_s.so.1 /usr/$LIB/libxcb.so.1:/usr/$LIB/libstdc++.so.6 /usr/$LIB/libgcc_s.so.1 /usr/$LIB/libxcb.so.1'
instead of the expected prepending of the path to self, so I guess I somehow messed up the strtok.
I get a lot of errors like those:
Error in 'sh': munmap_chunk(): invalid pointer: 0x00007fff3888af4a
which to me sounds like I'm freeing too much probably, but I can't find the culprit.
I hope this doesn't sound too much like a "hey fix this for me" post but I'm kinda hitting a wall here and any help would be very appreciated.
You cannot assume that an individual string in envp was allocated with malloc so free(string) could be Undefined Behaviour. It is virtually impossible to call exec* with a completely empty heap and the entire image will be replaced anyway, so it's not worth worrying about.
Your second strtok call should supply NULL as its first argument. See man strtok for an explanation and examples.
Do this straight forward:
Create a new pointer array with the size necessary to hold the new env/ var/s
strdup() all elements you need from the old to the new array.
Add new stuff as necessary.
Make sure the last pointer in the array is NULL.
Pass the new pointer array to the original execve().
Do not modify or even (try to) free() entries of the old environment.

How to prevent strcpy from overwriting another variable as well?

I'm trying to make a simple code that converts one type of data into another. I use strtok to extract one part of the data and then I run a long serial of if conditions to find the right output. However, when the correct output is found and written in the variable currentNote, it also seems to overwrite the variable comma for a reason I can't figure out. Here is the problematic part of the code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char sequence[] = "c1[M],c1[M],d3[L],c3[M],b2[M],(#A-2)[IKN],(#A-1)[L]";
char copy[] = "";
char *comma;
char currentNote[4] = "";
strcpy(copy, sequence);
comma = strtok(copy, ",");
if(strstr(comma, "c1") != 0) //c1
{
printf("%s\n\n", comma); //Here ...
strcpy(currentNote, "C5 ");
printf("%s\n\n", comma);
}
return 0;
}
And here's the outcome :
c1[M]
cC5
No need to say that strcpy(currentNote, "C5 "); is causing it. I don't know why though, I thought it would return c1[M] like I would like it to do. After some more experimentation it turns out that the secondprintf("%s\n\n", comma); will always return the first character of sequence followed by C5. I hope someone can find out, it would be very great.
You are calling
strcpy(copy, sequence) while copy is a 1 element length array. You need to define it by giving it sufficient size. Your code as is, is simply a UB. Redefine it like
char copy[100];
Or allocate sufficient memory to it dynamically using malloc.

Comparing char to string - C

so I've viewed multiple threads here now on this site about comparing my char array to a string or something of that sort with things like strcmp and strstr however whenever I compiled it, I got the error:
warning: incompatible implicit declaration of built-in function 'strstr' [enabled by default]
and honestly I have no idea what this means. I'm relatively new to C...
So here's my code:
int main(){
FILE * fPointer;
fPointer = fopen("test.txt", "r");
char action[10];
char num[100];
char* s;
while(fscanf(fPointer, "%s", action) != EOF){
s = strstr(action, "JUMP");
if(s != NULL){
puts("Jump");
}else{
puts("Don't Jump");
}
}
fclose(fPointer);
}
I've tried a few other things, but none of them worked out. My text file has a bunch of actions:
JUMP 4
CRUNCH 7
SITUP 8
and other similar things like that. I wanted the while loop to scan for each action, and then compare it to whatever to see if action is = to "jump" etc, etc, and if it is, then scan the number to tell me how many times to do each action.
Can someone help me with this? Thanks so much!
You haven't included the proper header.
#include <string.h>

Storing as using result of strtok in array in C

I'm trying to split the input from fgets using strtok, and store the results in an array, i.e. newArgs, so I can then call execvp and essentially execute the input passed by fgets.
E.g. ls -la will map to /bin/ls -la and execute correctly.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
char buff[1024];
fgets(buff, 1024, stdin);
buff[strcspn(buff, "\n")] = 0;
printf("%s\n", buff);
printf("%d\n", strlen(buff));
char *newArgs[30];
char *token;
char delim[2] = " ";
token = strtok(buff, delim);
int i = 0;
while(token != NULL)
{
if(newArgs[i])
{
sprintf(newArgs[i], "%s", token);
printf("%s\n", newArgs[i]);
}
token = strtok(NULL, delim);
i++;
}
execvp(newArgs[0], newArgs);
return 0;
}
I keep getting a Segmentation fault, even though I'm checking the existence of newArgs[i], which is a little odd. Any ideas as to what's going wrong?
You're not allocating any memory for each element of newArgs. Try using a multi-dimensional array, like newArgs[30][100]. Don't forget to ensure they're null terminated.
Problems I see:
You are using uninitialized values of newArgs[i]. You have:
char *newArgs[30];
This is an array of uninitialized pointers. Then, you go on to use them as:
if(newArgs[i])
That is cause for undefined behavior. You can fix that by initializing the pointers to NULL.
char *newArgs[30] = {};
You haven't allocated memory for newArgs[i] before calling
sprintf(newArgs[i], "%s", token);
That is also cause for undefined behavior. You can fix that by using:
newArgs[i] = strdup(token);
The list of arguments being passed to execvp must contains a NULL pointer.
From http://linux.die.net/man/3/execvp (emphasis mine):
The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a NULL pointer.
You are missing the last requirement. You need o make sure that one of the elements of newArgs is a NULL pointer. This problem will go away if you initialize the pointers to NULL.
You are not allocating memory for newArgs before storing it in the string.
Add
newArgs[i] = malloc(strlen(token));
before the if statement inside the for loop.
There is absolutely no reason to copy the tokens you are finding in buff.
That won't always be the case, but it certainly is here: buff is not modified before the execvp and execvp doesn't return. Knowing when not to copy a C string is not as useful as knowing how to copy a C string, but both are important.
Not copying the strings will simplify the code considerably. All you need to do is fill in the array of strings which you will pass to execvp:
char* args[30]; /* Think about dynamic allocation instead */
char** arg = &args[0];
*arg = strtok(buff, " ");
while (*arg++) {
/* Should check for overflow of the args array */
*arg = strtok(NULL, " ");
}
execvp(args[0], args);
Note that the above code will store the NULL returned by strtok at the end of the args array. This is required by execvp, which needs to know where the last arg is.

Stuck on Grabbing a title from a text file

I am attempting to grab a title from a text file in a way that is completely new to me. My code is set up as follows:
struct sequence
{ char *name;
char *sequence;
int sequencelen;
};
int main(int argc, char *argv[])
{
struct sequence *newseq;
getsequence("test.txt", newseq);
}
void getsequence(const char *file, struct sequence *seq)
{
FILE *fp = fopen(file, "r");
struct sequence *seqptr = malloc(sizeof(*seq));
char c;
if (!fp)
{
exit(1);
}
while ((c = fgetc(fp)) != "\n")
{
if (c == '>')
continue;
strcat(seqptr -> name, c);
}
printf("Name: %s", seqptr -> name); //Expected output: this_is_a_new_sequence_title
}
The structure for the text file is as follows:
>this_is_a_new_sequence_title
Using structs in this way is, like I said, new to me, but seeing how it is another way to use them I would like to know how to do it. I am unsure, however, if I'm using them correctly, especially with regards to the strcat function.
Do I have to dynamically allocate memory for the struct's member variables, and, if so, how would I go about doing that? Or do I just have everything horribly wrong?
You're never allocating memory for the string. So when you call strcat(), the destination string is uninitialized memory, leading to undefined behavior.
Also, the 2nd argument to strcat() is a string, not a character. That's more undefined behavior as the library function interprets the single character as the address of a string.
You need to initialize storage space for sequence when you allocate it. Also, for code like this (dynamic strings) it's good to separate "allocated room" from "string length", and store both.

Resources