You are not logged in.
Pages: 1
Well, ever since I switched to Linux, I've been interested in os development. An important part of the operating system is the shell. So recently, I decided to write my own shell, which I hope I can make featureful and robust enough to use in place of GNU Bash.
I am not so sure if this is the appropriate forum because it could work in Community Contribution too in my opinion and this isn't a programming question really, just sharing the source code, but you guys can criticize and suggest things.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char *args[80];
char input[80];
int errno;
int i;
int main(void) {
while(strcmp(input, "exit")) {
i = 1;
do {
printf("Aprz-0.3$ ");
gets(input);
} while(input[0] == '\0');
args[0] = strtok(input, " ");
while((args[i] = strtok(NULL, " ")) != NULL && ++i);
if(!strcmp(args[0], "cd")) {
chdir(args[1]);
continue;
}
if(fork() == 0 && strcmp(input, "exit")) {
errno = execvp(args[0], args);
if(errno < 0) printf("%s: command not found!\n", args[0]);
exit(1);
} else wait(NULL);
}
return 0;
}
This is version 0.3 of it. I've been sharing this with other people on two private forums, but they haven't been so enthusiastic as I am about it so I figured putting it in a public spot such as this full of technical experts and enthusiast will get me better input.
I am terribly sorry I haven't commented it either, haha! I meant to do that starting from day 1, but I slacked off on that instead since it's so small.
Oh, feel free to distribute, modify, and all that nonsense. Don't forget to give me credit though. Also please, if you're taking an operating system class and you're suppose to make a shell, don't cheat yourself and the class by using this.
I am mostly making this just for kicks, but I am also giving it a lot of attention right now.
Anyhow, criticism, questions, and suggestion will be greatly appreciated.
Last edited by Aprz (2009-04-15 02:19:57)
Offline
Cool. It's amazing to see how simple a shell really is when you think about it You'll need to put in some error checking etc (also don't use gets). You'll want to add redirection at some point too.
JABBER: krayon -A-T- chat.qdnx.org
E-MAIL: archlinuxforums -A-T- quadronyx.org
WEB: http://www.qdnx.org/krayon/
~o~
Offline
Cool. It's amazing to see how simple a shell really is when you think about it You'll need to put in some error checking etc (also don't use gets). You'll want to add redirection at some point too.
Try implementing (atleast) tab completion..then you should have your handful
No to mention this isn't a "complete" shell because it uses the already existing shell to run stuff..all execvp does is replace the process image with the running program..afaik the actual shell is still the one running things
Last edited by Wra!th (2009-04-15 08:17:08)
MacGregor DESPITE THEM!
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Offline
It replaces the process, not use it to execute it.
Edit: By the way, I am using it as my main shell now on both my root and non-root user.
Edit: Renamed some variables to be more suitable. Replaced gets() with fgets() which is better. I wasn't thinking . Got signal handling so ctrl-c won't kill my shell.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char *args[128];
char input[128];
int argc;
int ret;
void sighandler(int signo) {
write(1, "\r", 1);
}
int main(void) {
signal(SIGINT, SIG_IGN);
signal(SIGINT, sighandler);
while(strcmp(input, "exit")) {
argc = 1;
do {
printf("Aprz-0.3$ ");
fgets(input, 128, stdin);
} while(input[0] == '\0');
input[strlen(input) - 1] = '\0';
args[0] = strtok(input, " ");
while((args[argc] = strtok(NULL, " ")) != NULL && ++argc);
if(!strcmp(args[0], "cd")) {
chdir(args[1]);
continue;
}
if(!fork()) {
ret = execvp(args[0], args);
if(ret < 0 && strcmp(input, "exit")) printf("%s: command not found!\n", args[0]);
exit(0);
} else wait(NULL);
}
return 0;
}
I am happy with it so far.
Last edited by Aprz (2009-04-15 11:35:00)
Offline
So far, this is starting to seem like a really promising project. It might be used as a template shell for beginning shell devs.
It should be licensed (suggestion: gpl).
urxvtc / wmii / zsh / configs / onebluecat.net
Arch will not hold your hand
Offline
We had to do this same type of project for a class when I was still in school. We had about 2 weeks to do it and it had to do piping, redirection out and in, background processes, and run on both linux and minix. It was actually a very fun project. Unfortunately I lost the working source for mine due to another class I had at the time. Have fun.
archlinux - please read this and this — twice — then ask questions.
--
http://rsontech.net | http://github.com/rson
Offline
Heh, not so sure if it is a good template, but I guess all software, good or bad, should be free.
Edit: Current progress of Aprz-0.4. I actually took the seconds to annotate the code. I also added put putenv() so I wouldn't have to type /sbin/reboot and stuff like that. So you may want to edit it.
-code removed to keep post size small-
I hope by annotation the source code and putting envp() at line 48. This will make it easier to use and edit. I actually don't know how to pipe yet, but I am going to look at it soon. I hear it is easy.
Edit: Removed the code above with some very minor errors and posting it here. XD
/* Aprz Shell - an interactive prompt that execute commands
*
* Feel free to modify this however you wish, change it, redistribute it,
* blah blah blah, just as long as you give me credit for starting
* this mini project off. School childern shall not turn this in as
* their homework assignment by the way (even though I doubt this is
* even considered near a C+ right. What do you guys give this? A D-
* right now since there is no tab completion? :(
*
* If you notice any mistake in documentation in the source code, any
* minor (or major) programming errors, have a suggestion, or anything
* like that, feel free to notify me.
*
* Name is Andrew Przepioski.
* E-mail: aprzepioski@hotmail.com
*
* ========================================================================
* !!! IMPORTANT !!! IMPORTANT !!! IMPORTANT !!! IMPORTANT !!! IMPORTANT !!!
* =========================================================================
* Did I get your attention now? Yes at line 48, you need to edit it
* to fit you... I am just going to leave it as the default in
* in the source code and it is up to you to edit it! It is your
* PATH.
*
* THANKS
*
* Ventrue - Pointed out a few typos and grammatical errors.
* Milo - Pointed out that PATH doesnt need ':' at the end of it.
*/
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* args - my imitation of argv
* input - the user's input
* argc - my imitation of argc
* ret - return*/
char *args[128];
char input[128];
int argc;
int ret;
/* Isn't the name and what it is doing obvious enough?! Gosh... */
void sighandler(int signo) {
write(1, "\r", 1);
}
int main(void) {
/* Set PATH or else it would just be "/bin:/usr/bin:". */
putenv("PATH=/bin:/usr/bin");
/* If you're using firefox and have fancy things like flash,
* you'll want this. */
/*putenv("MOZ_PLUGIN_PATH=/usr/lib/mozilla/plugins:/opt/mozilla/lib/plugins");*/
/* Disable ctrl-c. This also disabled ctrl-d and other guys,
* I'll work on that later since I am feeling lazy. */
signal(SIGINT, SIG_IGN);
signal(SIGINT, sighandler);
/* Nice going Captain Obvious.. ;) Yes, this is the loop
* that keeps Aprz Shell alive until the user enters exit. */
while(strcmp(input, "exit")) {
/* argc 0 would be the program name. */
argc = 1;
/* Print out a lovely prompt and let the user type
* in junk. */
do {
printf("Aprz-0.4$ ");
fgets(input, 128, stdin);
} while(input[0] == '\0');
/* Fix a minor detail with using fgets(). */
input[strlen(input) - 1] = '\0';
/* Parse/tokenize the user's input using space as
* a delimiter. */
args[0] = strtok(input, " ");
while((args[argc] = strtok(NULL, " ")) != NULL && ++argc);
/* Magically change directories. */
if(!strcmp(args[0], "cd")) {
chdir(args[1]);
continue;
}
/* Initiate process and execute the user input. */
if(!fork()) {
ret = execvp(args[0], args);
if(ret < 0 && strcmp(input, "exit")) printf("%s: command not found!\n", args[0]);
exit(0);
} else wait(NULL);
}
return 0;
}
Edit: Hm... I think I'll need to do something like #define to set PATH. Seems like a pain to scroll down to edit that and edit me saying where it is at ^ cause it's not in the right spot anymore.
Last edited by Aprz (2009-04-17 22:47:36)
Offline
Hopefully double posting isn't a crime cause I think it would be even more of a crime to just let this die or to create a second post on the same subject.
I havn't made very much progress since I last posted this, but I have been experimenting with some header files such as dirent.h, regex.h, and termios.h.
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* Note: Using dirent.h for tab completion, but have not yet
* implemented it. Necessary for struct dirent *dptr and DIR *dirp. */
#define MAX 128 /* Max input size. */
char *args[MAX]; /* Imitation of argv. */
char input[MAX]; /* User's final input. */
char ch; /* Character used to build user's input. */
int argc; /* Imitation of argc. */
int i; /* Index for user's input. */
struct dirent *dptr; /* Contents of directory. */
DIR *dirp; /* The directory. */
/* Our signal handler. */
void sighandler(int signo) {
write(1, "\r", 1);
}
int main(void) {
/* Set PATH. By default, it is "/bin:/usr/bin". */
putenv("PATH=/bin:/usr/bin");
/* Disable ctrl-c and other signals. */
signal(SIGINT, SIG_IGN);
signal(SIGINT, sighandler);
/* Loop until the user's input is "exit". */
while(strcmp(input, "exit")) {
/* Assuming the user types in a program name. */
argc = 1;
/* This is our prompt. */
do {
/* Start index at 0. */
i = 0;
/* Print the prompt. */
printf("ash %% ");
/* Get the user's input. */
while((ch = getchar()) != '\n' && i < MAX) {
input[i] = ch;
++i;
}
/* Append \0 to make the user's input a string. */
input[i] = '\0';
} while(input[0] == '\0');
/* Tokenize the user's input. */
args[0] = strtok(input, " ");
while((args[argc] = strtok(NULL, " ")) != NULL && ++argc);
/* Change directory if the first token is "cd". */
if(!strcmp(args[0], "cd")) {
chdir(args[1]);
continue;
}
/* Initiate process and execute the user's input. */
if(!fork()) {
if(execvp(args[0], args) && strcmp(input, "exit")) printf("%s: command not found!\n", args[0]);
exit(0);
} else wait(NULL);
}
return 0;
}
I have not looked into GPLing this yet. I don't think there is any danger to this, haha, but I think I will eventually just incase when I get around to it.
I was playing around with dirent.h here pretty much making a duplicate of `ls' or `dir', but hopefully in my shell in the future for tab completion or regex and in a less pretty way (as in I am not going to be printing out guys, it's just gonna be so you can say /ho and hit tab to complete it or type in /ho* to complete it).
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
struct dirent *dptr;
DIR *dirp;
int main(void) {
if((dirp = opendir("/home/andrew")) == NULL) {
printf("Error opening directory.");
exit(1);
}
while(dptr = readdir(dirp)) {
printf("%s\n", dptr->d_name);
}
close(dirp);
return 0;
}
I didn't comment this. :[
^And to think that in Perl, this would just be <*>, lol.
A friend setup an ftp server for bzr so I am gonna be using that. Maybe later I'll setup something git. He still has to add an anonymous account, but once that is up, it should be easy for you guys to get the most current stuff with my shell, make whatever edits, whatever.
Last edited by Aprz (2009-06-08 10:03:55)
Offline
I really recommend hosting it on something like github. It's fantastic
[git] | [AURpkgs] | [arch-games]
Offline
Well, I was considering bzr first because my friend really liked it. On IRC, folks told me that in long term, git is probably better. So I've pretty much learn how to use both git and bzr, not hard, but so far just done it with bzr. Maybe tonight I'll set it up with git. My friend hasn't told me if he created an anonymous account for his bzr server. He better. -.-
Edit: I'd like to announce that the anonymous account has been setup. To get my shell, just do:
% bzr checkout ftp://anonymous@koti.meelo.org/ash
Wow, that's a lot of typing, lol. I am probably going to turn it into a packman package and a simple tarball and make it available that way. I am about to go into detail on bzr (I've only read the 5 minute guide, haha). So I'll probably be playing around with it. Still haven't read about termios.h yet. :[
Last edited by Aprz (2009-06-10 11:39:29)
Offline
do you plan on .aprzrc?
When everything's coming your way, you're in the wrong lane I say.
FAQ / Beginners Guide / The Arch Way
Offline
Yes, I actually did get started on that for changing just the PATH, but that's not on my uploaded code yet. I played around it separately from the shell.
Last edited by Aprz (2009-06-10 11:40:18)
Offline
Isn't it an idea to get the PATH out of /etc/profile? Nice shell though. Makes me wonder if I should make my own as well...
Offline
Love it so far! Only one problem... the bzr command should be:
% bzr checkout ftp://anonymous@koti.meelo.org/aprz/ash
Haha, my bad, my bad. Good catch.
Edit: There appears to be a problem with the anonymous account though. It was working earlier, but now it fails. :[
Edit: Well, chit chatting with my friend and it seems that their is just a permission error with .bzr when using push on bzr so it looks like it'll be down for a little bit. He told me he'll get back when to me when it works.
Edit: Ha, I learn a new thing about bzr every second. Apparantly it would be better for you guys to do:
% bzr branch ftp://anonymous@koti.meelo.org/aprz/ash
So it doesn't try to commit to the main branch.
It's still down though.
Last edited by Aprz (2009-06-10 13:36:40)
Offline
Now it should work again.
I'm now running a dedicated server, so in order to grab the snapshot run:
bzr branch bzr://koti.meelo.org/aprz/ash myBranch
Branch, because checkout is binded to the server, which is readonly to the public.
Ftp is used to commit changes, so that shall stay secret with Aprz.
But I realised, Aprz didn't actually upload his snapshot to my server before he went to sleep. So therefore this will only work as soon as Aprz uploads his project there and tells me about it, so I can chmod his files. There is currently a known bug with Bazaar + ftp, that creates the project with wrong permissions and that's what I've been fighting against today.
Offline
And everything should work now. I think Meelo meant:
% bzr branch bzr://anonymous@koti.meelo.org/aprz/ash myBranch
Or that's what I thought it was suppose to be, lol.
Offline
And everything should work now. I think Meelo meant:
% bzr branch bzr://anonymous@koti.meelo.org/aprz/ash myBranch
Or that's what I thought it was suppose to be, lol.
No, it uses dedicated 'bzr serve' which creates a bzr protocol, for which anonymous isn't anymore used. Anonymous is for ftp-access, so I meant what I said.
Offline
Blah, you make me feel stupid. :[ I didn't even notice the bzr://. I just took what you had and made the changes for what it would be if it was ftp://.
Offline
Hello.
Some time ago me with a friend had written a shell as a part for linux course. I developed it a little further, but right now i don't have time for it. Maybe you will find something useful in my code. I tried to comment it properly, but you know us lazy developers
The shell supports passing arguments to programs, redirection (>, >>, <), piping and running process in backgroud.
Ultra Stupid sHell
Offline
Hello.
Some time ago me with a friend had written a shell as a part for linux course. I developed it a little further, but right now i don't have time for it. Maybe you will find something useful in my code. I tried to comment it properly, but you know us lazy developers
The shell supports passing arguments to programs, redirection (>, >>, <), piping and running process in backgroud.
Ultra Stupid sHell
That looks like an excellent resource there I'm sure others will agree, thank you for posting this
Offline
That looks like an excellent resource there I'm sure others will agree, thank you for posting this
Thanks
I forgot to mention it has also history, aliases, multiple commands per line (divided by ";"), testing files (is directory, is exists, is current user is owner, is readable by current user, is file size 0) and viewing current jobs.
It has some bugs and ugly workarounds, but time was limited Maybe I'll fix it later.
Offline
Sounds very featureful, haha. I am still slacking. About to write to write a credit card validator in assembly instead, haha.
Last edited by Aprz (2009-07-05 11:20:10)
Offline
Pages: 1