Some more commits for cdebconf update; fixes textdb module, as well as
the text/slang/ncurses/bogl frontends
added man pages for some of the executables
r728
Randolph Chung
21 years ago
19 | 19 | |
20 | 20 | distclean: clean |
21 | 21 | -rm -f config.status config.log config.cache globalmakeflags |
22 | -rm -f src/makefile src/config.h | |
22 | -rm -f src/Makefile src/config.h man/Makefile | |
23 | 23 | |
24 | 24 | .PHONY: cdebconf clean distclean |
11 | 11 | Macros are used for various convenience things, and follow the naming convention |
12 | 12 | of their C++ or perl counterparts. |
13 | 13 | |
14 | : | |
14 | In general the code follows the following conventions: | |
15 | 15 | |
16 | $Id: coding.txt,v 1.3 2002/07/01 06:58:37 tausq Exp $ | |
16 | - variables and functions are lower-case. multi-word identifiers are joined | |
17 | by underbars (like_this). | |
18 | - tabs are 4 spaces. Avoid using ^I | |
19 | - braces are always on a line by itself, and line up with the controlling | |
20 | block construct. | |
21 | - in general, keep things consistent with the surrounding code | |
22 | ||
23 | $Id: coding.txt,v 1.4 2002/07/02 06:53:46 tausq Rel $ |
9 | 9 | so that new modules (for different frontends and backends) can be "plugged |
10 | 10 | in" without bloating the basic system. |
11 | 11 | |
12 | The system consists of the following objects: [see objects.dia] | |
12 | The system consists of the following objects: | |
13 | 13 | * Template - definition of a piece of configuration info |
14 | 14 | * Question - instantiation of a template -- with answer from the user, etc |
15 | 15 | * Frontend - UI that interacts with the user to get answers to questions |
16 | * Database - stores and retrieves template and question data | |
16 | * TemplateDb - database for storing template data | |
17 | * QuestionDb - database for storing configuration data ("questions") | |
17 | 18 | * ConfModule - interface to config script |
18 | 19 | |
19 | 20 | This closely follows the existing object hierarchy in perl-DebConf, though |
26 | 27 | [*1] _Configuration Management_, revision 6.2 (draft) by Wichert Akkerman |
27 | 28 | and Joey Hess |
28 | 29 | |
29 | $Id: design.txt,v 1.3 2002/07/01 06:58:37 tausq Exp $ | |
30 | $Id: design.txt,v 1.4 2002/07/02 06:53:46 tausq Rel $ |
13 | 13 | FRONTEND_MODULES=@FRONTEND_MODULES@ |
14 | 14 | |
15 | 15 | CC=@CC@ |
16 | CFLAGS=@CFLAGS@ | |
16 | CFLAGS=@CFLAGS@ -I. -I$(srcdir)/src | |
17 | 17 | POD2MAN=@POD2MAN@ |
18 | 18 | |
19 | 19 | %.o: %.c |
0 | include ../globalmakeflags | |
1 | ||
2 | VPATH = $(srcdir)/man | |
3 | ||
4 | CENTER=Debconf | |
5 | MANPAGES=dpkg-preconfigure.8 dpkg-reconfigure.8 debconf.7 | |
6 | ||
7 | all: $(MANPAGES) | |
8 | ||
9 | $(MANPAGES): | |
10 | @$(POD2MAN) --section=$(subst .,,$(suffix $@)) --center=$(CENTER) -d$(CENTER) $(srcdir)/man/$(basename $@).pod > $(basename $@).man |
0 | =head1 NAME | |
1 | ||
2 | debconf - run a debconf-using program | |
3 | ||
4 | =cut | |
5 | ||
6 | =head1 SYNOPSIS | |
7 | ||
8 | debconf [options] command [args] | |
9 | ||
10 | =head1 DESCRIPTION | |
11 | ||
12 | Debconf is a configuration system for Debian packages. For a debconf | |
13 | overview and documentation for sysadmins, see L<debconf(7)>. | |
14 | ||
15 | The B<debconf> program runs a program under debconf's control, setting it up | |
16 | to talk with debconf on stdio. The program's output is expected to be debconf | |
17 | protocol commands, and it is expected to read result codes on stdin. See | |
18 | L<debconf-devel(7)> for details about the debconf protocol. | |
19 | ||
20 | =head1 OPTIONS | |
21 | ||
22 | =over 4 | |
23 | ||
24 | =item B<-o>I<package>, B<--owner=>I<package> | |
25 | ||
26 | Tell debconf what package the command it is running is a part of. This is | |
27 | necessary to get ownership of registered questions right, and to support | |
28 | unregister and purge commands properly. | |
29 | ||
30 | =item B<-f>I<type>, B<--frontend=>I<type> | |
31 | ||
32 | Select the frontend to use. | |
33 | ||
34 | =item B<-p>I<value>, B<--priority=>I<value> | |
35 | ||
36 | Specify the minimum priority of question that will be displayed. | |
37 | ||
38 | =item B<-s>, B<--showold> | |
39 | ||
40 | Redisplay old, already seen questions. | |
41 | ||
42 | =back | |
43 | ||
44 | =head1 EXAMPLES | |
45 | ||
46 | To debug a shell script that uses debconf, you might use: | |
47 | ||
48 | DEBCONF_DEBUG=developer debconf my-shell-prog | |
49 | ||
50 | Or, you might use this: | |
51 | ||
52 | debconf --frontend=readline sh -x my-shell-prog | |
53 | ||
54 | =head1 SEE ALSO | |
55 | ||
56 | L<debconf-devel(7)>, L<debconf(7)> | |
57 | ||
58 | =cut | |
59 | ||
60 | =head1 AUTHOR | |
61 | ||
62 | Joey Hess <joeyh@debian.org> | |
63 | ||
64 | =cut | |
65 | ||
66 | =head1 HISTORY | |
67 | ||
68 | This manpage was "borrowed" from debconf. | |
69 | ||
70 | =cut | |
71 |
0 | =head1 NAME | |
1 | ||
2 | dpkg-preconfigure - let packages ask questions prior to their installation | |
3 | ||
4 | =head1 SYNOPSIS | |
5 | ||
6 | dpkg-preconfigure [options] package.deb | |
7 | ||
8 | dpkg-preconfigure --apt | |
9 | ||
10 | =head1 DESCRIPTION | |
11 | ||
12 | B<dpkg-preconfigure> lets packages ask questions before they are installed. | |
13 | It operates on a set of debian packages, and all packages that use debconf | |
14 | will have their config script run so they can examine the system and ask | |
15 | questions. | |
16 | ||
17 | =head1 OPTIONS | |
18 | ||
19 | =over 4 | |
20 | ||
21 | =item B<-f>I<type>, B<--frontend=>I<type> | |
22 | ||
23 | Select the frontend to use. | |
24 | ||
25 | =item B<-p>I<value>, B<--priority=>I<value> | |
26 | ||
27 | Set the lowest priority of questions you are interested in. Any questions | |
28 | with a priority below the selected priority will be ignored and their | |
29 | default answers will be used. | |
30 | ||
31 | =item B<--apt> | |
32 | ||
33 | Run in apt mode. It will expect to read a set of package filenames from | |
34 | stdin, rather than getting them as parameters. Typically this is used to | |
35 | make apt run dpkg-preconfigure on all packages before they are installed. | |
36 | To do this, add something like this to /etc/apt/apt.conf: | |
37 | ||
38 | // Pre-configure all packages before | |
39 | // they are installed. | |
40 | DPkg::Pre-Install-Pkgs { | |
41 | "dpkg-preconfigure --apt --priority=low"; | |
42 | }; | |
43 | ||
44 | =item B<-h>, B<--help> | |
45 | ||
46 | Display usage help. | |
47 | ||
48 | =back | |
49 | ||
50 | =cut | |
51 | ||
52 | =head1 SEE ALSO | |
53 | ||
54 | L<debconf(7)> | |
55 | ||
56 | =cut | |
57 | ||
58 | =head1 AUTHOR | |
59 | ||
60 | Joey Hess <joeyh@debian.org> | |
61 | ||
62 | =cut | |
63 | ||
64 | =head1 HISTORY | |
65 | ||
66 | This manpage was "borrowed" from debconf. | |
67 | ||
68 | =cut | |
69 |
0 | =head1 NAME | |
1 | ||
2 | dpkg-reconfigure - reconfigure an already installed package | |
3 | ||
4 | =head1 SYNOPSIS | |
5 | ||
6 | dpkg-reconfigure [options] packages | |
7 | ||
8 | =head1 DESCRIPTION | |
9 | ||
10 | B<dpkg-reconfigure> reconfigures packages after they have already been | |
11 | installed. Pass it the names of a package or packages to reconfigure. | |
12 | ||
13 | This has the same effect as re-installing the package, basically. I hope | |
14 | one day this will be called by dpkg --reconfigure | |
15 | ||
16 | =head1 OPTIONS | |
17 | ||
18 | =over 4 | |
19 | ||
20 | =item B<-f>I<type>, B<--frontend=>I<type> | |
21 | ||
22 | Select the frontend to use. The default frontend can be permanently changed | |
23 | by: | |
24 | ||
25 | dpkg-reconfigure debconf | |
26 | ||
27 | Note that if you normally have debconf set to use the noninteractive | |
28 | frontend, dpkg-reconfigure will use the dialog frontend instead, so you | |
29 | actually get to reconfigure the package. | |
30 | ||
31 | =item B<-p>I<value>, B<--priority=>I<value> | |
32 | ||
33 | Specify the minimum priority of question that will be displayed. | |
34 | dpkg-reconfigure normally shows low priority questions no matter what your | |
35 | default priority is. | |
36 | ||
37 | =item B<--all> | |
38 | ||
39 | Reconfigure all installed packages that use debconf. Warning: this may take | |
40 | a long time. | |
41 | ||
42 | =item B<-u>, B<--unseen-only> | |
43 | ||
44 | By default, all questions are shown, even if they have already been | |
45 | answered. If this parameter is set though, only questions that have not yet | |
46 | been seen will be asked. | |
47 | ||
48 | =item B<--force> | |
49 | ||
50 | Force dpkg-reconfigure to reconfigure a package even if the package is in an | |
51 | inconsistent or broken state. Use with caution. | |
52 | ||
53 | =item B<-h>, B<--help> | |
54 | ||
55 | Display usage help. | |
56 | ||
57 | =back | |
58 | ||
59 | =cut | |
60 | ||
61 | =head1 SEE ALSO | |
62 | ||
63 | L<debconf(7)> | |
64 | ||
65 | =cut | |
66 | ||
67 | =head1 AUTHOR | |
68 | ||
69 | Joey Hess <joeyh@debian.org> | |
70 | ||
71 | =cut | |
72 | ||
73 | =head1 HISTORY | |
74 | ||
75 | This manpage was "borrowed" from debconf. | |
76 | ||
77 | =cut | |
78 |
0 | 0 | include ../globalmakeflags |
1 | 1 | |
2 | VPATH = $(srcdir)/src | |
2 | vpath *.c $(srcdir)/src | |
3 | vpath *.h $(srcdir)/src | |
3 | 4 | |
4 | 5 | MAJOR=0 |
5 | 6 | MINOR=1 |
53 | 53 | path "/var/cache/debconf/config.dat"; |
54 | 54 | }; |
55 | 55 | |
56 | instance "to_db" { | |
56 | instance "to_db2" { | |
57 | 57 | driver "rfc822db"; |
58 | 58 | path "/tmp/test.dat"; |
59 | 59 | }; |
60 | ||
61 | instance "to_db" { | |
62 | driver "textdb"; | |
63 | path "/tmp/questions"; | |
64 | }; | |
60 | 65 | }; |
61 | 66 |
0 | 0 | #ifndef _DATABASE_H_ |
1 | 1 | #define _DATABASE_H_ |
2 | 2 | |
3 | /** | |
4 | * \file database.h | |
5 | * \brief Definitions of question_db and template_db objects | |
6 | */ | |
7 | ||
8 | /** | |
9 | * \def DEBCONF_MAX_CONFIGPATH_LEN | |
10 | * \brief maximum length of a configuration path to a database config | |
11 | */ | |
3 | 12 | #define DEBCONF_MAX_CONFIGPATH_LEN 128 |
4 | 13 | |
5 | 14 | /* Debconf database interfaces */ |
10 | 19 | struct question; |
11 | 20 | struct question_db; |
12 | 21 | |
22 | /** | |
23 | * Methods for a template database module | |
24 | */ | |
13 | 25 | struct template_db_module { |
14 | 26 | int (*initialize)(struct template_db *db, struct configuration *cfg); |
15 | 27 | int (*shutdown)(struct template_db *db); |
23 | 35 | struct template *(*iterate)(struct template_db *db, void **iter); |
24 | 36 | }; |
25 | 37 | |
38 | /** | |
39 | * Methods for a question database module | |
40 | */ | |
26 | 41 | struct question_db_module { |
27 | 42 | int (*initialize)(struct question_db *db, struct configuration *cfg); |
28 | 43 | int (*shutdown)(struct question_db *db); |
0 | include ../globalmakeflags | |
1 | ||
2 | MAJOR=0 | |
3 | MINOR=1 | |
4 | MICRO=0 | |
5 | LDFLAGS=-L. -ldebconf @RPATH@ | |
6 | LIB=libdebconf.so | |
7 | LIBNAME=libdebconf.so.$(MAJOR).$(MINOR).$(MICRO) | |
8 | SONAME=libdebconf.so.$(MAJOR).$(MINOR) | |
9 | DEBCONF=debconf | |
10 | TOOLS=debconf-loadtemplate debconf-convertdb dpkg-reconfigure | |
11 | BIN=$(DEBCONF) $(TOOLS) | |
12 | ||
13 | LIBOBJS=commands.opic configuration.opic confmodule.opic debug.opic \ | |
14 | database.opic debconfclient.opic frontend.opic priority.opic \ | |
15 | strutl.opic question.opic template.opic | |
16 | ||
17 | all: $(BIN) $(LIB) $(SONAME) | |
18 | @$(MAKE) -C modules $@ | |
19 | ||
20 | $(BIN): $(LIB) $(addsuffix .o,$(BIN)) | |
21 | @for bin in $(BIN); do \ | |
22 | echo Compiling tool $$bin; \ | |
23 | $(CC) $(CFLAGS) -o $$bin $$bin.o $(LDFLAGS); \ | |
24 | done | |
25 | ||
26 | $(LIBNAME): $(LIBOBJS) | |
27 | @echo Creating shared library $@ | |
28 | @$(CC) $(CFLAGS) -shared -Wl,-soname,$(SONAME) -o $@ $^ -ldl | |
29 | ||
30 | $(SONAME) $(LIB): $(LIBNAME) | |
31 | -@ln -sf $^ $@ | |
32 | ||
33 | install: | |
34 | install -d -m 755 ${bindir} | |
35 | install -d -m 755 ${sbindir} | |
36 | install -d -m 755 ${etcdir} | |
37 | install -d -m 755 ${libdir} | |
38 | install -d -m 755 ${moddir} | |
39 | install -d -m 755 ${sharedir} | |
40 | install -m 755 debconf debconf-loadtemplate ${bindir} | |
41 | install -m 755 dpkg-reconfigure ${sbindir} | |
42 | install -m 755 $(LIBNAME) ${libdir} | |
43 | ln -sf $(LIBNAME) ${libdir}/$(SONAME) | |
44 | ln -sf $(LIBNAME) ${libdir}/$(LIB) | |
45 | install -m 644 cdebconf.conf-dist ${etcdir}/cdebconf.conf | |
46 | install -m 644 client/confmodule ${sharedir} | |
47 | ln -sf ../../bin/$(DEBCONF) ${sharedir}/frontend | |
48 | ifneq ($(TARGET),udeb) | |
49 | install -m 755 debconf debconf-convertdb ${bindir} | |
50 | install -d -m 755 ${incdir} | |
51 | install -m 644 *.h ${incdir} | |
52 | endif | |
53 | @$(MAKE) -C modules $@ | |
54 | ||
55 | clean: | |
56 | -@rm -f $(BIN) $(LIB) $(LIBNAME) $(SONAME) *~ *.o *.opic | |
57 | @$(MAKE) -C modules clean | |
58 | ||
59 | .PHONY: clean lib |
0 | include ../../globalmakeflags | |
1 | ||
0 | 2 | SUBDIRS=db frontend |
1 | 3 | |
2 | 4 | all install clean: $(addsuffix /Makefile,$(SUBDIRS)) |
8 | 8 | #include <dirent.h> |
9 | 9 | #include <stdio.h> |
10 | 10 | #include <string.h> |
11 | #include <unistd.h> | |
11 | 12 | #include <sys/types.h> |
13 | #include <sys/stat.h> | |
12 | 14 | |
13 | 15 | static void translate_tag_name(char *buf) |
14 | 16 | { |
18 | 20 | if (*t == '/') *t = ':'; /* : is illegal in templates etc */ |
19 | 21 | } |
20 | 22 | |
21 | static char *template_filename(struct configuration *cfg, const char *tag) | |
23 | static char *template_filename(struct template_db *db, const char *tag) | |
22 | 24 | { |
23 | 25 | static char filename[1024]; |
26 | static char tmp[1024]; | |
24 | 27 | char tagname[1024]; |
25 | 28 | filename[0] = 0; |
26 | 29 | |
27 | 30 | strncpy(tagname, tag, sizeof(tagname)); |
28 | 31 | translate_tag_name(tagname); |
29 | 32 | |
33 | snprintf(tmp, sizeof(tmp), "%s::path", db->configpath); | |
34 | ||
30 | 35 | snprintf(filename, sizeof(filename), "%s/%s", |
31 | cfg->get(cfg, "database::driver::textdb::templatepath", | |
32 | TEXTDB_TEMPLATE_PATH), tagname); | |
36 | db->config->get(db->config, tmp, ""), tagname); | |
33 | 37 | |
34 | 38 | return filename; |
35 | 39 | } |
36 | 40 | |
37 | static char *question_filename(struct configuration *cfg, const char *tag) | |
41 | static char *question_filename(struct question_db *db, const char *tag) | |
38 | 42 | { |
39 | 43 | static char filename[1024]; |
44 | static char tmp[1024]; | |
40 | 45 | char tagname[1024]; |
46 | ||
41 | 47 | filename[0] = 0; |
42 | 48 | |
43 | 49 | strncpy(tagname, tag, sizeof(tagname)); |
44 | 50 | translate_tag_name(tagname); |
45 | 51 | |
52 | snprintf(tmp, sizeof(tmp), "%s::path", db->configpath); | |
53 | ||
46 | 54 | snprintf(filename, sizeof(filename), "%s/%s", |
47 | cfg->get(cfg, "database::driver::textdb::questionpath", | |
48 | TEXTDB_QUESTION_PATH), tagname); | |
55 | db->config->get(db->config, tmp, "."), tagname); | |
49 | 56 | |
50 | 57 | return filename; |
51 | 58 | } |
68 | 75 | } |
69 | 76 | |
70 | 77 | static struct template *textdb_lookup_cached_template( |
71 | const struct database *db, const char *tag) | |
72 | { | |
73 | struct db_cache *dbdata = db->data; | |
78 | const struct template_db *db, const char *tag) | |
79 | { | |
80 | struct template_db_cache *dbdata = db->data; | |
74 | 81 | struct template *result; |
75 | 82 | for (result = dbdata->templates; result; result = result->next) |
76 | 83 | { |
79 | 86 | return result; |
80 | 87 | } |
81 | 88 | |
82 | static void textdb_remove_cached_template(struct database *db, | |
89 | static void textdb_remove_cached_template(struct template_db *db, | |
83 | 90 | const char *tag) |
84 | 91 | { |
85 | struct db_cache *dbdata = db->data; | |
92 | struct template_db_cache *dbdata = db->data; | |
86 | 93 | struct template **result; |
87 | 94 | for (result = &dbdata->templates; *result; result = &(*result)->next) |
88 | 95 | { |
98 | 105 | static struct question *textdb_lookup_cached_question( |
99 | 106 | const struct database *db, const char *tag) |
100 | 107 | { |
101 | struct db_cache *dbdata = db->data; | |
108 | struct question_db_cache *dbdata = db->data; | |
102 | 109 | struct question *result; |
103 | 110 | for (result = dbdata->questions; result; result = result->next) |
104 | 111 | { |
108 | 115 | } |
109 | 116 | */ |
110 | 117 | |
111 | static int textdb_initialize(struct database *db, struct configuration *cfg) | |
112 | { | |
113 | struct db_cache *dbdata; | |
114 | dbdata = malloc(sizeof(struct db_cache)); | |
118 | static int textdb_template_initialize(struct template_db *db, struct configuration *cfg) | |
119 | { | |
120 | struct template_db_cache *dbdata; | |
121 | dbdata = malloc(sizeof(struct template_db_cache)); | |
115 | 122 | |
116 | 123 | if (dbdata == NULL) |
117 | 124 | return DC_NOTOK; |
118 | 125 | |
119 | dbdata->questions = NULL; | |
120 | 126 | dbdata->templates = NULL; |
121 | 127 | db->data = dbdata; |
122 | 128 | |
123 | 129 | return DC_OK; |
124 | 130 | } |
125 | 131 | |
126 | static int textdb_load(struct database *db) | |
127 | { | |
128 | return DC_OK; | |
129 | } | |
130 | ||
131 | static int textdb_save(struct database *db) | |
132 | { | |
133 | return DC_OK; | |
134 | } | |
135 | ||
136 | static int textdb_template_set(struct database *db, struct template *t) | |
132 | static int textdb_template_set(struct template_db *db, struct template *t) | |
137 | 133 | { |
138 | 134 | FILE *outf; |
139 | 135 | char *filename; |
140 | 136 | struct language_description *langdesc; |
141 | 137 | |
142 | 138 | if (t->tag == NULL) return DC_NOTOK; |
143 | filename = template_filename(db->config, t->tag); | |
139 | filename = template_filename(db, t->tag); | |
144 | 140 | |
145 | 141 | if ((outf = fopen(filename, "w")) == NULL) |
146 | 142 | return DC_NOTOK; |
177 | 173 | return DC_OK; |
178 | 174 | } |
179 | 175 | |
180 | static struct template *textdb_template_get_real(struct database *db, | |
176 | static struct template *textdb_template_get_real(struct template_db *db, | |
181 | 177 | const char *ltag) |
182 | 178 | { |
183 | 179 | struct configuration *rec; |
187 | 183 | const char *tmp; |
188 | 184 | |
189 | 185 | if (ltag == NULL) return DC_NOTOK; |
190 | filename = template_filename(db->config, ltag); | |
186 | filename = template_filename(db, ltag); | |
191 | 187 | |
192 | 188 | rec = config_new(); |
193 | 189 | if (rec->read(rec, filename) != DC_OK) |
249 | 245 | return t; |
250 | 246 | } |
251 | 247 | |
252 | static struct template *textdb_template_get(struct database *db, | |
248 | static struct template *textdb_template_get(struct template_db *db, | |
253 | 249 | const char *ltag) |
254 | 250 | { |
255 | 251 | struct template *result; |
257 | 253 | result = textdb_lookup_cached_template(db, ltag); |
258 | 254 | if (!result && (result = textdb_template_get_real(db, ltag))) |
259 | 255 | { |
260 | struct db_cache *dbdata = db->data; | |
256 | struct template_db_cache *dbdata = db->data; | |
261 | 257 | result->next = dbdata->templates; |
262 | 258 | dbdata->templates = result; |
263 | 259 | } |
265 | 261 | return result; |
266 | 262 | } |
267 | 263 | |
268 | static int textdb_template_remove(struct database *db, const char *tag) | |
264 | static int textdb_template_remove(struct template_db *db, const char *tag) | |
269 | 265 | { |
270 | 266 | char *filename; |
271 | 267 | |
273 | 269 | |
274 | 270 | textdb_remove_cached_template(db, tag); |
275 | 271 | |
276 | filename = template_filename(db->config, tag); | |
272 | filename = template_filename(db, tag); | |
277 | 273 | if (unlink(filename) == 0) |
278 | 274 | return DC_OK; |
279 | 275 | else |
280 | 276 | return DC_NOTOK; |
281 | 277 | } |
282 | 278 | |
283 | static struct template *textdb_template_iterate(struct database *db, | |
279 | static struct template *textdb_template_iterate(struct template_db *db, | |
284 | 280 | void **iter) |
285 | 281 | { |
286 | 282 | DIR *dir; |
287 | 283 | struct dirent *ent; |
284 | char tmp[1024]; | |
288 | 285 | |
289 | 286 | if (*iter == NULL) |
290 | 287 | { |
291 | dir = opendir(db->config->get(db->config, | |
292 | "database::driver::textdb::templatepath", | |
293 | TEXTDB_TEMPLATE_PATH)); | |
288 | snprintf(tmp, sizeof(tmp), "%s::path", db->configpath); | |
289 | dir = opendir(db->config->get(db->config, tmp, "")); | |
294 | 290 | if (dir == NULL) |
295 | 291 | return NULL; |
296 | 292 | *iter = dir; |
309 | 305 | return textdb_template_get(db, ent->d_name); |
310 | 306 | } |
311 | 307 | |
312 | static int textdb_question_set(struct database *db, struct question *q) | |
308 | static int textdb_question_initialize(struct question_db *db, struct configuration *cfg) | |
309 | { | |
310 | struct question_db_cache *dbdata; | |
311 | dbdata = malloc(sizeof(struct question_db_cache)); | |
312 | ||
313 | if (dbdata == NULL) | |
314 | return DC_NOTOK; | |
315 | ||
316 | dbdata->questions = NULL; | |
317 | db->data = dbdata; | |
318 | ||
319 | return DC_OK; | |
320 | } | |
321 | ||
322 | static int textdb_question_set(struct question_db *db, struct question *q) | |
313 | 323 | { |
314 | 324 | FILE *outf; |
315 | 325 | char *filename; |
317 | 327 | struct questionowner *owner; |
318 | 328 | |
319 | 329 | if (q->tag == NULL) return DC_NOTOK; |
320 | filename = question_filename(db->config, q->tag); | |
330 | filename = question_filename(db, q->tag); | |
321 | 331 | |
322 | 332 | if ((outf = fopen(filename, "w")) == NULL) |
323 | 333 | return DC_NOTOK; |
355 | 365 | return DC_OK; |
356 | 366 | } |
357 | 367 | |
358 | static struct question *textdb_question_get(struct database *db, | |
368 | static struct question *textdb_question_get(struct question_db *db, | |
359 | 369 | const char *ltag) |
360 | 370 | { |
361 | 371 | struct configuration *rec; |
364 | 374 | struct configitem *node; |
365 | 375 | |
366 | 376 | if (ltag == NULL) return DC_NOTOK; |
367 | filename = question_filename(db->config, ltag); | |
377 | filename = question_filename(db, ltag); | |
378 | ||
379 | INFO(INFO_DEBUG, "%s: filename = [%s]\n", __FILE__, filename); | |
368 | 380 | |
369 | 381 | rec = config_new(); |
370 | 382 | if (rec->read(rec, filename) != DC_OK) |
379 | 391 | q->value = STRDUP(unescapestr(rec->get(rec, "question::value", 0))); |
380 | 392 | q->defaultval = STRDUP(unescapestr(rec->get(rec, "question::default", 0))); |
381 | 393 | q->flags = rec->geti(rec, "question::flags", 0); |
382 | q->template = textdb_template_get(db, | |
383 | unescapestr(rec->get(rec, "question::template", 0))); | |
394 | q->template = db->tdb->methods.get(db->tdb, | |
395 | unescapestr(rec->get(rec, "question::template", ""))); | |
384 | 396 | |
385 | 397 | /* TODO: variables and owners */ |
386 | 398 | if ((node = rec->tree(rec, "question::variables")) != 0) |
398 | 410 | question_owner_add(q, node->tag); |
399 | 411 | } |
400 | 412 | |
413 | INFO(INFO_DEBUG, "Read q = %s\n", q->tag); | |
414 | ||
401 | 415 | if (q->tag == 0 || q->value == 0 || q->template == 0) |
402 | 416 | { |
403 | 417 | question_deref(q); |
409 | 423 | return q; |
410 | 424 | } |
411 | 425 | |
412 | static int textdb_question_disown(struct database *db, const char *tag, | |
426 | static int textdb_question_disown(struct question_db *db, const char *tag, | |
413 | 427 | const char *owner) |
414 | 428 | { |
415 | 429 | struct question *q = textdb_question_get(db, tag); |
420 | 434 | return DC_OK; |
421 | 435 | } |
422 | 436 | |
423 | static struct question *textdb_question_iterate(struct database *db, | |
437 | static struct question *textdb_question_iterate(struct question_db *db, | |
424 | 438 | void **iter) |
425 | 439 | { |
426 | 440 | DIR *dir; |
427 | 441 | struct dirent *ent; |
442 | static const char *path = ""; | |
443 | char tmp[1024]; | |
444 | int ret; | |
445 | struct stat st; | |
428 | 446 | |
429 | 447 | if (*iter == NULL) |
430 | 448 | { |
431 | dir = opendir(db->config->get(db->config, | |
432 | "database::driver::textdb::questionpath", | |
433 | TEXTDB_QUESTION_PATH)); | |
449 | snprintf(tmp, sizeof(tmp), "%s::path", db->configpath); | |
450 | path = db->config->get(db->config, tmp, "."); | |
451 | INFO(INFO_VERBOSE, "Checking %s -> %s\n", tmp, path); | |
452 | ||
453 | dir = opendir(path); | |
434 | 454 | if (dir == NULL) |
435 | 455 | return NULL; |
436 | 456 | *iter = dir; |
440 | 460 | dir = (DIR *)*iter; |
441 | 461 | } |
442 | 462 | |
443 | if ((ent = readdir(dir)) == NULL) | |
444 | { | |
445 | closedir(dir); | |
446 | return NULL; | |
447 | } | |
448 | ||
463 | do { | |
464 | if ((ent = readdir(dir)) == NULL) | |
465 | { | |
466 | INFO(INFO_DEBUG, "readdir returned NULL\n"); | |
467 | closedir(dir); | |
468 | return NULL; | |
469 | } | |
470 | ||
471 | snprintf(tmp, sizeof(tmp), "%s/%s", path, ent->d_name); | |
472 | ret = stat(tmp, &st); | |
473 | } while (ret < 0 || S_ISDIR(st.st_mode)); | |
474 | ||
475 | INFO(INFO_DEBUG, "Getting %s\n", ent->d_name); | |
449 | 476 | return textdb_question_get(db, ent->d_name); |
450 | 477 | } |
451 | 478 | |
452 | struct database_module debconf_database_module = | |
453 | { | |
454 | initialize: textdb_initialize, | |
455 | load: textdb_load, | |
456 | save: textdb_save, | |
457 | ||
458 | template_set: textdb_template_set, | |
459 | template_get: textdb_template_get, | |
460 | template_remove: textdb_template_remove, | |
461 | template_iterate: textdb_template_iterate, | |
462 | ||
463 | question_get: textdb_question_get, | |
464 | question_set: textdb_question_set, | |
465 | question_disown: textdb_question_disown, | |
466 | question_iterate: textdb_question_iterate | |
479 | struct template_db_module debconf_template_db_module = { | |
480 | initialize: textdb_template_initialize, | |
481 | set: textdb_template_set, | |
482 | get: textdb_template_get, | |
483 | remove: textdb_template_remove, | |
484 | iterate: textdb_template_iterate, | |
467 | 485 | }; |
486 | ||
487 | struct question_db_module debconf_question_db_module = { | |
488 | initialize: textdb_question_initialize, | |
489 | set: textdb_question_set, | |
490 | get: textdb_question_get, | |
491 | disown: textdb_question_disown, | |
492 | iterate: textdb_question_iterate, | |
493 | }; | |
494 |
0 | 0 | #ifndef _TEXTDB_H_ |
1 | 1 | #define _TEXTDB_H_ |
2 | ||
3 | #define TEXTDB_TEMPLATE_PATH "./templates" | |
4 | #define TEXTDB_QUESTION_PATH "./questions" | |
5 | 2 | |
6 | 3 | struct template; |
7 | 4 | struct question; |
8 | 5 | |
9 | struct db_cache { | |
6 | struct template_db_cache { | |
10 | 7 | struct template *templates; |
8 | }; | |
9 | ||
10 | struct question_db_cache { | |
11 | 11 | struct question *questions; |
12 | 12 | }; |
13 | 13 |
48 | 48 | /* FIXME: Needs disabled button widget. */ |
49 | 49 | static void drawnavbuttons(struct frontend *ui, struct question *q) |
50 | 50 | { |
51 | if(ui->cangoback(ui, q)) | |
51 | if(ui->methods.can_go_back(ui, q)) | |
52 | 52 | bowl_new_button(_("Previous"), DC_GOBACK); |
53 | if(ui->cangoforward(ui, q)) | |
53 | if(ui->methods.can_go_forward(ui, q)) | |
54 | 54 | bowl_new_button(_("Next"), DC_OK); |
55 | 55 | } |
56 | 56 | |
86 | 86 | drawdesctop(ui, q); |
87 | 87 | |
88 | 88 | /* Should be: bowl_new_radio(); drawnavbuttons(ui, q); */ |
89 | if(ui->cangoback(ui, q)) | |
89 | if(ui->methods.can_go_back(ui, q)) | |
90 | 90 | bowl_new_button(_("Previous"), 0); |
91 | 91 | bowl_new_button(_("Yes"), 1); |
92 | 92 | bowl_new_button(_("No"), 2); |
232 | 232 | ret = DC_OK; |
233 | 233 | (*handler(q->template->type))(ui, q); |
234 | 234 | if(ret == DC_OK) |
235 | ui->db->question_set(ui->db, q); | |
235 | ui->qdb->methods.set(ui->qdb, q); | |
236 | 236 | else |
237 | 237 | return ret; |
238 | 238 |
70 | 70 | mvwaddch(w, y, x, ' '); |
71 | 71 | } |
72 | 72 | |
73 | static int cangoback(struct frontend *ui) | |
73 | static int can_go_back(struct frontend *ui) | |
74 | 74 | { |
75 | 75 | return 1; |
76 | 76 | } |
77 | 77 | |
78 | static int cangoforward(struct frontend *ui) | |
78 | static int can_go_forward(struct frontend *ui) | |
79 | 79 | { |
80 | 80 | return 1; |
81 | 81 | } |
200 | 200 | /* draw the actual buttons, note that these are drawn in the |
201 | 201 | * query window instead of in the parent (like the frame) */ |
202 | 202 | |
203 | if (cangoback(ui)) | |
203 | if (can_go_back(ui)) | |
204 | 204 | { |
205 | 205 | if (selected == 0) wstandout(win); else wstandend(win); |
206 | 206 | mvwprintw(win, ybut-1, 2, "<Previous>"); |
207 | 207 | } |
208 | 208 | |
209 | if (cangoforward(ui)) | |
209 | if (can_go_forward(ui)) | |
210 | 210 | { |
211 | 211 | if (selected == 1) wstandout(win); else wstandend(win); |
212 | 212 | mvwprintw(win, ybut-1, COLS-10, "<Next>"); |
280 | 280 | switch (pos) |
281 | 281 | { |
282 | 282 | case 0: |
283 | if (cangoback(ui)) | |
283 | if (can_go_back(ui)) | |
284 | 284 | ret = DC_GOBACK; |
285 | 285 | /* go to previous if possible */ |
286 | 286 | break; |
330 | 330 | switch (pos) |
331 | 331 | { |
332 | 332 | case 0: |
333 | if (cangoback(ui)) | |
333 | if (can_go_back(ui)) | |
334 | 334 | ret = DC_GOBACK; |
335 | 335 | /* go to previous if possible */ |
336 | 336 | break; |
420 | 420 | switch (pos) |
421 | 421 | { |
422 | 422 | case 0: |
423 | if (cangoback(ui)) | |
423 | if (can_go_back(ui)) | |
424 | 424 | ret = DC_GOBACK; |
425 | 425 | /* go to previous if possible */ |
426 | 426 | break; |
520 | 520 | switch (ret) |
521 | 521 | { |
522 | 522 | case DC_OK: |
523 | obj->db->question_set(obj->db, q); | |
523 | obj->qdb->methods.set(obj->qdb, q); | |
524 | 524 | break; |
525 | 525 | case DC_GOBACK: |
526 | 526 | if (qlast != 0) |
6 | 6 | * |
7 | 7 | * Description: SLang-based cdebconf UI module |
8 | 8 | * |
9 | * $Id: slang.c,v 1.9 2002/07/01 06:58:38 tausq Exp $ | |
9 | * $Id: slang.c,v 1.10 2002/07/02 06:53:47 tausq Exp $ | |
10 | 10 | * |
11 | 11 | * cdebconf is (c) 2000-2001 Randolph Chung and others under the following |
12 | 12 | * license. |
272 | 272 | * |
273 | 273 | * draws the navigation buttons (previous, next) onto the screen |
274 | 274 | * |
275 | * TODO: if cangoback/forward is false, draw the buttons in a "disabled" | |
275 | * TODO: if can_go_back/forward is false, draw the buttons in a "disabled" | |
276 | 276 | * color |
277 | 277 | */ |
278 | 278 | static void slang_navbuttons(struct frontend *ui, struct question *q, |
295 | 295 | /* draw the actual buttons, note that these are drawn in the |
296 | 296 | * query window instead of in the parent (like the frame) */ |
297 | 297 | |
298 | if (ui->cangoback(ui, q)) | |
298 | if (ui->methods.can_go_back(ui, q)) | |
299 | 299 | { |
300 | 300 | slang_printf(ybut - 1, 2, (selected == 0 ? win->selectedcolor : |
301 | 301 | win->drawcolor), _(" <Previous> ")); |
302 | 302 | } |
303 | 303 | |
304 | if (ui->cangoforward(ui, q)) | |
304 | if (ui->methods.can_go_forward(ui, q)) | |
305 | 305 | { |
306 | 306 | slang_printf(ybut - 1, COLS-10, (selected == 1 ? |
307 | 307 | win->selectedcolor : win->drawcolor), _(" <Next> ")); |
682 | 682 | switch (ret) |
683 | 683 | { |
684 | 684 | case DC_OK: |
685 | obj->db->question_set(obj->db, q); | |
685 | obj->qdb->methods.set(obj->qdb, q); | |
686 | 686 | break; |
687 | 687 | case DC_GOBACK: |
688 | 688 | if (q->prev != NULL) |
9 | 9 | * friendly implementation. I've taken care to make the prompts work well |
10 | 10 | * with screen readers and the like. |
11 | 11 | * |
12 | * $Id: text.c,v 1.10 2002/07/01 06:58:38 tausq Exp $ | |
12 | * $Id: text.c,v 1.11 2002/07/02 06:53:47 tausq Exp $ | |
13 | 13 | * |
14 | 14 | * cdebconf is (c) 2000-2001 Randolph Chung and others under the following |
15 | 15 | * license. |
446 | 446 | texthandler_displaydesc(obj, q); |
447 | 447 | ret = question_handlers[i].handler(obj, q); |
448 | 448 | if (ret == DC_OK) |
449 | obj->db->question_set(obj->db, q); | |
449 | obj->qdb->methods.set(obj->qdb, q); | |
450 | 450 | else |
451 | 451 | return ret; |
452 | 452 | break; |