I have seen questions similar to this one on here before but I was unable to solve my problem from the answers to those.
I have a file libfoo.c from which I'm creating a shared object. Using gcc's __attribute__((constructor)), I'd like to print a message to a file when this shared object is loaded:
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static char *term = NULL;
static void init (void) __attribute__((constructor));
static void
init (void)
{
FILE *f = fopen ("lib.log", "w");
if (f)
{
if (isatty (STDOUT_FILENO))
{
char *tmp = ttyname (STDERR_FILENO);
if (tmp && *tmp)
{
term = strdup (tmp); // nevermind the memory leak
fprintf (f, "Found terminal %s\n", term);
}
}
else
fprintf (f, "Failed to find terminal\n");
fclose(f);
}
}
void *
malloc (size_t size)
{
return NULL;
}
The dummy malloc implementation (to be extended later) should replace stdlib.h's malloc in another dummy program, whose source code resides in main.c:
#include <stdlib.h>
int main (void)
{
char *m = malloc(1024);
(void)m;
return 0;
}
I'm compling and linking both files as follows:
gcc -o main main.c
gcc -fpic -shared -o libfoo libfoo.c
And then when I execute the following no file is created and no output is logged:
LD_PRELOAD=$(readlink -f libfoo) ./main
What is going on here? As a sidenote: how could I try to debug a problem like this using ltrace? ltrace "LD_PRELOAD=... ./main" is not a valid command.
EDIT: What is going on here? It seems at least printf works inside the shared object, but only inside the setup function, if I call printf inside malloc the program segfaults. In trying to at least figure out what terminal stdout is connected to I did the following (inside the setup function):
// ...
char buf[100];
buf[readlink ("/proc/self/fd/1", buf, 100)] = '\0';
printf ("STDOUT (buf): %s\n", buf);
char *tmp = ttyname (1);
printf ("STDOUT (ttyname): %s, %s\n", tmp, strerror (errno));
// ...
This prints:
STDOUT (buf): /dev/pts/1
STDOUT (ttyname): (null), Success
According to the ttyname manpage, that second line of output should be impossible. Am I completely misunderstanding something here?
here is what I ran, created from your code, and it ran perfectly, generating a file: lib.log
The contents of the file: lib.log
Found terminal /dev/pts/1
and now, the code I ran:
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static char *term = NULL;
static void init (void) __attribute__((constructor));
static void init (void)
{
FILE *f = fopen ("lib.log", "w");
if (f)
{
if (isatty (STDOUT_FILENO))
{
char *tmp = ttyname (STDERR_FILENO);
if (tmp && *tmp)
{
term = strdup (tmp); // nevermind the memory leak
fprintf (f, "Found terminal %s\n", temp);
}
}
else
fprintf (f, "Failed to find terminal\n");
fclose(f);
}
else
{
perror( "fopen failed" );
}
}
void *
myMalloc (size_t size)
{
(void)size;
return NULL;
}
int main (void)
{
char *m = myMalloc(1024);
(void)m;
return 0;
}
Of course, your posted code is missing a header file. Such a header file should be referenced/included by your main.c file and your libfoo.c file
Related
I am getting a segmentation fault when I want to run this program. It is supposed to by a self-written grep function but case-insensitive. The same code for case-sensitive works just fine so it might have something to do with tolower()?. Please help.
Used VS code in Ubuntu on a Windows PC.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main (int argc, char *argv[]) {
if (argc > 3) {
printf("Too many arguments. Only use 2: your search string and the file name.");
return -1;
}
//FILE * fp;
FILE * fp = fopen(argv[2], "r");
if(fp == NULL) {
perror("Unable to open file!");
return -1;
}
char * buffer = NULL;
size_t bufsize = 0;
char * lowerBuffer = malloc(sizeof(strlen(buffer)));
for (int i = 0; buffer[i] != '\0'; i++) {
lowerBuffer[i] = tolower(buffer[i]);
}
printf("tolower: %s", lowerBuffer);
while (getline(&buffer, &bufsize, fp) != -1) {
if (strstr(buffer, argv[1]))
{
printf("%s", buffer);
}
//printf("%zd", strlen(buffer));
}
fclose(fp);
free(buffer);
//getline();
return 0;
}
Compiled with gcc mygrepin.c, run with ./a.out test test.txt.
This is what my test.txt looks like:
hallo das ist ein Test.
test
test
test
test
test
I am expecting this output for this command ./a.out test test.txt:
hallo das ist ein Test.
test
test
test
test
test
You try to use
malloc(sizeof(strlen(buffer)))
on an object you just defined as Null
char * buffer = NULL;
Malloc is used to allocate space. What you want to do is to allocate space for the size of a string with the length of your variable buffer. Buffer is null.
Edit: As a comment pointed out not no space is allocated. It is either 4 or 8 depending on your machine. It works on the type. A pointer should return the value of 4 or 8 depending on your architecture of the system. Thanks to #mch for pointing that out. Even though this is true, the problem still remains and was caused by the buffer never being set to a value besides NULL.
Code link
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define OS_TYPE "/proc/sys/kernel/ostype"
#define OS_RELEASE "/proc/sys/kernel/osrelease"
#define V_BUFF 30
static const char * get_value(const char * file_path)
{
static char value[V_BUFF];
FILE *fd;
memset(value, 0, sizeof(value));
if ((fd = fopen(file_path, "r")) == NULL) {
fputs("Fopen function error.\n", stderr);
exit(EXIT_FAILURE);
}
while (fgets(value, V_BUFF, fd) == NULL) {
fputs( "Fscanf function error.\n", stderr);
exit(EXIT_FAILURE);
}
fclose(fd);
return value;
}
int main(void) {
fprintf(stdout, "%s%s", get_value(OS_TYPE), get_value(OS_RELEASE));
return EXIT_SUCCESS;
}
Where's wrong?
Why the result r same?
If added a fflush in while or out of while, the result also same.
Plz help me, tell what reason.
Thanks!
The arguments are evaluated then passed to fprintf to format them.
Since there's only one memory area (static) for both results, the last function call "wins" and you get twice the same result (note that order of evaluation is implementation defined, so you could get twice the first result, or twice the second)
Quickfix: as BLUEPIXY suggested, you could call fprintf twice:
fprintf(stdout, "%s", get_value(OS_TYPE));
fprintf(stdout, "%s", get_value(OS_RELEASE));
To fix that properly you'd have to allocate memory using malloc (char *value = malloc(V_BUFF);), but in that case you'd have to store the pointer to be able to free it, or pass an extra argument to the function, as a buffer to use internally, like some standard functions do.
const char * get_value(const char * file_path, char *value)
{
...
return value;
}
now you can get your call in one line with separate buffers and no memory leaks:
char vbuf[V_BUFF],obuf[V_BUFF];
fprintf(stdout, "%s%s", get_value(OS_TYPE,vbuf), get_value(OS_RELEASE,obuf));
I have drafted a code snippet that is to emulate the operation of ls -all in a custom shell named My$HELL
The main shell process invokes this code(by calling its executable through execlp).
Following is the code of the executable myls which is to do the work:-
myls.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
void search_dir(const char * arg);
void main(int argc, char *argv[])
{
int i;
if (argc==1)
search_dir(".");
for(i=1;i<argc;i++)
search_dir(argv[i]);
}
void search_dir(const char *arg)//Function to read directories and file attributes//
{
DIR *dirp;
struct dirent *dp;//Dirent structure used to read and store directory attributes//
char file_name[256];
char time[50]={"\0"};
struct tm *timeinfo;
struct stat prop_file;//stat function for accessing file attributes//
char type;
if((dirp=opendir(arg))==NULL)
{
perror("opendir");
return;
}
printf("\n\nDirectory \tTime last Modified\tSize\t\t Name\n");
while((dp=readdir(dirp))!=NULL) // Navigates the directory structure
{
if ( stat(dp->d_name,&prop_file)!=0) //Reading file attributes//
{
printf("\n%s:Error in reading the file attributes", dp->d_name );
continue;
}
if ( dp->d_type==8 )
{
type = '-';
}
else
{
type = 'd';
}
timeinfo=localtime(&(prop_file.st_mtime));
strftime(time,20,"%b %d %H:%M", timeinfo);
printf("\n %c\t\t %s\t\t%d\t\t %s",type,time,(int)prop_file.st_size,dp->d_name); //Printing ile attributes//
}
printf("\n");
}
Irrespective of the contents in the directory, the process displays certain fields after which the calling process terminates with a segmentation fault.
A GDB run is also of a little help (for being vague) and search on the error yields little result. Following is the debugged output:-
[~pbox/working/trial]<My$HELL>myls
Executing myls
Directory Time last Modified Size Name
d Aug 14 19:22 4096 ..
d Aug 14 18:42 4096 .
[~pbox/working/trial]<My$HELL>
Program received signal SIGSEGV, Segmentation fault.
strlen () at ../sysdeps/x86_64/strlen.S:106
106 ../sysdeps/x86_64/strlen.S: No such file or directory.
(gdb) Quit
From what I could understand such error are results of illegal variable/pointer assignments. Any help in pointing out the bug is highly appreciated.
Am also appending code segment of the main process from where myls is being called
main.c
.
.
else if(strcmp(command[0],"myls")==0) //command of type char ** stores the user input command check if the first field is 'myls'//
{
printf("Executing myls\n");
strcat(path,"/myls"); //path stores the directory path
result=execvp(path,command); //result of type int
exit(0);
}
.
.
Cheers and thanks in anticipation!!
the following code :
1) cleanly compiles
2) handles errors in an appropriate manner
3) does the job correctly
4) does not follow symbolic links
5) does not display the proper file type for every file
6) when accessing directories that are (in any way) protected
from casual reading, will output an error message
7) properly builds the path+filename before calling stat()
8) properly declares main() function and proper return
9) does not handle any options that are passed in.
10)does not seg fault
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
#include <string.h>
void search_dir(const char * arg);
int main(int argc, char *argv[])
{
int i;
char dirBuf[128] = {'\0'};
char * newline = NULL;
if (argc==1)
search_dir(".");
else
{
for(i=1;i<argc;i++)
{
newline = strcpy( dirBuf, argv[i] );
if( strstr( dirBuf, "\n") )
{
*newline = '\0';
}
search_dir(dirBuf);
}
}
return 0;
}
void search_dir(const char *arg)//Function to read directories and file attributes//
{
DIR *dirp;
struct dirent *dp;//Dirent structure used to read and store directory attributes//
char fileName[256];
char fileTime[50]={"\0"};
struct tm *timeinfo;
struct stat prop_file;//stat function for accessing file attributes//
char type;
printf( "%s\n", arg);
if( NULL == (dirp=opendir(arg)) )
{
perror("opendir failed");
return;
}
// implied else, opendir successful
printf("\n\nDirectory \tTime last Modified\tSize\t\t Name\n");
while( NULL != (dp=readdir(dirp)) ) // gets next entry in current directory,
{
strcpy(fileName, arg);
strcat(fileName, "/");
strcat(fileName, dp->d_name);
printf( "\nfileName: %s", fileName);
if ( stat(fileName,&prop_file) ) //Reading file attributes//
{
perror( "stat failed" );
printf("\n%s:Error in reading the file attributes", dp->d_name );
continue;
}
#ifdef _DIRENT_HAVE_D_OFF
// following if/else needs expansion
if ( dp->d_type==8 )
{
type = '-';
}
else
{
type = 'd';
}
#else
type = '?';
#endif
timeinfo=localtime(&(prop_file.st_mtime));
strftime(fileTime, 49, "%b %d %H:%M", timeinfo);
printf("\n %c\t\t %s\t\t%d\t\t %s",
type,
fileTime,
(int)prop_file.st_size,
dp->d_name); //Printing file attributes//
}
printf("\n");
closedir( dirp );
}
I am trying to create a function that will open a file for reading. Below is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
//char* readRecord(char individual);
void openfile(FILE peoplefile);
int main (int argc, char *argv[])
{
char *lname = (char *)malloc(25*sizeof(char));
if (argc < 2)
{
printf("\n\nUsage: %s <name>\n\n", argv[0]);
exit (-1);
}
else
{
strcpy(lname, argv[1]); //copies the last name from the command line int \
variable lname
printf("Your last name is %s\n",lname);
}
FILE *peoplefile;
openfile(peoplefile);
while(!feof(peoplefile))
{
printf("Hi\n");
}
return 0;
}
void openfile(FILE peoplefile)
{
peoplefile = fopen("./people.dat", "r");
if(peoplefile == NULL)
{
printf("Error opening people.dat file\n\n");
}
}
These are the errors I get when I compile my code:
prog1.c: In function `int main(int, char**)':
prog1.c:34: error: expected primary-expression before "peoplefile"
prog1.c: In function `void openfile(FILE)':
prog1.c:47: error: no match for 'operator=' in 'peoplefile = fopen(((const char*)"./people.dat"), ((const char*)"r"))'
/usr/include/stdio_impl.h:30: note: candidates are: __FILE& __FILE::operator=(const __FILE&)
prog1.c:48: error: no match for 'operator==' in 'peoplefile == 0'
Instead of
openfile(peoplefile);
I'd use
peoplefile = fopen("filename", "r")
Replace "filename" with whatever file name you're trying to open for read.
void openfile(FILE peoplefile)
{
peoplefile = fopen("./people.dat", "r");
That is wrong. fopen returns a pointer to FILE, i.e., a FILE*. If you need to set the argument for the caller then you will need to add another level of indirection as arguments are passed by value (copy) in C, so...
int openfile(FILE **peoplefile)
{
if (!peoplefile) return 1;
*peoplefile = fopen(...);
/* ... */
}
I would prefer a function which simply returned a FILE*, and then your whole openfile function is meaningless; just call fopen directly, no need to wrap it. In main, just use:
peoplefile = fopen("./people.dat", "r");
if (!peoplefile) {
print_some_error();
return 1;
}
Your code also contains an error; if you fail to open the file, you print an error message, but continue to use the file handle anyway!
You can also change
//char* readRecord(char individual);
void openfile(FILE peoplefile);
to
//char* readRecord(char individual);
void openfile(FILE *peoplefile);
and implement as following
void openfile(FILE *peoplefile)
{
peoplefile = fopen("./people.dat", "r");
if(peoplefile == NULL)
{
printf("Error opening people.dat file\n\n");
}
}
I've never had so much trouble writing data to files! I'm running GCC from MinGW, because I'm used to using GCC in Linux. I usually use the Linux system calls open(), write(), and read(), but I'm writing a Windows program now and I had trouble using read()/write() in Windows, so I'm just using the standard libraries. Anyway, the problem I'm having is I have no idea how to write to a file! I've defined "FILE *" variables, used fopen(), with "r+b", "wb", and "w+b", but I still cannot write to my output file with fwrite() or fprintf(). I don't know what I'm even doing wrong! Here's my source:
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#define DEBUG 1
/*** Global functions ***/
double highfreq(double deg);
/*** Global variables ***/
double sin_now;
unsigned int *ptr;
unsigned char *key, *infilename, *outfilename;
FILE *infile, *outfile, *keyfile;
const char *pipe_name="[pipe]";
int main(int argc, char *argv[]) {
unsigned int x, y, z;
if(argc!=3) {
fprintf(stderr, "Syntax error: %s <infile.txt> <outfile.wav>", argv[0]);
return 1;
}
if(argv[1][0]=='-') {
infile=stdin;
infilename=(unsigned char *)pipe_name;
}
else {
infilename=argv[1];
if((infile=fopen(infilename, "rb"))==NULL) {
fprintf(stderr, "Could not open input file for modulation.\n", infile);
return 2;
}
}
if(argv[2][0]=='-') {
outfile=stdout;
outfilename=(unsigned char *)pipe_name;
}
else {
outfilename=argv[2];
if((infile=fopen(outfilename, "wb"))==NULL) {
fprintf(stderr, "Could not open/create output file for modulation.\n", outfile);
return 3;
}
}
if(DEBUG) printf("Input file:\t%s\nOutput file:\t%s\n", infilename, outfilename);
fprintf(outfile, "Why won't this work!?\n");
fclose(infile);
fclose(outfile);
return 0;
}
double highfreq(double deg) {
double conv, rad;
conv=M_PI/180;
rad=deg*conv;
return sin(rad);
}
I'm eventually going to make a WAV file as output, hence the "highfreq()" function, but for now I can't even get it to write to a file! fprintf() returns with an error value of -1, if that helps anyone. I don't really understand, though because from what I read, this simply indicates there was an error, but nothing more.
outfilename=argv[2];
if((infile=fopen(outfilename, "wb"))==NULL) {
That's the second time in your code you assign the result of fopen to infile. You probably wanted outfile there.