This question already has answers here:
Undefined reference to `sin` [duplicate]
(4 answers)
Closed 7 years ago.
I have a little problem with my source code. gcc speak to me:
undefined reference to `round' but I don't know why because i'm using stdio.h, stdlib.h, math.h... :-( Can You help me with solve this problem?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <math.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#define VERYBIG 200
int dir_size(const char* dirname)
{
int size = 0;
char path[VERYBIG];
struct stat tmp;
DIR* cat = opendir(dirname);
struct dirent* entry;
while ((entry = readdir(cat)))
{
if (!((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)))
{
path[0] = 0;
strcat(path, dirname);
strcat(path, "/");
strcat(path, entry->d_name);
if (lstat(path, &tmp) == -1)
perror("lstat");
if (S_ISDIR(tmp.st_mode))
{
size += round(tmp.st_blocks / 2);
size += dir_size(path);
}
else
{
size += round(tmp.st_blocks / 2);
}
}
}
return size;
}
void rozmiar(int blocks, int h)
{
if (h == 0)
printf("%d\t", blocks);
else
{
double newbl;
if (blocks < 1024)
printf("%dK\t", blocks);
else if (blocks < (1024 * 1024))
{
newbl = blocks / 1024;
printf("%0.1fM\t", round(newbl));
}
else
{
newbl = blocks / (1024 * 1024);
printf("%0.1fB\t", round(newbl));
}
}
}
void do_du(char dirname[], int s, int h)
{
DIR* kat;
struct dirent* wpis;
int sum = 0, dsize = 0;
if ((kat = opendir(dirname)) == NULL)
fprintf(stderr, "du2: cannot open %s\n", dirname);
struct stat info;
char path[VERYBIG];
while ((wpis = readdir(kat)) != NULL)
{
if (!((strcmp(wpis->d_name, ".") == 0) || (strcmp(wpis->d_name, "..") == 0)))
{
path[0] = 0;
strcat(path, dirname);
strcat(path, "/");
strcat(path, wpis->d_name);
if (lstat(path, &info) == -1)
perror("lstat");
if (S_ISDIR(info.st_mode))
{
dsize = dir_size(path) + round(info.st_blocks / 2);
sum += dsize;
if (s == 0)
{
rozmiar(dsize, h);
printf("%s\n", wpis->d_name);
}
}
else
{
sum += round(info.st_blocks / 2);
if (s == 0)
{
rozmiar(round(info.st_blocks / 2), h);
printf("%s\n", wpis->d_name);
}
}
}
}
if (stat(dirname, &info) == -1)
perror("stat");
sum += round(info.st_blocks / 2);
rozmiar(sum, h);
printf("%s\n", dirname);
}
int main(int ac, char* av[])
{
char optstring[] = "sh";
int opcja, human = 0, suma = 0;
while ((opcja = getopt(ac, av, optstring)) != -1)
{
switch (opcja)
{
case 's':
suma = 1;
break;
case 'h':
human = 1;
break;
case '?':
printf("Usage: du2 [-s] [-h] [KATALOG]\n\t-s\twyswietla wielkosc "
"katalogu\n\t-h\twysiwetla wielkosci plikow w kilo-/mega-/gigabajtach\n");
exit(1);
}
}
if (human != 0 || suma != 0)
{
av++;
ac--;
}
if (ac == 1)
do_du(".", suma, human);
else
do_du(*++av, suma, human);
return 0;
}
It must be a linker error.
Try compiling the program like this
gcc program.c -lm
Related
I was writing a simple shared memory test program like below.
And I used a line like below.
e_intf[i % 8].flag = i;
I thought it should be like below.
e_intf[i % 8]->flag = i;
But if I use "->" operator, I have errors.
This is a full source code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#define SHM_KEY 0x9998
typedef struct _ethernet_interface {
char name[8];
int32_t flag;
} Ethernet_Interface_t;
int32_t memory_update(void)
{
int32_t i = 0;
int32_t shmid;
Ethernet_Interface_t *e_intf;
int32_t ret;
shmid = shmget(SHM_KEY, 8 * sizeof(Ethernet_Interface_t), 0644|IPC_CREAT);
if (shmid == -1)
{
perror("Shared Memory");
return -1;
}
e_intf = shmat(shmid, NULL, 0);
if (e_intf == (void *)-1)
{
perror("Shared Memory Attach");
return -1;
}
while (1)
{
e_intf[i % 8].flag = i;
if (i < 8)
{
sprintf(e_intf[i % 8].name, "%s%d", "eth", (i % 8));
}
printf("memory_update : e_intf[%d].name = %s, e_intf[%d] = %d\n", i % 8, e_intf[i % 8].name, (i % 8), i);
sleep(2);
i++;
}
ret = shmdt(e_intf);
if (ret == -1)
{
perror("shmdt");
return -1;
}
return 0;
}
int32_t memory_read(void)
{
int32_t i;
int32_t shmid;
Ethernet_Interface_t *e_intf;
int32_t ret;
shmid = shmget(SHM_KEY, 8 * sizeof(Ethernet_Interface_t), 0644|IPC_CREAT);
if (shmid == -1)
{
perror("Shared Memory");
return -1;
}
e_intf = shmat(shmid, NULL, 0);
if (e_intf == (void *)-1)
{
perror("Shared Memory Attach");
return -1;
}
i = 0;
while (1)
{
printf("[%d]memory_read : index = %d\n", i, (i % 8));
printf("[%d]memory_read : e_intf[%d].name = %s\n", i, (i % 8), e_intf[i % 8].name);
printf("[%d]memory_read : e_intf[%d].flag = %d\n", i, (i % 8), e_intf[i % 8].flag);
if (e_intf[i % 8].flag == 42)
{
printf("[%d]memory_read : Exiting\n", i);
break;
}
sleep(1);
i++;
}
ret = shmdt(e_intf);
if (ret == -1)
{
perror("shmdt");
return -1;
}
ret = shmctl(shmid, IPC_RMID, 0);
if (ret == -1)
{
perror("shmctl");
return -1;
}
return 0;
}
int32_t main(int32_t argc, char *argv[])
{
pid_t pid;
pid = fork();
if (pid == 0)
{
/* child process */
memory_update();
}
else
{
/* parent process */
memory_read();
}
exit(0);
}
But when I made another simple test program for pointer operation.
I can use "->" operator as I expected.
Here is the source code for the test program for pointer operation.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct _ethernet_interface {
char name[8];
int32_t flag;
} Ethernet_Interface_t;
int32_t main(int32_t argc, char *argv[])
{
Ethernet_Interface_t intf;
Ethernet_Interface_t *p_intf;
p_intf = malloc(sizeof(Ethernet_Interface_t));
intf.flag = 1111;
p_intf->flag = 2222;
printf("intf.flag = %d\n", intf.flag);
printf("p_intf->flag = %d\n", p_intf->flag);
return 0;
}
Can someone point out why I am confused with these 2 cases?
The answer is very simple - index dereferences the pointer:
pointer[n] === *(pointer + n)
so in your case:
e_intf[i % 8] === *(e_intf + i % 8)
and
e_intf[i % 8].flag == (*(e_intf + i % 8)).flag
if you want to use the -> operator you need pointer, not referenced object.
(&e_intf[i % 8]) -> flag
or
(e_intf + i % 8) -> flag
I have an application running on an unprivileged user, but at some point this program needs to run another one as a root, would be nice if I can reuse a configured PAM module, like, su, sudo, login or anyone.
So I am trying to write some code to authenticate the root and run this program using PAM, like sudo does, but I cant ask for password, it needs to be automatic. This unprivileged program in a specific time will have the access to root password.
Tried this example here https://www.netbsd.org/docs/guide/en/chap-pam.html but on pam_authenticate, it always return PAM_AUTH_ERR, I have tried all configured modules on my ubuntu 18.04.
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <stdio.h>
#include <sys/wait.h>
#include <err.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <grp.h>
#include <assert.h>
#include <string>
#include <vector>
int converse(int n, const struct pam_message **msg, struct pam_response **resp, void *data)
{
struct pam_response *aresp;
char buf[PAM_MAX_RESP_SIZE];
int i;
data = data;
if (n <= 0 || n > PAM_MAX_NUM_MSG)
return (PAM_CONV_ERR);
if ((aresp = (struct pam_response *) calloc(n, sizeof *aresp)) == NULL)
return (PAM_BUF_ERR);
for (i = 0; i < n; ++i) {
aresp[i].resp_retcode = 0;
aresp[i].resp = NULL;
switch (msg[i]->msg_style) {
case PAM_PROMPT_ECHO_OFF:
//aresp[i].resp = strdup(getpass(msg[i]->msg));
aresp[i].resp = strdup("mypass");
aresp[i].resp_retcode = 0;
if (aresp[i].resp == NULL)
goto fail;
break;
case PAM_PROMPT_ECHO_ON:
fputs(msg[i]->msg, stderr);
if (fgets(buf, sizeof buf, stdin) == NULL)
goto fail;
aresp[i].resp = strdup(buf);
if (aresp[i].resp == NULL)
goto fail;
break;
case PAM_ERROR_MSG:
fputs(msg[i]->msg, stderr);
if (strlen(msg[i]->msg) > 0 &&
msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
fputc('\n', stderr);
break;
case PAM_TEXT_INFO:
fputs(msg[i]->msg, stdout);
if (strlen(msg[i]->msg) > 0 &&
msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
fputc('\n', stdout);
break;
default:
goto fail;
}
}
*resp = aresp;
return (PAM_SUCCESS);
fail:
for (i = 0; i < n; ++i) {
if (aresp[i].resp != NULL) {
memset(aresp[i].resp, 0, strlen(aresp[i].resp));
free(aresp[i].resp);
}
}
memset(aresp, 0, n * sizeof *aresp);
*resp = NULL;
return (PAM_CONV_ERR);
}
static struct pam_conv conv = {
converse,
//misc_conv,
NULL
};
extern char **environ;
static pam_handle_t *pamh;
static struct pam_conv pamc;
static void
usage(void)
{
fprintf(stderr, "Usage: su [login [args]]\n");
exit(1);
}
int
main(int argc, char *argv[])
{
char hostname[64];
const char *user, *tty;
char **args, **pam_envlist, **pam_env;
struct passwd *pwd;
int o, pam_err, status;
pid_t pid;
while ((o = getopt(argc, argv, "h")) != -1)
switch (o) {
case 'h':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc > 0) {
user = *argv;
--argc;
++argv;
} else {
user = "root";
}
int pam_status = PAM_SUCCESS;
/* initialize PAM */
//pamc.conv = &openpam_ttyconv;
if ((pam_status = pam_start("passwd", user, &conv, &pamh)) != PAM_SUCCESS)
{
assert(false);
}
/* set some items */
gethostname(hostname, sizeof(hostname));
if ((pam_err = pam_set_item(pamh, PAM_RHOST, hostname)) != PAM_SUCCESS)
{
assert(false);
}
user = getlogin();
if ((pam_err = pam_set_item(pamh, PAM_RUSER, user)) != PAM_SUCCESS)
{
assert(false);
}
tty = ttyname(STDERR_FILENO);
if ((pam_err = pam_set_item(pamh, PAM_TTY, tty)) != PAM_SUCCESS)
{
assert(false);
}
/* authenticate the applicant */
pam_err = pam_authenticate(pamh, PAM_SILENT);
if (pam_err != PAM_SUCCESS)
{
printf("Pam Error (%d)\n", pam_err);
warn("pam_authenticate");
assert(false);
}
printf("AUTHENTICATED ;-)");
assert(false);
if ((pam_err = pam_acct_mgmt(pamh, 0)) == PAM_NEW_AUTHTOK_REQD)
pam_err = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
if (pam_err != PAM_SUCCESS)
{
assert(false);
}
/* establish the requested credentials */
if ((pam_err = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS)
{
assert(false);
}
/* authentication succeeded; open a session */
if ((pam_err = pam_open_session(pamh, 0)) != PAM_SUCCESS)
{
assert(false);
}
/* get mapped user name; PAM may have changed it */
pam_err = pam_get_item(pamh, PAM_USER, (const void **)&user);
if (pam_err != PAM_SUCCESS || (pwd = getpwnam(user)) == NULL)
{
assert(false);
}
/* export PAM environment */
if ((pam_envlist = pam_getenvlist(pamh)) != NULL) {
for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env) {
putenv(*pam_env);
free(*pam_env);
}
free(pam_envlist);
}
std::vector<std::string> arguments;
arguments.resize(argc + 2);
char * args_ptr [arguments.size()];
arguments[0] = pwd->pw_shell;
args_ptr[argc +1] = NULL;
args_ptr[0] = (char *)arguments[0].c_str();
for (int i = 0; i < argc; i++)
{
arguments[i + 1] = argv[i];
args_ptr[i+1] = (char *)arguments[i+1].c_str();
}
/* set uid and groups */
if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
warn("initgroups()");
_exit(1);
}
if (setgid(pwd->pw_gid) == -1) {
warn("setgid()");
_exit(1);
}
if (setuid(pwd->pw_uid) == -1) {
warn("setuid()");
_exit(1);
}
execve(args_ptr[0], args_ptr, environ);
warn("execve()");
_exit(1);
pamerr:
fprintf(stderr, "Sorry\n");
err:
pam_end(pamh, pam_err);
exit(1);
}
I expect to fork in a elevated child and run my new program, without asking for password.
I wrote a program for an assignment I have, but I made a mistake and set as
constant the number of users that this program can work with because of that struct limitation. I tried to do some realloc to expand the struct but it didn't work, and I got:
gcc: error: O"SxW��D(/��A>A�0: No such file or directory
gcc: fatal error: no input files
compilation terminated.
Here is my code with todos near the relevant lines, I would appreciate very much a method that will help me to make that code less rigid with relation to the number of users. Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <dirent.h>
#include <memory.h>
#include <unistd.h>
#include <wait.h>
#define MAX_LENGTH 160
#define STDERR_FILDES 2
#define OPERATION_FAILED (-1)
#define BUFFER_SIZE 512
#define CONFIG_PLACE 1
#define CORRECT_ARGS_NUM 2
#define WRONG_ARGS_NUM_MSG "Wrong number of program arguments. Please enter 2 arguments."
#define SPACE_CHAR ' '
#define NEW_LINE_CHAR '\n'
#define NULL_CHAR '\0'
#define NULL_STR "\0"
#define SLASH_CHAR '/'
#define SLASH_STR "/"
#define CURR_DIR "."
#define PAR_DIR ".."
#define C_EXTENT "c"
#define EXT_DOT '.'
#define NUM_OF_USERS 5 //todo: here I define the rigid number of users.
#define ZERO_SCORE "0"
#define SON 0
#define NO_FILE "NO_C_FILE"
#define TIMEOUT "TIMEOUT"
#define COMP_ERR "COMPILATION_ERROR"
#define SIXTY_SCORE "60"
#define BAD_OUT "BAD_OUTPUT"
#define EIGHTY_SCORE "80"
#define SIM_OUT "SIMILAR_OUTPUT"
#define HUNDRED_SCORE "100"
#define GREAT_OUT "GREAT_JOB"
#define EQUAL 0
#define EXE_FILE_NAME "temp.out"
#define RUN_FILE_NAME "./temp.out"
#define COMP_FILE_NAME "./comp.out"
#define RES_FILE_NAME "res.txt"
#define OPER "gcc"
#define OPT_FLAG "-o"
#define RESULTS_FILE_REL_PATH "results.csv"
#define RESULTS_FILE_PERMISSIONS 0644
#define CSV_LINE_MAX_LEN 500
#define CSV_SEPARATOR ","
#define CSV_END_LINE "\n"
#define SECONDS_TO_SLEEP 5
#define WAIT_FOR_ANY_CHILD 0
#define IDENTICAL 3
#define SIMILAR 2
#define DIFFERENT 1
enum Bool
{
false = 0,
true = 1
};
typedef struct User {
char name[MAX_LENGTH];
char filePath[MAX_LENGTH];
char dirPath[MAX_LENGTH];
char score[MAX_LENGTH];
char scoreInfo[MAX_LENGTH];
} User;
/**
* Prints an error message using write function to file descriptor
* number 2 (stderr), and exits with error status -1 (translates to 255).
*/
void sysCallFailureProcedure() {
char errorMsg[] = "Error in system call\n";
write(STDERR_FILDES, errorMsg, sizeof(errorMsg)-1);
exit(OPERATION_FAILED);
}
/**
* Get the file's extension.
* #param filename The filename.
* #return The file's extension.
*/
char *getFilenameExt(char *filename) {
char *dot = strrchr(filename, EXT_DOT);
if(!dot || dot == filename) return "";
return dot + 1;
}
/**
* Get the configurations from the configurations file.
* #param configfilePath The configurations file.
* #param mainDirPath The main directory path.
* #param inputFilePath The input file path.
* #param correctResFilePath The correct result file path.
*/
void getConfigFromFile(char* mainDirPath, char* inputFilePath, char* correctResFilePath, char* configfilePath){
int configFileDes = open(configfilePath, O_RDONLY);
if (configFileDes < 0){
sysCallFailureProcedure();
}
int retVal;
char buff[BUFFER_SIZE];
while ((retVal = read(configFileDes, buff, sizeof(buff))) > 0){
int lineNumber = 1;
int lineIdx = 0;
int i=0;
for (; i<retVal; i++) {
if (lineNumber == 1){
if (buff[i] == NEW_LINE_CHAR || buff[i] == SPACE_CHAR || buff[i] == NULL_CHAR) {
lineNumber = 2;
lineIdx = 0;
} else {
mainDirPath[lineIdx] = buff[i];
lineIdx++;
}
}
else if (lineNumber == 2){
if (buff[i] == NEW_LINE_CHAR || buff[i] == SPACE_CHAR || buff[i] == NULL_CHAR) {
lineNumber = 3;
lineIdx = 0;
} else {
inputFilePath[lineIdx] = buff[i];
lineIdx++;
}
}
else if (lineNumber == 3){
if (buff[i] != NEW_LINE_CHAR && buff[i] != SPACE_CHAR && buff[i] != NULL_CHAR) {
correctResFilePath[lineIdx] = buff[i];
lineIdx++;
}
}
}
}
if (retVal < 0){
sysCallFailureProcedure();
}
if (close(configFileDes) < 0){
sysCallFailureProcedure();
}
}
/**
* Get the C file.
* #param user The user.
* #param userNum The user Num.
* #param directory The directory.
* #param filePath The file path.
*/
void getCFile(User* user, int userNum, char* directory,char* filePath){
DIR* pDir = opendir(directory);
if (pDir == NULL){
sysCallFailureProcedure();
}
struct dirent* pDirent;
while((pDirent = readdir(pDir))!=NULL) {
if ((pDirent->d_type == DT_DIR) && (strcmp(pDirent->d_name, CURR_DIR) != 0)
&& (strcmp(pDirent->d_name, PAR_DIR) != 0)){
char dir[MAX_LENGTH]={};
strcpy(dir,directory);
int length = strlen(dir);
if (dir[length] != SLASH_CHAR) {
strcat(dir, SLASH_STR);
}
strcat(dir, pDirent->d_name);
getCFile(user, userNum, dir, filePath);
} else if (pDirent->d_type == DT_REG) {
char* extension = getFilenameExt(pDirent->d_name);
if(strcmp(extension,C_EXTENT) == 0) {
strcpy(filePath, pDirent->d_name);
strcpy(user[userNum].dirPath, directory);
break;
}
}
}
}
/**
* Process the main directory.
* #param users The users.
* #param userNum The user num.
* #param mainDirPath The main directory path.
*/
void processMainDir(User* users, int* userNum, char* mainDirPath){
DIR* pDir = opendir(mainDirPath);
if (pDir == NULL){
sysCallFailureProcedure();
}
struct dirent* pDirent;
int usersSize = NUM_OF_USERS; // todo: remove if may...
int userSize = sizeof(struct User);
while ((pDirent = readdir(pDir))!=NULL) {
if ((pDirent->d_type == DT_DIR) && (strcmp(pDirent->d_name, CURR_DIR) != 0)
&& (strcmp(pDirent->d_name, PAR_DIR) != 0)){
strcpy(users[*userNum].name, pDirent->d_name);
char path[MAX_LENGTH] = {};
char dir[MAX_LENGTH]={};
strcpy(dir, mainDirPath);
int length = strlen(dir);
if (dir[length] != SLASH_CHAR) {
strcat(dir, SLASH_STR);
}
strcat(dir, pDirent->d_name);
getCFile(users, *userNum, dir, path);
strcpy(users[*userNum].filePath, path);
(*userNum)++;
if ((*userNum) >= usersSize){
usersSize += NUM_OF_USERS;
users = (User*) realloc(users, usersSize * userSize); // todo: check it out. it doesn't work!
if (users == NULL){
sysCallFailureProcedure();
}
}
}
}
if (closedir(pDir) == OPERATION_FAILED){
sysCallFailureProcedure();
}
}
/*
* Return true if there is an executable file.
*/
enum Bool isThereExecutable(){
char workingDir[BUFFER_SIZE];
DIR* pDir;
struct dirent* pDirent;
getcwd(workingDir, sizeof(workingDir));
if ((pDir = opendir(workingDir)) == NULL){
sysCallFailureProcedure();
}
while ((pDirent = readdir(pDir)) != NULL){
if (strcmp(pDirent->d_name, EXE_FILE_NAME) == EQUAL){
return true;
}
}
return false;
}
/**
* Fill up the results file.
* #param resultsFilePath The path to the results file.
* #param userNum The number of users.
* #param users The users struct.
*/
void fillTheResultsFile(char* resultsFilePath, int userNum, User* users){
int resultsFileDes = open(resultsFilePath, O_WRONLY | O_CREAT | O_TRUNC, RESULTS_FILE_PERMISSIONS);
if (resultsFileDes < 0){
sysCallFailureProcedure();
}
int i;
for (i=0; i<userNum; i++) {
char line[CSV_LINE_MAX_LEN] = {};
strcpy(line, users[i].name);
strcat(line, CSV_SEPARATOR);
strcat(line, users[i].score);
strcat(line, CSV_SEPARATOR);
strcat(line, users[i].scoreInfo);
if (i < userNum -1){
strcat(line, CSV_END_LINE);
}
if (write(resultsFileDes, line, sizeof(line)-1) < 0){
sysCallFailureProcedure();
}
}
if (close(resultsFileDes) < 0){
sysCallFailureProcedure();
}
}
/**
* Execute a file.
* #param argv The file's args.
*/
void executeFile(char* argv[]){
pid_t pId = fork();
if (pId == SON) {
int retVal = execvp(argv[0], &argv[0]);
if (retVal == OPERATION_FAILED) {
sysCallFailureProcedure();
}
}else{
waitpid(pId, NULL, WCONTINUED);
}
}
void executeProg(User* users, int userNum, char* inputFilePath, char* correctResFilePath){
char* runArgs[] = {RUN_FILE_NAME, NULL};
int status;
pid_t pId = fork();
if (pId == SON){
int inputFileFileDes = open(inputFilePath, O_RDONLY);
if (inputFileFileDes < 0){
sysCallFailureProcedure();
}
int resFileFileDes = open(RES_FILE_NAME, O_WRONLY | O_CREAT | O_TRUNC, RESULTS_FILE_PERMISSIONS);
if (resFileFileDes < 0){
sysCallFailureProcedure();
}
if (dup2(inputFileFileDes, STDIN_FILENO) < 0){
sysCallFailureProcedure();
}
if (dup2(resFileFileDes, STDOUT_FILENO) < 0){
sysCallFailureProcedure();
}
if (execvp(runArgs[0], &runArgs[0]) < 0){
sysCallFailureProcedure();
}
if (close(inputFileFileDes) < 0){
sysCallFailureProcedure();
}
if (close(resFileFileDes) < 0){
sysCallFailureProcedure();
}
} else {
sleep(SECONDS_TO_SLEEP);
if (waitpid(pId, &status, WNOHANG) == 0){
strcpy(users[userNum].scoreInfo, TIMEOUT);
strcpy(users[userNum].score, ZERO_SCORE);
} else {
char* copmArguments[] = {COMP_FILE_NAME , RES_FILE_NAME, correctResFilePath, NULL};
pid_t pId2 = fork();
if (pId2 == SON){
if (execvp(copmArguments[0], &copmArguments[0]) < 0){
sysCallFailureProcedure();
}
} else{
waitpid(pId2, &status, WAIT_FOR_ANY_CHILD);
if (WIFEXITED(status)){
int compRes = WEXITSTATUS(status);
if (compRes == IDENTICAL){
strcpy(users[userNum].scoreInfo, GREAT_OUT);
strcpy(users[userNum].score, HUNDRED_SCORE);
} else if (compRes == SIMILAR){
strcpy(users[userNum].scoreInfo, SIM_OUT);
strcpy(users[userNum].score, EIGHTY_SCORE);
} else if (compRes == DIFFERENT){
strcpy(users[userNum].scoreInfo, BAD_OUT);
strcpy(users[userNum].score, SIXTY_SCORE);
}
}
if (unlink(EXE_FILE_NAME) < 0){
sysCallFailureProcedure();
}
if (unlink(RES_FILE_NAME) < 0){
sysCallFailureProcedure();
}
}
}
}
}
/**
* Get the scores and score info's.
* #param inputFilePath The input file path.
* #param correctResFilePath The correct result file path.
* #param users The users.
* #param userNum The user num.
*/
void getScoresAndInfo(char* inputFilePath, char* correctResFilePath, User* users, int userNum){
int i;
for (i=0; i<userNum; i++) {
if (strcmp(NULL_STR, users[i].filePath) == EQUAL){
strcpy(users[i].scoreInfo, NO_FILE);
strcpy(users[i].score, ZERO_SCORE);
} else {
char CompletePathToFile[MAX_LENGTH] = {};
strcpy(CompletePathToFile, users[i].dirPath);
strcat(CompletePathToFile, SLASH_STR);
strcat(CompletePathToFile, users[i].filePath);
char* executeArguments[] = {OPER, OPT_FLAG, EXE_FILE_NAME, CompletePathToFile, NULL};
executeFile(executeArguments);
if (!isThereExecutable()){
strcpy(users[i].scoreInfo, COMP_ERR);
strcpy(users[i].score, ZERO_SCORE);
} else {
executeProg(users, i, inputFilePath, correctResFilePath);
}
}
}
}
int main(int argc, char *argv[]) {
if (argc != CORRECT_ARGS_NUM) {
printf(WRONG_ARGS_NUM_MSG);
exit(OPERATION_FAILED);
}
char mainDirPath[MAX_LENGTH] = {};
char inputFilePath[MAX_LENGTH] = {};
char correctResFilePath[MAX_LENGTH] = {};
getConfigFromFile(mainDirPath, inputFilePath,correctResFilePath, argv[CONFIG_PLACE]);
User* users = (User*)malloc(sizeof(User) * NUM_OF_USERS); // todo: here I malloc the users struct
int idx = 0;
if (users == NULL){
sysCallFailureProcedure();
}
processMainDir(users, &idx, mainDirPath);
getScoresAndInfo(inputFilePath, correctResFilePath, users, idx);
fillTheResultsFile(RESULTS_FILE_REL_PATH, idx, users);
}
The last Code I just posted now works. That is, it is able to copy all files from one directory to another. But now, I wanted to update it in such a way that it copies also directories including it contents be it files or folders.
Here is what I did so far, but this has been unable to accomplish my dream.
I really don't know what is wrong with the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#define Max 8192
int copy_files(char *src, char *dest);
int copy_dir(char *srcpath, char *destpath);
int copy_dir(char *srcpath, char *destpath)
{
DIR *sdp = NULL;
DIR *ddp = NULL;
struct dirent *entry;
struct stat sb;
char tempsrc[strlen(srcpath)+1];
char tempdest[strlen(destpath)+1];
strcat(srcpath, "/");
strcat(destpath, "/");
strcpy(tempdest, destpath);
strcpy(tempsrc, srcpath);
if( (sdp = opendir(srcpath)) == NULL )
{
printf ("%s is not an existing directory\n", srcpath);
return 0;
}
else
{
while( (entry = readdir(sdp)) )
{
stat(entry->d_name, &sb);
// printf("Cannot open directory\n");
// exit(EXIT_FAILURE);
switch (sb.st_mode & S_IFMT)
{
case S_IFREG:
{
strcat(tempdest, entry->d_name);
strcat(tempsrc, entry->d_name);
copy_files(tempsrc, tempdest);
strcpy(tempdest, destpath);
strcpy(tempsrc, srcpath);
break;
}
case S_IFDIR:
{
strcat(tempsrc, entry->d_name);
strcat(tempdest, entry->d_name);
mkdir(tempdest, 0777);
ddp = opendir(tempdest);
copy_dir(tempsrc, tempdest);
strcpy(tempdest, destpath);
strcpy(tempsrc, srcpath);
break;
}
}
}
closedir(sdp);
closedir(ddp);
return 1;
}
}
int copy_files(char *src, char *dest)
{
int sfd, dfd, ret_in, ret_out;
char buff[Max];
if ( (sfd = open(src, O_RDONLY)) == -1 )
{
printf("Error while reading %s\n", src);
perror(src);
exit(1);
}
if ( (dfd = creat(dest, 0644)) == -1 )
{
printf("Error while creating %s\n", dest);
perror(dest);
exit(1);
}
while( (ret_in = read(sfd, &buff, Max)) > 0 )
{
ret_out = write (dfd, &buff, ret_in);
if (ret_out != ret_in)
{
printf("write error to %s", dest);
perror(dest);
exit(1);
}
if (ret_in == -1)
{
printf("read error from %s", src);
perror(src);
exit(1);
}
}
close(sfd);
close(dfd);
return 1;
}
int main(int argc, char *argv[])
{
int i;
if (argc != 3)
{
printf ("Usage: Programme_name src dest\n e.g. ./cp src dest\n");
exit(1);
}
char *srcp = argv[1];
char *destp = argv[2];
if (srcp[0] == '/' && destp[0] == '/')
{
for (i = 1; i <= strlen(destp); i++)
destp[(i-1)] = destp[i];
for (i = 1; i <= strlen(srcp); i++)
srcp[(i-1)] = srcp[i];
copy_dir(srcp, destp);
}
else if (srcp[0] != '/' && destp[0] == '/') //./ass1 test /t2
{
for (i = 1; i <= strlen(destp); i++)
destp[i-1] = destp[i];
strcat(destp, "/");
strcat(destp, srcp);
copy_files(srcp, destp);
}
else
{
printf ("Usage: Programme_name src dest\n e.g. ./cp src dest\n");
exit(1);
}
}
You are indefinitely adding /. to the temporary source and destination paths when the directory entry . is read, which is present in all directories. Instead, you should skip the . and .. entries.
Another error is the dimensioning of the temporary paths:
char tempsrc[strlen(srcpath)+1];
char tempdest[strlen(destpath)+1];
The arrays are made just long enough to hold the original paths, though sub-directory names are then appended, overflowing the arrays. Better:
char tempsrc[PATH_MAX];
char tempdest[PATH_MAX];
I am trying to make a simple shell program with the C language which have the options of redirecting stdin and stdout and making a pipe but it's giving me a segmentation fault error. Maybe the problem is in the getline but I'm not sure. Here is the code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#define R 0
#define W 1
#define LINE_LEN 25
struct Job {
char* command;
char** argv;
int stdin;
int stdout;
} typedef Job;
int tokens_number = 0;
int sign_place = 0;
int contain_left = 0;
int contain_right = 0;
int contain_line = 0;
char** parse_cmdline (char * cmdline ){
char** arg = calloc(15, sizeof(char*));
char temp_cmd[LINE_LEN*10];
strcpy(temp_cmd, cmdline);
char * tmp;
tmp = strtok(temp_cmd, " ");
while(tmp != NULL) {
arg[tokens_number] = (char*) malloc(LINE_LEN * sizeof(char*));
strcpy(arg[tokens_number],tmp);
tmp = strtok(NULL, " ");
tokens_number++;
}
//LAST ELEMENT IS NULL
arg[tokens_number+1] = NULL;
return arg;
}
void check_for_special_signs(char** argv){
int i;
for(i=0; i<tokens_number; i++){
if(strcmp(argv[i], "<") == 0){
contain_left = 1;
sign_place = i;
return;
}else if(strcmp(argv[i], ">") == 0){
contain_right = 1;
sign_place = i;
return;
}else if(strcmp(argv[i], "|") == 0){
contain_line = 1;
sign_place = i;
return;
}
}
}
void fork_child(Job* my_job) {
pid_t pid = fork();
if (pid == 0) {
execv(my_job -> command, my_job -> argv);
perror(my_job -> command);
} else if (pid > 0) {
int status;
wait(&status);
} else
perror("fork");
}
char** create_argv(char** argv){
int i;
int j = 0;
char** argvs = calloc(sign_place,sizeof(char*));
if(sign_place!=0){
for(i=0; i < sign_place ; i++){
argvs[i] = (char*) malloc(sizeof(char*));
strcpy(argvs[i],argv[i]);
}
return argvs;
}else{
return argv;
}
}
void close_job(Job* my_job) {
if (my_job -> stdin != STDIN_FILENO)
close(my_job -> stdin);
if (my_job -> stdout != STDOUT_FILENO)
close(my_job -> stdout);
free(my_job);
}
int main() {
size_t s = 512;
char* buffer = malloc(s * sizeof(char));
char** sep_cmd = malloc(s * sizeof(char));
while (getline(&buffer, &s, stdin) != EOF) {
Job* my_job;
int my_pipe[2];
int in = 0;
int out = 1;
sep_cmd = parse_cmdline(buffer);
my_job->command = sep_cmd[0];
my_job->argv = sep_cmd;
my_job->stdin = in;
my_job->stdout = out;
check_for_special_signs(my_job->argv);
pid_t pid = fork();
if (pid == 0) {
if(contain_left == 1){
in = open(my_job->argv[sign_place + 1], O_RDONLY);
if(in < 0){
perror("open()");
}
my_job->argv = create_argv(my_job->argv);
my_job->stdin = in;
}else if(contain_right == 1){
out = open(my_job->argv[sign_place + 1], O_WRONLY | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (out < 0)
perror("open()");
my_job->argv = create_argv(my_job->argv);
my_job->stdout = out;
}else if(contain_line == 1){
pipe(my_pipe);
if (my_job -> stdin == my_pipe[R])
close(my_pipe[W]);
else
close(my_pipe[R]);
}
execv(my_job -> command, my_job -> argv);
perror(my_job -> command);
} else if (pid > 0) {
int status;
wait(&status);
} else{
perror("fork");
}
close_job(my_job);
free(buffer);
buffer = (char*) malloc(s * sizeof(char));
}
free(buffer);
return 0;
}
That way I can't see if there are more mistakes in the code. Please if you see more mistakes list them too.
Thank you.
You forgot to allocate memory for my_job in main function