Creating a simple shell in C causes linking error - c

I am creating a simple shell in C that can execute commands, do stdout redirects and piping. So far I got only the redirecting part done but for some reason when i try to compile collect2 throws an error.
The util.c file that I am including:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#include<errno.h>
#include"util.h"
void setSigHandler(){
void (*oldHandler)();
oldHandler = signal(SIGINT, SIG_IGN);
signal(SIGTERM, oldHandler);
}
void prompt(){
char* user = getlogin();
printf("[%s]-->$", user);
}
void getNextCommand(){
errno = 0;
cmd = malloc(sizeof *cmd);
if(cmd == NULL){
char* error = strerror(errno);
printf("malloc:%s\n", error);
exit(EXIT_FAILURE);
}
fgets(cmd->payload, sizeof(cmd->payload), stdin);
if(cmd->payload[strlen(cmd->payload) - 1] == '\n'){
cmd->payload[strlen(cmd->payload) - 1] = '\0';
}
}
void parseCommandString(){
cmd->payloadArgc = 0;
char* buffer = strtok(cmd->payload, " ");
while(buffer != NULL){
cmd->payloadArgv[cmd->payloadArgc] = buffer;
if(!strcmp(cmd->payloadArgv[cmd->payloadArgc], ">")){
cmd->payloadArgv[cmd->payloadArgc] = NULL;
fileName = strtok(NULL, " ");
break;
}
if(!strcmp(cmd->payloadArgv[cmd->payloadArgc], "|")){
cmd->payloadArgv[cmd->payloadArgc] = NULL;
pCount++;
break;
}
buffer = strtok(NULL, " ");
cmd->payloadArgc++;
}
}
And my main file :
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>
#include<signal.h>
#include<sys/file.h>
#include<fcntl.h>
#include"util.h"
int execCommand();
int main(){
setSigHandler();
while(1){
prompt();
getNextCommand();
//pdsh exits on "close"
if(!strcmp(cmd->payloadArgv[0], "close")) break;
parseCommandString();
}
return 0;
}
int execCommand()
{
errno = 0;
int newFd;
// Fork process
pid_t pid = fork();
// Error
if (pid == -1) {
char* error = strerror(errno);
printf("fork: %s\n", error);
return -1;
}
// Child process
else if (pid == 0) {
if(fileName != NULL){
newFd = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, 0755);
if(newFd == -1){
char* error = strerror(errno);
printf("open: %s\n", error);
return -2;
}
dup2(newFd, STDOUT_FILENO);
close(newFd);
}
// Execute command
execvp(cmd->payloadArgv[0], cmd->payloadArgv);
// Error occurred
char* error = strerror(errno);
printf("shell: %s: %s\n", cmd->payloadArgv[0], error);
return -2;
}
// Parent process
else {
close(newFd);
fileName = NULL;
// Wait for child process to finish
int childStatus;
waitpid(pid, &childStatus, 0);
return 0;
}
}
And the error from collect2:
/tmp/ccIXS72e.o:(.bss+0x0): multiple definition of `fileName'
/tmp/ccINCcwP.o:(.bss+0x0): first defined here
/tmp/ccIXS72e.o:(.data+0x0): multiple definition of `pCount'
/tmp/ccINCcwP.o:(.data+0x0): first defined here
/tmp/ccIXS72e.o:(.data+0x4): multiple definition of `newDescriptor'
/tmp/ccINCcwP.o:(.data+0x4): first defined here
collect2: error: ld returned 1 exit status
What is causing this?
I know my main.c code is a little ugly sorry for that.
Edit: The util.h as requested:
#ifndef UTIL_H_
#define UTIL_H_
#define TRUE 1
#define FALSE !TRUE
#define STDOUT 0
#define STDIN 1
#define MAX_CMD_LENGHT 500
#define MAX_CMD_ARGS_LENGHT 50
char* fileName = NULL;
int pCount = -1;
int newDescriptor = -1;
Command cmd;
typedef struct commandR* Command;
struct commandR{
char payload[MAX_CMD_LENGHT];
char* payloadArgv[MAX_CMD_ARGS_LENGHT];
int payloadArgc;
};
void setSigHandler();
void prompt();
void getNextCommand();
void parseCommand();
#endif
Edit 2: After a suggestion I have modified my code. Error still goes off.
util.h
#ifndef UTIL_H_
#define UTIL_H_
#define TRUE 1
#define FALSE !TRUE
#define STDOUT 0
#define STDIN 1
#define MAX_CMD_LENGHT 500
#define MAX_CMD_ARGS_LENGHT 50
extern int newDescriptor;
extern char* fileName;
extern int pCount;
typedef struct commandR* Command;
struct commandR{
char payload[MAX_CMD_LENGHT];
char* payloadArgv[MAX_CMD_ARGS_LENGHT];
int payloadArgc;
};
extern Command cmd;
void setSigHandler();
void prompt();
void getNextCommand();
void parseCommand();
#endif
util.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#include<errno.h>
#include"util.h"
char* fileName = NULL;
int pCount = -1;
int newDescriptor = -1;
Command cmd;
void setSigHandler(){
void (*oldHandler)();
oldHandler = signal(SIGINT, SIG_IGN);
signal(SIGTERM, oldHandler);
}
void prompt(){
char* user = getlogin();
printf("[%s]-->$", user);
}
void getNextCommand(){
errno = 0;
cmd = malloc(sizeof *cmd);
if(cmd == NULL){
char* error = strerror(errno);
printf("malloc:%s\n", error);
exit(EXIT_FAILURE);
}
fgets(cmd->payload, sizeof(cmd->payload), stdin);
if(cmd->payload[strlen(cmd->payload) - 1] == '\n'){
cmd->payload[strlen(cmd->payload) - 1] = '\0';
}
}
void parseCommandString(){
cmd->payloadArgc = 0;
char* buffer = strtok(cmd->payload, " ");
while(buffer != NULL){
cmd->payloadArgv[cmd->payloadArgc] = buffer;
if(!strcmp(cmd->payloadArgv[cmd->payloadArgc], ">")){
cmd->payloadArgv[cmd->payloadArgc] = NULL;
fileName = strtok(NULL, " ");
break;
}
if(!strcmp(cmd->payloadArgv[cmd->payloadArgc], "|")){
cmd->payloadArgv[cmd->payloadArgc] = NULL;
pCount++;
break;
}
buffer = strtok(NULL, " ");
cmd->payloadArgc++;
}
}

The problem is that you have variables defined in the header file. So when you compile each .c file, they both contain a copy of those variables. This causes the linker error of multiple definitions.
What you need to do is declare them in the header file with the extern keyword. That allows the variables to be used without being defined. Then you define them in exactly one .c file.
util.h:
extern char* fileName;
extern int pCount;
extern int newDescriptor;
extern Command cmd;
util.c:
char* fileName = NULL;
int pCount = -1;
int newDescriptor = -1;
Command cmd;
Also note that the variables are initialized where they are defined, not where they are declared.
EDIT:
It looks like the problem is how you're compiling. You need to compile main.c and util.c to object files, then link the resulting object files:
gcc -Wall -Wextra -g -c main.c
gcc -Wall -Wextra -g -c util.c
gcc -Wall -Wextra -g -o main main.o util.o
Also, you need to put the declaration of parseCommandString into util.h, and you need to include sys/types.h and sys/wait.h in main.c for waitpid.

Related

ebpf program function is not triggering prints nothing in simple program hook for kprobe function that exists in proc/kallsyms file

So I have this function in my driver for network NIC and this function appears in proc/kallsyms[https://stackoverflow.com/a/67766463/4808760] file with base address this is the function
static int rtl8169_poll(struct napi_struct *napi, int budget)
{
struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
struct net_device *dev = tp->dev;
int work_done;
rtl_tx(dev, tp, budget);
work_done = rtl_rx(dev, tp, budget);
if (work_done < budget && napi_complete_done(napi, work_done))
rtl_irq_enable(tp);
return work_done;
}
appears as
ffffffffc02d2210 t rtl8169_poll [r8169]
and this is my ebpf program
SEC("kprobe/rtl8169_poll")
int bpf_prog2(struct pt_regs *ctx)
{
int sc_nr = (int)PT_REGS_PARM1(ctx);
char *fmt="HELLO from FWDALI %d %d";
bpf_trace_printk(fmt,1,sc_nr);
bpf_trace_printk(fmt ,2,sc_nr);
/* dispatch into next BPF program depending on syscall number */
//bpf_tail_call(ctx, &progs, sc_nr);
/* fall through -> unknown syscall */
//if (sc_nr >= __NR_getuid && sc_nr <= __NR_getsid) {
// char fmt[] = "-----FWD-------------------------syscall=%d (one of get/set uid/pid/gid)\n";
// bpf_trace_printk(fmt, sizeof(fmt), sc_nr);
//}
return 0;
}
And this is my simple userspace code
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <sys/prctl.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <sys/resource.h>
#include <fcntl.h>
#ifdef __mips__
#define MAX_ENTRIES 6000 /* MIPS n64 syscalls start at 5000 */
#else
#define MAX_ENTRIES 1024
#endif
/* install fake seccomp program to enable seccomp code path inside the kernel,
* so that our kprobe attached to seccomp_phase1() can be triggered
*/
void read_trace_pipe(void)
{
int trace_fd;
//printf("-%s-\n",DEBUGFS);
trace_fd = open( "/sys/kernel/debug/tracing/trace_pipe", O_RDONLY, 0);
if (trace_fd < 0)
return;
while (1) {
static char buf[4096];
ssize_t sz;
sz = read(trace_fd, buf, sizeof(buf) - 1);
if (sz > 0) {
buf[sz] = 0;
puts(buf);
}
}
}
static void install_accept_all_seccomp(void)
{
struct sock_filter filter[] = {
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
};
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
.filter = filter,
};
if (prctl(PR_SET_SECCOMP, 2, &prog))
perror("prctl");
}
int main(int ac, char **argv)
{
struct bpf_link *link = NULL;
struct bpf_program *prog;
struct bpf_object *obj;
int key, fd, progs_fd;
const char *section;
char filename[256];
FILE *f;
snprintf(filename, sizeof(filename), "%s_kern.o", argv[1]);
obj = bpf_object__open_file(filename, NULL);
if (libbpf_get_error(obj)) {
fprintf(stderr, "ERROR: opening BPF object file failed\n");
return 0;
}
prog = bpf_object__find_program_by_name(obj, "bpf_prog2");
if (!prog) {
printf("finding a prog in obj file failed\n");
goto cleanup;
}
/* load BPF program */
if (bpf_object__load(obj)) {
fprintf(stderr, "ERROR: loading BPF object file failed\n");
goto cleanup;
}
link = bpf_program__attach(prog);
if (libbpf_get_error(link)) {
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
link = NULL;
goto cleanup;
}
progs_fd = bpf_object__find_map_fd_by_name(obj, "progs");
if (progs_fd < 0) {
fprintf(stderr, "ERROR: finding a map in obj file failed\n");
goto cleanup;
}
bpf_object__for_each_program(prog, obj) {
section = bpf_program__section_name(prog);
/* register only syscalls to PROG_ARRAY */
if (sscanf(section, "kprobe/%d", &key) != 1)
continue;
fd = bpf_program__fd(prog);
bpf_map_update_elem(progs_fd, &key, &fd, BPF_ANY);
}
install_accept_all_seccomp();
f = popen("dd if=/dev/zero of=/dev/null count=5", "r");
(void) f;
read_trace_pipe();
cleanup:
bpf_link__destroy(link);
bpf_object__close(obj);
return 0;
}
SO i like if some take a look at above and explain what exactly I need to add to my ebpf program for kprobe and also what I need to do in my userspace loader program..
I am still having tough time with getting to loads of stuff that tells its simple to implement to use this magical line SEC("kprobe/rtl8169_poll") or something with just loading the program from userspace and its done, But I havent started thinking much of ebpf since ebpf is kind of failed in this simple function hook
this link gave me the idea that I can hook to this function https://stackoverflow.com/a/67766463/4808760

not able to cat trough system call

I am trying to cat some file into another new files, but to my surprise its not working.
Able to do the same if i execute the same command on terminal, but through system call, it not working.
I just need a new set of eyes to look and point out the problem please
#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#define COMMON_COMMAND "cd %s;cat %s >> %s"
#define RPATH "/home/spark/R/"
#define R_CERTIFICATE_NOT_FOUND 2
#define RESULT_NOT_FOUND_FILE 5
#define DIR_CERTIFICATE_NOT_FOUND 6
#define RESULT_SUCCESS 0
#define BUFFER_SIZE 1000
/*Final file*/
#define COMMON_FILE "common_file_"
static int prepare_FinFiles(const char *rpath,char *common_file);
static int ReadFiles(const char *path,char *common_file);
int main()
{
char Finfile[BUFFER_SIZE] = {0};
char cmd[50] = {0};
struct timeval t1;
gettimeofday(&t1, NULL);
srand(t1.tv_usec);
prepare_FinFiles(RPATH,Finfile);
strcpy(cmd,"cat ");
strcat(cmd,Finfile);
printf(" cmd output ==> \n");
system(cmd);
return 0;
}
static int prepare_FinFiles(const char *rpath,char *common_file)
{
char command[BUFFER_SIZE] = {0};
char temp_files[BUFFER_SIZE] = {0};
int32_t count_no_files = 0;
char cmd[BUFFER_SIZE] = {0};
sprintf(common_file, "%s%d%s", "/home/spark/"COMMON_FILE,random(),".txt");
strcpy(cmd,"touch ");
strcat(cmd, common_file);
system(cmd);
if( ReadFiles(rpath,common_file) == RESULT_NOT_FOUND_FILE)
{
return R_CERTIFICATE_NOT_FOUND;
}
else if(retVal == DIR_CERTIFICATE_NOT_FOUND)
{
printf("dir not found\n");
return DIR_CERTIFICATE_NOT_FOUND;
}
else
{
printf("R read success\n");
char Finfile[BUFFER_SIZE] = {0};
char cmd[50] = {0};
strcpy(cmd,"cat ");
strcat(cmd,common_file);
printf("cmd : %s\n",cmd);
printf("The return value is: %d\n", WEXITSTATUS(system(cmd)));
}
}
static int32_t ReadFiles(const char *path,char *common_file)
{
DIR *dir = opendir(path);
struct dirent *dp;
char command[BUFFER_SIZE] = {0};
char temp_files[BUFFER_SIZE] = {0};
int count_no_files =0;
printf("Reading from %s path\n", path);
if(!dir)
{
return DIR_CERTIFICATE_NOT_FOUND;
}
else
{
while ((dp = readdir(dir)) != NULL)
{
if( strncmp(dp->d_name,".",strlen(".")) &&
strncmp(dp->d_name,"..",strlen(".."))
)
{
strncat(temp_files,dp->d_name,strlen(dp->d_name));
strncat(temp_files," ",strlen(" "));
count_no_files++;
}
}
if(count_no_files == 0)
{
return RESULT_NOT_FOUND_FILE;
}
else
{
memset(command,0,sizeof(command));
sprintf(command, COMMON_COMMAND, path,temp_files,common_file);
printf("command = %s\n", command);
return RESULT_SUCCESS;
}
}
}
output
Reading from /home/spark/R/ path
command = cd /home/spark/R/;cat file1.txt >> /home/spark/R/common_file_931058571.txt
R read success
cmd : cat /home/spark/R/common_file_931058571.txt
The return value is: 0
but through system call, it not working
Because you do not call system at all.
Your code contains 3 calls to system:
// in main
system(cmd); // cmd contains "cat /home/spark/common_file_<random>.txt"
// in prepare_FinFile
system(cmd); // cmd contains "touch /home/spark/common_file_<random>.txt"
...
printf("cmd : %s\n",cmd);
printf("The return value is: %d\n", WEXITSTATUS(system(cmd)));
// cmd contains "cat /home/spark/R/common_file_931058571.txt"
The command in question would be this:
printf("command = %s\n", command);
// command contains "cd /home/spark/R/;cat file1.txt >> /home/spark/R/common_file_931058571.txt"
return RESULT_SUCCESS;
But you never execute it. You just print it.

C - getting error *** stack smashing detected ***

I know it might be a duplicate question but I couldn't find a solution for my problem yet.
What I want to do
I'm trying to write in C a sort of simulation of a growing society where there are 2 types of persons, A and B (2 people in my example).
A accepts "engagement proposals" from B
The communication between A, B and gestore is handled with message queues
gestore decides attributes of every "person" and then creates them with execve, passing each attribute as argument
There is a main message queue where each A process sends a message with its info and the key of his private message queue
B reads from the main message queue and then communicates with A using the given key found in the message
I'm under Linux Mint 18.3 32 bit.
The problem
It always gives the error stack smashing detected in file
My files
header.h
#ifndef _HEAD_H
#define _HEAD_H
#include <unistd.h>
#include <sys/msg.h>
#define OFFSET 1000000
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
struct person{
char type;
int name;
unsigned long genome;
};
struct msg_text {
pid_t pid;
char type;
int name;
unsigned long genome;
int key_of_love;
pid_t partner;
};
struct mymsg {
long mtype;
struct msg_text mtxt;
};
int initSemAvailable(int, int);
int initSemInUse(int, int);
int reserveSem(int, int);
int releaseSem(int, int);
#endif
header.c
#include <sys/sem.h>
#include <sys/types.h>
#include "header.h"
int initSemAvailable(int semId, int semNum)
{
union semun arg;
arg.val = 1;
return semctl(semId, semNum, SETVAL, arg);
}
int initSemInUse(int semId, int semNum)
{
union semun arg;
arg.val = 0;
return semctl(semId, semNum, SETVAL, arg);
}
int reserveSem(int semId, int semNum) {
struct sembuf sops;
sops.sem_num = semNum;
sops.sem_op = -1;
sops.sem_flg = 0;
return semop(semId, &sops, 1);
}
int releaseSem(int semId, int semNum) {
struct sembuf sops;
sops.sem_num = semNum;
sops.sem_op = 1;
sops.sem_flg = 0;
return semop(semId, &sops, 1);
}
gestore.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "header.h"
#ifndef MAX_PEOPLE
#define MAX_PEOPLE 5
#endif
#ifndef GENES
#define GENES 1000000
#endif
#ifndef BIRTH_DEATH
#define BIRTH_DEATH 5
#endif
#define SIZE_N 15
//handle signals
struct sigaction sa;
sigset_t my_mask;
void handle_signal(int);
//remove every IPC object
void remove_all();
//terminate every child
void terminate_children();
//free memory
void free_all();
//print every field of message
void print_msg(struct mymsg);
unsigned int init_people;
int * child_status;
pid_t * initial_children;
char * child_name;
char * child_genome;
char * child_sem;
char * child_sem2;
char * child_msgq_a;
//message queue
struct msqid_ds msq;
int msgq_a;
//semaphores
int sem_init_people;
int sem_init_people2;
int main(void)
{
init_people = 0;//will contain initial number of people
int i = 0;
pid_t child;//fork value
unsigned long random_ulong = 0;
child_name = (char *)calloc(SIZE_N, sizeof(char));
child_genome = (char *)calloc(SIZE_N, sizeof(char));
child_sem = (char*)calloc(SIZE_N, sizeof(char));
child_sem2 = (char*)calloc(SIZE_N, sizeof(char));
child_msgq_a = (char*)calloc(SIZE_N, sizeof(char));
char * args[8] = {};
char * envs[] = {NULL};
if( child_name == NULL || child_genome == NULL
|| child_sem == NULL || child_sem2 == NULL
|| child_msgq_a == NULL){
perror("there's a null variable");
exit(EXIT_FAILURE);
}
//handle signals
sa.sa_handler = &handle_signal;
sa.sa_flags = 0;
sigemptyset(&my_mask);
sigaction(SIGALRM, &sa, NULL);
sigaction(SIGUSR1, &sa, NULL);
printf("\nSTARTING SIMULATION\n\n");
init_people = 2;
initial_children = (pid_t *)calloc(init_people,
sizeof(pid_t));
//create 2 semaphores
sem_init_people = semget(IPC_PRIVATE, 1,
0666|IPC_CREAT|IPC_EXCL);
if( sem_init_people == -1 ){
if(errno == EEXIST){
if( semctl(sem_init_people, 0,
IPC_RMID, NULL) == -1 ){
perror("rm sem_init_people");
exit(EXIT_FAILURE);
}
}else{
perror("semget init_people");
exit(EXIT_FAILURE);
}
}
sem_init_people2 = semget(IPC_PRIVATE, 1,
0666|IPC_CREAT|IPC_EXCL);
if( sem_init_people2 == -1 ){
if(errno == EEXIST){
if( semctl(sem_init_people2, 0,
IPC_RMID, NULL) == -1 ){
perror("remove sem_init_people2");
exit(EXIT_FAILURE);
}
}else{
perror("semget sem_init_people2");
exit(EXIT_FAILURE);
}
}
//create message queue
msgq_a = msgget(IPC_PRIVATE, 0666|IPC_CREAT|IPC_EXCL);
if(msgq_a == -1){
if( errno == EEXIST ){//if exists
// delete message queue
if( msgctl(msgq_a, IPC_RMID, &msq) == -1 )
perror("rmid");
}else
perror("msgget queue A");
exit(EXIT_FAILURE);
}
//initialize sem_init_people to 0 (reserved)
if( initSemInUse(sem_init_people, 0) == -1 ){
perror("initSemInUse for sem_init_people");
exit(EXIT_FAILURE);
}
//initialize sem_init_people2 to 0 (reserved)
if( initSemInUse(sem_init_people2, 0) == -1 ){
perror("initSemInUse for sem_init_people");
exit(EXIT_FAILURE);
}
//RWX permissions for people processes
if( chmod("./A", 0777) != 0 ){
perror("chmod person A");
exit(EXIT_FAILURE);
}
if( chmod("./B", 0777) != 0 ){
perror("chmod person B");
exit(EXIT_FAILURE);
}
printf("Generating %u people\n\n", init_people);
//generate initial population
for(i = 0; i < init_people; i++){
//TYPE
if( i%2 == 0 )
args[0] = "./A";
else
args[0] = "./B";
//NAME
if( sprintf(child_name, "%d", i+65) < 0 ){
perror("printf NAME execve");
exit(EXIT_FAILURE);
}
args[1] = child_name;
//GENOME
if( sprintf(child_genome, "%lu",
(long)i+100000) < 0 ){
perror("sprintf GENOME execve");
exit(EXIT_FAILURE);
}
args[2] = child_genome;
//semaphore 1
if( sprintf(child_sem, "%d",
sem_init_people) < 0 ){
perror("sprintf sem_init_prople execve");
exit(EXIT_FAILURE);
}
args[3] = child_sem;
//semaphore 2
if( sprintf(child_sem2, "%d",
sem_init_people2) < 0 ){
perror("sprintf sem_init_prople2 execve");
exit(EXIT_FAILURE);
}
args[4] = child_sem2;
//msg queue
if( sprintf(child_msgq_a, "%d", msgq_a) < 0 ){
perror("sprintf child_msgq_a execve");
exit(EXIT_FAILURE);
}
args[5] = child_msgq_a;
//final argument
args[6] = NULL;
switch(child = fork()){
case -1:{ //error
perror("fork init_people");
exit(EXIT_FAILURE);
}
case 0:{//child
if( execve(args[0], args, envs) == -1 ){
perror("execve");
}
//execve didnt't work
exit(EXIT_FAILURE);
}
default:{//parent
printf("[type:%c][name:%c][pid:%d][gen:%s][sem1:%s]\
[sem2:%s][msgq:%s]\n",
args[0][2],
atoi(args[1]),
(int)child,
args[2],
args[3],
args[4],
args[5] );
//add every child in the array
initial_children[i] = child;
}
}//-switch
}//-for
//wait for every child to be ready to start
for(i = 0; i < init_people; i++){
if( reserveSem(sem_init_people, 0) != 0 ){
perror("reserveSem sem_init_people");
exit(EXIT_FAILURE);
}
}
//allow every child to start
for(i = 0; i < init_people; i++){
if( releaseSem(sem_init_people2, 0) != 0 ){
perror("releaseSem sem_init_people2");
exit(EXIT_FAILURE);
}
}
//wait for termination of every child
if( waitpid(-1, child_status, (int)WNOHANG) == -1 ){
perror("waitpid");
}
printf("Father is now waiting...\n");
for(i = 0; i < 3; i++){
sleep(3);
}
terminate_children();
remove_all();
free_all();
return EXIT_SUCCESS;
}
void handle_signal(int signum)
{
switch(signum){
case SIGUSR1:{
pid_t pidA = 0, pidB = 0;
unsigned long genomeA = 0, genomeB = 0;
struct mymsg msg1, msg2;
int msg_flag = 0;
//ignore sigusr1
if( sigaddset(&my_mask, SIGUSR1) == -1 ){
perror("sigaddset");
exit(EXIT_FAILURE);
}
//read for every message
while(msg_flag == 0){
if( msgrcv(msgq_a, &msg1, sizeof(msg1),
OFFSET+getpid(), IPC_NOWAIT) == -1 ){
if( errno == ENOMSG ){
msg_flag = -1;
printf("gestore is empty\n");
}else{ //random error happened
perror("msgrcv parent A and B");
exit(EXIT_FAILURE);
}
}else{
print_msg(msg1);
msg_flag = 0;
}
}
//do not ignore SIGUSR1
if( sigdelset(&my_mask, SIGUSR1) == -1 ){
perror("sigdelset");
exit(EXIT_FAILURE);
}
break;
}
default:{}
}
}
void terminate_children()
{
int i = 0;
for(i = 0; i < init_people; i++){
if( kill(initial_children[i], 0) == 0 ){
if( kill(initial_children[i], SIGTERM) == -1){
perror("kill sigterm to child");
}
}
}
}
void remove_all()
{
//...
}
void free_all()
{
//...
}
void print_msg(struct mymsg msg)
{
printf("gestore rcv [mtype:%lu][pid:%d][type:%c]\
[name:%c][gen:%lu][key<3:%d][pid<3:%d]\n",
msg.mtype,
(int)msg.mtxt.pid,
msg.mtxt.type,
msg.mtxt.name,
msg.mtxt.genome,
msg.mtxt.key_of_love,
(int)msg.mtxt.partner );
}
personA.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "header.h"
#define NMEMB 50
void accept_lover(int msgq, int love_msg_queue,
struct mymsg love_letter, struct person myself);
void reject_lover(int, struct mymsg love_letter);
struct sigaction sa;
void handle_signal(int);
void print_rcvd_msg(struct mymsg);
void print_sent_msg(struct mymsg);
struct msqid_ds msq;
int love_msg_queue;
int main(int argc, char** argv)
{
if(argc < 6){
perror("A argc");
exit(EXIT_FAILURE);
}
struct person myself;//info of A process
myself.type = 'A';
myself.name = (int)atoi(argv[1]);
myself.genome = (unsigned long)atol(argv[2]);
int sem_init_people, sem_init_people2;
sem_init_people = (int)atoi(argv[3]);
sem_init_people2 = (int)atoi(argv[4]);
int msgq = atoi(argv[5]);
struct mymsg msg_out, love_letter;
struct msqid_ds msq;
int engaged = -1;
int count_refused = 0;
sa.sa_handler = &handle_signal;
sigaction(SIGTERM, &sa, NULL);
//tell parent you're ready
if( releaseSem(sem_init_people, 0) != 0 ){
perror("releaseSem sem_init_people");
exit(EXIT_FAILURE);
}
//wait for parent permission
if( reserveSem(sem_init_people2, 0) != 0 ){
perror("reserveSem sem_init_people2");
exit(EXIT_FAILURE);
}
//create personal message queue of love
love_msg_queue = msgget(IPC_PRIVATE,
0666|IPC_CREAT|IPC_EXCL);
if( love_msg_queue == -1 ){
if( errno == EEXIST ){//if exists
// delete message queue
if( msgctl(love_msg_queue,
IPC_RMID, &msq) == -1 ){
perror("rmid queue of love");
exit(EXIT_FAILURE);
}
}else{
perror("msgget queue of love");
exit(EXIT_FAILURE);
}
}
//create message with correct info of process A
msg_out.mtype = myself.genome;
msg_out.mtxt.pid = getpid();
msg_out.mtxt.type = myself.type;
msg_out.mtxt.genome = myself.genome;
msg_out.mtxt.name = myself.name;
msg_out.mtxt.key_of_love = love_msg_queue;
msg_out.mtxt.partner = -1;
//when A accepts B engaged = 0
while(engaged != 0){
//send info in message queue
if( msgsnd(msgq, &msg_out, sizeof(msg_out), 0)
== -1 ){
if(errno == EINTR)
perror("A caught a signal and failed \
a blocked msgsnd");
else
perror("A msgsnd");
exit(EXIT_FAILURE);
}
print_sent_msg(msg_out);
//wait for love letter from B
if( msgrcv(love_msg_queue, &love_letter,
sizeof(love_letter), 0, 0) == -1 ){
perror("A msgrcv love letter from B");
exit(EXIT_FAILURE);
}
print_rcvd_msg(love_letter);
//accept B if..
if( count_refused >= 2 ){
engaged = 0;//B is good, EXIT loop
accept_lover(msgq, love_msg_queue,
love_letter, myself);
printf("[A:%d]accepted[B:%d]\n",(int)getpid(),
(int)love_letter.mtxt.pid);
}else{
reject_lover(love_msg_queue,love_letter);
printf("[A:%d] refused %d times\n",
(int)getpid(),count_refused+1);
count_refused++;
}
}
pause();
return EXIT_SUCCESS;
}
void handle_signal(int signum)
{
switch(signum){
case SIGTERM:{
printf("A SIGTERM from parent\n");
// delete message queue if exists
if( (msgctl(love_msg_queue, IPC_RMID,
&msq) == -1) && (errno != EIDRM) ){
perror("A rmid 2");
}
break;
}
default:{}
}
}
void accept_lover(int msgq, int love_msg_queue,
struct mymsg love_letter, struct person myself)
{
struct mymsg
msg_to_B, msg_to_gestore1, msg_to_gestore2;
//tell B you accept his request (key_of_love = 0)
msg_to_B.mtype = love_letter.mtype; //pid of B
msg_to_B.mtxt.pid = getpid();
msg_to_B.mtxt.type = 'A';
msg_to_B.mtxt.name = myself.name;
msg_to_B.mtxt.genome = myself.genome;
msg_to_B.mtxt.key_of_love = 0; //0 means accepted
msg_to_B.mtxt.partner = -1;
//send msg to B in queue of love
if( msgsnd(love_msg_queue, &msg_to_B,
sizeof(msg_to_B), 0) == -1 ){
perror("A msgsnd to B accept lover");
exit(EXIT_FAILURE);
}
print_sent_msg(msg_to_B);
//tell gestore that A accepted a request from B
//send message with info of A
//send message with info of B
//A
msg_to_gestore1.mtype = OFFSET + getppid();
msg_to_gestore1.mtxt.pid = getpid();
msg_to_gestore1.mtxt.type = 'A';
msg_to_gestore1.mtxt.name = myself.name;
msg_to_gestore1.mtxt.genome = myself.genome;
msg_to_gestore1.mtxt.key_of_love = 0;
msg_to_gestore1.mtxt.partner = love_letter.mtype;
//B
msg_to_gestore2.mtype = OFFSET + getppid();
msg_to_gestore2.mtxt.pid = love_letter.mtype;
msg_to_gestore2.mtxt.type = 'B';
msg_to_gestore2.mtxt.name = love_letter.mtxt.name;
msg_to_gestore2.mtxt.genome = love_letter.mtxt.genome;
msg_to_gestore2.mtxt.key_of_love = 0;
msg_to_gestore2.mtxt.partner = getpid();
//send msg B
if( msgsnd(msgq, &msg_to_gestore2,
sizeof(msg_to_gestore2), 0) == -1 ){
perror("A msg_to_gestore2");
exit(EXIT_FAILURE);
}
//send msg A
if( msgsnd(msgq, &msg_to_gestore1,
sizeof(msg_to_gestore1), 0) == -1 ){
perror("A msg_to_gestore1");
exit(EXIT_FAILURE);
}
print_sent_msg(msg_to_gestore2);
print_sent_msg(msg_to_gestore1);
/*messages for gestore have mtype=OFFSET+father_pid
so that others can't read messages with mtype greater
than OFFSET and father can directly receive messages
knowing both OFFSET and his pid. */
}
void reject_lover(int love_msg_queue,
struct mymsg love_letter)
{
love_letter.mtxt.key_of_love = -1;
if( (msgsnd(love_msg_queue, &love_letter,
sizeof(love_letter), 0) == -1) ){
perror("A error refusing B in msgsnd");
exit(EXIT_FAILURE);
}
print_sent_msg(love_letter);
}
void print_rcvd_msg(struct mymsg msg)
{
printf("A received [mtype:%lu][pid:%d][type:%c]\
[name:%c][gen:%lu][key<3:%d][pid<3:%d]\n",
msg.mtype,
(int)msg.mtxt.pid,
msg.mtxt.type,
msg.mtxt.name,
msg.mtxt.genome,
msg.mtxt.key_of_love,
(int)msg.mtxt.partner );
}
void print_sent_msg(struct mymsg msg)
{
printf("A sent [mtype:%lu][pid:%d][type:%c][name:%c]\
[gen:%lu][key<3:%d][pid<3:%d]\n",
msg.mtype,
(int)msg.mtxt.pid,
msg.mtxt.type,
msg.mtxt.name,
msg.mtxt.genome,
msg.mtxt.key_of_love,
(int)msg.mtxt.partner );
}
personB.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "header.h"
//send message to A process and wait for response
int flirt(struct mymsg msg, struct person myself);
void print_rcvd_msg(struct mymsg);
void print_sent_msg(struct mymsg);
int main(int argc, char** argv)
{
if(argc < 6){
perror("B argc");
exit(EXIT_FAILURE);
}
struct person myself;
myself.type = 'B';
myself.name = (int)atoi(argv[1]);
myself.genome = (unsigned long)atol(argv[2]);
int sem_init_people, sem_init_people2;
sem_init_people = (int)atoi(argv[3]);
sem_init_people2 = (int)atoi(argv[4]);
int love_response = 1;
int msgq = atoi(argv[5]);
struct mymsg msg_out, msg_in;
struct msqid_ds msq;
//tell parent you're ready
if( releaseSem(sem_init_people, 0) != 0 ){
perror("release sem_init_people child proc");
exit(EXIT_FAILURE);
}
//wait for parent permission to start living
if( reserveSem(sem_init_people2, 0) != 0 ){
perror("reserve sem_init_people2 child proc");
exit(EXIT_FAILURE);
}
//when love_response is 0 A accepted B requests
while(love_response != 0){
//read message from queue
if( msgrcv(msgq, &msg_in, sizeof(msg_in),
-OFFSET, 0) < 1 ){
perror("msgrcv");
exit(EXIT_FAILURE);
}
print_rcvd_msg(msg_in);
//send message to A process and wait for a response
love_response = flirt(msg_in, myself);
printf("2----------------------------\n");
}
//TODO: get ready to terminate
return 0;
}
int flirt(struct mymsg msg, struct person myself)
{
int queue_of_love = msg.mtxt.key_of_love;
pid_t pid_A = msg.mtxt.pid;
struct mymsg love_letter, msg_in;
//create love letter
love_letter.mtype = getpid();
love_letter.mtxt.pid = getpid();
love_letter.mtxt.type = 'B';
love_letter.mtxt.name = myself.name;
love_letter.mtxt.genome = myself.genome;
love_letter.mtxt.key_of_love = -1;
love_letter.mtxt.partner = -1;
//send love letter to A to introduce yourself
if( msgsnd(queue_of_love, &love_letter,
sizeof(love_letter), 0) == -1 ){
perror("B - msg send love");
exit(EXIT_FAILURE);
}
printf("[B:%d] sent<3to [A:%d][mtype:%d][pid:%d]\
[type:%c][gen:%lu][name:%c][love:%d]\n",
(int)getpid(), (int)pid_A,
(int)love_letter.mtype,
(int)love_letter.mtxt.pid,
(int)love_letter.mtxt.type,
(unsigned long)love_letter.mtxt.genome,
love_letter.mtxt.name,
love_letter.mtxt.key_of_love );
//wait for response from A
if( msgrcv(queue_of_love, &msg_in, sizeof(msg_in),
getpid(), 0) == -1 ){
perror("B can't wait for A's response");
exit(EXIT_FAILURE);
}
print_rcvd_msg(msg_in);
//if key of love 0 then accepted love request
printf("1 ----------------------------\n");
return msg_in.mtxt.key_of_love;
}
void print_rcvd_msg(struct mymsg msg)
{
printf("B received [mtype:%lu][pid:%d][type:%c]\
[name:%c][gen:%lu][key<3:%d][pid<3:%d]\n",
msg.mtype,
(int)msg.mtxt.pid,
msg.mtxt.type,
msg.mtxt.name,
msg.mtxt.genome,
msg.mtxt.key_of_love,
(int)msg.mtxt.partner );
}
void print_sent_msg(struct mymsg msg)
{
printf("B sent [mtype:%lu][pid:%d][type:%c]\
[name:%c][gen:%lu][key<3:%d][pid<3:%d]\n",
msg.mtype,
(int)msg.mtxt.pid,
msg.mtxt.type,
msg.mtxt.name,
msg.mtxt.genome,
msg.mtxt.key_of_love,
(int)msg.mtxt.partner );
}
To compile and execute the project
gcc -c header.c
gcc -c personA.c header.c
gcc -c personB.c header.c
gcc -Wall -Wextra -Wconversion -pedantic -std=gnu11 -o A personA.o header.o
gcc -Wall -Wextra -Wconversion -pedantic -std=gnu11 -o B personB.o header.o
gcc -c gestore.c header.c
gcc -Wall -Wextra -Wconversion -std=gnu11 -pedantic -o gestore gestore.o header.o
./gestore
Note the lines of code in personB.c.
printf("1----------------------------\n");
printf("2----------------------------\n");
The second line doesn't get printed because of the error.
Thank you in advance for the help.
Ouput
output error, stack smashing detected
Valgrind valgrind --leak-check=full -v ./gestore gives this output:
==8647== HEAP SUMMARY:
==8647== in use at exit: 0 bytes in 0 blocks
==8647== total heap usage: 7 allocs, 7 frees, 4,179 bytes allocated
==8647==
==8647== All heap blocks were freed -- no leaks are possible
==8647==
==8647== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8647== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
EDIT
Should I link and compile like this?
gcc -c -Wall -Wextra -Wconversion -std=gnu11 -ggdb header.c
gcc -c -Wall -Wextra -Wconversion -std=gnu11 -ggdb personA.c header.c
gcc -c -Wall -Wextra -Wconversion -std=gnu11 -ggdb personB.c header.c
gcc -Wall -pedantic -ggdb -o A personA.o header.o
gcc -Wall -pedantic -ggdb -o B personB.o header.o
gcc -c -Wall -Wextra -Wconversion -std=gnu11 -ggdb gestore.c header.c
gcc -Wall -pedantic -ggdb -o gestore gestore.o header.o
I 'heavily' edited this answer and removed statements that no longer applied, due to OPs modifying the posted code.
Note: when modifying the posted code, in general, DO NOT modify the original posted code, rather post the modified code as an EDIT. For the current question, suggest just posting interleaved code, perhaps via
#if 0
<old code>
#else
<new code>
#endif
===================
in the 'main()function that repeatedly callssystem()` Suggest the compile steps enable the warnings. At a minimum use these compile options:
-Wall -Wextra -Wconversion -pedantic -std=gnu11
Note: the above parameters need to be in the compile statements, not the link statements.
and to make debugging much easier, suggest the compile and link options include:
-ggdb
Also, that main() function will perform ALL the steps every time. Suggest writing a makefile (and executing it with make) so only those files that have changed will be re-compiled/ re-linked
================
Note: there is the setup for a message queue that the code omits, so the default values will be used. Those default values may not be correct for the OPs application.
Here is a cut/paste of a typical setup of a message queue:
Note: the code is from an application that contains LOTS of message queues taskSelector selects which message queue
/* initialize the queue attributes */
attr[taskSelector].mq_flags = 0;
attr[taskSelector].mq_maxmsg = 10;
attr[taskSelector].mq_msgsize =
sizeof(struct structITC)
+ dWEB_PAYLOAD_OVERHEAD
+ dMAX_DATA_BLOCK_SIZE;
attr[taskSelector].mq_curmsgs = 0;
================
the posted code fails to define:
struct msqid_ds -- oops it is defined in one of the header files
=================
when a check of argc indicates that the user did not enter all the needed command line parameters, then the code should output a USAGE message and exit. Something similar to:
fprintf( stderr, "USAGE: %s ..description of all needed parameters..\n", argv[0] );
exit( EXIT_FAILURE );

Can't figure out seg fault

Why do I keep getting a set fault when I try and pass -H in the command line as a flag? -h (help) is working perfectly but -H(header) messes up every single time.
I have a main function as well which calls parse_command_line by passing the argc & argc.
the bool is defined as bool header = false;
the file is char** file = NULL;
and the reason I have the file+=1; in the code is so that it compiles because I am using a makefile that changes all warnings into errors.
#include "parse.h" /* prototypes for exported functions */
#include "../main/unused.h"
#include <stdlib.h>
#include <getopt.h>
#include <stdio.h>
#include <stdint.h>
int
parse_command_line (int argc, char **argv, bool *header, char **file)
{
int oc = 0;
file += 1;
bool help = false;
struct option long_options[] =
{
{"header", no_argument, NULL, 'H'},
{"help", no_argument, NULL, 'h'},
{0, 0, 0, 0}
};
while ((oc = getopt_long(argc, argv, "+Hh", long_options, NULL)) != -1)
{
printf("The value of oc = %d\n", oc);
switch(oc)
{
case 'h':
help = true;
break;
case 'H':
printf("inside case H");
*header = true;
break;
case '?':
fprintf(stderr, "Unknown flag = -%c, type -h or --help for help!\n", optopt);
exit(EXIT_FAILURE);
break;
default:
break;
}
}
printf("Out of loop"); if (optind+1 != argc)
{
fprintf(stderr, "Uh oh, invalid input! Try again with -h or --help for help!\n");
exit(EXIT_FAILURE);
}
if (help)
{
printf("\nHaving some trouble? Let me show you the ropes!\n\n");
printf("Format: ydi <option(s)> mini-elf-file\n\n");
printf("Here's your options:\n");
printf("-h --help Display usage\n");
printf("-H --header Show the Mini-Elf header\n");
exit(1);
}
if (header)
{
printf("Inside HEader");
FILE *file;
uint16_t nums[6];
file = fopen(argv[optind], "r");
#define STRUCT_ITEMS 7
fread(nums, 16, 6, file);
int cur_print;
for (cur_print = 0; cur_print < STRUCT_ITEMS; cur_print++)
{
printf("%d ", nums[cur_print]);
}
}
return 0;
}
My parse.h file is as follows:
#ifndef __PARSE_COMMAND_LINE__
#define __PARSE_COMMAND_LINE__
#include <stdbool.h>
int parse_command_line (int argc, char **argv, bool *header, char **file);
#endif
There are other files such as elf.h and elf.c which I have not implemented and are not called at all at this point, which leads me to believe they are not going to be the problem and don't need to post the small 2 line files. My main function is as follows:
#include <stdio.h> /* standard I/O */
#include <stdlib.h>
#include "unused.h" /* UNUSED macro */
#include "../cmdline/parse.h" /* command line parser */
#include "../y86/elf.h" /* Mini-ELF format */
int
main (int argc UNUSED, char **argv UNUSED)
{
printf ("Congratulations, you have compiled your source code!\n");
bool header = false;
char **file = NULL;
parse_command_line (argc, argv, &header, file);
return 0;
}
And the file unused.h (because the compiler will make unused variables an error instead of warning) is as follows:
#ifndef __UNUSED__
#define __UNUSED__
#define UNUSED __attribute__ ((unused))
#endif
The code doesn't check the return value of fopen, which will be NULL in case of an error. Dereferencing NULL in the fread call causes a segfault.

C - wait, fail when getting the returned value

I have the following problem: In my code, here in line 83, I have this: check = wait(NULL);
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include <sys/stat.h>
#include <sys/types.h>
//---------------------------------
//Function: parse_cmdline(const char* cmdline)
//This function takes the input from stdin
//and returns it as array of strings.
//If stdin is /bin/ls -l /usr/include
//the function will return ["/bin/ls","-l","/usr/include"]
//---------------------------------
char** parse_cmdline(const char* cmdline) {
int count, word_count = 0;
char** line_parsed, line_return;
char *pch, *cmdline_copy = (char*)malloc(sizeof(char)*(strlen(cmdline)+1));
strcpy(cmdline_copy, cmdline);
pch = strtok(cmdline_copy," \n\t\r");
while (pch != NULL) {
++word_count;
pch = strtok(NULL, " \n\t\r");
}
line_parsed = (char**)malloc((word_count+1)*sizeof(char*));
count = 0;
strcpy(cmdline_copy, cmdline);
pch = strtok(cmdline_copy," \n\t\r");
while (pch != NULL) {
line_parsed[count] = (char*)malloc((strlen(pch) + 1)*sizeof(char));
strcpy(line_parsed[count], pch);
++count;
pch = strtok(NULL," \n\t\r");
}
line_parsed[count] = NULL;
free(cmdline_copy);
return line_parsed;
}
int main() {
int count = 0, check;
size_t size;
char* line;
char** cmdline;
while(1) {
check = 0;
printf("$Monkey Eats:< ");
getline(&line, &size, stdin);
cmdline = parse_cmdline(line);
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return -1;
} else if(pid == 0) {
struct stat _stat;
stat(cmdline[0],&_stat);
if(_stat.st_mode & S_IXUSR){
execvp(cmdline[0], cmdline);
}else fprintf(stderr,"%s: Permission denied!\n",cmdline[0]);
perror("");
exit(1);
}else {
check = wait(NULL);
}
count = 0;
while(cmdline[count] != NULL) {
free(cmdline[count]);
++count;
}
free(cmdline);
}
return 0;
}
It makes me a problem. When I run it and when I type a command I have the following message:
$Monkey Eats:< ls
ls: Permission denied!
No such file or directory
If I have only wait(NULL); the program runs normally without a problem. Can somebody tell me what is the problem? Thank you :)
The problem is trying to run ls. execvp() doesn't know where ls is. Try running /bin/ls as your command.
The problem is: stat(cmdline[0],&_stat); - the return code is not checked. What if file not found ? The program continues, and finds that _stat.st_mode & S_IXUSR is 0 (randomly).
However you may test the program as is with "/bin/ls" as input..

Resources