SIGSEGV segmentation fault with regards to the pwd.c file? - c

#include <unistd.h>
#include <pwd.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
uid_t userIdFromName(char *name)
{
struct passwd* pwd;
pwd=getpwnam(name);
if(pwd==NULL)
{
perror("gepwnam\n");
exit(EXIT_FAILURE);
}
return pwd->pw_uid;
}
int main(int argc, char* argv[])
{
uid_t uid;
int totalEntries=0;
DIR* dir;
struct dirent* newFile;
char strUID[65];
if(argc<1)
{
fprintf(stderr,"The format is: %s name",argv[0]);
exit(EXIT_FAILURE);
}
uid=userIdFromName(argv[1]);
dir=opendir("/proc/");
sprintf(strUID,"%d",uid);
while((readdir(dir))!=NULL)
{
totalEntries++;
}
char* dirNames[1000];
char* dirIds[1000];
int newCount=0;
dir=opendir("/proc/");
while((newFile=readdir(dir))!=NULL)
{
char statusFilePath[65]="/proc/";
strcat(statusFilePath,newFile->d_name);
strcat(statusFilePath,"/status");
FILE* statusFile=fopen(statusFilePath,"r");//one of the file has been opened;
size_t size;
char* lineData;
if(statusFile==NULL)
continue;
int currentPoisition=0;
while((getline(&lineData,&size,statusFile))!=-1)
{
if(strncmp("Uid:",lineData,strlen("Uid:"))==0)
{
char* dataLine;
currentPoisition=ftell(statusFile);
fseek(statusFile,0,SEEK_SET);
if(strstr(lineData,strUID)!=NULL)
{
int forName=0,forPid=0;
while((getline(&dataLine,&size,statusFile))!=-1)
{
if(strncmp("Name:",dataLine,strlen("Name:"))==0)
{
printf("%s\n",dataLine);
dirNames[newCount]=dataLine;
forName=1;
}
if(strncmp("Pid:",dataLine,strlen("Pid:"))==0)
{
printf("%s\n",dataLine);
dirIds[newCount]=dataLine;
forPid=1;
}
if(forName==1&&forPid==1)
{
newCount++;
}
}
}
fseek(statusFile,0,SEEK_SET);
fseek(statusFile,currentPoisition,SEEK_SET);
}
}
}
/* int runner=0;
while(runner<newCount)
printf("%s\n",dirNames[runner++]);*/
}
I have been unable to understand the core-dumps generated for this program.The program crashes halfway. Here is the core-dump info:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007f4ed8699d9c in _nss_files_getpwnam_r (name=0x0, result=0x7f4ed8896140 , buffer=0x559f75c7e2a0 "root", buflen=1024, errnop=0x7f4ed889a4c0) at nss_files/files-pwd.c:32
32 nss_files/files-pwd.c: No such file or directory.
I thank you for your help.

Have you qualified the contents of argv[1] before using it here?
uid=userIdFromName(argv[1]);
Also, among other issues, using a variable created as:
char* lineData;
in a function such as:
while((getline(&lineData,&size,statusFile))!=-1)
Will likely cause a seg-fault, as you are attempting to write to a location that you do not own.
Same for:
char *dataLine;
...
while((getline(&dataLine,&size,statusFile))!=-1)
etc.
Create memory and an address for these (and any other like them) before using.
eg:
size_t size = 1000;
char *lineData = malloc(size*(sizeof(*lineData));
if(lineDate)
{
//continue to use lineData
free(lineData);//when done using it
...

Related

Segmentation fault in recursive function, while parsing directories

I am trying to make a program that returns the total size of a directory. The program takes the path to the directory, parses it, if it finds a file(done using a function) it adds the size, else
I recall the function. After some debugging i found out that the line containing the call to the recursive function give a segmentation fault and i have absolutely no idea how to fix it.
my code
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
int isDirectory(const char* fileName) {
DIR* dir=opendir(fileName);
if(dir!=NULL) {
closedir(dir);
return 1;
} else if(errno == ENOTDIR) {
return 0;
} else return -1;
closedir(dir);
}
int getFileSize(char* fileName) {
FILE* file;
file=fopen(fileName,"r");
fseek(file,0,SEEK_END);
int size=ftell(file);
fclose(file);
return size;
}
int getAllSize(char* dirName) {
DIR* dir;
char* name=dirName;
int size=0;
struct dirent *dent;
dir=opendir(dirName);
if(dir!=NULL) {
while((dent=readdir(dir))!=NULL) {
char help[1000000];
memset(help,0,sizeof help);
if(strcmp(dent->d_name,"..") && strcmp(dent->d_name,".")) {
strcat(help,name);
strcat(help,"/");
strcat(help,dent->d_name);
printf("%s\n",help);
if(isDirectory(help)==1) {
getAllSize(name);
} else{
printf("before %d\n",size);
size+=getFileSize(help);
printf("after %d\n",size);
}
}
}
} else {
printf("sal1\n");
}
closedir(dir);
printf("%d",size);
return size;
}
int main(int argc,char** argv) {
getAllSize("/home/rares/Documents/OS/Lab3");
return 0;
}

splitting files in C- Segmentation fault

I'm new to the subject of splitting files and header files in C.
I get a Segmentation fault (core dumped) when i'm trying to run main. I don't get any more errors.
I tried to trace the problam and I think it is the line:
syntax_check(fp, symb_table, &IC, &DC); in the main.c.
I'm just trying to pass from main.c the parameters *fp and another array strcture(symbol[]) to a function in syntax_check(in syntax_check.c) and do some actions.
main.c:
#include "main.h"
int main()
{
FILE *fp;
int DC=0;
int IC=100;
symbol symb_table[20];
if (!(fp=fopen("file.txt", "r")))
{
printf("Error opening file");
exit(0);
}
syntax_check(fp, symb_table, &IC, &DC);
fclose(fp);
return 0;
}
main.h:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
char name[10];
int address;
int external;
int action;
} symbol;
int syntax_check(FILE*, symbol[], int*, int*);
syntax_check.c:
#include "syntax_check.h"
int syntax_check(FILE *fp, symbol symb_table[], int *IC, int *DC)
{
char buff[80]; /*line to read*/
char buff2[20]; /**/
int i=0;
fgets (buff, 80, fp);
while (buff[i]!='\0'||buff[i]!=' '||buff[i]!='\t')
{
buff2[i]=buff[i];
i++;
}
buff[i]='\0';
if (exist(buff2))
printf("legal");
else
printf("illegal");
return 0;
}
syntax_check.h:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
char name[10];
int address;
int external;
int action;
} symbol;
FILE *fp;
int exist(char action[]);

parsing a string into tokens without strtok/lexer

I want to parse a string into an array of tokens . '\n' and ';' are delimiters , for e.g. :
hello;hello
world
should be converted to an array containing: {"hello","hello","world"}.
I tried many different methods for doing this and always I fail (since it needs a dynamic array of char * I have trouble with implementing it).
Please note that I cannot use strtok or lexical analyzer.
How may I do this ? Any points ?
EDIT : here is one of methods I tried to use but I get segmentation fault (maybe a memory access issue somewhere in my code) :
#include <stdio.h>
#include <malloc.h>
#include <fcntl.h>
#include <string.h>
typedef struct {
int fd;
char *path;
int size;
char *mem;
struct stat st;
} file;
file *readfile(char *path) {
file *a=malloc(sizeof(file));
a->path=path;
a->fd=open(a->path,O_RDONLY);
if(a->fd<0) return 0;
fstat(a->fd,&a->st);
a->size=a->st.st_size;
a->mem=malloc(a->size);
read(a->fd,a->mem,a->size);
return a;
}
void releasefile(file *a) {
free(a->mem);
close(a->fd);
free(a);
}
char **parse(int *w,file *a) {
int i,j=0;
w=0;
for(i=0;i<=a->size;i++) {
if(a->mem[i]=='\n' || a->mem[i]==';') { a->mem[i]='\0'; j++; }
}
char **out=malloc(sizeof(char *)*j);
for(i=0;i<=a->size;i++) {
if(a->mem[i-1]!='\0') continue;
out[*w]=malloc(strlen(a->mem+i)+1);
memcpy(out[*w],a->mem+i,strlen(a->mem+i)+1);
w++;
return out;
}
int main(int argc,char **argv) {
file *a=readfile(argv[1]);
int *w=malloc(sizeof(int));
char **tokens=parse(w,a);
int i;
for(i=0;i<=*w;i++) {
puts(tokens[i]);
}
releasefile(a);
// ATM no need to check for mem leaks :)
}
Algorithm description : read file, put \0 where you see a delimiter, start and push tokens seprated by \0 into an array.
What has happened to computer science?
Anyway write a FSA - http://en.wikipedia.org/wiki/Finite-state_machine
Can do this using a table

Want to create a file with write mode in C

I am new in C. I want to create a file in linux C program and write environment variables in it. If file already exist I want to open and append. I have written the following code.
char *envFile=getenv("FILENAME");
int fdEnv=-1;
fdEnv=open(envFile,O_CREAT,O_RDWR,O_APPEND);
printf("%d",fdEnv);
char** env;
if(fdEnv>0)
{
for (env = environ; *env != 0; env++)
{
char *thisEnv = *env;
printf("%s",thisEnv);
write(fdEnv,thisEnv,strlen(thisEnv));
}
close(fdEnv);
}
But when I run it first time. A blank file is created. And it stays locked after execution. Looks like some error. Second time it fdEnv stays less than 0.
I really don't understand what is happening here. Please help.
Try using | to separate the flags.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
extern char **environ;
int main(void)
{
char *envFile = getenv("FILENAME");
int fdEnv = -1;
fdEnv = open(envFile, O_CREAT|O_RDWR|O_APPEND, 0644);
printf("%d\n", fdEnv);
int i = 0;
while (environ[i]) {
printf("%s\n", environ[i]);
write(fdEnv, environ[i], strlen(environ[i]));
char lf = '\n';
write(fdEnv, &lf, 1);
i++;
}
close(fdEnv);
return 0;
}
I've run above code on my linux computer and it works.
extern char **environ;
int main()
{
char **env;
char* filename = getenv("FILENAME")
const char* mode = "a";
FILE* file = fopen( filename, mode );
for ( env = environ; *env; ++env )
fprintf( file, "%s\n", *env );
fclose(file);
return(0);
}
You should think about handling when getenv fails, is blank, etc; let me know if you have any questions.

Wrong result when copying an array of strings

I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* user;
char* passwd;
int nr;
void test()
{
int i=0;
for(i=0;i<argc;i++)
printf("Hello %s \n",user);
}
int main(int argc,char*argv[])
{
int i;
nr=argc;
for (i=0; i<argc; i++)
{
user=strdup(argv[i]);
}
test();
return 0;
}
The result is the argv[argc] on all the positions. How can I fix this? I wwant to have that test() outside the loop.
**
EDIT
**
After the ANSWERS here this is my new code, which is not working. Can anyone say why?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* user;
void test(int n)
{
int i=0;
for(i=0;i<n;i++)
printf("%s \n",user[i]);
}
int main(int argc,char*argv[])
{
user = (char*) malloc(argc*sizeof(char));
int i;
for (i=0;i<argc;i++)
{
user[i]=argv[i];
}
test(argc);
return 0;
}
You are assigning to both password and user at each iteration of the for loop. The final values you see are from the last iteration. Also, there is memory leak due to overwriting the pointers from previous strdup calls. In fact, you do not need a loop:
int main(int argc,char*argv[])
{
if(argc == 3) {
user=strdup(argv[1]);
passwd=strdup(argv[2]);
} else {
// error: usage
}
test();
return 0;
}
If you want to have multiple user/password combinations:
char *user[256], *passwd[256];
void test(int n) {
int i;
for(i=0;i<n;i++)
printf("Hello %s \n",user[i]);
}
int main(int argc,char*argv[])
{
int i;
for(i = 0; i < argc && i < 256; i+=2) {
user[i]=strdup(argv[i]);
passwd[i]=strdup(argv[i+1]);
}
test(argc);
return 0;
}
Because you overwrite the pointers user and passwd in every iteration. Hence, you'll only see the last string.
If you can tell your aim of the program, a better answer can be provided. Because I am not sure whether you want to read one user and passwd Or an array of users and passwds.
After you edit, I see you want to read an array of strings:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** user;
// or char *user[100]; /* If you want a fix length array of pointers. Now, you dont have to malloc. /*
char* passwd;
int nr;
void test(int argc)
{
int i=0;
for(i=0;i<argc;i++)
printf("Hello %s \n",user[i]);
}
int main(int argc,char*argv[])
{
int i;
nr=argc;
user = malloc(argc*sizeof(char*));
for (i=0; i<argc; i++)
{
user[i]=strdup(argv[i]);
}
test(argc);
return 0;
}
Of course; in test() you don't use i other than a loop variable and in main() you keep overwriting the previous value of user and passwd. In effect, what you do is:
user = strdup(argv[0]); /* Note: argv[0] is the program name. */
passwd = strdup(argv[0]);
user = strdup(argv[1]);
passwd = strdup(argv[1]);
user = strdup(argv[2]);
passwd = strdup(argv[2]);
user = strdup(argv[3]);
passwd = strdup(argv[3]);
printf("%s %s \n", user, passwd);
With this information, can you fix your program?
$ cat trash.c
#include <stdio.h>
#include <string.h>
void test(FILE* stream, char* usr, char* pass) {
fprintf( stream, "%s#%s\n", usr, pass);
}
int main(int argc, char** argv) {
int i = 1;
if (argc % 2) {
while(argv[i]) {
test(stdout, argv[i], argv[i + 1]);
i += 2;
}
}
return 0;
}
$ clang trash.c
$ ./a.out user1 pass1 user2 pass2
user1#pass1
user2#pass2
$
also if you call strdup() don't forget to free memory, because strdup called malloc().

Resources