Program doesn't segfault only when stepping through debugger (gdb) - c

This program I wrote to automatically turn my network's auto configuration logic only segfaults if I run through the program without breaking. When running through a debugger with breakpoints, it runs perfectly fine. When run through a debugger without breakpoints, it segfaults. Is there a bug in this program that I'm not noticing?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define COMLEN 64
#define BUFSIZE 128
const char *program_name;
typedef enum errors
{
SUCCESS = 0,
MEM_ERROR,
FILE_ERROR,
USAGE_ERROR,
} Error;
void terminal_error(Error e)
{
switch (e)
{
case MEM_ERROR:
fputs("Memory error!\n", stderr);
break;
case FILE_ERROR:
fputs("File error!\n", stderr);
break;
case USAGE_ERROR:
fprintf(stderr, "Incorrect usage. Try %s [y|n]\n", program_name);
break;
default:
fputs("Unknown error!\n", stderr);
break;
}
exit(e);
}
Error read_file(FILE *fp, char **buffer)
{
long len;
fseek(fp, 0, SEEK_END);
len = ftell(fp);
fseek(fp, 0, SEEK_SET);
if ((*buffer = malloc(len+1)) == NULL)
return MEM_ERROR;
if (fread(*buffer, 1, len, fp) != len)
return FILE_ERROR;
buffer[len+1] = '\0';
return SUCCESS;
}
Error get_interface(char *name)
{
const char *cmd = "netsh wlan show networks";
FILE *fp;
// open pipe to parse output from command and run command
if ((fp = popen(cmd, "rb")) == NULL)
return FILE_ERROR;
// read the piped output into buffer
char *buffer = NULL;
Error res;
res = read_file(fp, &buffer);
if (res != SUCCESS)
return res;
fclose(fp);
// parse the buffer
// needle delimits the start of the interface name in the command
// end_needle delimits the end of the interface name
const char *needle = "Interface name : ";
const char *end_needle = " \r\nThere";
// end will point to end_needle (end of interface name)
char *end = NULL;
// name points to one-past the end of the needle (start of interface
// name)
name = strstr(buffer, needle);
name += strlen(needle);
end = strstr(buffer, end_needle);
*end = '\0'; // terminates the interface name
return SUCCESS;
}
int main(int argc, const char *argv[])
{
const char *template = "netsh wlan set autoconfig enabled=%s interface=\"%s\"";
char interface_name[BUFSIZE] = {0};
program_name = argv[0];
Error res = SUCCESS;
// get name of wireless interfacew
res = get_interface(interface_name);
if (res != SUCCESS)
terminal_error(res);
char *op;
if (argc > 1)
// arguments were provided
{
if (strcmp(argv[1], "y") == 0)
op = "yes";
else if (strcmp(argv[1], "n") == 0)
op = "no";
else
terminal_error(USAGE_ERROR);
char command[COMLEN];
sprintf(command, template, op, interface_name);
system(command);
}
else
// no arguments were provided
{
system("netsh wlan show settings");
}
return 0;
}

Related

Segmenting a subtring from a main string C

Get specific content from a file and store it in a variable. So far I get that I can convert the file content into a string. But I'm not sure how can I 'extract' the content from the string I converted and would like some help.
The original file looks something like this:
XXXXXX
XXXXX
Addr = 12:23:34:45:45
XXX
XXX
I need to extract and store the Addr as a string. Want to look for the prefix Addr = and just copy it into a buffer. But I don't know how can I do it...
So far my code looks like below:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
//So far I'm looking for it using the MAC addr format
const char *get_mac_addr(char *str, char *dest) {
if (str == NULL)
return 0;
char *start = NULL;
int token_count = 0;
char *ptr = str;
if (*ptr && *(ptr + 1)) // skip two chars in the beginning of the string
ptr += 2;
else
return 0;
while (*ptr != '\0' && *ptr != '\n' && *ptr != '\r') {
if (token_count == 5)
break;
/* if ':' found and previous two characters are hexidecimal digits then
the substring could be part of MAC
*/
if (*ptr == ':' && isxdigit(*(ptr - 1)) && isxdigit(*(ptr - 2))) {
token_count++;
if (start == NULL)
start = ptr - 2;
int i = 0;
while (*ptr != '\0' && i++ < 3)
ptr++;
} else {
start = NULL;
token_count = 0;
ptr++;
}
}
strcpy(dest, start);
return dest;
}
const char *file2str(){
/* declare a file pointer */
FILE *infile;
char *buffer;
long numbytes;
char dest[18];
/* open an existing file for reading */
infile = fopen("~/Desktop/file.config", "r");
/* quit if the file does not exist */
//if (infile == NULL)
// return 1;
/* Get the number of bytes */
fseek(infile, 0L, SEEK_END);
numbytes = ftell(infile);
/* reset the file position indicator to
the beginning of the file */
fseek(infile, 0L, SEEK_SET);
/* grab sufficient memory for the
buffer to hold the text */
buffer = (char *)calloc(numbytes, sizeof(char));
/* memory error */
//if(buffer == NULL)
// return 1;
/* copy all the text into the buffer */
fread(buffer, sizeof(char), numbytes, infile);
fclose(infile);
/* confirm we have read the file by
outputing it to the console */
printf("The file called test.dat contains this text\n\n%s", buffer);
//memset(dest, '/0', sizeof(dest));
get_mac_addr(buffer, dest);
/* free the memory we used for the buffer */
//free(buffer);
printf("Dest is \n\n%s", dest);
return dest;
}
int main() {
printf(file2str);
return 0;
}
I really appreciate your help. Please bare with me as I'm not very good at c programming. I would like to convert the main function into one function so I can directly call it and return a string. I converted the main function as following, but I'm not sure why when I print it, there is nothing show up:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
const char *MACadd()
{
char buf[256];
char *addr = NULL;
FILE *in = xfopen("~Desktop/file.config", "r");
while( fgets(buf, sizeof buf, in) ){
addr = strstr(buf, "Addr = ");
if( addr && addr < buf + sizeof buf - ADDRLEN){
addr += strlen("Addr = ");
addr[ADDRLEN] = '\0';
break;
}
}
//printf("addr = %s\n", addr);
return addr;
}
FILE *xfopen(const char *path, const char *mode)
{
FILE *fp = fopen(path, mode);
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
int main(){
printf("%s", MACadd());
return 0;
}
You could read the file line by line with the fgets function and use the sscanf function to extract the relevant portion like that:
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#define ISXDGT(c) isxdigit((unsigned char)(c))
static bool is_macaddr (const char *s)
{
return ISXDGT(s[0]) && ISXDGT(s[1]) && s[2] == ':'
&& ISXDGT(s[3]) && ISXDGT(s[4]) && s[5] == ':'
&& ISXDGT(s[6]) && ISXDGT(s[7]) && s[8] == ':'
&& ISXDGT(s[9]) && ISXDGT(s[10]) && s[11] == ':'
&& ISXDGT(s[12]) && ISXDGT(s[13]) && s[14] == ':'
&& ISXDGT(s[15]) && ISXDGT(s[16]);
}
bool get_macaddr_from_file (const char *filename, char *macaddr)
{
char line[4096];
bool done = false;
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open the file '%s'\n", filename);
return false;
}
while (fgets(line, sizeof line, fp) != NULL) {
/* Modify the prefix (" Addr = " here) at your convenience */
if (sscanf(line, " Addr = %17s", macaddr) == 1 && is_macaddr(macaddr)) {
done = true;
break;
}
}
fclose(fp);
return done;
}
int main (void)
{
char macaddr[18];
if (get_macaddr_from_file("file.conf", macaddr)) {
printf("MAC: %s\n", macaddr);
}
}
char *extract(const char *str, char *buff)
{
char *addr = strstr(str, "Addr");
if(addr)
{
addr += sizeof("Addr") - 1;
while(!isdigit((unsigned char)*addr))
{
if(*addr == '\n' || !*addr)
{
addr = NULL;
break;
}
addr++;
}
if(addr)
{
while(*addr && *addr != '\n' && (isdigit(*addr) || *addr == ':'))
{
*buff++ = *addr++;
}
*buff = 0;
}
}
return addr ? buff : NULL;
}
void main(int argc, char** argv)
{
char *str = "XXXXXX\nXXXXX\n\nAddr = 12:23:234:145:45 \nXXX\nXXX\n";
char mac[30];
if(extract(str,mac)) printf("Hurray!!! `%s`\n", mac);
else printf("MIsareble failure\n");
}
https://godbolt.org/z/6TjK8b
This gets a little tricky if you don't want to restrict yourself to a fixed maximum line length, but it's probably sufficient to do something like:
#define ADDRLEN 14
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
int
main(int argc, char **argv)
{
char buf[256];
char *addr = NULL;
FILE *in = xfopen(argc > 1 ? argv[1] : "-", "r");
while( fgets(buf, sizeof buf, in) ){
addr = strstr(buf, "Addr = ");
if( addr && addr < buf + sizeof buf - ADDRLEN){
addr += strlen("Addr = ");
addr[ADDRLEN] = '\0';
break;
}
}
printf("addr = %s\n", addr);
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
To break this into a function, you need to be a little bit careful. In your attempt, you've passed back references to local variables which cease to exist after the function returns. Perhaps you want something like:
#define ADDRLEN 14
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
const char *
MACadd(const char *path, char *buf, size_t s)
{
char *addr = NULL;
FILE *in = xfopen(path, "r");
while( fgets(buf, s, in) ){
addr = strstr(buf, "Addr = ");
if( addr && addr < buf + s - ADDRLEN){
addr += strlen("Addr = ");
addr[ADDRLEN] = '\0';
break;
}
}
return addr;
}
FILE *xfopen(const char *path, const char *mode)
{
FILE *fp = fopen(path, mode);
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
int
main(void)
{
char buf[256];
printf("%s", MACadd("input", buf, sizeof buf));
return 0;
}
I think that is easier than you are doing, once you moved the file contnent in a string, use strstr() - here ther is the description http://www.cplusplus.com/reference/cstring/strstr/ - to find "addr = " and then get the string from there to the character "\n"
follow this example
#include<string.h>
#include<stdio.h>
#define endchrptr(ptr1, ptr2, ptr3) (ptr1 < ptr2 ? (ptr1<ptr3?ptr1:ptr3) : (ptr2<ptr3?ptr2:ptr3))
bool get_mac_addr(const char* source, char *dest) {
if(source!=NULL&&dest!=NULL) {
char* addr_pointer=strstr(source, "Addr = ")+7;//find where the address start
char* end_addr_pointer=endchrptr(strchr(addr_pointer, '\n'), strchr(addr_pointer, '\r'), strchr(addr_pointer, '\0'));//find where the address ends
if(end_addr!=NULL) {
for(int i=0; i<end_addr_pointer-addr_pointer; ++i) {//copy the address
dest[i]=addr_pointer[i];
}
dest[end_addr_pointer-addr_pointer],
}
else return false;
}
else return false;
}
int main()
{
char *str = "XXXXXX\nXXXXX\n\nAddr = 12:23:234:145:45 \nXXX\nXXX\n";
char mac[30];
get_mac_addr(str, mac);
printf("%s", mac);
}
I just tried in DevC++ and it works.
Let me know if it works.
There are multiple problems in the code:
fopen("~/Desktop/file.config", "r"); will fail because the ~ in the filename is not expanded to the home directory by fopen, it is a feature of the command shell. Use the full path instead, or take the filename as an argument.
you do not check for fopen() failure: passing a null stream pointer to fseek has undefined behavior and will probably crash the program.
printf(file2str); is a major mistake: you try to use the bytes from the function as a format string, you will get garbage output and possibly a crash because of undefined behavior. Use printf("%s\n", file2str()); instead.
there is no need to read the whole file in memory at once for this problem, just reading one line at a time is much simpler. Furthermore, you do not allocate enough memory for the null terminator, so you get undefined behavior with using buffer as a C string.
get_mac_addr is way too complicated: you could use strstr to locate the string "Addr = " and extract the following word.
Here is a simpler version:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
const char *get_mac_address(const char *str, char *dest) {
if (!strncmp(buf, "Addr = ", 7)) {
const char *p = buf + 7;
for (i = 0; i < 17; i++) {
if (i % 3 == 2) {
if (p[i] != ':')
break;
} else {
if (!isxdigit((unsigned char)p[i]))
break;
}
}
if (i == 17 && !isalnum((unsigned char)p[i]) {
memcpy(dest, p, 17);
dest[17] = '\0';
return dest;
}
}
return NULL;
}
int main() {
char buf[256];
char address[20];
FILE *fp = fopen("/home/ImTrying/Desktop/file.config", "r");
if (fp != NULL) {
while (fgets(fp, buf, sizeof buf)) {
if (get_mac_address(buf, address)) {
printf("Dest is %s\n", address);
break;
}
}
fclose(fp);
}
return 0;
}

Segmentation faulting in assignment

I'm currently learning C and I came from java. Our assignment asked us to count strings from either a file that could be added or it asks for the user to input a string. We just started using pointers and i looked up the different reasons why segmentation faults happened but I have no idea how to check for which issue it is. I initialized all my pointers to NULL but it still didn't work and from what i read that was the most common reason why a segmentation fault happens.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int debug = 0;
int
main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
FILE* infile = NULL;
int c, err = 0;
int lflag = 0, sflag = 0, count = 0; //flags and count
char *shortWord = NULL, *longWord = NULL; //variable for shortest and longest word
int shortest = 100, longest = 0; //longest char 100, shortest 0
char *string = NULL;
char *pch = NULL;
static char usage[] = "usage: %s [-l] [-s] [filename]\n";
while ((c = getopt(argc, argv, "ls")) != -1)
switch (c)
{
case 'l':
lflag = 1;
break;
case 's':
sflag = 1;
break;
case '?':
err = 1;
break;
}
if (err)
{
fprintf(stderr, usage, argv[0]);
exit(1);
}
//checks for file and then runs loop for word count
infile = fopen("myfile.txt","r");
if (infile != NULL)
{
fgets(string, 100, infile);
pch = strtok (string, " ,.-");
while(pch != NULL)
{
count++;
if (strlen(pch) > longest)
longWord = pch;
if (strlen(pch) < shortest)
shortWord = pch;
pch = strtok (NULL, " ,.");
}
}
//else, asks for string
else
{
printf("Enter your string: \n");
fgets(string, 100, stdin);
int len = strlen(string);
count = len;
pch = strtok ( string, " ,.-");
while(pch != NULL)
{
count++;
if (strlen(pch) > longest)
longWord = pch;
if (strlen(pch) < shortest)
shortWord = pch;
pch = strtok (NULL, " ,.");
}
}
//following lines compute value based on arguments
if(lflag == 1)
{
printf("Longest word is %s", longWord);
}
if(sflag == 1)
{
printf("Shortest word is %s", shortWord);
}
printf("Word count = %.2d\n", count);
exit(0);
}
Their are some issues in your code:
You initialized string to NULL, then used it as an input buffer for fgets(). fgets() reqiures a pointer to an array of chars, either declared on the stack or dynamically allocated with malloc(3). You can set an input buffer such as char string[100].
fgets() must be checked, as it returns NULL when unable to read a line.
Your delimiter for strtok() is not accounting for the \n character appended by fgets(). You can either remove this newline, or include it in the delimter. If you want to include it in the delimeter, make sure your delimiter is " ,.-\n".
You could create function which parses your input with strtok(), as this would allow your main() to be shorter and reduce the repetitiveness in the code. An example function prototype could be void longest_shortest_words(char line[], char **longest, char **shortest, size_t *word_count);, whereby you pass the longest, shortest words along with the number of words back to main() via pointers. You could also just store the longest and shortest words in a 2D array or array of pointers.
You should also explicitly check that your file was opened correctly. Something like this should be included:
infile = fopen("myfile.txt", "r");
if (infile == NULL) {
fprintf(stderr, "Failed to open file\n");
exit(EXIT_FAILURE);
}
When checking opt, checking ? as a character in your switch statement is not right. Instead of:
case '?':
err = 1;
break;
Use default, which covers any other invalid option entered. Here is how you can use it:
default:
fprintf(stderr, "usage: %s [-l] [-s] [filename]\n", argv[0]);
exit(EXIT_FAILURE);
Checking sflag and lflag at the end is not enough. You should check if longWord and shortWord are not NULL.
Here is some example code which demonstrates these points:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define LINESIZE 100
void longest_shortest_words(char line[], char **longest, char **shortest, size_t *wordcount);
void print_output(int lflag, int sflag, char *longword, char *shortword, size_t wordcount);
void remove_newline(char line[]);
int main(int argc, char * const argv[]) {
FILE *infile;
char line[LINESIZE] = {'\0'};
int opt, sflag = 0, lflag = 0;
size_t wordcount = 0;
const char *optstr = "ls";
char *longword = NULL, *shortword = NULL;
while ((opt = getopt(argc, argv, optstr)) != -1) {
switch(opt) {
case 'l':
lflag = 1;
break;
case 's':
sflag = 1;
break;
default:
fprintf(stderr, "usage: %s [-l] [-s] [filename]\n", argv[0]);
exit(EXIT_FAILURE);
}
}
/* Checking if file is in directory */
infile = fopen("myfile.txt", "r");
if (infile == NULL) {
fprintf(stderr, "Failed to open file\n");
exit(EXIT_FAILURE);
}
/* checking if line exists in file */
if (fgets(line, LINESIZE, infile) == NULL) {
fprintf(stderr, "No line found in file.\n");
printf("\nEnter string instead:\n");
if (fgets(line, LINESIZE, stdin) != NULL) {
remove_newline(line);
longest_shortest_words(line, &longword, &shortword, &wordcount);
/* checking that longWord, shortWord and word_count are valid */
if (longword != NULL && shortword != NULL && wordcount > 0) {
print_output(lflag, sflag, longword, shortword, wordcount);
}
}
/* file has line, do stuff with it */
} else {
remove_newline(line);
longest_shortest_words(line, &longword, &shortword, &wordcount);
print_output(lflag, sflag, longword, shortword, wordcount);
}
exit(EXIT_SUCCESS);
}
/* function for printing output, can be improved */
void print_output(int lflag, int sflag, char *longword, char *shortword, size_t wordcount) {
if (lflag) {
printf("Longest word: %s\n", longword);
}
if (sflag) {
printf("Shortest word: %s\n", shortword);
}
if (wordcount > 0) {
printf("Word count = %zu\n", wordcount);
}
}
/* function for removing newline, and checking that input hasnt exceeded limit */
void remove_newline(char line[]) {
size_t slen;
slen = strlen(line);
if (slen > 0 && line[slen-1] == '\n') {
line[slen-1] = '\0';
} else {
fprintf(stderr, "\nToo many characters in input.\n");
exit(EXIT_FAILURE);
}
}
/* function which parses line, and saves longWord and shortWord in pointers */
void longest_shortest_words(char line[], char **longword, char **shortword, size_t *wordcount) {
char *word = NULL;
const char *delim = " ,.";
word = strtok(line, delim);
if (word != NULL) {
*longword = word;
*shortword = word;
*wordcount = 1;
}
while ((word = strtok(NULL, delim)) != NULL) {
(*wordcount)++;
if (strlen(word) > strlen(*longword)) {
*longword = word;
} else if (strlen(word) < strlen(*shortword)) {
*shortword = word;
}
}
}
Note: The code shown above can be improved, it is just to show you another approach to your problem.

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. :).

RAMFS mounting program

I rewrote a bash script into a standalone C program for mounting the current directory into the ramfs. However I still use "system()" for some of the functions. The only thing that still bothers me is the use of C mount function. In my code I call it with a system call but I want to know what is the right use in my case for C`s system.
int main(int argc, char* argv[])
{
(void) argc; // unused
bool matched_result = false;
// extra size
char pwd[512]={0};
getcwd(pwd, sizeof(pwd)/sizeof(pwd[0]));
printf("Current working dir is: %s\n", pwd);
// Check is already mounted ramfs on the current directory.
// The beter way is manual parsing.
// in order to avoid that process we have to write dirwalker
// to list all mounted fses but for now will use this one
FILE* mntstatus = popen("mount", "r");
// assume no more than 512 chars per line
char buff[512]={0};
while (fgets(buff, 512, mntstatus) != NULL) {
char* match = strchr(buff, '/');
// trim 3 whitespaces from the end
trim_end(match, ' ', 3);
if (strcmp(match, pwd)==0) {
printf("Match: [%s]\n", match);
matched_result = true;
break; // no need to search more
}
}
// our cwd is not mounted
if (!matched_result) {
// empty, ok we can mount here
// just efective-uid is not enough for mount
// i need real-uid
setuid(0);
int res = mount_filesystem(pwd, "ramfs", "ramfs", 0, "rw", 0);
//int res = system("mount -t ramfs ramfs `pwd`");
if (res == 0) {
printf("Mount ok\n");
// convert to octals
int octal_perms = strtol(g_Permissions, 0, 8);
if (chmod(pwd, octal_perms) < 0) {
fprintf(stderr, "%s: error in chmod(%s, %s) - %d (%s)\n",
argv[0], // program
pwd, // current dir
g_Permissions, // with permissions
errno, // Ermac :)
strerror(errno));
exit(1);
}
} else {
printf("Mount failed!\n");
return 1;
}
} else {
printf("Dude you are ok!\n");
}
return 0;
}
void trim_end(char *str, const char delim, int count)
{
char* begin = str;
char* end = &str[strlen(str)-1];
int i=0;
while ((i < count) && ( begin != end)) {
if (*end == delim) {
i++;
}
*end-- = 0;
}
}
void register_exit_callback(cbAtExit ex)
{
atexit(ex);
}
int mount_filesystem(const char *src, const char *tgt, const char *fstype, unsigned long flags,
const char *mode, const char *uid)
{
char mode_uid[256]={0};
if((mode != NULL) && (uid != NULL)) {
sprintf(mode_uid, "mode=%s,uid=%s", mode, uid);
}
int result = mount(src, tgt, fstype, flags, mode_uid);
// handle result outside
return result;
}

Circuit Simulator in C input

I have to create a circuit based off the inputs of a text file i read.
The first text file I use has the circuit description and then the next has the actual binary values of the circuit you end up creating.
Example:
INPUTVAR 3 A B C
OUTPUTVAR 1 Q
AND A B w
AND A C x
OR w x Q
the format of this example means that there are 3 input variables called A, B , C. There is also 1 output variable called Q. The And creates an expression called w= A.B. along with x=A.C. and the or is Q = w.x. My problem is that I do not know how to read in this input since it isnt the same format every time. The amount of variables after the INPUTVAR depends on what that first number says. I am confused on how I can interpret this in code, I know how to read in data that is formatted. Any hints or help provided will be appreciated.
I believe I need to use fgets() to do it line by line.
with help I have came up with the following code
FILE *circuit;
circuit = fopen(argv[1],"r");
char line[50];
char *str;
while (fgets(line,sizeof(line),circuit) != NULL)
{
str = strtok(line," "); //space is DELIM
printf("str is: %s\n",str);
}
I am geting the following outputs from the text file that I included as an example:
str is: INPUTVAR
str is: OUTPUTVAR
str is: AND
str is: AND
str is: OR
How do I go about getting the characters after the first word of each line?
I adjusted your code [please pardon any gratuitous style cleanup]:
FILE *circuit;
circuit = fopen(argv[1], "r");
char line[50];
char *str;
char *cp;
while (1) {
cp = fgets(line, sizeof(line), circuit);
if (cp == NULL)
break;
cp = strchr(line,'\n');
if (cp != NULL)
*cp = 0;
cp = line;
while (1) {
str = strtok(cp, " ");
cp = NULL;
if (str == NULL)
break;
printf("str is: %s\n", str);
}
}
UPDATE: Per your request, here is a more generalized solution that gets you closer. This compiles but is untested. But, it should give you the idea.
// circuit -- circuit simulator
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// command parsing control
// NOTE: this can be build up if desired
struct cmd {
const char *cmd_str; // command string
const char *(*cmd_parse)(struct cmd *); // command parse function
};
// forward declarations
const char *parse_inputvar(struct cmd *cmd);
const char *parse_outputvar(struct cmd *cmd);
const char *parse_and(struct cmd *cmd);
const char *parse_or(struct cmd *cmd);
// list of supported commands
struct cmd cmdlist[] = {
{ .cmd_str = "INPUTVAR", .cmd_parse = parse_inputvar },
{ .cmd_str = "OUTPUTVAR", .cmd_parse = parse_outputvar },
{ .cmd_str = "AND", .cmd_parse = parse_and },
{ .cmd_str = "OR", .cmd_parse = parse_or },
{ .cmd_str = NULL }
};
int
main(int argc,char **argv)
{
FILE *circuit;
char line[5000];
char *cp;
struct cmd *cmd;
const char *err;
--argc;
++argv;
circuit = fopen(*argv, "r");
while (1) {
cp = fgets(line, sizeof(line), circuit);
if (cp == NULL)
break;
cp = strchr(line,'\n');
if (cp != NULL)
*cp = 0;
cp = strtok(line," ");
err = NULL;
for (cmd = cmdlist; cmd->cmd_str != NULL; ++cmd) {
if (strcmp(cp,cmd->cmd_str) == 0) {
err = cmd->cmd_parse(cmd);
break;
}
}
if (cmd->cmd_str == NULL)
printf("unknown command -- '%s'\n",cp);
if (err != NULL)
printf("error in %s command -- %s\n",cmd->cmd_str,err);
}
fclose(circuit);
}
const char *
parse_inputvar(struct cmd *cmd)
{
char *cp;
char *sym;
int cnt;
int idx;
const char *err = NULL;
do {
// get the count string
cp = strtok(NULL," ");
if (cp == NULL) {
err = "missing count";
break;
}
// decode count string into number
cnt = atoi(cp);
if (cnt <= 0) {
err = "bad count";
break;
}
for (idx = 0; idx < cnt; ++idx) {
sym = strtok(NULL," ");
if (sym == NULL) {
err = "missing symbol";
break;
}
// NOTE: sym will be invalid after we return so we need to preserve
// it now
sym = strdup(sym);
// do whatever ...
}
} while (0);
return err;
}
const char *
parse_outputvar(struct cmd *cmd)
{
const char *err = NULL;
return err;
}
const char *
parse_and(struct cmd *cmd)
{
const char *err = NULL;
return err;
}
const char *
parse_or(struct cmd *cmd)
{
const char *err = NULL;
return err;
}
You can read the line of input, using fgets(), as a string and them do a split() function on it to parse it into numbers. The split creates an array of strings using spaces as delimiters. The first string will be INPUTVAR in string format, then you can do an atoi() on that to convert to a number.

Resources