Newsgroup: it.comp.os.linux.development
Titolo: Come scrivere il mio proprio shell

Ciao, mi servirebbe sapere dove potrei trovare qualche piccola
informazione sul come scrivere un mio proprio piccolo shell per Linux,
per imparare e pratticare un po'. Per esempio, alcuna pagina web
con una piccola spiegazione su come si potrebbe fare oppure
un esempio di mini-shell.... ( a parte la possibilità, chiaramente,
di dare uno sguardo al source code di un shell come bash, ma
non ho molta voglia di dare uno sguardo a 5000 righe di source
code per farmi un piccolo mini-shell sperimentale di 100!!!)
Grazie in anticipo a chi mi vorrà informare e a tutti dall'attenzione
                          Sergio Gayol , Universtià di Oviedo, Spagna

 
Per cominciare le man page di fork, wait, exec sono quello da cui devi 
partire.
Poi puoi ridurre la mole di righe da guardare vedendo quello che fa ash.
Ciao
Simone

Poi puoi ridurre la mole di righe da guardare vedendo quello che fa ash.
Tante grazie, Simone. Ma comunque, alcuno conoscerebbe dove
trovare un esempio più piccolo di quanto siano i shell che si usano
realmente su Linux, uno da esempio per l'insegamento sui S.O. e/o
la sua programmazione. Ho sentito che c'è un libro, per esempio,
americano, che contiene un tale esempio come parte dell'insegnamento
delle tecniche di programmazione in ambiente Unix\Linux, ma non si
trova facilmente da queste parti, se non comprandolo in Amazon
e non è troppo economico, mentre la maggioranza dei concetti di
programmazione Linux si trovano più facilmente su altre fonti. Il
problema con questo caso è che cercando come programmare
un linux shell si trovano migliaia di pagine indicando come
programmare scripts per bash, ma non come programmare un proprio
shell, anche se piccolino e soltanto sperimentale. Grazie ancora,
                                                       Sergio

 trova facilmente da queste parti, se non comprandolo in Amazon
Se ti riferisci a /Advanced programming in the UNIX environment/, e`
disponibile in rete anche il tarball che contiene i sorgenti degli
esempi del libro, sul sito dell'autore mi pare. Prova a cercare con
google.
Quella shell e` comunque _veramente_ minimale, forse troppo per te.
$ wc -l shell1.c
     31 shell1.c
-- 
Fabio Bonelli  fabio161616(at)
libero.it
 blackmagic(at)
penguinpowered.com
And on the seventh day, He exited from append mode.

 la sua programmazione. 
Uh, Marco Iannaccone aveva creato una piccola shell per un progetto
all'universita`. 
Cmq, la struttura di massima sara` questa:
int main () {
 
	while(1) {
		leggi_input();
		parse_input();
		if (comando_interno)
			esegui_comando_interno;
		if (comando_esterno) {
 
			if (esiste(comando_esterno)) {
 
				if (fork() == 0) {
					/* Child */
					execv(programma, argomenti);
				} else
					wait(NULL);
			} else
				fprintf(stderr, "Errore!!\n");
		}
	}
}
 
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net
Software is like sex; it's better when it's free.
Linus Torvalds

Ecco, come in Subject, grazie a tutti dall'aiuto.
                                             Sergio

Sergio Gayol Menendez wrote:

..Questa shell l'ho realizzata in poco tempo cercando di renderla degna di
poter essere
chiamata 'funonziante'..Il codice poteva essere migliore ma non da'
problemi..Le uniche
cose in più rispetto al minimo sono la ricerca dei comandi/file
all'interno del PATH e
qualche messaggio d'errore sparso qua e là, e l'unico comando interno
realizzato è 'cd'
(a parte 'exit'..)..Lo spunto di quest'idea e lo schema
dell'implementazione le ho prese
da Kronos che ha postato prima di me..
..Spero ti piaccia e ti aiuti per quello che ti serve,
      tano..
//  FILE tanosh.c
//  (c) by TANO..
//
//  La mia shell personale..
//  Versione 0.1.00 (sviluppo)
//
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#define TANOSH_MESSAGE "  Versione 0.1.00 - sviluppo\n\n"
#define LEN 80
#define ARG 10
#define TRUE 1
#define FALSE 0
#define SPACE ' '
#define NEW_LINE '\n'
#define EOT '\0'
#define MARKS ':'
#define BACKSLASH '/'
#define TANOSH_PROMPT "_ "
/*  Variabili d'ambiente..  */
char *HOME;
char *PATH;
void envy()
{
    HOME = getenv("HOME");
    PATH = getenv("PATH");
    return;
}
/*  Funzioni..  */
void copy(char *one, char *two)
{
    int i;
    i = 0;
    do
 one[i] = two[i];
    while (two[i++] != EOT);
    return;
}
int split(char *line, char *argv[])
{
    int i, j;
    int booly;
    int n;
    char tmp[LEN];
    booly = FALSE;
    n = 0;
    j = 0;
    for (i = 0; i < LEN; i++) {
 if (line[i] != SPACE && line[i] != NEW_LINE && line[i] != EOT) {
     booly = TRUE;
     tmp[j++] = line[i];
     continue;
 }
 if (line[i] == SPACE && booly == TRUE) {
     booly = FALSE;
     argv[n] = (char *) malloc(LEN);
     tmp[j] = EOT;
     copy(argv[n], tmp);
     j = 0;
     n++;
     continue;
 }
 if (line[i] == NEW_LINE || line[i] == EOT) {
     if (booly == TRUE) {
  argv[n] = (char *) malloc(LEN);
  tmp[j] = EOT;
  copy(argv[n], tmp);
  n++;
     }
     break;
 }
    }
    argv[n] = NULL;
    return n;
}
void readline(char *line)
{
    int i;
    for (i = 0; i < LEN - 1; i++) {
 line[i] = getchar();
 if (line[i] == NEW_LINE) {
     line[i] = EOT;
     break;
 }
    }
}
int len(char *one)
{
    int i;
    i = 0;
    while (1) {
 if (one[i] == EOT)
     break;
 i++;
    }
    return i;
}
int cmp(char *one, char *two)
{
    int i;
    if (len(one) != len(two))
 return FALSE;
    for (i = 0; i < len(one); i++)
 if (one[i] != two[i])
     return FALSE;
    return TRUE;
}
void insert(char *one, char *two)
{
    int i, l;
    char three[LEN];
    for (i = 0; i < len(one); i++)
 three[i] = one[i];
    for (i = len(one); i <= len(one) + len(two); i++)
 three[i] = two[i - len(one)];
    copy(two, three);
    return;
}
int main()
{
    char line[LEN];
    char *path;
    char *argv[ARG];
    char littlepath[LEN];
    int i, j, n;
    printf("\n  tanosh.c - (c) by TANO..\n");
    printf("\n  La mia shell personale..\n");
    printf(TANOSH_MESSAGE);
    while (TRUE) {
 envy();
 printf(TANOSH_PROMPT);
 readline(line);
 n = split(line, argv);
 if (n != 0)
     path = argv[0];
 else {
     path = NULL;
     continue;
 }
 if (cmp(path, "exit") == TRUE)
     break;
 else if (cmp(path, "cd") == TRUE) {
     if (n == 1)
  chdir(HOME);
     else if (n == 2) {
  if (chdir(argv[1]) == -1)
      printf("\n  can't change directory!!\n");
     } else
  printf("\n  too many arguments!!\n");
     for (i = 0; i < n; i++)
  free(argv[i]);
 } else {
     if (fork() == 0) {
  int henry;
  henry = FALSE;
  if (execv(path, argv) == -1) {
      henry = TRUE;
      j = 0;
      for (i = 0; i <= len(PATH); i++) {
   littlepath[j] = PATH[i];
   if (PATH[i] == MARKS || PATH[i] == EOT) {
       char help[LEN];
       copy(help, argv[0]);
       littlepath[j] = BACKSLASH;
       littlepath[j + 1] = EOT;
       insert(littlepath, argv[0]);
       if (execv(path, argv) != -1) {
    henry = FALSE;
    break;
       }
       copy(argv[0], help);
       j = 0;
       continue;
   }
   j++;
      }
  }
  for (i = 0; i < n; i++)
      free(argv[i]);
  if (henry == TRUE)
      printf("\n  No file..\n");
  exit(0);
     } else
  wait(NULL);
 }
    }
}


l'idea è buona, la didattica anche... la strada può darsi che sia la 
giusta...
solo 3 cose:
1- ho perso 20 minuti per editarmi il codice e reindentarlo per capire come     
	fluiva. (ma il tasto TAB la tua tastiera ce l'ha?? e i commenti non     
	li usi? guarda che servono anche a te!)
2- Sei sicuro che sia una buona idea usare questo sproposito di if annidati
    piuttosto che dare ad un'altra funzione (e uno switch) il compito reale     
	di interprete?
    	se decidi di estenderti la shell con altri comandi builtin diventi     
	matto...
    	(parti dal pwd, almeno uno sa dove si trova!!)
3- i messaggi di errore, mandali sullo stderr già dalle prime release,     
	quando la shell sarà grande a sufficienza, torneranno utili!
buon lavoro comunque,
ciao  ;-)

 	li usi? guarda che servono anche a te!)
Se hai Emacs, carica il file e dai questi due comandi:
M-x mark-whole-buffer
M-x indent-region
Voila`, tutto indentato.  Si`, ormai per stavolta e` fatta, ma se ti
serve in futuro sai come fare. :-)
Massimiliano

Ta daaaà!!Ecco la nuova versione grazie ai suggerimenti di punkarruso(preferivo
se eri
skaarruso, ah ah!!)..Questa è, cioè, sembra più modulare di quella precedente,
ma ho
trovato un quasi-bug o non so cosa..Se nel listato inserisci una printf(line)
dopo la
linea:
fprintf(stdout,SHH_PROMPT);
readline(line);
printf("QUALSIASI_COSA_ANCHE_LINE");
<-----------------------------Esattamente qui!!
(io ho fatto una funzione parse() per appendere tutto in un history file..)
noterai che
eseguendo la shell se il comando inserito è conosciuto all'interno del
PATH(
es.ls
) o
anche interno(l'importante è che venga eseguito..) la shell reagisce così:
QUALSIASI_COSA_ANCHE_LINE
..Se invece non riesce a eseguirlo così:
QUALSIASI_COSA_ANCHE_LINE
QUALSIASI_COSA_ANCHE_LINE
..Cosa c'è che non va?
..Io penso abbia a che fare coi processi(?!?!) ma non saprei..
..Spero che qualcuno mi faccia sapere, io intanto lo ringrazio,
                                                                tano
POST SCRIPTUM: Se il codice è identato così è perchè faccio un copia-incolla da
               linux a windows.. Io idento(si dice identare o indentare?) così:
               indent -kr file.c
//  FILE shh.c
//  (c) by TANO..
//
//  La mia piccola shell personale..
//  Versione 0.2.00 (Sviluppo)
//
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
/*  Definizioni..  */
#define LEN        80
#define ARG        10
#define TRUE        1
#define FALSE       0
#define SPACE      ' '
#define NEW_LINE   '\n'
#define EOT        '\0'
#define MARKS      ':'
#define BACKSLASH  '/'
#define SHH_MESSAGE "\n  Shh.c\n\n  My little shell.."
#define SHH_VERSION "\n  Version 0.2.00 (Development)\n\n"
#define SHH_PROMPT  "[Shh]_ "
/*  Messaggi..  */
#define MSG_NO_FOUND  "\n  No file or command..\n"
#define MSG_CD_HENRY  "\n  Can't change directory..\n"
#define MSG_TOO_MANY  "\n  Too many arguments..\n"
#define MSG_EXIT      "\n  Bye bye!!\n"
/*  Variabili d'ambiente..  */
char *HOME;
char *PATH;
/*  Codice..  */
/*  get_env_var:
    Aggiorna le variabili d'ambiente..  */
void get_env_var()
{
    HOME = getenv("HOME");
    PATH = getenv("PATH");
    return;
}
/*  split:
    Suddivide la linea letta in comando e argomenti..  */
int split(char *line, char *argv[])
{
    int i, j;
    int booly;
    int n;
    char tmp[LEN];
    booly = FALSE;
    n = 0;
    j = 0;
    for (i = 0; i < LEN; i++) {
 if (line[i] != SPACE && line[i] != NEW_LINE && line[i] != EOT) {
     booly = TRUE;
     tmp[j++] = line[i];
     continue;
 }
 if (line[i] == SPACE && booly == TRUE) {
     booly = FALSE;
     argv[n] = (char *) malloc(LEN);
     tmp[j] = EOT;
     strcpy(argv[n], tmp);
     j = 0;
     n++;
     continue;
 }
 if (line[i] == NEW_LINE || line[i] == EOT) {
     if (booly == TRUE) {
  argv[n] = (char *) malloc(LEN);
  tmp[j] = EOT;
  strcpy(argv[n], tmp);
  n++;
     }
     break;
 }
    }
    argv[n] = NULL;
    return n;
}
/*  Comandi interni..  */
void built_in_cd(char *path, char *argv[], int n)
{
    int i;
    if (n == 1)
 chdir(HOME);
    else if (n == 2) {
 if (chdir(argv[1]) == -1)
     fprintf(stderr, MSG_CD_HENRY);
    } else
 fprintf(stderr, MSG_TOO_MANY);
    for (i = 0; i < n; i++)
 free(argv[i]);
    return;
}
void built_in_exit(char *path, char *argv[], int n)
{
    if (n != 1)
 fprintf(stderr, MSG_TOO_MANY);
    else {
 fprintf(stdout, MSG_EXIT);
 exit(0);
    }
    return;
}
void built_in_pwd(char *path, char *argv[], int n)
{
    if (n != 1)
 fprintf(stderr, MSG_TOO_MANY);
    else {
 fprintf(stdout, getcwd(NULL, 0));
 fprintf(stdout, "\n");
    }
    return;
}
/*  built_in:
    Verifica se è un comando interno..  */
int built_in(char *path, char *argv[], int n)
{
    if (strcmp(path, "cd") == FALSE) {
 built_in_cd(path, argv, n);
 return TRUE;
    } else if (strcmp(path, "pwd") == FALSE) {
 built_in_pwd(path, argv, n);
 return TRUE;
    } else if (strcmp(path, "exit") == FALSE)
 built_in_exit(path, argv, n);
    else
 return FALSE;
}
/*  readline:
    input da tastiera..  */
void readline(char *line)
{
    int i;
    for (i = 0; i < LEN; i++) {
 line[i] = getchar();
 if (line[i] == NEW_LINE) {
     line[i] = EOT;
     break;
 }
    }
    return;
}
/*  insert:
    Concatena due stringhe..
    two <- onetwo..  */
void insert(char *one, char *two)
{
    int i, l;
    char three[LEN];
    for (i = 0; i < strlen(one); i++)
 three[i] = one[i];
    for (i = strlen(one); i <= strlen(one) + strlen(two); i++)
 three[i] = two[i - strlen(one)];
    strcpy(two, three);
    return;
}
/*  main..  */
int main()
{
    char line[LEN];
    char *path;
    char *argv[ARG];
    char littlepath[LEN];
    int i, j, n;
    fprintf(stdout, SHH_MESSAGE);
    fprintf(stdout, SHH_VERSION);
    while (TRUE) {
 get_env_var();
 fprintf(stdout, SHH_PROMPT);
 readline(line);
 n = split(line, argv);
 if (n != 0)
     path = argv[0];
 else {
     path = NULL;
     continue;
 }
 if (built_in(path, argv, n) == TRUE);
 else {
     if (fork() == 0) {
  int henry;
  henry = FALSE;
  if (execv(path, argv) == -1) {
      henry = TRUE;
      j = 0;
      for (i = 0; i <= strlen(PATH); i++) {
   littlepath[j] = PATH[i];
   if (PATH[i] == MARKS || PATH[i] == EOT) {
       char help[LEN];
       strcpy(help, argv[0]);
       littlepath[j] = BACKSLASH;
       littlepath[j + 1] = EOT;
       insert(littlepath, argv[0]);
       if (execv(path, argv) != -1) {
    henry = FALSE;
    break;
       }
       strcpy(argv[0], help);
       j = 0;
       continue;
   }
   j++;
      }
  }
  for (i = 0; i < n; i++)
      free(argv[i]);
  if (henry == TRUE)
      fprintf(stderr, MSG_NO_FOUND);
  exit(0);
     } else
  wait(NULL);
 }
    }
}




QUALSIASI_COSA_ANCHE_LINE

QUALSIASI_COSA_ANCHE_LINE
QUALSIASI_COSA_ANCHE_LINE



               indent -kr file.c
//  FILE shh.c
//  (c) by TANO..
//
//  La mia piccola shell personale..
//  Versione 0.2.00 (Sviluppo)
//
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
/*  Definizioni..  */
#define LEN        80
#define ARG        10
#define TRUE        1
#define FALSE       0
#define SPACE      ' '
#define NEW_LINE   '\n'
#define EOT        '\0'
#define MARKS      ':'
#define BACKSLASH  '/'
#define SHH_MESSAGE "\n  Shh.c\n\n  My little shell.."
#define SHH_VERSION "\n  Version 0.2.00 (Development)\n\n"
#define SHH_PROMPT  "[Shh]_ "
/*  Messaggi..  */
#define MSG_NO_FOUND  "\n  No file or command..\n"
#define MSG_CD_HENRY  "\n  Can't change directory..\n"
#define MSG_TOO_MANY  "\n  Too many arguments..\n"
#define MSG_EXIT      "\n  Bye bye!!\n"
/*  Variabili d'ambiente..  */
char *HOME;
char *PATH;
/*  Codice..  */
/*  get_env_var:
    Aggiorna le variabili d'ambiente..  */
void get_env_var()
{
    HOME = getenv("HOME");
    PATH = getenv("PATH");
    return;
}
/*  split:
    Suddivide la linea letta in comando e argomenti..  */
int split(char *line, char *argv[])
{
    int i, j;
    int booly;
    int n;
    char tmp[LEN];
    booly = FALSE;
    n = 0;
    j = 0;
    for (i = 0; i < LEN; i++) {
 if (line[i] != SPACE && line[i] != NEW_LINE && line[i] != EOT) {
     booly = TRUE;
     tmp[j++] = line[i];
     continue;
 }
 if (line[i] == SPACE && booly == TRUE) {
     booly = FALSE;
     argv[n] = (char *) malloc(LEN);
     tmp[j] = EOT;
     strcpy(argv[n], tmp);
     j = 0;
     n++;
     continue;
 }
 if (line[i] == NEW_LINE || line[i] == EOT) {
     if (booly == TRUE) {
  argv[n] = (char *) malloc(LEN);
  tmp[j] = EOT;
  strcpy(argv[n], tmp);
  n++;
     }
     break;
 }
    }
    argv[n] = NULL;
    return n;
}
/*  Comandi interni..  */
void built_in_cd(char *path, char *argv[], int n)
{
    int i;
    if (n == 1)
 chdir(HOME);
    else if (n == 2) {
 if (chdir(argv[1]) == -1)
     fprintf(stderr, MSG_CD_HENRY);
    } else
 fprintf(stderr, MSG_TOO_MANY);
    for (i = 0; i < n; i++)
 free(argv[i]);
    return;
}





void readline(char *line)
{
    int i;
    for (i = 0; i < LEN; i++) {
 line[i] = getchar();
 if (line[i] == NEW_LINE) {
     line[i] = EOT;
     break;
 }
    }
    return;
}
/*  insert:
    Concatena due stringhe..
    two <- onetwo..  */
void insert(char *one, char *two)
{
    int i, l;
    char three[LEN];
    for (i = 0; i < strlen(one); i++)
 three[i] = one[i];
    for (i = strlen(one); i <= strlen(one) + strlen(two); i++)
 three[i] = two[i - strlen(one)];
    strcpy(two, three);
    return;
}
/*  main..  */
int main()
{
    char line[LEN];
    char *path;
    char *argv[ARG];
    char littlepath[LEN];
    int i, j, n;
    fprintf(stdout, SHH_MESSAGE);
    fprintf(stdout, SHH_VERSION);
    while (TRUE) {
 get_env_var();
 fprintf(stdout, SHH_PROMPT);
 readline(line);
 n = split(line, argv);
 if (n != 0)
     path = argv[0];
 else {
     path = NULL;
     continue;
 }
 if (built_in(path, argv, n) == TRUE);
 else {
     if (fork() == 0) {
  int henry;
  henry = FALSE;
  if (execv(path, argv) == -1) {
      henry = TRUE;
      j = 0;
      for (i = 0; i <= strlen(PATH); i++) {
   littlepath[j] = PATH[i];
   if (PATH[i] == MARKS || PATH[i] == EOT) {
       char help[LEN];
       strcpy(help, argv[0]);
       littlepath[j] = BACKSLASH;
       littlepath[j + 1] = EOT;
       insert(littlepath, argv[0]);
       if (execv(path, argv) != -1) {
    henry = FALSE;
    break;
       }
       strcpy(argv[0], help);
       j = 0;
       continue;
   }
   j++;
      }
  }
  for (i = 0; i < n; i++)
      free(argv[i]);
  if (henry == TRUE)





QUALSIASI_COSA_ANCHE_LINE

QUALSIASI_COSA_ANCHE_LINE
QUALSIASI_COSA_ANCHE_LINE



               indent -kr file.c
//  FILE shh.c
//  (c) by TANO..
//
//  La mia piccola shell personale..
//  Versione 0.2.00 (Sviluppo)
//
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
/*  Definizioni..  */
#define LEN        80
#define ARG        10
#define TRUE        1
#define FALSE       0
#define SPACE      ' '
#define NEW_LINE   '\n'
#define EOT        '\0'
#define MARKS      ':'
#define BACKSLASH  '/'
#define SHH_MESSAGE "\n  Shh.c\n\n  My little shell.."
#define SHH_VERSION "\n  Version 0.2.00 (Development)\n\n"
#define SHH_PROMPT  "[Shh]_ "
/*  Messaggi..  */
#define MSG_NO_FOUND  "\n  No file or command..\n"
#define MSG_CD_HENRY  "\n  Can't change directory..\n"
#define MSG_TOO_MANY  "\n  Too many arguments..\n"
#define MSG_EXIT      "\n  Bye bye!!\n"
/*  Variabili d'ambiente..  */
char *HOME;
char *PATH;
/*  Codice..  */
/*  get_env_var:
    Aggiorna le variabili d'ambiente..  */
void get_env_var()
{
    HOME = getenv("HOME");
    PATH = getenv("PATH");
    return;
}
/*  split:
    Suddivide la linea letta in comando e argomenti..  */
int split(char *line, char *argv[])
{
    int i, j;
    int booly;
    int n;
    char tmp[LEN];
    booly = FALSE;
    n = 0;
    j = 0;
    for (i = 0; i < LEN; i++) {
 if (line[i] != SPACE && line[i] != NEW_LINE && line[i] != EOT) {
     booly = TRUE;
     tmp[j++] = line[i];
     continue;
 }
 if (line[i] == SPACE && booly == TRUE) {
     booly = FALSE;
     argv[n] = (char *) malloc(LEN);
     tmp[j] = EOT;
     strcpy(argv[n], tmp);
     j = 0;
     n++;
     continue;
 }
 if (line[i] == NEW_LINE || line[i] == EOT) {
     if (booly == TRUE) {
  argv[n] = (char *) malloc(LEN);
  tmp[j] = EOT;
  strcpy(argv[n], tmp);
  n++;
     }
     break;
 }
    }
    argv[n] = NULL;
    return n;
}
/*  Comandi interni..  */
void built_in_cd(char *path, char *argv[], int n)
{
    int i;
    if (n == 1)
 chdir(HOME);
    else if (n == 2) {
 if (chdir(argv[1]) == -1)
     fprintf(stderr, MSG_CD_HENRY);
    } else
 fprintf(stderr, MSG_TOO_MANY);
    for (i = 0; i < n; i++)
 free(argv[i]);
    return;
}





void readline(char *line)
{
    int i;
    for (i = 0; i < LEN; i++) {
 line[i] = getchar();
 if (line[i] == NEW_LINE) {
     line[i] = EOT;
     break;
 }
    }
    return;
}
/*  insert:
    Concatena due stringhe..
    two <- onetwo..  */
void insert(char *one, char *two)
{
    int i, l;
    char three[LEN];
    for (i = 0; i < strlen(one); i++)
 three[i] = one[i];
    for (i = strlen(one); i <= strlen(one) + strlen(two); i++)
 three[i] = two[i - strlen(one)];
    strcpy(two, three);
    return;
}
/*  main..  */
int main()
{
    char line[LEN];
    char *path;
    char *argv[ARG];
    char littlepath[LEN];
    int i, j, n;
    fprintf(stdout, SHH_MESSAGE);
    fprintf(stdout, SHH_VERSION);
    while (TRUE) {
 get_env_var();
 fprintf(stdout, SHH_PROMPT);
 readline(line);
 n = split(line, argv);
 if (n != 0)
     path = argv[0];
 else {
     path = NULL;
     continue;
 }
 if (built_in(path, argv, n) == TRUE);
 else {
     if (fork() == 0) {
  int henry;
  henry = FALSE;
  if (execv(path, argv) == -1) {
      henry = TRUE;
      j = 0;
      for (i = 0; i <= strlen(PATH); i++) {
   littlepath[j] = PATH[i];
   if (PATH[i] == MARKS || PATH[i] == EOT) {
       char help[LEN];
       strcpy(help, argv[0]);
       littlepath[j] = BACKSLASH;
       littlepath[j + 1] = EOT;
       insert(littlepath, argv[0]);
       if (execv(path, argv) != -1) {
    henry = FALSE;
    break;
       }
       strcpy(argv[0], help);
       j = 0;
       continue;
   }
   j++;
      }
  }
  for (i = 0; i < n; i++)
      free(argv[i]);
  if (henry == TRUE)





QUALSIASI_COSA_ANCHE_LINE

QUALSIASI_COSA_ANCHE_LINE
QUALSIASI_COSA_ANCHE_LINE



               indent -kr file.c
//  FILE shh.c
//  (c) by TANO..
//
//  La mia piccola shell personale..
//  Versione 0.2.00 (Sviluppo)
//
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
/*  Definizioni..  */
#define LEN        80
#define ARG        10
#define TRUE        1
#define FALSE       0
#define SPACE      ' '
#define NEW_LINE   '\n'
#define EOT        '\0'
#define MARKS      ':'
#define BACKSLASH  '/'
#define SHH_MESSAGE "\n  Shh.c\n\n  My little shell.."
#define SHH_VERSION "\n  Version 0.2.00 (Development)\n\n"
#define SHH_PROMPT  "[Shh]_ "
/*  Messaggi..  */
#define MSG_NO_FOUND  "\n  No file or command..\n"
#define MSG_CD_HENRY  "\n  Can't change directory..\n"
#define MSG_TOO_MANY  "\n  Too many arguments..\n"
#define MSG_EXIT      "\n  Bye bye!!\n"
/*  Variabili d'ambiente..  */
char *HOME;
char *PATH;
/*  Codice..  */
/*  get_env_var:
    Aggiorna le variabili d'ambiente..  */
void get_env_var()
{
    HOME = getenv("HOME");
    PATH = getenv("PATH");
    return;
}
/*  split:
    Suddivide la linea letta in comando e argomenti..  */
int split(char *line, char *argv[])
{
    int i, j;
    int booly;
    int n;
    char tmp[LEN];
    booly = FALSE;
    n = 0;
    j = 0;
    for (i = 0; i < LEN; i++) {
 if (line[i] != SPACE && line[i] != NEW_LINE && line[i] != EOT) {
     booly = TRUE;
     tmp[j++] = line[i];
     continue;
 }
 if (line[i] == SPACE && booly == TRUE) {
     booly = FALSE;
     argv[n] = (char *) malloc(LEN);
     tmp[j] = EOT;
     strcpy(argv[n], tmp);
     j = 0;
     n++;
     continue;
 }
 if (line[i] == NEW_LINE || line[i] == EOT) {
     if (booly == TRUE) {
  argv[n] = (char *) malloc(LEN);
  tmp[j] = EOT;
  strcpy(argv[n], tmp);
  n++;
     }
     break;
 }
    }
    argv[n] = NULL;
    return n;
}
/*  Comandi interni..  */
void built_in_cd(char *path, char *argv[], int n)
{
    int i;
    if (n == 1)
 chdir(HOME);
    else if (n == 2) {
 if (chdir(argv[1]) == -1)
     fprintf(stderr, MSG_CD_HENRY);
    } else
 fprintf(stderr, MSG_TOO_MANY);
    for (i = 0; i < n; i++)
 free(argv[i]);
    return;
}





void readline(char *line)
{
    int i;
    for (i = 0; i < LEN; i++) {
 line[i] = getchar();
 if (line[i] == NEW_LINE) {
     line[i] = EOT;
     break;
 }
    }
    return;
}
/*  insert:
    Concatena due stringhe..
    two <- onetwo..  */
void insert(char *one, char *two)
{
    int i, l;
    char three[LEN];
    for (i = 0; i < strlen(one); i++)
 three[i] = one[i];
    for (i = strlen(one); i <= strlen(one) + strlen(two); i++)
 three[i] = two[i - strlen(one)];
    strcpy(two, three);
    return;
}
/*  main..  */
int main()
{
    char line[LEN];
    char *path;
    char *argv[ARG];
    char littlepath[LEN];
    int i, j, n;
    fprintf(stdout, SHH_MESSAGE);
    fprintf(stdout, SHH_VERSION);
    while (TRUE) {
 get_env_var();
 fprintf(stdout, SHH_PROMPT);
 readline(line);
 n = split(line, argv);
 if (n != 0)
     path = argv[0];
 else {
     path = NULL;
     continue;
 }
 if (built_in(path, argv, n) == TRUE);
 else {
     if (fork() == 0) {
  int henry;
  henry = FALSE;
  if (execv(path, argv) == -1) {
      henry = TRUE;
      j = 0;
      for (i = 0; i <= strlen(PATH); i++) {
   littlepath[j] = PATH[i];
   if (PATH[i] == MARKS || PATH[i] == EOT) {
       char help[LEN];
       strcpy(help, argv[0]);
       littlepath[j] = BACKSLASH;
       littlepath[j + 1] = EOT;
       insert(littlepath, argv[0]);
       if (execv(path, argv) != -1) {
    henry = FALSE;
    break;
       }
       strcpy(argv[0], help);
       j = 0;
       continue;
   }
   j++;
      }
  }
  for (i = 0; i < n; i++)
      free(argv[i]);
  if (henry == TRUE)





QUALSIASI_COSA_ANCHE_LINE

QUALSIASI_COSA_ANCHE_LINE
QUALSIASI_COSA_ANCHE_LINE



               indent -kr file.c
//  FILE shh.c
//  (c) by TANO..
//
//  La mia piccola shell personale..
//  Versione 0.2.00 (Sviluppo)
//
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
/*  Definizioni..  */
#define LEN        80
#define ARG        10
#define TRUE        1
#define FALSE       0
#define SPACE      ' '
#define NEW_LINE   '\n'
#define EOT        '\0'
#define MARKS      ':'
#define BACKSLASH  '/'
#define SHH_MESSAGE "\n  Shh.c\n\n  My little shell.."
#define SHH_VERSION "\n  Version 0.2.00 (Development)\n\n"
#define SHH_PROMPT  "[Shh]_ "
/*  Messaggi..  */
#define MSG_NO_FOUND  "\n  No file or command..\n"
#define MSG_CD_HENRY  "\n  Can't change directory..\n"
#define MSG_TOO_MANY  "\n  Too many arguments..\n"
#define MSG_EXIT      "\n  Bye bye!!\n"
/*  Variabili d'ambiente..  */
char *HOME;
char *PATH;
/*  Codice..  */
/*  get_env_var:
    Aggiorna le variabili d'ambiente..  */
void get_env_var()
{
    HOME = getenv("HOME");
    PATH = getenv("PATH");
    return;
}
/*  split:
    Suddivide la linea letta in comando e argomenti..  */
int split(char *line, char *argv[])
{
    int i, j;
    int booly;
    int n;
    char tmp[LEN];
    booly = FALSE;
    n = 0;
    j = 0;
    for (i = 0; i < LEN; i++) {
 if (line[i] != SPACE && line[i] != NEW_LINE && line[i] != EOT) {
     booly = TRUE;
     tmp[j++] = line[i];
     continue;
 }
 if (line[i] == SPACE && booly == TRUE) {
     booly = FALSE;
     argv[n] = (char *) malloc(LEN);
     tmp[j] = EOT;
     strcpy(argv[n], tmp);
     j = 0;
     n++;
     continue;
 }
 if (line[i] == NEW_LINE || line[i] == EOT) {
     if (booly == TRUE) {
  argv[n] = (char *) malloc(LEN);
  tmp[j] = EOT;
  strcpy(argv[n], tmp);
  n++;
     }
     break;
 }
    }
    argv[n] = NULL;
    return n;
}
/*  Comandi interni..  */
void built_in_cd(char *path, char *argv[], int n)
{
    int i;
    if (n == 1)
 chdir(HOME);
    else if (n == 2) {
 if (chdir(argv[1]) == -1)
     fprintf(stderr, MSG_CD_HENRY);
    } else
 fprintf(stderr, MSG_TOO_MANY);
    for (i = 0; i < n; i++)
 free(argv[i]);
    return;
}





void readline(char *line)
{
    int i;
    for (i = 0; i < LEN; i++) {
 line[i] = getchar();
 if (line[i] == NEW_LINE) {
     line[i] = EOT;
     break;
 }
    }
    return;
}
/*  insert:
    Concatena due stringhe..
    two <- onetwo..  */
void insert(char *one, char *two)
{
    int i, l;
    char three[LEN];
    for (i = 0; i < strlen(one); i++)
 three[i] = one[i];
    for (i = strlen(one); i <= strlen(one) + strlen(two); i++)
 three[i] = two[i - strlen(one)];
    strcpy(two, three);
    return;
}
/*  main..  */
int main()
{
    char line[LEN];
    char *path;
    char *argv[ARG];
    char littlepath[LEN];
    int i, j, n;
    fprintf(stdout, SHH_MESSAGE);
    fprintf(stdout, SHH_VERSION);
    while (TRUE) {
 get_env_var();
 fprintf(stdout, SHH_PROMPT);
 readline(line);
 n = split(line, argv);
 if (n != 0)
     path = argv[0];
 else {
     path = NULL;
     continue;
 }
 if (built_in(path, argv, n) == TRUE);
 else {
     if (fork() == 0) {
  int henry;
  henry = FALSE;
  if (execv(path, argv) == -1) {
      henry = TRUE;
      j = 0;
      for (i = 0; i <= strlen(PATH); i++) {
   littlepath[j] = PATH[i];
   if (PATH[i] == MARKS || PATH[i] == EOT) {
       char help[LEN];
       strcpy(help, argv[0]);
       littlepath[j] = BACKSLASH;
       littlepath[j + 1] = EOT;
       insert(littlepath, argv[0]);
       if (execv(path, argv) != -1) {
    henry = FALSE;
    break;
       }
       strcpy(argv[0], help);
       j = 0;
       continue;
   }
   j++;
      }
  }
  for (i = 0; i < n; i++)
      free(argv[i]);
  if (henry == TRUE)





QUALSIASI_COSA_ANCHE_LINE

QUALSIASI_COSA_ANCHE_LINE
QUALSIASI_COSA_ANCHE_LINE



               indent -kr file.c
//  FILE shh.c
//  (c) by TANO..
//
//  La mia piccola shell personale..
//  Versione 0.2.00 (Sviluppo)
//
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
/*  Definizioni..  */
#define LEN        80
#define ARG        10
#define TRUE        1
#define FALSE       0
#define SPACE      ' '
#define NEW_LINE   '\n'
#define EOT        '\0'
#define MARKS      ':'
#define BACKSLASH  '/'
#define SHH_MESSAGE "\n  Shh.c\n\n  My little shell.."
#define SHH_VERSION "\n  Version 0.2.00 (Development)\n\n"
#define SHH_PROMPT  "[Shh]_ "
/*  Messaggi..  */
#define MSG_NO_FOUND  "\n  No file or command..\n"
#define MSG_CD_HENRY  "\n  Can't change directory..\n"
#define MSG_TOO_MANY  "\n  Too many arguments..\n"
#define MSG_EXIT      "\n  Bye bye!!\n"
/*  Variabili d'ambiente..  */
char *HOME;
char *PATH;
/*  Codice..  */
/*  get_env_var:
    Aggiorna le variabili d'ambiente..  */
void get_env_var()
{
    HOME = getenv("HOME");
    PATH = getenv("PATH");
    return;
}
/*  split:
    Suddivide la linea letta in comando e argomenti..  */
int split(char *line, char *argv[])
{
    int i, j;
    int booly;
    int n;
    char tmp[LEN];
    booly = FALSE;
    n = 0;
    j = 0;
    for (i = 0; i < LEN; i++) {
 if (line[i] != SPACE && line[i] != NEW_LINE && line[i] != EOT) {
     booly = TRUE;
     tmp[j++] = line[i];
     continue;
 }
 if (line[i] == SPACE && booly == TRUE) {
     booly = FALSE;
     argv[n] = (char *) malloc(LEN);
     tmp[j] = EOT;
     strcpy(argv[n], tmp);
     j = 0;
     n++;
     continue;
 }
 if (line[i] == NEW_LINE || line[i] == EOT) {
     if (booly == TRUE) {
  argv[n] = (char *) malloc(LEN);
  tmp[j] = EOT;
  strcpy(argv[n], tmp);
  n++;
     }
     break;
 }
    }
    argv[n] = NULL;
    return n;
}
/*  Comandi interni..  */
void built_in_cd(char *path, char *argv[], int n)
{
    int i;
    if (n == 1)
 chdir(HOME);
    else if (n == 2) {
 if (chdir(argv[1]) == -1)
     fprintf(stderr, MSG_CD_HENRY);
    } else
 fprintf(stderr, MSG_TOO_MANY);
    for (i = 0; i < n; i++)
 free(argv[i]);
    return;
}





void readline(char *line)
{
    int i;
    for (i = 0; i < LEN; i++) {
 line[i] = getchar();
 if (line[i] == NEW_LINE) {
     line[i] = EOT;
     break;
 }
    }
    return;
}
/*  insert:
    Concatena due stringhe..
    two <- onetwo..  */
void insert(char *one, char *two)
{
    int i, l;
    char three[LEN];
    for (i = 0; i < strlen(one); i++)
 three[i] = one[i];
    for (i = strlen(one); i <= strlen(one) + strlen(two); i++)
 three[i] = two[i - strlen(one)];
    strcpy(two, three);
    return;
}
/*  main..  */
int main()
{
    char line[LEN];
    char *path;
    char *argv[ARG];
    char littlepath[LEN];
    int i, j, n;
    fprintf(stdout, SHH_MESSAGE);
    fprintf(stdout, SHH_VERSION);
    while (TRUE) {
 get_env_var();
 fprintf(stdout, SHH_PROMPT);
 readline(line);
 n = split(line, argv);
 if (n != 0)
     path = argv[0];
 else {
     path = NULL;
     continue;
 }
 if (built_in(path, argv, n) == TRUE);
 else {
     if (fork() == 0) {
  int henry;
  henry = FALSE;
  if (execv(path, argv) == -1) {
      henry = TRUE;
      j = 0;
      for (i = 0; i <= strlen(PATH); i++) {
   littlepath[j] = PATH[i];
   if (PATH[i] == MARKS || PATH[i] == EOT) {
       char help[LEN];
       strcpy(help, argv[0]);
       littlepath[j] = BACKSLASH;
       littlepath[j + 1] = EOT;
       insert(littlepath, argv[0]);
       if (execv(path, argv) != -1) {
    henry = FALSE;
    break;
       }
       strcpy(argv[0], help);
       j = 0;
       continue;
   }
   j++;
      }
  }
  for (i = 0; i < n; i++)
      free(argv[i]);
  if (henry == TRUE)
