Number of processes with same name in Linux [c] - c

I have problem with achieving int output of numbers of running processes with same PID.
Eg.
ps aux | grep program1
shows me 3 process, 2 of my main app (parent and child). I wanna know how to get it in C. my point is to get like number "2" because i have two processes with same name. As far as i know i cannot get terminal output to C variable so I really dont have idea how to get it.The problem is that I must get this information on progmam2 not program1.
Thanks!

Check this out, I think this is not advanced at all
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>
#include <fcntl.h>
void readProcessName(const char *const comm, char name[PATH_MAX])
{
int fd;
int size;
fd = open(comm, O_RDONLY);
if (fd == -1)
return;
if ((size = read(fd, name, PATH_MAX)) > 1)
name[size - 1] = '\0';
else
name[0] = '\0';
close(fd);
}
void findProcessByName(const char *const find)
{
DIR *dir;
struct dirent *entry;
dir = opendir("/proc");
if (dir == NULL)
return;
chdir("/proc");
while ((entry = readdir(dir)) != NULL)
{
struct stat st;
char comm[PATH_MAX];
const char *name;
char procname[PATH_MAX];
name = entry->d_name;
if (stat(name, &st) == -1)
continue;
if (S_ISDIR(st.st_mode) == 0)
continue;
/* this will skip .. too, and any hidden file? there are no hidden files I think */
if (name[0] == '.')
continue;
snprintf(comm, sizeof(comm), "%s/comm", name);
if (stat(comm, &st) == -1)
continue;
readProcessName(comm, procname);
if (strcmp(procname, find) == 0)
printf("%s pid: %s\n", procname, name);
}
closedir(dir);
}
int main(int argc, char **argv)
{
findProcessByName("process-name-here");
return 0;
}

Related

How to give filenames to a parent procces using FIFO(in C)?

I have 2 processes, one reads from the input a filename, this filename is then given to the child process.The child process determinates in which directories the given file exits and the child procces gives all the directory names back to the parent who then prints these directory names.I need to do this using FIFO(named pipes).I got stuck at the part where the child prcess gives the parent the directory names.Could someone please help?
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
#include <dirent.h>
extern int errno;
#define FIFO "/tmp/fifo0002.1"
//searches for the direrctories
void listdir( const char *dir, const char *filename)
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;
char *subdir;
if((dp = opendir(dir)) == NULL)
{
fprintf(stderr,"cannot open directory: %s\n", dir);
return;
}
while((entry = readdir(dp)) != NULL)
{
if(lstat(entry->d_name, &statbuf) == 0)
{
if(statbuf.st_mode & S_IFDIR)
{
/* Found a directory, but ignore . and .. */
if(strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0)
continue;
// allocate space for parent directory, "/", subdir, plus NULL terminator
subdir = malloc(strlen(dir) + strlen(entry->d_name) + 2);
// Concatenate directory name
strcpy(subdir, dir);
strcat(subdir, "/");
strcat(subdir, entry->d_name);
/* Recurse at a new indent level */
listdir(subdir,filename);
free(subdir);
}
else
{
if(statbuf.st_mode & S_IFREG ){
if (strcmp(entry->d_name,filename)==0){
printf("%s\n",dir);}}
}
}
}
closedir(dp);
}
int main (void)
{ int r_fifo, w_fifo, r1_fifo, w1_fifo;
char filename[100];
printf("enter filename:");
scanf("%s",filename);
char buf[100];
char buf2[100];
pid_t pid;
if ((mkfifo (FIFO, S_IRUSR | S_IWUSR)) == -1) {
/* FIFO exists */
if(errno == EEXIST)
perror ("mkfifo()");
else {
perror("mkfifo()");
exit (EXIT_FAILURE);
} }
pid = fork ();
if (pid == -1)
{ perror ("fork()");
exit (EXIT_FAILURE);
}
else if (pid > 0) {
/*parent procces */
if ((r_fifo = open (FIFO, O_RDONLY)) < 0) {
perror ("open()");
exit (EXIT_FAILURE); }
write (w_fifo, filename, strlen (filename));
/*wait for child */
while (wait (NULL) != pid);
/*read from FIFO -> the directory names
read (r_fifo, buf, strlen (filename));
buf2[strlen(buf2)] = '\0';
printf(" directories:\n %s\n",buf2);*/
}
else {
/*child procces */
if ((w_fifo = open (FIFO, O_WRONLY)) < 0) {
perror ("open()");
exit (EXIT_FAILURE); }
/*Read from FIFO filename */
read (r_fifo, buf, strlen (buf));
buf[strlen(filename)] = '\0';
//printf("%s\n",buf);
listdir("/home/folder1",filename);
//close (w_fifo); /* EOF */
exit (EXIT_SUCCESS); }
return EXIT_SUCCESS;}
The parent process opens the pipe for reading and stores the descriptor in r_fifo. Then it immediately tries to write to the pipe, using the uninitialized w_fifo descriptor.
The child process does the opposite, open the pipe for writing (assigning to w_fifo) then attempts to read using the uninitialized r_fifo variable.
The parent process should open the pipe for writing, and the child process should open for reading. And both needs to use the correct and initialized variables.
There are also many other problems, like you using the strlen function on uninitialized arrays, which will not get the size of the arrays. And in the client you read into buf but use strlen(filename) to set the terminator. And you never initialize filename At all and still pass it to the listdir function.
And you really need to check what read and write returns.

How to use execvp() to execute a command

So I'm trying to create a custom shell for my school project. My method was to create child process, and have that process execute the command using the execvp() function that my professor briefly mentioned in class that we are meant to use. Here's my code, as always, any help is appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#define MAX_LINE 80
int main(int argc, char *argv[])
{
char *input = (char*)malloc(MAX_LINE*sizeof(char));
int should_run = 1;
while(should_run){
printf("osh>");
fflush(stdout);
pid_t pid;
pid = fork();
if(pid < 0){
printf("error with creating chiled process");
return 0;
}
if(pid == 0){
fgets(input, MAX_LINE, stdin);
char *token = strtok(input," ");
if(execvp(token[0], token) < 0){
printf("Error in execution.");
return(0);
}
//should_run = 0;
}
waitpid(pid, 1, 0);
}
return 0;
}
The prototype of execvp is
int execvp(const char *file, char *const argv[]);
It expects a pointer to char as the first argument, and a NULL-terminated
pointer to an array of char*. You are passing completely wrong arguments.
You are passing a single char as first argument and a char* as the second.
Use execlp instead:
int execlp(const char *file, const char *arg, ...
/* (char *) NULL */);
So
char *token = strtok(input," \n");
if(token == NULL)
{
fprintf(stderr, "only delimiters in line\n");
exit(1);
}
if(execlp(token, token, NULL) < 0){
fprintf(stderr, "Error in execution: %s\n", strerror(errno));
exit(1);
}
Also the convention in UNIX is to print error messages to stderr and a process with an error should
have an exit status other than 0.
As Pablo's states, you are passing the wrong arguments to execvp().
You can consider coding by yourself a function (char **strsplit(char *str, char delim)) which takes a string and split it into smaller pieces, returning an array of strings.
Also don't ignore compiler's warnings, they tell you a lot of things, and I suggest you to compile with gcc -Wall -Wextra -Werror to get almost any possible error in your program.
I tell you this because waitpid() takes as second argument a pointer to integer, to get an update of the status of the forked program. With this status you how the program exited (normally, segf, bus error...), you can use it to print an error if something went wrong.
You can consider using execv() instead (I know I'm going off topic, but you can learn useful things doing this), and find by yourself the correct executable(s).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#define MAX_LINE 255
char **strsplit(char *str, char delim);
char *strjoin(char const *s1, char const *s2);
int isexec(char *path)
{
struct stat buf;
lstat(path, &buf);
if (S_ISREG(buf.st_mode) && (S_IXUSR & buf.st_mode))
return (1);
return (0);
}
static char *find_exec_readdir(char *paths, char *cmd)
{
DIR *dir;
struct dirent *dirent;
char *exec;
exec = NULL;
if ((dir = opendir(paths)) != NULL)
{
while ((dirent = readdir(dir)) != NULL)
{
if (!strcmp(dirent->d_name, cmd))
{
exec = strdup(dirent->d_name);
break ;
}
}
if (closedir(dir))
dprintf(2, "Failed closing dir.\n");
}
return (exec);
}
char *find_exec(char *cmd, char **paths)
{
char *exec;
char *path;
char *tmp;
int i;
i = -1;
exec = NULL;
path = NULL;
if ((cmd[0] == '.' || cmd[0] == '/'))
{
if (isexec(cmd))
return (strdup(cmd));
return (NULL);
}
while (paths[++i])
if ((exec = find_exec_readdir(paths[i], cmd)) != NULL)
{
tmp = strjoin(paths[i], "/");
path = strjoin(tmp, exec);
free(tmp);
free(exec);
break ;
}
return (path);
}
int handle_return_status(int status)
{
int sig;
int i;
if (!WIFEXITED(status) && WIFSIGNALED(status))
{
sig = WTERMSIG(status);
i = -1;
while (++i <= 13)
{
if (print_signal_error(sig))
{
return (-1);
}
}
dprintf(2, "Process terminated with unknown signal: %d\n", sig, NULL);
return (-1);
}
return (0);
}
int main(int argc, char *argv[])
{
char *input = NULL;
char **command = NULL;
int should_run = 1;
int status = 0;
(void)argc;
(void)argv;
if ((input = (char*)malloc(MAX_LINE*sizeof(char))) == NULL)
return (dprintf(2, "Failed to malloc, abort.\n"));
while(should_run){
printf("osh> ");
fflush(stdout);
pid_t pid;
pid = fork();
if(pid < 0)
return (dprintf(2, "error with creating chiled process\n"));
if(pid == 0){
fgets(input, MAX_LINE, stdin);
command = strsplit(input, ' ');
command[0] = find_exec(command[0], strsplit(getenv("PATH"), ':'));
if(execv(command[0], &command[1]) < 0)
return (dprintf(2, "Error in execution.\n"));
//should_run = 0;
}
waitpid(pid, &status, 0);
handle_ret_status(status);
}
return 0;
}

How to print out process name if i know the pid using c? [duplicate]

Hello!
I wanto to make simple c proggram what will work like ps -e. The only colums that should be shown are PID and CMD. Thats my code:
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
#include <stdio.h>
#include <regex.h>
int main()
{
DIR *dir;
struct dirent *entry;
if ((dir = opendir("/proc")) == NULL)
perror("operation error");
else
{
printf("PID CMD\n");
while ((entry = readdir(dir)) != NULL)
printf(" %s\n", entry->d_name);
closedir(dir);
}
return 0;
}
My questins are:
1) How i can show only folders with numbers(i don't know how to implement regcomp())?
2)How to near PID write CMD (I can't glue(?) strings with path if is folder with number)?
This is an hint ... Try to develop your code starting from this! :)
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
int readData(char *dirname);
int readData(char *dirname)
{
FILE * file;
char buffer[1024]={0};
sprintf(buffer,"/proc/%s/stat",dirname);
file = fopen(buffer,"r");
if (!file)
return errno;
while(fgets(buffer,sizeof(buffer),file))
puts(buffer);
if (file)
fclose(file);
return errno;
}
int main(void)
{
DIR * dir;
struct dirent * entry;
if ( (dir = opendir("/proc")) == NULL )
perror("operation error");
while ((entry = readdir(dir))) {
if ( strlen(entry->d_name) == strspn(entry->d_name, "0123456789"))
if (readData(entry->d_name))
break;
}
if (dir)
closedir(dir);
return errno;
}

Fork function doesnt execute child process code

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
int show_dir_content(char *path);
int show_dir_content(char *path)
{
char readbuffer[80];
char buffer[150];
char uzun[9999];
int totalfound = 0;
DIR *d = opendir(path);
if(d == NULL)
return -3;
struct dirent *dir;
int piper[2];
pid_t typer = 0;
while((dir = readdir(d)) != NULL)
{
pipe(piper);
typer = fork();
if(typer == 0)
{
close(piper[0]);
if(dir->d_type != DT_DIR)
{ // if the type is not directory blue
// printf("%s\n",dir->d_name);
sprintf(buffer, "%s", dir->d_name);
write(piper[1], buffer, (strlen(buffer) + 1));
}
else if(dir->d_type == DT_DIR && strcmp(dir->d_name, ".") != 0 &&
strcmp(dir->d_name, "..") != 0) // if it is a directory
{
char d_path[255]; // here I am using sprintf which is safer than
// strcat
sprintf(d_path, "%s/%s", path, dir->d_name);
show_dir_content(d_path); // recall with the new path
}
exit(0);
close(piper[1]);
}
else if(typer > 0)
{
close(piper[1]);
read(piper[0], readbuffer, sizeof(readbuffer));
// strcat(uzun,readbuffer);
// close(piper[0]);
break;
}
}
while(wait(NULL) > 0)
;
closedir(d);
// printf("%s x_x\n",uzun);
return totalfound + 1; // finally close the directory
}
int main(int argc, char **argv)
{
show_dir_content(argv[1]);
return (0);
}
It doesn't execute on forked child, only on parent and only once.
I use Linux Mint 18 and gcc comes with it.
i don't what causes it, it doesn't seems to be Segmentation fault because it exits correctly. I would be more then happy if anyone can see my errors here
I'm debugging on CLion.

C programming: How to get directory name?

I'm writing a code for printing out the path from root to current directory or referred directory, using recursive function. but I can't get the directory name, only get ..
Problem happened among base case and call
dirent->name.
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
static void list_dir (const char * dir_name)
{
DIR * d;
struct dirent *e;
struct stat sb;
struct stat sb2;
long childIno;
long parentIno;
char parent[200];
stat(dir_name, &sb);
if (stat(dir_name, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
childIno = (long) sb.st_ino;
/* get parent dir name */
snprintf(parent, sizeof(parent), "%s/..", dir_name);
d = opendir(parent);
stat(parent, &sb2);
if (stat(parent, &sb2) == -1) {
perror("stat2");
printf("parent name: \n");
exit(EXIT_FAILURE);
}
parentIno = (long) sb2.st_ino;
if (d == NULL) {
printf("Cannot open dircetory '%s'\n", parent);
}
/*below code is really messed up*/
if (childIno == parentIno) {
while ((e = readdir(d)) != NULL) {
printf("base case %s\n", e->d_name);
break;
}
}else{
list_dir(parent);
}
/*code above here is really messed up*/
/* After going through all the entries, close the directory. */
closedir (d);
}
int main (int argc, char** argv)
{
list_dir (argv[1]);
return 0;
}
right result should be when typing command line
./pathto .
should print out path from root directory to my current directory
or if command line as this
./pathto file.txt
should print out path from root directory to file.txt
Doing this using <dirent.h> and stat is possible, but really tricky. POSIX offers a function for this called realpath. Omitting error checking:
#include <limits.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char buf[PATH_MAX];
puts(realpath(argv[1], buf));
return 0;
}

Resources