PDA

View Full Version : [Source] Linux Minishell C



bulk_4me
11-11-2005, 06:31 PM
Description

All right I am ****ing tired from all the noob **** people post in this forum. This is a useful example, and a custom implementation of the List interface. I just ****ing hate to use default STL when they are not needed. It's also an example of pipes and inter-program communication in Linux.

Requirements

GNU C compiler & Linux.

No, I'm not posting a tutorial nor answering questions just ****ing read & learn.

As you may notice I suck in C but the bitch ass professor said no Java.. so **** it. Hope you like it.

lista.h
struct Nodo {
char *comando;
struct Nodo *siguiente;
};

typedef struct Nodo *nPointer;

nPointer creadNodo (char *);
void insertaNodo (nPointer *, nPointer *, char *);
void eliminaNodo (nPointer *, nPointer *);
void destruyeNodo (nPointer *);


lista.c
#include <stdlib.h>
#include "lista.h"

nPointer crearNodo(char *comando) {
nPointer temporal = (nPointer)malloc(sizeof(struct Nodo));

if (temporal != NULL){
temporal->comando = comando;
temporal->siguiente = NULL;
}

return temporal;
}

void insertaNodo(nPointer *cabeza, nPointer *cola, char *comando) {
nPointer temporal = crearNodo(comando);

if (temporal == NULL) return;

if(*cabeza == NULL) {
*cabeza = temporal;
*cola= temporal;
}
else {
(*cola)->siguiente = temporal;
*cola = temporal;
}
}

void eliminaNodo(nPointer *cabeza, nPointer *cola) {
nPointer temporal=*cabeza;

if(*cabeza == *cola) {
*cabeza = NULL;
*cola = NULL;
}
else {
*cabeza = (*cabeza)->siguiente;
free(temporal);
}
}

void destruyeNodo(nPointer *cabeza){
if(*cabeza==NULL) return;

destruyeNodo(&((*cabeza)->siguiente));
(*cabeza)->siguiente=NULL;
free(*cabeza);
}


dtsh.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include "lista.h"

#define MAX 256
#define MAXCHARS 1024
#define PROMPT ">> "
#define SALIR "exit\n"

void extraerStrings();
void ejecutarProceso(char *);
void obetenerRedireccion();
char * obtenInput(char *);
char * obtenOutput(char *);
int segundoPlano();
int validarCmdString();
void concatenarStrings();

char lineaDeComandos[MAXCHARS];
nPointer cabeza, cola;
int _segundoPlano = 0;
int _concatenar = 0;
char *in, *out;
char nin[100], nout[100];

int main() {
int numeroPipes = 0;
system("clear");
in = (char *)malloc(256*sizeof(char));
out =(char *)malloc(256 *sizeof(char));
signal(SIGINT,SIG_IGN);

while(strcmp(lineaDeComandos,SALIR) != 0){
destruyeNodo(&cabeza);
cola = NULL;
cabeza = NULL;
numeroPipes = 0;
_concatenar = 0;
fprintf(stderr,(PROMPT));
fgets(lineaDeComandos,MAXCHARS,stdin);
if(strcmp(lineaDeComandos,SALIR) != 0){
extraerStrings(&numeroPipes);
_segundoPlano = segundoPlano();
if(_segundoPlano!= -1){
cola->comando=strtok(cola->comando, "&");
obetenerRedireccion();
if(validarCmdString() == 1){
concatenarStrings();
}
}
}
}

destruyeNodo(&cabeza);
}

void concatenarStrings(){
nPointer temporal;
char pipa[]=" | ";
char *cola;
char destino[MAXCHARS+100]={'\0'};
for(temporal = cabeza; temporal != NULL; temporal = temporal->siguiente){
strcat(destino, temporal->comando);
strcat(destino, pipa);
}
cola = strrchr(destino, '|');
(*cola)= '\n';
ejecutarProceso(destino);
}

int validarCmdString(){
nPointer temporal = cabeza;
int ret=1, i=0;

while(temporal!=NULL && ret==1){
if(strlen(temporal->comando) == 0){
ret=5;
}
else{
ret = 0;
for(i=0; temporal->comando[i]!='\0'; i++)
if(temporal->comando[i] != ' '){
ret = 1;
break;
}
if(ret == 0)
fprintf(stderr,"Comando en blanco\n");
}
temporal = temporal->siguiente;
}
return ret;
}

int segundoPlano(){
char *_cabeza;
char *_cola;
int ret = 0, i = 0;
_cabeza = strchr(cola->comando,'&');
_cola = strrchr(cola->comando,'&');
if(_cabeza != 0){
if(_cabeza == _cola){
ret = 1;
_cabeza++;
for(i=0;_cabeza[i]!='\0';i++){
if(_cabeza[i]!='\n' && _cabeza[i]!='\0' && _cabeza[i]!=' '){
fprintf(stderr,"Caracteres inesperados despues de &\n");
ret = -1;
break;
}
}
}
else{
fprintf(stderr,"Se encontraron mas '&' de los soportados\n");
ret = -1;
}
}
return ret;
}

void obetenerRedireccion(){
char *lastCmd;
char *tok;
int apnd=0,i=0,j=0;
nin[0]='\0';
nout[0]='\0';
lastCmd=cola->comando;
in=obtenInput(lastCmd);
out=obtenOutput(lastCmd);
if(in!=NULL){
strcpy(nin,in);
for(i=0;nin[i]!='\0';i++)
if(nin[i]==' ')
nin[i]='\0';
}
if(out!=NULL){
strcpy(nout,out);
for(j=0;nout[j]!='\0';j++)
if(nout[j]==' ')
nout[j]='\0';
}
tok=strtok(lastCmd,"&<>\n");
cola->comando=tok;
}

char * obtenInput(char *cmd){
char copia[256]={'\0'};
char *tok;
strcpy(copia,cmd);
if(strchr(copia,'<')!=0){
tok=strtok(strchr(copia,'<'),"<");
tok=strtok(tok," \n");
return tok;
}
return NULL;
}

char * obtenOutput(char *cmd){
char copia[256]={'\0'};
char *tok;
strcpy(copia,cmd);
if(strchr(copia,'>')!=0){
if((strrchr(copia,'>'))==(strchr(copia,'>')+1))
_concatenar=1;
tok=strtok(strchr(copia,'>'),">");
tok=strtok(tok," \n");
return tok;
}
return NULL;
}

void extraerStrings(int *numPipes){
char *bloque;
char *linea;
int i=0;
bloque=(char *)malloc(MAXCHARS*sizeof(char));
linea=(char *)malloc(MAXCHARS*sizeof(char));
linea=strcpy(linea,lineaDeComandos);
bloque=strtok(linea,"|\n");
while(1){
insertaNodo(&cabeza,&cola,bloque);
(*numPipes)++;
bloque=strtok(NULL,"|\n");
if (bloque==NULL)
break;
}
(*numPipes)--;
}


void ejecutarProceso(char *s){
int i=0,j=0;
int pipa[2];
pid_t prev, pid;
int espera, status;
char *arr[MAX+1];
int glob=0;
char *tok, copia[MAX + 2];

strcpy(copia, s);
tok=strtok(s," \n");
while(1){
arr[glob++]=tok;
tok=strtok(NULL," \n");
if(tok==NULL)
break;
}

if (!glob)
return;
arr[glob] = NULL;

if(!strcmp(arr[0],"cd")){
chdir(arr[1]);
return;
}

switch (pid = fork()) {
case -1:
fprintf(stderr,"No se puede hacer el fork\n");
break;
case 0:
signal(SIGINT,SIG_DFL);
if (nin[0]!='\0'){
if(!freopen(nin,"r",stdin)){
fprintf(stderr,"Error al redireccionar la entrada: %s\n",strerror(errno));
exit(1);
}
}
if (nout[0]!='\0'){
if(!freopen(nout,(_concatenar==1?"a":"w"),stdout)){
fprintf(stderr,"Error al redireccionar la salida: %s\n",strerror(errno));
exit(1);
}
}
for (i = 0; i < glob; i++) {
for (j = i; i < glob; i++)
if (!strcmp(arr[i], "|"))
break;
arr[i] = NULL;
if (i < glob) {
pipe(pipa);
switch (prev = fork()) {
case -1:
fprintf(stderr,"No se puede hacer el fork\n");
exit(1);
case 0:
close(pipa[0]);
if (pipa[1] != STDOUT_FILENO) {
dup2(pipa[1], STDOUT_FILENO);
close(pipa[1]);
}
break;
default:
close(pipa[1]);
if (pipa[0] != STDIN_FILENO) {
dup2(pipa[0], STDIN_FILENO);
close(pipa[0]);
}
break;
}
if (!prev)
break;
}
}
execvp(arr[j], arr + j);
fprintf(stderr,"No se puede ejecutar el comando\n");
exit(1);
default:
if(!_segundoPlano)
wait(&status);
}
}


How to compile

gcc -c lista.c
gcc lista.o dtsh.c -o minishell

How to run

./minishell

Features

1 Kb command line
Unlimited Pipes
Bidirectional I/O redirection
Ability to redirect output to a file using the ">" directive
Ability to redirect and append output to an existent file using the ">>" directive
Background execution

Use "exit" to end the minishell.

gamepin126
11-11-2005, 06:36 PM
Secksy. I gotta say, you're the second coolest foreign person I know.

HARD_ON
11-11-2005, 06:37 PM
to bad i dont use linix.

gamepin126
11-11-2005, 06:38 PM
I was gonna install it, for job security reasons. But I was lazy. I was gonna install Gentoo cause I heard it was easy for people new to linux to play with. But then again...it takes like 4 hours to install...meh.

HARD_ON
11-11-2005, 06:44 PM
ya'll know of any good linix emulators?

bulk_4me
11-11-2005, 06:49 PM
ya'll know of any good linix emulators?
Cygwin (UNIX), but that's just stupid.

Also gamepin... don't be gay and install Debian.

Dyndrilliac
11-11-2005, 08:55 PM
Description

All right I am ****ing tired from all the noob **** people post in this forum. This is a useful example, and a custom implementation of the List interface. I just ****ing hate to use default STL when they are not needed. It's also an example of pipes and inter-program communication in Linux.

Is this directed at my Vector Sorting code? If so, I'm sorry; I didn't feel like making a custom vector class just for the purpose of showing people how to sort them. Hell, if I was worried about performance I would have used something besides Bubble sort.

BloodyBlade
11-11-2005, 09:02 PM
bulk, you seem so angry about this.

The only Linux experience I have is Red Hat. Infact, I think my ****box in the garage still has it installed.

bulk_4me
11-11-2005, 09:54 PM
Is this directed at my Vector Sorting code? If so, I'm sorry; I didn't feel like making a custom vector class just for the purpose of showing people how to sort them. Hell, if I was worried about performance I would have used something besides Bubble sort.
It was not specifically directed to your thread, I was talking in general... still Bubble Sort = Lamest Sorting Algorithm. I'm glad you posted that, I just feel that we (in general) should post good examples, that's all.

Dyndrilliac
11-11-2005, 10:08 PM
Well, I felt that implementing specific sorting algorithms was not the issue, it was showing the basic concept of sorting a data structure and making use of a data structure that a newbie would not normally used for the general purpose of holding data.

If it bothers you that much, I will update it with a divide and conquer sorting algorithm like quick sort. :)

bulk_4me
11-11-2005, 10:14 PM
Well, I felt that implementing specific sorting algorithms was not the issue, it was showing the basic concept of sorting a data structure and making use of a data structure that a newbie would not normally used for the general purpose of holding data.
Will be looking forward your contributions.