/*----------------------------------------------------------------
shortopt
Il programma usa i parametri opzionali, cioe' quelli che iniziano
con il - (meno). Sono previsti 2 parametri: un file e l'indi-
cazione se compremerlo o decomprimerlo. In pratica:
programma -fxxxx -c // per comprimere
programma -fxxxx -d // per decomprimere
In caso di compressione, si puo' aggiungere un numero, compreso
tra 1 e 9, che indica la massima velocita' (1) oppure la migliore
compressione (9). In mancanza, viene usato il 6.
Messaggistica
ci sono xxxx parametri extra
ci sono xxxx parametri non opzionali
exec error
getopt error
parametri incompleti|errati
parametro xxxx duplicato/incompatibile
autoesplicativi
---(O)---
Un programma puo' essere congegnato in modo da poter essere
chiamato con dei parametri del tipo:
-x[valore]
ovvero il carattere - (meno) seguito da 1 carattere. Opzional-
mente il carattere puo' essere seguito, senza separatori, da un
valore. Un esempio e' la compilazione di un programma C che
richieda la libreria matematica e lo strip dell'eseguibile. Il
comando e':
cc ... -lm -s
Questi parametri, detti "opzionali", vengono gestiti tramite la
chiamata alla funzione getopt (inserire lo header getopt.h).
Se un programma e' congegnato in modo da essere chiamato con dei
parametri opzionali, ad esempio «x» e «y», allora la defizione
del main e della getopt devono essere correlate come segue:
int main (int argc, char **argv)
getopt (argc, argv, "x:y")
ove argc e' il numero dei parametri con cui l'eseguibile e' stato
chiamato ed argv e' un array di puntatori alle stringhe co-
stituenti i parametri. Come 3^ parametro della getopt c'e' una
stringa contenente i caratteri che contraddistinguono i
parametri. Ciascun carattere puo' essere seguito da nessun, 1 op-
pure 2 : (doppio punto). Il singolo : indica che l'opzione
richiede un valore, mentre il doppio : indica che un valore puo'
seguire il parametro. L'assenza di : indica che non sono pre-
visti valori.
La getopt restituisce il carattere del parametro, se esso e' ri-
conosciuto. Oppure un errore. Alla fine della scansione dei
parametri viene restituito EOF. Nel caso di errore, si puo' con-
trollare la diagnostica ponendo a zero la variabile intera
opterr, da definire come extern int. E' possibile sapere se ci
sono dei parametri extra (non opzionali). Alla fine della scan-
sione dei parametri la variabile optind -da definire come extern
int- conterra' il numero dei parametri opzionali, validi o no,
aumentato di 1. argc, come al solito, contiene il numero totale
dei parametri. Se le due quantita' non coincidono allora sono
presenti dei parametri non opzionali. Se infine sono previsti
dei valori, allora bisogna predisporre delle apposite variabili
per ospitarli. Ma la getopt restituisce un puntatore al valore,
considerato sempre come una stringa. Il puntatore viene messo in
optarg, da definire come «extern char *».
----------------------------------------------------------------*/
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define True 1
#define False !True
int main (int argc, char **argv)
{
char *d = NULL, degr [3], *f = NULL;
unsigned char mask = 0;
extern char *optarg;
int c, op = 0, err = False;
extern int opterr, optind;
void checkey (int, unsigned char *, int, int *);
memset (degr, (int) NULL, sizeof degr);
opterr = 0;
while ((c = getopt (argc, argv, "c::df:")) != EOF)
switch (c)
{
case 'c':
checkey (1, &mask, c, &err);
d = optarg;
op = c;
break;
case 'd':
checkey (1, &mask, c, &err);
op = c;
break;
case 'f':
f = optarg;
break;
default:
fprintf (stderr, "getopt error\n");
err = True;
break;
}
if (optind != argc)
fprintf (stderr, "ci sono %d parametri extra\n", argc - optind);
if (op == 0 || f == NULL || err)
{
fprintf (stderr, "parametri incompleti|errati\n");
exit (EXIT_FAILURE);
}
else
if (op == 'c')
{
if (d == NULL)
strcpy (degr, "-6");
else
strcpy (degr, "-"), strcat (degr, d);
execl ("/bin/gzip", "gzip", degr, f, NULL);
}
else
execl ("/bin/gunzip", "gunzip", f, NULL);
fprintf (stderr, "exec error\n");
exit (EXIT_SUCCESS);
}
void checkey (int i, unsigned char *m, int op, int *e)
{
unsigned char tmp = 0;
tmp = (1 << i);
if (! ((tmp & *m) ^ tmp))
{
fprintf (stderr, "parametro (%c) duplicato/incompatibile\n", op);
*e = True;
}
else
*m |= tmp;
}