C program hangs after execution - c

I'm new to C programming. I made a very short program to merge all the files in a folder.
The program runs and produces the right output, but after execution it hangs and I have to manually kill it.
Any ideas why?
The important functions here are scandir and append_to_file
/*
MERGE: Merges text files. Gives the ability to merge a list of files or all files in a
directory with specified extension.
*/
#include <stdio.h>
#include <dirent.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
/* Function prototypes */
int append_to_file(const char *filename, const char *outfilename); // Appends the contents of filename to outfilename
int scandir(char dirname[], char const *ext, char outfile[]); // Scans a directory for files of a specific extension and merges them
bool has_extension(char const *name, char const *ext);
void usage(); // Prints out usage information (help) to the console
void path_combine(char *dest, const char *path1, const char *path2); // Combines a directory name and filename to a single filepath
int main(int argc, char *argv[])
{
int i, // Counters
nfiles; // Number of files merged
if (argc == 4)
{
nfiles = scandir(argv[1], argv[2], argv[3]);
printf("Merged %s files\n", nfiles);
return 0;
}
else
{
printf("Wrong input, quitting");
return 1;
}
}
int append_to_file(const char *filename, const char *outfilename)
{
FILE *infile, *outfile;
char ch;
infile = fopen(filename, "r");
outfile = fopen(outfilename, "a");
if (infile == NULL)
{
printf("Input file is empty, skipping...\n");
return 1;
}
while ((ch = fgetc(infile)) != EOF)
fputc(ch, outfile);
fclose(infile);
fclose(outfile);
return 0;
}
int scandir(char dirname[], char const *ext, char outfile[])
/* Scans a directory and merges all files of given extension */
{
DIR *d = NULL;
struct dirent *dir = NULL;
char filepath[strlen(dirname) + 255];
int i = 0;
d = opendir(dirname);
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if (has_extension(dir->d_name, ext))
{
path_combine(filepath, dirname, dir->d_name);
printf("%s\n", filepath);
append_to_file(filepath, outfile);
i++;
}
}
closedir(d);
}
return i;
}
bool has_extension(char const *name, char const *ext)
{
size_t len = strlen(name);
return len > 4 && strcmp(name+len-4, ext) == 0;
}
void path_combine(char *dest, const char *path1, const char *path2)
{
const char *last_char = path1;
int append_sep = 0;
char sep[] = "/";
#ifdef WIN32
sep[0] = '\\';
#endif
/* Find the last character in the first path*/
while(*last_char != '\0')
last_char++;
/* If the last character is not a seperator, we must add it*/
if (strcmp(last_char, sep) !=0)
{
append_sep = 1;
}
strcpy(dest, path1);
if (append_sep)
strcat(dest, sep);
strcat(dest, path2);
}
void usage()
{
printf("\t=================\n");
printf("\t MERGE\n");
printf("\t=================\n");
printf("Merge two or more text files\n");
printf("Usage:\n");
printf("\tCall merge with a directory name and desired extension:\n");
printf("\tmerge DIRNAME .csv OUTPUTFILE\n\n");
};

As the compiler warned you (if you compile with gcc -Wall -g), the following line:
printf("Merged %s files\n", nfiles);
is wrong, since nfiles is an int. You probably want
printf("Merged %d files\n", nfiles);
Read about undefined behavior. You've got one. Read also carefully the documentation of every function you are using, starting with printf(3) & fopen(3) & perror(3) & exit(3). Don't forget to handle failure, e.g:
FILE *infile, *outfile;
char ch;
infile = fopen(filename, "r");
outfile = fopen(outfilename, "a");
if (infile == NULL) {
printf("failed to open %s (%s), skipping...\n",
filename, strerror(errno));
return 1;
}
if (outfile == NULL) {
perror(outfilename);
exit(EXIT_FAILURE);
}
Learn how to use your debugger (gdb). If on Linux, use also strace(1) and valgrind.

Ah.
I thought I was using the debugger, by specifying -g when compiling:
gcc main.c -g -o main.exe
But it was still hanging.
If I included the flags -Wall and -Werror it soon told me that I had a string formatting error.
the line printf("Merged %s files\n", nfiles) needed to be changed to printf("Merged %d files\n", nfiles).
Compiling with -Wall and -Werror soon pointed out this mistake.

Related

Write a String to filename in c

I have this code and can´t get it properly to work. I want to write the String Output into a file.
static void wr_message_user_info_login(wi_p7_message_t *message) {
wi_date_t *date;
wi_string_t *string, *interval;
wi_p7_uint32_t uid, build, bits;
wr_printf_block(WI_STR("Login: %#"),
wi_p7_message_string_for_name(message, WI_STR("wired.user.login")));
char *filename = "/.wirebot/wirebot.login";
char *home_dir = getenv("HOME");
char *filepath = malloc(strlen(home_dir) + strlen(filename) + 1);
sprintf(filepath, "%s%s", home_dir, filename);
FILE *fp;
fp = fopen(filepath, "w");
if (fp == NULL)
{
}
else
{
fputs((WI_STR("Login: %#")), fp);
);
fclose(fp);
}
"Login: %#" should be writed to file. Echoing is working fine.
You provided a snippet of code with a lot of stuff missing. If you strip the stuff you haven't told us about it seems to work:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void wr_message_user_info_login() {
const char *filename = "/.wirebot/wirebot.login";
const char *home_dir = getenv("HOME");
char *filepath = malloc(strlen(home_dir) + strlen(filename) + 1);
if(!filepath) {
printf("malloc failed\n");
return;
}
sprintf(filepath, "%s%s", home_dir, filename);
FILE *fp = fopen(filepath, "w");
if (!fp) {
printf("fopen failed\n");
free(filepath);
return;
}
free(filepath);
fputs("Login: %#", fp);
fclose(fp);
}
int main() {
wr_message_user_info_login();
}
and example run:
$ mkdir ~/.wirebot && ./a.out && cat ~/.wirebot/wirebot.login
Login: %#
Maybe the directory ~/.wirebot doesn't exist on your host?

INI file reader function is addressing wrong values to my structure, How do I solve this?

This is for a project for university (small replica of a Catan game) and I'm struggling a bit with this part, we have the read an INI file with fairly simple formatting, it only has some comments starting with ';' and then it's just tags with a value in front:
xdim=4
ydim=5
N=D
S=L2
E=S10
W=D
etc...
I have this function to read from an INI file and address the read values to the correct struct element. But it seems like it doesn't even read the file, the struct is a simple struct with xdim and ydim, after I call the func xdim is '&d&d&d&d etc...' and ydim is 0
I've tried placing in some printf's just to see if the values from the INI file itself where being read wrong, but nothing is printed.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 128
typedef struct UNIT { /**struct used in an array for the rest of the INI values*/
char N[4];
char S[4];
char W[4];
char E[4];
char Building;
}UNIT;
typedef struct{ /**This is declared in main and passed to the functions*/
UNIT *grid;
unsigned int xdim;
unsigned int ydim;
} MAP_CONFIG;
void set_config_val(MAP_CONFIG *config, const char *key, int val) {
if (config == NULL)
return;
if (strcmp(key, "xdim") == 0){
printf("here");
config->xdim = val;
}
else if (strcmp(key, "ydim") == 0){
printf("here");
config->ydim = val;
}
else{
;
}
}
void read_config(MAP_CONFIG *config,FILE *f) {
char str[MAX];
char *token;
const char *delim = "=\n";
while (1) {
fgets(str, MAX, f);
if(feof(f)!= 0) break;
puts(str);
if (strchr(str, '=')!=NULL) {
char varname[MAX];
int value;
token = strtok(str, delim);
strcpy(varname, token);
token = strtok(NULL, delim);
value = atoi(token);
printf("&d", token);
set_config_val(config, varname, value);
}
}
config = malloc(sizeof(MAP_CONFIG));
config->grid = calloc(config->xdim * config->ydim, sizeof(UNIT));
close(f);
return;
}
open file function:
FILE *openFile(char *nome, char *mode) {
FILE *f;
printf("Opening file %s\n", nome);
f = fopen(nome, mode);
if (f == NULL) {
fprintf(stderr, "*** It was not possible to open the file %s.", nome);
exit(1);
}
return f;
}
test main im using:
int main(int argc, char **argv) {
MAP_CONFIG map;
MAP_CONFIG *mapa = &map;
FILE *f;
char *filename;
for (int i = 0; i < argc; i++)
printf("Parametro %d: %s\n", i, argv[i]);
if (argc >= 2) {
filename = argv[1];
}
else {
printf("Opening base map file..\n");
filename = "mapa.ini";
}
f = openFile(filename, "r");
read_config(mapa, f);
printf("%d %d", map.xdim, map.ydim);
return 0;
}
I just want it to read the xdim and ydim, and then repeat the process to an array of structs for each struct to get the correct value of the N,S,E,W present in the INI file... Help!

LibCurl undefined references

Trying to make a translation program in C using Libcurl. Text editor is Atom and using gnu compiler.
When compiling as "gcc example.c" i get these errors:
Navid#LAPTOP-ASS7BGNB /c/users/navid/desktop/Lipcurl/libcurl-sample-master/curl
$ gcc projektzwei.c
C:\Users\Navid\AppData\Local\Temp\ccwZwaAr.o:projektzwei.c:(.text+0xa18): undefined reference to `_imp__curl_easy_init'
C:\Users\Navid\AppData\Local\Temp\ccwZwaAr.o:projektzwei.c:(.text+0xa4a): undefined reference to `_imp__curl_easy_setopt'
C:\Users\Navid\AppData\Local\Temp\ccwZwaAr.o:projektzwei.c:(.text+0xa83): undefined reference to `_imp__curl_easy_setopt'
C:\Users\Navid\AppData\Local\Temp\ccwZwaAr.o:projektzwei.c:(.text+0xa90): undefined reference to `_imp__curl_easy_perform'
C:\Users\Navid\AppData\Local\Temp\ccwZwaAr.o:projektzwei.c:(.text+0xaa6): undefined reference to `_imp__curl_easy_strerror'
C:\Users\Navid\AppData\Local\Temp\ccwZwaAr.o:projektzwei.c:(.text+0xacf): undefined reference to `_imp__curl_easy_cleanup'
collect2.exe: error: ld returned 1 exit status
And when compiling as "gcc projektzwei.c -lcurl" i get this error:
Navid#LAPTOP-ASS7BGNB /c/users/navid/desktop/Lipcurl/libcurl-sample-master/curl
$ gcc projektzwei.c -lcurl
c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find -lcurl
collect2.exe: error: ld returned 1 exit status
This is my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "stdafx.h"
#include "libcurl/include/curl/curl.h"
#ifdef _DEBUG
#pragma comment(lib, "libcurl/lib/libcurl_a_debug.lib")
#else
#pragma comment(lib, "libcurl/lib/libcurl_a.lib")
#endif
#define TEXT_MAX 2000
#define CANDIDAT_INPUT 2 /*Amount of valid inputs for candidat*/
#define PARTY_INPUT 14 /*Amount of valid inputs for parties*/
void prepare_files(char *Key);
void Introduction(int Sprog);
void Assemble_URL_To_Translate(int Sprog, FILE *fp);
char *create_URL(char Key[], char Source[], char Target[], char Message[]);
const char *chosen_language(int Target);
int valid_input_checker(const char **index, int array_lenght, char input[]);
void create_message(FILE *fp, char *Message);
void fil_print(FILE *fp);
void Partier(char input[], int Sprog, char chosen_party[]);
const char *chosen_party(char parti_input[]);
void Candidat_Exist(char parti_input[], int Sprog, char chosen_party[]);
char *delete_space(char text[]);
void match_and_insert(int(*str_pred)(char*), char str[], int str_in_len, const char *prefix, char str_out[], int str_out_len);
int space_detector(char* cp);
void translator(void);
int main(void)
{
int Sprog;
/*User is asked to choose language*/
printf("Choose language:\n"
"(1) Dansk\n(2) English\n(3) Turk\n(4) Polski\n(5) Alearabia"
"\n(6) Deutsch\n(7) Kurdi\n(8) Romanesc\n(9) Bosanski\n(10) Soomaali\n");
scanf("%d", &Sprog);
Introduction(Sprog); /*Initializes the program with the given language*/
return 0;
}
void prepare_files(char *Key)
{
FILE *fp;
fp = fopen("API.txt", "r");
if (fp == NULL)
{
printf("Filen kunne ikke �bnes.\n");
exit(EXIT_FAILURE);
}
while (!feof(fp))
{
fscanf(fp, "%s", Key);
}
}
void Assemble_URL_To_Translate(int Sprog, FILE *fp)
{
/*laver api key, target, message og url*/
char SOURCE[5] = "da";
char TARGET[5];
char MESSAGE[TEXT_MAX];
char KEY[100];
char URL[TEXT_MAX];
URL[0] = '\0';
prepare_files(KEY);
strcpy(TARGET, chosen_language(Sprog));
create_message(fp, MESSAGE);
fp = fopen("Translate_Input.txt", "w");
strcat(URL, create_URL(KEY, SOURCE, TARGET, MESSAGE));
fprintf(fp, "%s", URL);
fil_print(fp);
}
void Introduction(int Sprog)
{
/*Function to print introduction at the chosen language and ask the user what their next move is.*/
FILE *fp;
char parti_input[5]; /*Array for user input*/
const char *valid_inputs[PARTY_INPUT] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "b" }; /*All the valid input options in the scanf*/
char party[50]; /*Array to store the string containing what party has been chosen*/
/*This will be replaced when we got a translator function.*/
fp = fopen("Introduktion.txt", "r");
Assemble_URL_To_Translate(Sprog, fp);
translator();
do /*Asks the user to tell us what party they want to have a look at or optionally, go back.*/
{
printf("Press:\n"
"(1) Alternativet\n(2) Det Konversative Folkeparti\n(3) DF\n(4) Enhedslisten\n"
"(5) Fjordlisten\n(6) Kristendemokraterne\n(7) Liberal Alliance\n(8) Nationalpartiet\n"
"(9) Nye Borgerlige\n(10) Radikale Venstre\n(11) SF\n(12) Socialdemokraterne\n(13) Venstre\n"
"(b) for at gaa tilbage\n");
scanf("%s", &parti_input);
}
while (valid_input_checker(valid_inputs, PARTY_INPUT, parti_input) == 0);
if (strchr(parti_input, 'b') != NULL)
{
main();
}
else
{
strcpy(party, chosen_party(parti_input));
Partier(parti_input, Sprog, party);
}
}
char *create_URL(char Key[], char Source[], char Target[], char Message[])
{
char URL[TEXT_MAX] = "https://www.googleapis.com/language/translate/v2?key=&source=&target=&q=";
char *URLptr = URL;
sprintf(URL, "https://www.googleapis.com/language/translate/v2?key=%s&source=%s&target=%s&q=", Key, Source, Target);
Message = delete_space(Message);
strcat(URL, Message);
return URLptr;
}
const char *chosen_language(int Target)
{
/*Finds out what party has been chosen and returns it as a string.*/
const char *sprog[] = { "da", "en", "tr", "pl", "ar", "de", "ku", "ro", "bs", "so" };
return sprog[Target - 1]; /*-1 cause array index starts at 0, but the users lowest valid input is 1*/
}
const char *chosen_party(char parti_input[])
{
/*Finds out what party has been chosen and returns it as a string.*/
int input_tal = atoi(parti_input);
const char *partier[] = { "Alternativet", "Det_Konversative_Folkeparti", "DF", "Enhedslisten"
,"Fjordlisten", "Kristendemokraterne", "Liberal_Alliance", "Nationalpartiet"
,"Nye_Borgerlige", "Radikale_Venstre", "SF", "Socialdemokraterne", "Venstre" };
return partier[input_tal - 1]; /*-1 cause array index starts at 0, but the users lowest valid input is 1*/
}
int valid_input_checker(const char **index, int array_lenght, char input[])
{
/*Algoritme to find out if the entered input from the user is valid.*/
for (int i = 0; i < array_lenght; i++)
{
if (strcmp(index[i], input) == 0) /*If we find a match, we return 1*/
{
return 1;
}
else if (i == array_lenght && (strcmp(index[i], input) != 0)) /*If we have been through the entire index og valid input without a match, we return 0*/
{
return 0;
}
}
return 0;
}
void create_message(FILE *fp, char *Message)
{
int ch;
int i = 0;
while ((ch = fgetc(fp)) != EOF)
{
Message[i] = ch;
i++;
}
Message[i] = '\0';
fclose(fp); /*As soon as we are done with the file we close it. ALWAYS do this.*/
}
void fil_print(FILE *fp)
{
/*Simple algoritme to print a file.*/
int ch;
int i = 0;
char str[400]; /*Array where the file is getting stored*/
while ((ch = fgetc(fp)) != EOF)
{
str[i] = ch;
i++;
}
str[i] = '\0';
//printf("%s\n", str); /*Prints the file*/
fclose(fp); /*As soon as we are done with the file we close it. ALWAYS do this.*/
}
void Partier(char parti_input[], int Sprog, char chosen_party[])
{
/*Function to print the overview of what the chosen party stands for and gives the user the option to view the candidats or go back.*/
FILE *fp;
char kandidat_input[5]; /*This is the input we get from the user, which tells us whether they user wants to look at candidats for the party, og go back.*/
const char *valid_inputs[CANDIDAT_INPUT] = { "1", "b" }; /*Array of valid inputs for the scanf*/
char party_intro[50]; /*Array to store the path for the party overview file.*/
sprintf(party_intro, "Partier/%s/M�rkesager.txt", chosen_party); /*Stores the path*/
printf("party: %s\n", party_intro); /*Nice to have, not necessary. Tells you what path it is going to print from.*/
fp = fopen(party_intro, "r"); /*Opens the file at the given path*/
fil_print(fp); /*Prints the file*/
do/*User is asked to tell what their next move is*/
{
printf("tryk:\n"
"(1) Se partiets kandidater\n");
printf("(b) for at gaa tilbage\n");
scanf("%s", &kandidat_input);
}
while (valid_input_checker(valid_inputs, CANDIDAT_INPUT, kandidat_input) == 0); /*We have a function 'valid_input_checker' which returns either 1 or 0. If 1,
the users input was valid and the program will proceed. If 0, the input was incorrect
and the user is asked again to type something.*/
if (strchr(kandidat_input, 'b') != NULL) /*Checks if the input was 'b'*/
{
Introduction(Sprog);
}
else
Candidat_Exist(parti_input, Sprog, chosen_party);
}
void Candidat_Exist(char parti_input[], int Sprog, char chosen_party[])
{
/*Prints every single candidat for the given party.*/
FILE *fp;
char user_input[5];
char candidattxt[50]; /*Array to later store the string used to open the candidat text file in fopen.*/
char path[40]; /*Array to tell your computer where it is going to find the text file.*/
sprintf(path, "Partier/%s/Kandidat_\0", chosen_party); /*Takes the users chosen party and adds it to the path, to determine where we are going to find the text files.*/
int size = 2;
/*Algoritme to check if the next candidat exist and will print it if it does. If it exist, the 'size' is incremented by 1, so we keep cycling through the list of
candidats. If it doesn't, we break.*/
for (int i = 1; i < size; i++)
{
sprintf(candidattxt, "%s%d.txt", path, i); /*All candidates are saved as "Kandidat_X" where X is an integer starting at 1. We finish the path by specifying what
file want to check.*/
fp = fopen(candidattxt, "r"); /*Opens the candidats text file*/
if (fp != NULL) /*Checks if the file exist*/
{
/*printf("candi: %s\n", candidattxt); Command to show you what candidat is getting printet*/
fil_print(fp);
fclose(fp);
size++;
}
else if (fp == NULL)
{
break;
}
}
do/*User is asked to tell what their next move is*/
{
printf("tryk:\n(b) for at gaa tilbage\n");
scanf("%s", &user_input);
}
while (strcmp(user_input, "b") != 0); /*We have a function 'valid_input_checker' which returns either 1 or 0. If 1,
the users input was valid and the program will proceed. If 0, the input was incorrect
and the user is asked again to type something.*/
Partier(parti_input, Sprog, chosen_party);
}
char *delete_space(char text[])
{
char str_res[TEXT_MAX];
char *str_res_ptr = str_res;
int i, j, k;
/* Initialize str_res til zero */
for (i = 0; i < TEXT_MAX; ++i)
str_res[i] = '\0';
printf("len: %d\n", strlen(text));
match_and_insert(space_detector, text, 200, "%20", str_res, TEXT_MAX);
for (j = 0, k = 0; j < 200; j++)
{
str_res[j - k] = str_res[j];
if (str_res[j] == ' ')
k++;
}
str_res[j] = '\0';
return str_res_ptr;
}
void match_and_insert(int(*str_pred)(char*), char str[], int str_in_len, const char *prefix, char str_out[], int str_out_len)
/*Shoutout til Kurt N�rmark*/
{
int i = 0, o = 0;
while (i < str_in_len)
{
int match_result = str_pred(str + i);
if (match_result > 0)
{
strcpy(str_out + o, prefix);
o += strlen(prefix);
strncpy(str_out + o, str + i, match_result);
i += match_result; o += match_result;
}
else if (match_result == 0)
{
str_out[o++] = str[i++];
}
else
{
printf("Should not happen!\n");
exit(EXIT_FAILURE);
}
}
}
int space_detector(char* cp)
{
int result = isspace(cp[0]);
if (result)
return 1;
else
return 0;
}
void translator(void)
{
CURL *curl;
CURLcode res;
int ch, i = 0;
char Message[2000];
FILE *fp2;
fp2 = fopen("Translate_Input.txt", "r");
while ((ch = fgetc(fp2)) != EOF)
{
Message[i] = ch;
i++;
}
Message[i] = '\0';
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, Message);
FILE *fp = fopen("target.txt", "w");
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
fclose(fp);
}
}
I've searched around a bit and it seems most people get it fixed by adding the
-lcurl at the end of the gcc command but it just doesn't work for me. Any ideas?
Based on this line:
#include "libcurl/include/curl/curl.h"
it looks like you've not installed curl on your machine, you've just downloaded the source and compiled it. That's not the wrong way to do it, but it does make your life more difficult.
Firstly you need to correct the above line as it should be
#include <curl/curl.h>
You then need to tell the compiler where the include files are by adding "-Ilibcurl/include". By doing this, it means that if/when you install libcurl properly, you won't need to make any changes to your code - you can just remove the -I option.
Secondly, you also need to tell the compiler (technically the linker) where the libraries are with the -L option. It looks like that should be "-Llibcurl/lib/"
So to summarise, having fixed the include line as per above, your command to compile your code should look like:
gcc -Ilibcurl/include -Llibcurl/lib projektzwei.c -lcurl

C Program - warning: assignment makes pointer from integer without a cast

I'm trying to read a file and store its content in a variable, here's my code:
#define _BSD_SOURCE
#include <stdio.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
// CEK ROUTER MODEL
char* router_model;
char* model() {
char filename[] = "/tmp/cpuinfo";
char* key = "system type";
char* value;
FILE *file = fopen(filename, "r");
if (file != NULL) {
char line[1000];
while (fgets(line, sizeof line, file) != NULL) /* read a line from a file */ {
//fprintf(stdout, "%s", line); //print the file contents on stdout.
if (strncmp(line, key, strlen(key)) == 0) {
char* value = strchr(line, ':');
value += 2;
router_model = strdup(value);
break; // once the key has been found we can stop reading
}
}
fclose(file);
}
else {
perror(filename); //print the error message on stderr.
}
return router_model;
}
// TULIS SERIAL NUMBER KE FILE
char tulis(char p[100]) {
// Write a serial number to a file
char sn[30];
char encrypt_sn[300];
printf("Serial Number:\n");
scanf("%s", sn);
FILE *f = fopen("/tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c", "w");
if (f == NULL) {
printf("Error opening file!\n");
exit(1);
}
fprintf(f,"Serial Number: %s", sn);
fclose(f);
sprintf(encrypt_sn, "ccrypt -e /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c -K %s", p);
system(encrypt_sn);
system("mv /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c");
printf("Serial number is saved in /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c\n");
return 0;
}
// BACA SERIAL NUMBER & SIMPAN DALAM SEBUAH VARIABLE
char baca(char p[100]) {
// Store the serial number from a file in a variable
char line[50];
char decrypt_sn[300];
char key[30] = "Serial Number";
char *serial_number;
if( access( "/tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c", F_OK ) != -1 ) {
system("cp /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c /tmp/");
system("mv /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt");
sprintf(decrypt_sn, "ccrypt -d /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt -K %s", p);
system(decrypt_sn);
FILE *file = fopen("/tmp/fsn-55cfc8770b69cc07268fae7f25ee444c", "r");
if (file == NULL) {
printf("Error opening file!\n");
exit(1);
}
while (fgets(line, sizeof line, file) != NULL) /* read a line from a file */ {
//fprintf(stdout, "%s", line); //print the file contents on stdout.
if (strncmp(line, key, strlen(key)) == 0) {
char* value = strchr(line, ':');
value += 2;
serial_number = strdup(value);
break; // once the key has been found we can stop reading
}
}
fclose(file);
//printf("Your hardware serial number is: (%s)\n", serial_number);
remove("/tmp/fsn-55cfc8770b69cc07268fae7f25ee444c");
}
else {
printf("fsn not found\n");
return -1;
}
return 0;
}
int main(int argc, char* argv[]) {
char *r;
char *del;
char *decrypt;
int ret;
char input[30];
char *p;
char *original_sn;
p = "MmI4MTUxM2FjMjRlMDkzYmRkZGQyMjcwMjQ4OWY3MDAwNGZiYTM0MWNkZGIxNTdlYzAxN2";
//tulis(p);
original_sn = baca(p);
printf("SN: %s\n", original_sn);
return 0;
}
The file is /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c and the content of that file is Serial Number: 1866203214226041 and original_sn should output 1866203214226041. However when I run that code I get:
test.c: In function ‘main’:
test.c:105:14: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
original_sn = baca(p);
^
SN: (null)
How do I fix it ?
This happens because your baca function returns a char, whereas you are assigning its return value to a char *. Maybe you wanted to use a char variable.
If function baca can change the contents of the memory block pointed by the input argument:
Change this:
char* p = "MmI4MTUxM2FjMjRlMDkzYmRkZGQyMjcwMjQ4OWY3MDAwNGZiYTM0MWNkZGIxNTdlYzAxN2";
To this:
char p[] = "MmI4MTUxM2FjMjRlMDkzYmRkZGQyMjcwMjQ4OWY3MDAwNGZiYTM0MWNkZGIxNTdlYzAxN2";
If function baca cannot change the contents of the memory block pointed by the input argument:
Change this:
char baca(char p[])
To this:
char baca(const char* p)
In baca you are allocating initialised memory using strdup:
serial_number = strdup(value);
, then you do nothing with that.
It is clear that you think that the function returns a pointer to that memory so you can print it's content. However, it is not what you are doing. Because all your baca function is doing is returning a value indecating if it sucseede (0) or not (-1). And you are jut ignoring that pointer and leaving some wasted unused memory allocated by your prog.
Their are 2 methodes to fix your code:
Method1 : returning the serial_number
char* baca(const char* p) {
// Store the serial number from a file in a variable
char line[50];
char decrypt_sn[300];
char key[30] = "Serial Number";
char *serial_number=NULL;
if( access( "/tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c", F_OK ) != -1 ) {
system("cp /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c /tmp/");
system("mv /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt");
sprintf(decrypt_sn, "ccrypt -d /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt -K %s", p);
system(decrypt_sn);
FILE *file = fopen("/tmp/fsn-55cfc8770b69cc07268fae7f25ee444c", "r");
if (file == NULL) {
printf("Error opening file!\n");
exit(1);
}
while (fgets(line, sizeof line, file) != NULL) /* read a line from a file */ {
//fprintf(stdout, "%s", line); //print the file contents on stdout.
if (strncmp(line, key, strlen(key)) == 0) {
char* value = strchr(line, ':');
if(value!=NULL){/*testing the return value for erros so you prog doesn't cruch*/
value += 2;
serial_number = strdup(value);
}
/*in case off erreor you can choose one of two options:*/
/*optinon1: print an error mesage then kill your prog*/
else{
printf("Error: corrupted file!\n");
exit(1);
}
/*option 2: removing the else part your baca then will return NULL and the calling code should understand that an error has occured*/
break;
}
}
fclose(file);
remove("/tmp/fsn-55cfc8770b69cc07268fae7f25ee444c");
}
else {
printf("fsn not found\n");
}
return serial_number;
}
int main(int argc, char* argv[]) {
char *r;
char *del;
char *decrypt;
int ret;
char input[30];
char *p;
char *original_sn;
p = "MmI4MTUxM2FjMjRlMDkzYmRkZGQyMjcwMjQ4OWY3MDAwNGZiYTM0MWNkZGIxNTdlYzAxN2";
//tulis(p);
original_sn = baca(p);
if(original_sn!=NULL){
printf("SN: %s\n", original_sn);
free(original_sn);/*you should free the memory allocated by strdup once you are done using it.*/
}
else{
printf("An error has occured\n");
}
return 0;
}
Method2 : pass by reference
char baca(const char* p, char **serial_number) {
// Store the serial number from a file in a variable
char line[50];
char decrypt_sn[300];
char key[30] = "Serial Number";
char ret = 0;/*the return value 0 means no error.*/
if( access( "/tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c", F_OK ) != -1 ) {
system("cp /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c /tmp/");
system("mv /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt");
sprintf(decrypt_sn, "ccrypt -d /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt -K %s", p);
system(decrypt_sn);
FILE *file = fopen("/tmp/fsn-55cfc8770b69cc07268fae7f25ee444c", "r");
if (file == NULL) {
printf("Error opening file!\n");
exit(1);
}
while (fgets(line, sizeof line, file) != NULL) /* read a line from a file */ {
//fprintf(stdout, "%s", line); //print the file contents on stdout.
if (strncmp(line, key, strlen(key)) == 0) {
char* value = strchr(line, ':');
if(value!=NULL){/*testing the return value for erros so you prog doesn't cruch*/
value += 2;
*serial_number = strdup(value);
}
/*in case off erreor you can choose one of two options:*/
else{
/*optinon1: print an error mesage then kill your prog*/
/*option 2: making the return value non 0 and the calling code should understand that an error has occured*/
#define OPTION1
#ifdef OPTION1
printf("Error: corrupted file!\n");
exit(1);
#else
ret=-2; //to used this option comment out #define OPTION1
#endif
}
break;
}
}
fclose(file);
remove("/tmp/fsn-55cfc8770b69cc07268fae7f25ee444c");
}
else {
printf("fsn not found\n");
ret=-1;
}
return ret;
}
int main(int argc, char* argv[]) {
char *r;
char *del;
char *decrypt;
int ret;
char input[30];
char *p;
char *original_sn=NULL;
p = "MmI4MTUxM2FjMjRlMDkzYmRkZGQyMjcwMjQ4OWY3MDAwNGZiYTM0MWNkZGIxNTdlYzAxN2";
//tulis(p);
switch(baca(p,&original_sn))
{
case 0: //evrything is fine
printf("SN: %s\n", original_sn);
free(original_sn);
break;
case -1:/* handle each error as you should*/
case -2:
default:
printf("An error has occured\n");
}
return 0;
}
Hope this helps. :).

Reading 2 byte at a time from a binary file

I have an elf file that called example. I wrote following code which it's read the content of the example file in the binary mode and then I wanted to save their content in another file called example.binary. But when I run the following program it shows me a segmentation fault. What's wrong with this program? I can't find out my mistake.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// typedef macro
typedef char* __string;
//Function prototypes
void readFileToMachine(__string arg_path);
int main(int argc, char *argv[]) {
__string pathBinaryFile;
if(argc != 2){
printf("Usage : ./program file.\n");
exit(1);
}
pathBinaryFile = argv[1];
readFileToMachine(pathBinaryFile);
return EXIT_SUCCESS;
}
void readFileToMachine(__string arg_path){
int ch;
__string pathInputFile = arg_path;
__string pathOutputFile = strcat(pathInputFile, ".binary");
FILE *inputFile = fopen(pathInputFile, "rb");
FILE *outputFile = fopen(pathOutputFile, "wb");
ch = getc(inputFile);
while (ch != EOF){
fprintf(outputFile, "%x" , ch);
ch = getc(inputFile);
}
fclose(inputFile);
fclose(outputFile);
}
You have no room to concatenate extention to path so you have to create space for that.
One solution could be:
char ext[] = ".binary";
pathOutputFile = strdup(arg_path);
if (pathOutputFile != NULL)
{
pathOutputFile = realloc(pathOutputFile, strlen(arg_path) + sizeof(ext));
if (pathOutputFile != NULL)
{
pathOutputFile = strcat(pathInputFile, ext);
// YOUR STUFF
}
free(pathOutputFile);
}
Side note: typedef a pointer is not a good idea...
change your typedef to typedef char* __charptr
void rw_binaryfile(__charptr arg_path){
FILE *inputFile;
FILE *outputFile;
__charptr extension = ".binary";
__charptr pathOutputFile = strdup(arg_path);
if (pathOutputFile != NULL){
pathOutputFile = realloc(pathOutputFile, strlen(arg_path) + sizeof(extension));
if (pathOutputFile != NULL){
pathOutputFile = strcat(pathOutputFile, ".binary");
inputFile = fopen(arg_path, "rb");
outputFile = fopen(pathOutputFile, "wb");
write_file(inputFile, outputFile);
}
}
}
void write_file(FILE *read, FILE *write){
int ch;
ch = getc(read);
while (ch != EOF){
fprintf(write, "%x" , ch);
ch = getc(read);
}
}

Resources