1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <dirent.h>
6 #include "ipsvd_check.h"
7 #include "sgetopt.h"
8 #include "error.h"
9 #include "open.h"
10 #include "lock.h"
11 #include "strerr.h"
12 #include "stralloc.h"
13 #include "direntry.h"
14 #include "cdb.h"
15 #include "cdb_make.h"
16 #include "str.h"
17 
18 #define USAGE " cdb cdb.tmp dir"
19 #define VERSION "$Id: 940f83f1189944815f693d2f54ee1616b3f85763 $"
20 #define FATAL "ipsvd-cdb: fatal: "
21 #define WARNING "ipsvd-cdb: warning: "
22 
23 const char *progname;
24 char *instdir;
25 char *cdbfn;
26 char *tmpfn;
27 
28 struct cdb_make c;
29 struct cdb cdb;
30 int fdcdb;
31 int fdtmp;
32 static stralloc sa ={0};
33 static stralloc tmp ={0};
34 
usage()35 void usage() { strerr_die4x(111, "usage: ", progname, USAGE, "\n"); }
die_nomem()36 void die_nomem() { strerr_die2x(111, FATAL, "out of memory."); }
fatal(char * m0)37 void fatal(char *m0) { strerr_die3sys(111, FATAL, m0, ": "); }
fatal2(char * m0,char * m1)38 void fatal2(char *m0, char *m1) {
39   strerr_die5sys(111, FATAL, m0, ": ", m1, ": ");
40 }
warn(char * m0,char * m1)41 void warn(char *m0, char *m1) { strerr_warn4(WARNING, m0, ": ", m1, 0); }
42 
main(int argc,char ** argv)43 int main(int argc, char **argv) {
44   int mydir;
45   DIR *dir;
46   direntry *d;
47   struct stat s;
48   int ac;
49   int i;
50 
51   progname =*argv++;
52 
53   if (! argv || ! *argv) usage();
54   cdbfn =*argv++;
55   if (! argv || ! *argv) usage();
56   tmpfn =*argv++;
57   if (! argv || ! *argv) usage();
58   instdir =*argv;
59 
60   if ((mydir =open_read(".")) == -1)
61     fatal("unable to open current directory");
62 
63   /* open cdb.tmp */
64   if ((fdtmp =open_trunc(tmpfn)) == -1) fatal2("unable to create", tmpfn);
65   if (cdb_make_start(&c, fdtmp) == -1) fatal2("unable to create", tmpfn);
66 
67   if (chdir(instdir) == -1) fatal2("unable to change dir", instdir);
68   if (! (dir =opendir("."))) fatal2("unable to open dir", instdir);
69   errno =0;
70   while ((d =readdir(dir))) {
71     if (d->d_name[0] == '.') {
72       if (d->d_name[1] == 0) continue;
73       if (d->d_name[1] == '.') continue;
74     }
75     if (stat(d->d_name, &s) == -1) {
76       warn("unable to stat", d->d_name);
77       errno =0;
78       continue;
79     }
80     sa.len =0;
81     ac =ipsvd_check(0, &sa, &tmp, ".", 0, d->d_name, 0);
82     if (ac == -1) fatal2("unable to read instruction", d->d_name);
83     if (ac == IPSVD_ERR) fatal2("unable to read", "."); /* impossible? */
84 
85     switch(ac) {
86     case IPSVD_EXEC:
87       sa.s[sa.len -1] ='X';
88       if (cdb_make_add(&c, d->d_name, str_len(d->d_name), sa.s, sa.len) == -1)
89         fatal2("unable to add entry", instdir);
90       continue;
91     case IPSVD_DENY:
92       if (! sa.len) {
93         if (cdb_make_add(&c, d->d_name, str_len(d->d_name), "D", 1) == -1)
94           fatal2("unable to add entry", instdir);
95         continue;
96       }
97     case IPSVD_INSTRUCT:
98       for (i =0; i < sa.len; i++) if (sa.s[i] == '\n') sa.s[i] =0;
99       sa.s[sa.len -1] ='I';
100       if (cdb_make_add(&c, d->d_name, str_len(d->d_name), sa.s, sa.len) == -1)
101         fatal2("unable to add entry", instdir);
102       continue;
103     }
104     warn("ignore", d->d_name);
105   }
106   /* catch errno? */
107   closedir(dir);
108   if (cdb_make_finish(&c) == -1) fatal2("unable to write cdb", tmpfn);
109   if (fsync(fdtmp) == -1) fatal2("unable to write cdb", tmpfn);
110   close(fdtmp);
111   if (fchdir(mydir) == -1) fatal("unable to change to previous directory");
112   close(mydir);
113   if (rename(tmpfn, cdbfn) == -1) fatal2("unable to replace", cdbfn);
114   _exit(0);
115 }
116