PDA

View Full Version : System Calls in C



Flying Mullet
04-19-2009, 09:09 PM
Mulley's brain is tired from looking at C code all day and he's ready to call for help.

I have two programs using system calls in C that I need to write and neither of them are working correctly. The first one takes two parameters, an existing folder and the name of a new folder. The program should create the new folder and copy the contents of the old folder (i.e. files) into the new folder. My program will create the new folder and create the files in the new folder, but it won't write the contents to the files. Here's what I have so far:



#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>

int main (int argc, char *argv[])
{
int count;
char buffer[1024];
int folderNew, fileNew, fileOld;
DIR *folderOld;
struct dirent * file;

// ensure the proper number of command line arguments are passed in
if (argc !=3) {
fprintf (stderr,"need 3 args\n");
return 1;
}

// create the new folder
folderNew = mkdir(argv[2],00644);
if (folderNew == -1) {
printf ("can not create: %s\n", argv[2]);
/* fprintf (stderr,"errstring is: %s\n",strerror(errno));; */
return 0;
}

// open the old folder
folderOld = opendir (argv[1]);
if (folderOld == NULL) {
fprintf (stderr,"can not open: %s\n", argv[1]);
/* fprintf (stderr,"errstring is: %s\n",strerror(errno)); */
return 0;
}


// copy the contents
/*
while ( (count = read(folderOld, buffer, sizeof(buffer))) > 0)
{
printf ("in loop\n");
write (folderNew, buffer, count);
}
*/

while (file = readdir(folderOld))
{
// printf ("inode: %ld file name: %s file type: %d offset: %ld length: %d\n",file->d_ino, file->d_name, file->d_type, file->d_off, file->d_reclen);


// only copy the proper file types
if(file->d_type != 4)
{
// navigate to the old folder
chdir(argv[1]);

// open the old file
fileOld = open ("dummy.txt",O_RDONLY);
if (fileOld == -1)
{
fprintf (stderr,"can not open: %s\n", file->d_name);
/* fprintf (stderr,"errstring is: %s\n",strerror(errno)); */
return 0;
}

// navigate to the new folder
chdir("..");
chdir(argv[2]);

// create the new file
fileNew = creat (file->d_name,00644);
if (fileNew == -1)
{
printf ("can not create: %s\n", file->d_name);
/* fprintf (stderr,"errstring is: %s\n",strerror(errno));; */
return 0;
}


while ( (count = read(fileOld, buffer, sizeof(buffer))) > 0)
{
write (fileNew, buffer, count);
}

// navigate back to the parent folder
chdir("..");


}


}

return 0;
}


My second program is supposed to create two child processes. Then the parent sends a message to each child, each child sends a message to the parent, then everything shuts down gracefully. When I'm in the child process/file, it says it there is no such file or directory when I tell it to open the pipe from the parent to receive the message. Here's what I have:

<i>parent.c</i>



/* a simple first example, showing output */

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>


int main(int argc, char **argv)
{
pid_t child1pid;
pid_t child2pid;

char message1[]="Hi Child1, this is your parent!!!";
char message2[]="Hi Child2, this is your parent!!!";
int fd1, fd2;
char buff[128];
int num;

/* create new named pipes in current directory with
permissions 777 (rwx for everyone) */
mknod("toChild1", 010777,0);
mknod("toChild2", 010777,0);

/* parent process here */
printf("Howdy from parent process %d\n", getpid());

/* split child 1 here */
if ((child1pid=fork()) == 0) { /* child */
execlp("./child", "./child", "1", "toChild1", NULL);
perror("oops, child had an error!");

/* write to child 1 on that named pipe */
fd1 = open("toChild1", O_WRONLY);
num = write(fd1, message1, sizeof(message1));

return 1;
}
else
{
/* split child 2 here */
if ((child2pid=fork()) == 0) { /* child */
execlp("./child", "./child", "2", "toChild2", NULL);
perror("oops, child had an error!");

/* write to child 2 on that named pipe */
fd2 = open("toChild2", O_WRONLY);
num = write(fd2, message2, sizeof(message2));

return 1;
}
// parent display
else { /* parent */
printf("parent: child1's process id is %d\n",child1pid);
printf("parent: child2's process id is %d\n",child2pid);
printf("parent is going to wait for children to end...\n");
wait();

}
}

/* remove the named pipes from the directory */
close(fd1);
close(fd2);

printf("Bye from the parent!!\n");
}


<i>child.c</i>


#include <stdio.h>
#include <fcntl.h>

int main(int argc, char **argv)
{
if (argc < 2){
printf ("Must supply argument!\n");
return -1;
}

char message[]="Hi Parent!!!";
int fd;
char buff[128];
int num;

printf("Howdy, I'm child %s.\n", argv[1]);
printf("Child %s stream to read is %s.\n", argv[1], argv[2]);

/* read data from the pipe that the parent created */
if ((fd = open(argv[2], O_RDONLY)) == -1) {
perror ("on open of child stream");
// unlink(childName);
return 1;
}

num = read(fd, buff, 128);
printf ("\nChild %s received: %s\n\n", argv[1], buff);
close(fd);

// sleep(atoi(argv[1]));

printf("Bye from child %s!!!\n", argv[1]);
}

Samuraid
04-20-2009, 07:52 AM
Apologies, I don't have too much time to look at this at the moment. However, in the case of the first program, you should check the return value of write() and see if the write is supposedly successful or not.

Flying Mullet
04-21-2009, 09:37 PM
Turns out they were environmental problems and not code problems.

With my copy program, I had my open and create files swapped so I accidentally overwrote the old file with a clean new one without realizing it at one point, then switched them and went on my merry way, not checking to see if there were contents to the files. Thus it was behaving as it should, copying empty files. xD

With my parent/child program, I had the files on a memory stick and the file system format didn't allow for creation of pipes. Once I copied the files onto my hard drive and ran it the pipes were created and I was able to move forward.

The worst part is I spent at least four hours trying to fix code that wasn't broken. It was as bad as using = instead of == to test equality and not realizing it.

Flying Mullet
04-21-2009, 09:39 PM
I do have a follow-up question, how do you concatenate a string argument to an existing string? I tried something like this and I got some nasty stack error messages and my process was killed.



char message[]="Hi Parent from Child ";
strcat(message, argv[1]);
strcat(message, "!!!");

Samuraid
04-22-2009, 03:13 AM
Your character array "message" needs to be large enough to accommodate "Hi Parent from Child " as well as the data in argv[1].

The way you defined it, it will only have enough storage for "Hi Parent from Child " as well as the terminating \0 null byte.
You probably will want to dynamically allocate a character array large enough to accommodate both:



const char message_prefix[] = "Hi Parent from Child ";
char * message;

/* Allocate a character array of length message_prefix + length of argv[1]
* plus 1 extra character for the terminating null byte.
*/
if ((message = malloc(strlen(message_prefix) + strlen(argv[1]) + 1)) == 0)
{
/* The allocation failed for some reason. */
perror("malloc");
exit(1);
}

/* Copy the message_prefix to the beginning of our string. */
strcpy(message, message_prefix);

/* concatenate argv[1] on the end */
strcat(message, argv[1]);

/* Do stuff with your string here... */

/* ALWAYS free the dynamic allocations when you are done. */
free(message);

This has not been tested nor syntax checked at all, so have fun with it. :p
You'll need to include stdlib.h if you haven't already.

Flying Mullet
04-22-2009, 01:06 PM
Bah, yes, I forgot to note that message was initialized to a size of 30 when I posted that code block. Oh well, I'll try the malloc stuff instead. This reminds me why I like working with Java. :p

NeoTifa
04-25-2009, 02:36 AM
You have like 4 blank include statements. :\

Samuraid
04-25-2009, 08:17 AM
&amp;lt; = &lt;
Etc...

They are there if you view the HTML source of this page. :)

NeoTifa
04-29-2009, 03:09 AM
Pfftttt HTML is for pussies..... :(