leggi-passwd.c

Transcript

leggi-passwd.c
leggi-passwd.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
25/11/2015
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define SIZE 100 /* dimensione dei buffer di lettura */
#define DIM 100 /* dimensione del vettore nomi */
int main(int argc, char **argv)
{
FILE *fin = fopen(argv[1], "r");
FILE *fout = argc<3 ? stdout : fopen(argv[2], "w");
/*
* assert termina il programma se il test non è vero
* con un messaggio del tipo
% ./leggi-passwd file-che-non-esiste
assertion "fin && fout" failed: file "leggi-passwd.c", line 23
* serve per il debugging non per l'utente finale
* se definisco la macro NDEBUG il compilatore non considera
* assert(...)
*/
assert(fin && fout); /* richiede assert.h */
1
leggi-passwd.c
25/11/2015
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#if 0
45
nelle versioni recenti di Unix la password non viene memorizzata (
in questo file)
nelle vecchie era presente ma crittograta (qualcosa come $1$
oTc1DHLi$m4cqP7MVPu2Plrw/6Ov.v/)
#endif
43
44
46
/*
* si noti che SIZE e DIM pur assumendo lo stesso valore
* sono logicamente indipendenti
*/
char nome[SIZE], passwd[SIZE], dir[SIZE], shell[SIZE];
/* buffer mi serve per leggere una riga intera */
char buffer[1000];
char *nomi[DIM];
esempio di file /etc/passwd:
root:x:0:0:root:/root:/bin/bash
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
kermit:x:1000:1000:Kermit the Frog,,,:/home/kermit:/bin/bash
nome utente:password:identificativo utente:identificativo gruppo:
descrizione:directory di lavoro:shell utilizzata
2
leggi-passwd.c
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
25/11/2015
/*
* legge al massimo DIM righe oppure fino al termine del file
* fgets restituisce NULL se si incontra EOF (end of file)
*/
int n;
for(n=0; n<DIM && fgets(buffer, sizeof(buffer), fin); n++) {
/*
* %[^:]: legge una stringa costituita da un qualunque
carattere
* escluso ':' poi viene letto necessariamente il carattere ':'
*
* %*d l'asterisco indica che viene letto un dato
* (in questo caso un intero) ma non memorizzato
*/
int id; /* è usata solo nel ciclo */
if(sscanf(buffer, "%[^:]:%[^:]:%d:%*d:%*[^:]:%[^:]:%s",
nome, passwd, &id, dir, shell) != 5) {
fprintf(stderr,"Errore nella riga
%d\n%s\n",n+1,buffer);
}
fprintf(fout, "%s %s %d %s %s\n",
nome, passwd, id, dir, shell);
nomi[n] = nome;
}
3
leggi-passwd.c
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
25/11/2015
#if __STDC_VERSION__ < 199901L
int i;
for(i=0; i<n; i++) {
printf("%2i %s\n", i+1, nomi[i]);// %i è equivalente a %d
}
#else
for(int i=0; i<n; i++) {
sprintf(buffer, "%2i %s.\n", i+1, nomi[i]);
fputs(buffer, stdout);
}
#endif
return 0;
}
#if 0
in analogia a sscanf esiste anche sprintf
(scrive in un buffer di caratteri - cioè crea una stringa)
si può sostituire la riga 72 con:
sprintf(buffer, "%2i %s\n", i+1, nomi[i]);
fputs(buffer, stdout);
lo standard C99 ammette la definizione di variabili in un ciclo for
vedi riga 75 (compilare con l'opzione -std=c99)
#endif
4
leggi-passwd.c
94
95
96
97
98
99
100
101
102
103
25/11/2015
/*
* nomi[n] = nome;
* va corretto in:
* nomi[n] = strdup(nome);
*
* char* strdup(char *s) (duplica stringa - richiede string.h) fa
* una copia della stringa in una nuova locazione di memoria il cui
* indirizzo viene restiuito come risultato della funzione
*/
5