Using C language to use system calls

I need to write a C program (not a C++ program) that allows some tasks to be preformed automatically from a menu-driven interface. Automate the following tasks:

  1. Rename a file
  2. Delete a file or a directory
  3. Output Process Information
  4. Execute �mode 644 ls -l�
  5. Exit

I need to know what steps should I follow to achieve the result. is it possible to ask the user to enter all the names and commands in 1 line or I should ask him one by one.
thank you

#include <stdio.h>
#include <fcntl.h>
#include <sys/errno.h>

int main (void) 
{
	int ch;
	char oldfn;
	char newfn;
	
	printf("\tMenu:\n");
	printf("\t1: Rename a file\n");
	printf("\t2: Delete a file or a directory\n");
	printf("\t3: Output Process Information\n");
	printf("\t4: Execute \"mode 644 ls -l\"\n");
	printf("\t5: Exit\n");
	printf("\t Enter your choice: \n");
	scanf("%d",&ch); 
	do
	{
		switch (ch)
		{
			case 1:printf("Enter the name of file and the new name :\n");
			printf("old file name: ");
			scanf("%s",&oldfn);
			printf("new file name: ");
			scanf("%s",&newfn);
			if ( rename(const char *oldfn, const char *newfn) == 0  )
			{
				printf("file is renamed");
			}
			break;
			case 2:printf("case 2\n");
			break;
			case 3:printf("case 3\n");
			break;
			case 4:printf("case 4\n");
			break;
			case 5:printf("exit\n");
			break;
			default:printf("Enter a number between 1-5\n");
			exit(0);
		}
		scanf("%d",&ch);
		
	}
	while ((ch>=1)||(ch<=5));
		
}

Langara college, Vancouver, Canada - Miss Hengame Hamavand - CPSC 1280

It's possible to do it either way. Line-by-line is probably easier.

Your using scanf incorrectly every time you use it. You can't store a string in a char, since a string is a char array, and you shouldn't be using scanf to read raw data. Read lines then feed them into sscanf, or your code may get stuck in infinite loops whenever the user types something wrong.

I'd do this:

while(1)
{
        char buf[512];
        int selection;
        if(fgets(buf, 512, stdin) == NULL) break; // Read line, quit on error
        // Convert line into number
        if(sscanf(buf, "%d", &selection) != 1)
        {
                fprintf(stderr, "you did not type a number\n");
                continue;
        }

        switch(selection)
        {
...
        }
}

Also, you cannot store an entire string inside a single character. You'll need to feed sscanf an array for the filenames. Something like this:

char fname[512];
printf("Please enter a filename:\n");
// Read a line
fgets(fname, 512, stdin);
// chop the newline off the end of the line
for(n=0; fname[n]; n++) if(fname[n] == '\n') fname[n]='\0';

System calls you'll need are unlink to remove files, open to read or create files, read to read from files, write to write to files, and close to close file descriptors once you're done.

Include files you'll need for all those are

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

1 Like

How should I implement this code inside the c script by using execl function?

find . Maxdepth 1 -perm 0644 

That is just like writing a script, not calling system calls

find is based on the nftw() call and uses stat semantics - it returns among other things a struct stat.

To answer your question--
You should consider system(). It calls execl for you and then calls waitpid.

system("find . maxdepth 1 -perm 0644 ");

The reason to call syscalls directly in C instead of using execl() is to eliminate process creation which has a lot of overhead that you have in a shell script. system() and execl() are doing nothing you cannot do in a shell script in this case.

Problem is I am not supposed to use system

---------- Post updated 11-22-12 at 12:38 AM ---------- Previous update was 11-21-12 at 10:51 PM ----------

execl("/usr/bin/find","find . -maxdepth 1 -perm 644",(char *)NULL);

it doesnt work properly. do you know what is the problem?

it doesnt look for files in the current directory and list all the files in the hard disk with permisoon 644

Each argument to the executable should be a different argument to execl. Give the execl man page a closer read.

Regards,
Alister

1 Like

It really looks to me like you are expected to use system calls like chmod(), unlink(), and
nftw() or readdir(). Embedding shell commands does not appear (to me) to be what is expected.

When you delete a directory, you have to delete all the files in the directory first. Then unlink the directory itself. Exactly what

rm -R ./directory_name 

does

Like they said, it's not a shell, it doesn't split for you.

Also, if it did work, your program would immediately quit, because execl doesn't launch a new program -- it replaces your current program. If you want to create a new process, you have to fork first, then exec. Watch the return value of fork carefully. It creates a clone of your process, and its return value is the only thing which tells them which is which. You have to make sure your child process only does what the child should be doing and not anything else, make sure it quits if exec doesn't work and such.