I am writing a command line tool in C to control UNDERTALE save files (cuz why not) and I keep getting a segmentation fault whenever I take input from the user.
Here is all my code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#define KILOBYTE 1024
/* The 'm()' is so i know what line the fault happens on */
void m(void) {
printf("X");
}
int main(int argc, char**argv) {
FILE *file;
if (file = fopen("~/.undersave", "r")) {
// Do some code that I haven't written yet
}
else {
char path[KILOBYTE] = "";
printf("It seems that this is your fist time using UNDERSAVE.\nWe just need to go through some quick installation steps.\nWhere do you want your UNDERTALE save folder to be located? >>> ");
m();
fgets(path, KILOBYTE, stdin);
/*
The fault happens here, when it asks me,
i put in the input like normal, but
when I press enter, I get a fault before
it prints 'X'
*/
m();
mkdir(path, 0777);
m();
file = fopen("~/.undersave", "w");
m();
fprintf(file, "%s", path);
m();
fclose(file);
}
return 0;
}
CodePudding user response:
Most likely both calls to fopen
fail, because on Unix-like systems ~
-expansion is a feature of the shell, and isn't applied to a program opening a file directly with fopen
or open
. If you want to open a file relative to your home directory, either include the full path, or use getenv
to read the HOME
environment variable and construct the path within your program. Or, better still, make the filename a command-line argument; those arguments are expanded by the shell before your program sees them, so then ~
expansion would just work.
So the fopen
for writing returns NULL, which you don't test for (a more serious bug). And you then try to fprintf
to a null file pointer, which naturally crashes.
Also, your printf("X")
is not a good diagostic, because output to a terminal is usually buffered. The X's won't actually be written to the screen until a new line is printed, or until you try to read from stdin, or some other special conditions occur. So I suspect the program actually crashes later than you think, on the fprintf
instead of the fgets
. See Why does printf not flush after the call unless a newline is in the format string? and then put fflush(stdout)
after the printf
in your m()
function.