[SOLVED] How do I implement a CD builtin to a C Shell?
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Distribution: Debian, Kali Linux, Linux Mint, BackTrack, elementary OS
Posts: 26
Rep:
How do I implement a CD builtin to a C Shell?
I have written (with the help of the community at LQ) a C Shell, named vsh. I now need to implement the CD command. I have tried various implementations, but nothing I have tried works. My code is as follows:
Code:
/**
@file vsh.c
@author George Gibson
@date Wednesday 29th July 2015
@brief vsh Shell Version 1.0 BETA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#define LINESIZE 1024
#define RL_BUFSIZE 1024
#define TOK_BUFSIZE 64
#define TOK_DELIM " \t\r\n\a"
char **split_line(char *line)
{
int bufsize = TOK_BUFSIZE, position = 0;
char **tokens = malloc(bufsize * sizeof(char*));
char *token, **tokens_backup;
if (!tokens) {
fprintf(stderr, "vsh: allocation error\n");
exit(EXIT_FAILURE);
}
token = strtok(line, TOK_DELIM);
while (token != NULL) {
tokens[position] = token;
position++;
if (position >= bufsize) {
bufsize += TOK_BUFSIZE;
tokens_backup = tokens;
tokens = realloc(tokens, bufsize * sizeof(char*));
if (!tokens) {
free(tokens_backup);
fprintf(stderr, "vsh: allocation error\n");
exit(EXIT_FAILURE);
}
}
token = strtok(NULL, TOK_DELIM);
}
tokens[position] = NULL;
return tokens;
}
int main(int argc, char **argv)
{
int finish = 0;
char *user = getenv("USER");
char hostname[1024];
char *pwd = getenv("PWD");
char line[LINESIZE] = {0};
char lineCopy[LINESIZE] = {0};
char *command = NULL;
char **args;
// Print out a welcome message
printf("Welcome to vsh\n");
// Print out the message of the day
system("/bin/cat /etc/motd");
printf("\n");
gethostname(hostname, 1024);
while (!finish)
{
// Update 'pwd' variable
pwd = getenv("PWD");
// Print out prompt
printf("[");
printf(user);
printf("@");
printf(hostname);
printf("] ");
printf(pwd);
printf(" $ ");
fflush(stdout);
if(NULL == fgets(line, sizeof line, stdin))
{
// If NULL, leave vsh
finish = 1;
printf("\nLeaving vsh\n");
}
else
{
// If there is something there...
printf("The command read was s", line);
printf("\n");
char *newLine = strchr(line, '\n');
if(newLine != NULL)
{
*newLine = '\0';
strcpy(lineCopy, line);
}
command = strchr(line, ' ');
if(command != NULL)
{
*command++ = '\0';
printf("Command= _%s_\n\n", line);
}
args = split_line(line);
if(strcmp(line, "") == 0) {
fprintf(stderr, "vsh: Expected command\n");
}
else if(strcmp(line, "cd") == 0)
{
printf("cd not available in BETA versions of vsh");
}
else if(strcmp(line,"programmer") == 0)
{
printf("The programmer of vsh is George Gibson\n");
}
else if(strcmp(line,"ver") == 0)
{
printf("The current version is 1.0\n");
}
else if(strcmp(line, "help") == 0)
{
printf("Help for vsh\n\nType a command to run it. The builtin commands are : cd, programmer, ver, help and exit.Their functions are as follows:\n\ncd: Change Directory. Changes the current working directory.\n\nprogrammer: Display the programmers of vsh.\n\nver: Display the version of vsh you are running.\n\nhelp: Launches this program.\n\nexit: Leave vsh Shell.\n\nThese are the only builtins in vsh, but note that if you define a command in /bin with one of these names, your program will not run in vsh unless you use it's explicit name (/bin/yourprogram) rather than \"yourprogram\". vsh 1.0 written and programmed by George Gibson.\n");
}
else if(strcmp(line,"exit") == 0)
{
finish = 1;
printf("\nLeaving vsh...\n");
getchar();
}
else
{
// Run the command
pid_t pid;
int err;
pid=fork();
if(pid == -1) {
perror("vsh");
}
else if(pid == 0) {
execvp(args[0], args);
perror("vsh");
}
else {
waitpid(pid, &err, 0);
}
}
}
}
return 0;
}
Distribution: Debian, Kali Linux, Linux Mint, BackTrack, elementary OS
Posts: 26
Original Poster
Rep:
I call it in the following manner:
Code:
directory = args[1];
chdir(directory);
It compiles fine, but nothing happens when I run the cd command with or without an input. It reads the command, but does not change the working directory.
That's still not really enough context, but I guess that you either you misparsed args[1] and ignored the error returned by chdir, or you called chdir in a subprocess (i.e. after forking); chdir only affects the current process.
Distribution: Debian, Kali Linux, Linux Mint, BackTrack, elementary OS
Posts: 26
Original Poster
Rep:
OK, taken your advice and added a perror("cd"), now I get the error 'cd: Bad address'. I've had this error before, but that was being executing in a different manner, and thus won't work here. If I try to do args[0], I get 'cd: No such file or directory'.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.