configure.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. /*
  2. * dpkg - main program for package management
  3. * configure.c - configure packages
  4. *
  5. * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
  6. * Copyright © 1999, 2002 Wichert Akkerman <wichert@deephackmode.org>
  7. *
  8. * This is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include <config.h>
  22. #include <compat.h>
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <sys/wait.h>
  26. #include <sys/termios.h>
  27. #include <assert.h>
  28. #include <errno.h>
  29. #include <ctype.h>
  30. #include <string.h>
  31. #include <time.h>
  32. #include <fcntl.h>
  33. #include <dirent.h>
  34. #include <unistd.h>
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include <dpkg/macros.h>
  38. #include <dpkg/i18n.h>
  39. #include <dpkg/dpkg.h>
  40. #include <dpkg/dpkg-db.h>
  41. #include <dpkg/buffer.h>
  42. #include <dpkg/file.h>
  43. #include <dpkg/subproc.h>
  44. #include <dpkg/triglib.h>
  45. #include "filesdb.h"
  46. #include "main.h"
  47. static int conffoptcells[2][2] = {
  48. /* Distro !edited. */ /* Distro edited. */
  49. { cfo_keep, cfo_install }, /* User !edited. */
  50. { cfo_keep, cfo_prompt_keep }, /* User edited. */
  51. };
  52. static void md5hash(struct pkginfo *pkg, char *hashbuf, const char *fn);
  53. static void showdiff(const char *old, const char *new);
  54. static enum conffopt promptconfaction(struct pkginfo *pkg, const char *cfgfile,
  55. const char *realold, const char *realnew,
  56. int useredited, int distedited,
  57. enum conffopt what);
  58. static void
  59. deferred_configure_conffile(struct pkginfo *pkg, struct conffile *conff)
  60. {
  61. struct filenamenode *usenode;
  62. static const char EMPTY_HASH[] = "-";
  63. char currenthash[MD5HASHLEN + 1], newdisthash[MD5HASHLEN + 1];
  64. int useredited, distedited;
  65. enum conffopt what;
  66. struct stat stab;
  67. struct varbuf cdr = VARBUF_INIT, cdr2 = VARBUF_INIT;
  68. char *cdr2rest;
  69. int r;
  70. usenode = namenodetouse(findnamenode(conff->name, fnn_nocopy), pkg);
  71. r = conffderef(pkg, &cdr, usenode->name);
  72. if (r == -1) {
  73. conff->hash = EMPTY_HASH;
  74. return;
  75. }
  76. md5hash(pkg, currenthash, cdr.buf);
  77. varbufreset(&cdr2);
  78. varbufaddstr(&cdr2, cdr.buf);
  79. varbufaddc(&cdr2, 0);
  80. /* XXX: Make sure there's enough room for extensions. */
  81. varbuf_grow(&cdr2, 50);
  82. cdr2rest = cdr2.buf + strlen(cdr.buf);
  83. /* From now on we can just strcpy(cdr2rest, extension); */
  84. strcpy(cdr2rest, DPKGNEWEXT);
  85. /* If the .dpkg-new file is no longer there, ignore this one. */
  86. if (lstat(cdr2.buf, &stab)) {
  87. if (errno == ENOENT)
  88. return;
  89. ohshite(_("unable to stat new distributed conffile '%.250s'"),
  90. cdr2.buf);
  91. }
  92. md5hash(pkg, newdisthash, cdr2.buf);
  93. /* Copy the permissions from the installed version to the new
  94. * distributed version. */
  95. if (!stat(cdr.buf, &stab))
  96. file_copy_perms(cdr.buf, cdr2.buf);
  97. else if (errno != ENOENT)
  98. ohshite(_("unable to stat current installed conffile `%.250s'"),
  99. cdr.buf);
  100. /* Select what to do. */
  101. if (!strcmp(currenthash, newdisthash)) {
  102. /* They're both the same so there's no point asking silly
  103. * questions. */
  104. useredited = -1;
  105. distedited = -1;
  106. what = cfo_identical;
  107. } else if (!strcmp(currenthash, NONEXISTENTFLAG) && fc_conff_miss) {
  108. fprintf(stderr,
  109. _("\n"
  110. "Configuration file `%s', does not exist on system.\n"
  111. "Installing new config file as you requested.\n"),
  112. usenode->name);
  113. what = cfo_newconff;
  114. useredited = -1;
  115. distedited = -1;
  116. } else if (!strcmp(conff->hash, NEWCONFFILEFLAG)) {
  117. if (!strcmp(currenthash, NONEXISTENTFLAG)) {
  118. what = cfo_newconff;
  119. useredited = -1;
  120. distedited = -1;
  121. } else {
  122. useredited = 1;
  123. distedited = 1;
  124. what = conffoptcells[useredited][distedited] |
  125. cfof_isnew;
  126. }
  127. } else {
  128. useredited = strcmp(conff->hash, currenthash) != 0;
  129. distedited = strcmp(conff->hash, newdisthash) != 0;
  130. what = conffoptcells[useredited][distedited];
  131. if (!strcmp(currenthash, NONEXISTENTFLAG))
  132. what |= cfof_userrmd;
  133. }
  134. debug(dbg_conff,
  135. "deferred_configure '%s' (= '%s') useredited=%d distedited=%d what=%o",
  136. usenode->name, cdr.buf, useredited, distedited, what);
  137. what = promptconfaction(pkg, usenode->name, cdr.buf, cdr2.buf,
  138. useredited, distedited, what);
  139. switch (what & ~(cfof_isnew | cfof_userrmd)) {
  140. case cfo_keep | cfof_backup:
  141. strcpy(cdr2rest, DPKGOLDEXT);
  142. if (unlink(cdr2.buf) && errno != ENOENT)
  143. warning(_("%s: failed to remove old backup '%.250s': %s"),
  144. pkg->name, cdr2.buf, strerror(errno));
  145. cdr.used--;
  146. varbufaddstr(&cdr, DPKGDISTEXT);
  147. varbufaddc(&cdr, 0);
  148. strcpy(cdr2rest, DPKGNEWEXT);
  149. trig_file_activate(usenode, pkg);
  150. if (rename(cdr2.buf, cdr.buf))
  151. warning(_("%s: failed to rename '%.250s' to '%.250s': %s"),
  152. pkg->name, cdr2.buf, cdr.buf, strerror(errno));
  153. break;
  154. case cfo_keep:
  155. strcpy(cdr2rest, DPKGNEWEXT);
  156. if (unlink(cdr2.buf))
  157. warning(_("%s: failed to remove '%.250s': %s"),
  158. pkg->name, cdr2.buf, strerror(errno));
  159. break;
  160. case cfo_install | cfof_backup:
  161. strcpy(cdr2rest, DPKGDISTEXT);
  162. if (unlink(cdr2.buf) && errno != ENOENT)
  163. warning(_("%s: failed to remove old distributed version '%.250s': %s"),
  164. pkg->name, cdr2.buf, strerror(errno));
  165. strcpy(cdr2rest, DPKGOLDEXT);
  166. if (unlink(cdr2.buf) && errno != ENOENT)
  167. warning(_("%s: failed to remove '%.250s' (before overwrite): %s"),
  168. pkg->name, cdr2.buf, strerror(errno));
  169. if (!(what & cfof_userrmd))
  170. if (link(cdr.buf, cdr2.buf))
  171. warning(_("%s: failed to link '%.250s' to '%.250s': %s"),
  172. pkg->name, cdr.buf, cdr2.buf, strerror(errno));
  173. /* Fall through. */
  174. case cfo_install:
  175. printf(_("Installing new version of config file %s ...\n"),
  176. usenode->name);
  177. case cfo_newconff:
  178. strcpy(cdr2rest, DPKGNEWEXT);
  179. trig_file_activate(usenode, pkg);
  180. if (rename(cdr2.buf, cdr.buf))
  181. ohshite(_("unable to install `%.250s' as `%.250s'"),
  182. cdr2.buf, cdr.buf);
  183. break;
  184. default:
  185. internerr("unknown conffopt '%d'", what);
  186. }
  187. conff->hash = nfstrsave(newdisthash);
  188. modstatdb_note(pkg);
  189. varbuf_destroy(&cdr);
  190. varbuf_destroy(&cdr2);
  191. }
  192. /**
  193. * Process the deferred configure package.
  194. *
  195. * The algorithm for deciding what to configure first is as follows:
  196. * Loop through all packages doing a ‘try 1’ until we've been round
  197. * and nothing has been done, then do ‘try 2’ and ‘try 3’ likewise.
  198. * The incrementing of ‘dependtry’ is done by process_queue().
  199. *
  200. * Try 1:
  201. * Are all dependencies of this package done? If so, do it.
  202. * Are any of the dependencies missing or the wrong version?
  203. * If so, abort (unless --force-depends, in which case defer).
  204. * Will we need to configure a package we weren't given as an
  205. * argument? If so, abort ─ except if --force-configure-any,
  206. * in which case we add the package to the argument list.
  207. * If none of the above, defer the package.
  208. *
  209. * Try 2:
  210. * Find a cycle and break it (see above).
  211. * Do as for try 1.
  212. *
  213. * Try 3 (only if --force-depends-version):
  214. * Same as for try 2, but don't mind version number in dependencies.
  215. *
  216. * Try 4 (only if --force-depends):
  217. * Do anyway.
  218. *
  219. * @param pkg The package to act on.
  220. */
  221. void
  222. deferred_configure(struct pkginfo *pkg)
  223. {
  224. struct varbuf aemsgs = VARBUF_INIT;
  225. struct conffile *conff;
  226. int ok;
  227. if (pkg->status == stat_notinstalled)
  228. ohshit(_("no package named `%s' is installed, cannot configure"),
  229. pkg->name);
  230. if (pkg->status == stat_installed)
  231. ohshit(_("package %.250s is already installed and configured"),
  232. pkg->name);
  233. if (pkg->status != stat_unpacked && pkg->status != stat_halfconfigured)
  234. ohshit(_("package %.250s is not ready for configuration\n"
  235. " cannot configure (current status `%.250s')"),
  236. pkg->name, statusinfos[pkg->status].name);
  237. if (dependtry > 1)
  238. if (findbreakcycle(pkg))
  239. sincenothing = 0;
  240. ok = dependencies_ok(pkg, NULL, &aemsgs);
  241. if (ok == 1) {
  242. varbuf_destroy(&aemsgs);
  243. pkg->clientdata->istobe = itb_installnew;
  244. add_to_queue(pkg);
  245. return;
  246. }
  247. trigproc_reset_cycle();
  248. /* At this point removal from the queue is confirmed. This
  249. * represents irreversible progress wrt trigger cycles. Only
  250. * packages in stat_unpacked are automatically added to the
  251. * configuration queue, and during configuration and trigger
  252. * processing new packages can't enter into unpacked. */
  253. ok = breakses_ok(pkg, &aemsgs) ? ok : 0;
  254. if (ok == 0) {
  255. sincenothing = 0;
  256. varbufaddc(&aemsgs, 0);
  257. fprintf(stderr,
  258. _("dpkg: dependency problems prevent configuration of %s:\n%s"),
  259. pkg->name, aemsgs.buf);
  260. varbuf_destroy(&aemsgs);
  261. ohshit(_("dependency problems - leaving unconfigured"));
  262. } else if (aemsgs.used) {
  263. varbufaddc(&aemsgs, 0);
  264. fprintf(stderr,
  265. _("dpkg: %s: dependency problems, but configuring anyway as you requested:\n%s"),
  266. pkg->name, aemsgs.buf);
  267. }
  268. varbuf_destroy(&aemsgs);
  269. sincenothing = 0;
  270. if (pkg->eflag & eflag_reinstreq)
  271. forcibleerr(fc_removereinstreq,
  272. _("Package is in a very bad inconsistent state - you should\n"
  273. " reinstall it before attempting configuration."));
  274. printf(_("Setting up %s (%s) ...\n"), pkg->name,
  275. versiondescribe(&pkg->installed.version, vdew_nonambig));
  276. log_action("configure", pkg);
  277. trig_activate_packageprocessing(pkg);
  278. if (f_noact) {
  279. pkg->status = stat_installed;
  280. pkg->clientdata->istobe = itb_normal;
  281. return;
  282. }
  283. if (pkg->status == stat_unpacked) {
  284. debug(dbg_general, "deferred_configure updating conffiles");
  285. /* This will not do at all the right thing with overridden
  286. * conffiles or conffiles that are the ‘target’ of an override;
  287. * all the references here would be to the ‘contested’
  288. * filename, and in any case there'd only be one hash for both
  289. * ‘versions’ of the conffile.
  290. *
  291. * Overriding conffiles is a silly thing to do anyway :-). */
  292. modstatdb_note(pkg);
  293. /* On entry, the ‘new’ version of each conffile has been
  294. * unpacked as ‘*.dpkg-new’, and the ‘installed’ version is
  295. * as-yet untouched in ‘*’. The hash of the ‘old distributed’
  296. * version is in the conffiles data for the package. If
  297. * ‘*.dpkg-new’ no longer exists we assume that we've
  298. * already processed this one. */
  299. for (conff = pkg->installed.conffiles; conff; conff = conff->next)
  300. deferred_configure_conffile(pkg, conff);
  301. pkg->status = stat_halfconfigured;
  302. }
  303. assert(pkg->status == stat_halfconfigured);
  304. modstatdb_note(pkg);
  305. maintainer_script_postinst(pkg, "configure",
  306. informativeversion(&pkg->configversion) ?
  307. versiondescribe(&pkg->configversion,
  308. vdew_nonambig) : "",
  309. NULL);
  310. pkg->eflag = eflag_ok;
  311. post_postinst_tasks(pkg, stat_installed);
  312. }
  313. /**
  314. * Dereference a file by following all possibly used symlinks.
  315. *
  316. * @param[in] pkg The package to act on.
  317. * @param[out] result The dereference conffile path.
  318. * @param[in] in The conffile path to dereference.
  319. *
  320. * @return An error code for the operation.
  321. * @retval 0 Everything went ok.
  322. * @retval -1 Otherwise.
  323. */
  324. int
  325. conffderef(struct pkginfo *pkg, struct varbuf *result, const char *in)
  326. {
  327. static struct varbuf symlink = VARBUF_INIT;
  328. struct stat stab;
  329. int r;
  330. int loopprotect;
  331. varbufreset(result);
  332. varbufaddstr(result, instdir);
  333. if (*in != '/')
  334. varbufaddc(result, '/');
  335. varbufaddstr(result, in);
  336. varbufaddc(result, 0);
  337. loopprotect = 0;
  338. for (;;) {
  339. debug(dbg_conffdetail, "conffderef in='%s' current working='%s'",
  340. in, result->buf);
  341. if (lstat(result->buf, &stab)) {
  342. if (errno != ENOENT)
  343. warning(_("%s: unable to stat config file '%s'\n"
  344. " (= '%s'): %s"),
  345. pkg->name, in, result->buf, strerror(errno));
  346. debug(dbg_conffdetail, "conffderef nonexistent");
  347. return 0;
  348. } else if (S_ISREG(stab.st_mode)) {
  349. debug(dbg_conff, "conffderef in='%s' result='%s'",
  350. in, result->buf);
  351. return 0;
  352. } else if (S_ISLNK(stab.st_mode)) {
  353. debug(dbg_conffdetail, "conffderef symlink loopprotect=%d",
  354. loopprotect);
  355. if (loopprotect++ >= 25) {
  356. warning(_("%s: config file '%s' is a circular link\n"
  357. " (= '%s')"), pkg->name, in, result->buf);
  358. return -1;
  359. }
  360. varbufreset(&symlink);
  361. varbuf_grow(&symlink, stab.st_size + 1);
  362. r = readlink(result->buf, symlink.buf, symlink.size);
  363. if (r < 0) {
  364. warning(_("%s: unable to readlink conffile '%s'\n"
  365. " (= '%s'): %s"),
  366. pkg->name, in, result->buf, strerror(errno));
  367. return -1;
  368. }
  369. assert(r == stab.st_size); /* XXX: debug */
  370. symlink.used = r;
  371. varbufaddc(&symlink, '\0');
  372. debug(dbg_conffdetail,
  373. "conffderef readlink gave %d, '%s'",
  374. r, symlink.buf);
  375. if (symlink.buf[0] == '/') {
  376. varbufreset(result);
  377. varbufaddstr(result, instdir);
  378. debug(dbg_conffdetail,
  379. "conffderef readlink absolute");
  380. } else {
  381. for (r = result->used - 2; r > 0 && result->buf[r] != '/'; r--)
  382. ;
  383. if (r < 0) {
  384. warning(_("%s: conffile '%.250s' resolves to degenerate filename\n"
  385. " ('%s' is a symlink to '%s')"),
  386. pkg->name, in, result->buf, symlink.buf);
  387. return -1;
  388. }
  389. if (result->buf[r] == '/')
  390. r++;
  391. result->used = r;
  392. debug(dbg_conffdetail,
  393. "conffderef readlink relative to '%.*s'",
  394. (int)result->used, result->buf);
  395. }
  396. varbufaddbuf(result, symlink.buf, symlink.used);
  397. varbufaddc(result, 0);
  398. } else {
  399. warning(_("%s: conffile '%.250s' is not a plain file or symlink (= '%s')"),
  400. pkg->name, in, result->buf);
  401. return -1;
  402. }
  403. }
  404. }
  405. /**
  406. * Generate a file contents MD5 hash.
  407. *
  408. * The caller is responsible for providing a buffer for the hash result
  409. * at least MD5HASHLEN + 1 characters long.
  410. *
  411. * @param[in] pkg The package to act on.
  412. * @param[out] hashbuf The buffer to store the generated hash.
  413. * @param[in] fn The filename.
  414. */
  415. static void
  416. md5hash(struct pkginfo *pkg, char *hashbuf, const char *fn)
  417. {
  418. static int fd;
  419. fd = open(fn, O_RDONLY);
  420. if (fd >= 0) {
  421. push_cleanup(cu_closefd, ehflag_bombout, NULL, 0, 1, &fd);
  422. fd_md5(fd, hashbuf, -1, _("md5hash"));
  423. pop_cleanup(ehflag_normaltidy); /* fd = open(cdr.buf) */
  424. close(fd);
  425. } else if (errno == ENOENT) {
  426. strcpy(hashbuf, NONEXISTENTFLAG);
  427. } else {
  428. warning(_("%s: unable to open conffile %s for hash: %s"),
  429. pkg->name, fn, strerror(errno));
  430. strcpy(hashbuf, "-");
  431. }
  432. }
  433. /**
  434. * Show a diff between two files.
  435. *
  436. * @param old The path to the old file.
  437. * @param new The path to the new file.
  438. */
  439. static void
  440. showdiff(const char *old, const char *new)
  441. {
  442. pid_t pid;
  443. pid = subproc_fork();
  444. if (!pid) {
  445. /* Child process. */
  446. const char *pager;
  447. const char *shell;
  448. char cmdbuf[1024]; /* command to run */
  449. pager = getenv(PAGERENV);
  450. if (!pager || !*pager)
  451. pager = DEFAULTPAGER;
  452. sprintf(cmdbuf, DIFF " -Nu %.250s %.250s | %.250s",
  453. old, new, pager);
  454. shell = getenv(SHELLENV);
  455. if (!shell || !*shell)
  456. shell = DEFAULTSHELL;
  457. execlp(shell, shell, "-c", cmdbuf, NULL);
  458. ohshite(_("failed to run %s (%.250s)"), DIFF, cmdbuf);
  459. }
  460. /* Parent process. */
  461. subproc_wait(pid, "shell");
  462. }
  463. /**
  464. * Spawn a new shell.
  465. *
  466. * Create a subprocess and execute a shell to allow the user to manually
  467. * solve the conffile conflict.
  468. *
  469. * @param confold The path to the old conffile.
  470. * @param confnew The path to the new conffile.
  471. */
  472. static void
  473. spawn_shell(const char *confold, const char *confnew)
  474. {
  475. pid_t pid;
  476. fputs(_("Type `exit' when you're done.\n"), stderr);
  477. pid = subproc_fork();
  478. if (!pid) {
  479. /* Child process */
  480. const char *shell;
  481. shell = getenv(SHELLENV);
  482. if (!shell || !*shell)
  483. shell = DEFAULTSHELL;
  484. /* Set useful variables for the user. */
  485. setenv("DPKG_SHELL_REASON", "conffile-prompt", 1);
  486. setenv("DPKG_CONFFILE_OLD", confold, 1);
  487. setenv("DPKG_CONFFILE_NEW", confnew, 1);
  488. execlp(shell, shell, "-i", NULL);
  489. ohshite(_("failed to exec shell (%.250s)"), shell);
  490. }
  491. /* Parent process. */
  492. subproc_wait(pid, "shell");
  493. }
  494. /**
  495. * Prompt the user for how to resolve a conffile conflict.
  496. *
  497. * When encountering a conffile conflict during configuration, the user will
  498. * normally be presented with a textual menu of possible actions. This
  499. * behavior is modified via various --force flags and perhaps on whether
  500. * or not a terminal is available to do the prompting.
  501. *
  502. * @param pkg The package owning the conffile.
  503. * @param cfgfile The path to the old conffile.
  504. * @param realold The path to the old conffile, dereferenced in case of a
  505. * symlink, otherwise equal to cfgfile.
  506. * @param realnew The path to the new conffile, dereferenced in case of a
  507. * symlink).
  508. * @param useredited A flag to indicate whether the file has been edited
  509. * locally. Set to nonzero to indicate that the file has been modified.
  510. * @param distedited A flag to indicate whether the file has been updated
  511. * between package versions. Set to nonzero to indicate that the file
  512. * has been updated.
  513. * @param what Hints on what action should be taken by defualt.
  514. *
  515. * @return The action which should be taken based on user input and/or the
  516. * default actions as configured by cmdline/configuration options.
  517. */
  518. static enum conffopt
  519. promptconfaction(struct pkginfo *pkg, const char *cfgfile,
  520. const char *realold, const char *realnew,
  521. int useredited, int distedited, enum conffopt what)
  522. {
  523. const char *s;
  524. int c, cc;
  525. if (!(what & cfof_prompt))
  526. return what;
  527. statusfd_send("status: %s : %s : '%s' '%s' %i %i ",
  528. cfgfile, "conffile-prompt",
  529. realold, realnew, useredited, distedited);
  530. do {
  531. /* Flush the terminal's input in case the user involuntarily
  532. * typed some characters. */
  533. tcflush(STDIN_FILENO, TCIFLUSH);
  534. fprintf(stderr, _("\nConfiguration file `%s'"), cfgfile);
  535. if (strcmp(cfgfile, realold))
  536. fprintf(stderr, _(" (actually `%s')"), realold);
  537. if (what & cfof_isnew) {
  538. fprintf(stderr,
  539. _("\n"
  540. " ==> File on system created by you or by a script.\n"
  541. " ==> File also in package provided by package maintainer.\n"));
  542. } else {
  543. fprintf(stderr, !useredited ?
  544. _("\n Not modified since installation.\n") :
  545. !(what & cfof_userrmd) ?
  546. _("\n ==> Modified (by you or by a script) since installation.\n") :
  547. _("\n ==> Deleted (by you or by a script) since installation.\n"));
  548. fprintf(stderr, distedited ?
  549. _(" ==> Package distributor has shipped an updated version.\n") :
  550. _(" Version in package is the same as at last installation.\n"));
  551. }
  552. /* No --force-confdef but a forcible situtation. */
  553. /* TODO: check if this condition can not be simplified to
  554. * just !fc_conff_def */
  555. if (!(fc_conff_def && (what & (cfof_install | cfof_keep)))) {
  556. if (fc_conff_new) {
  557. fprintf(stderr, _(" ==> Using new file as you requested.\n"));
  558. cc = 'y';
  559. break;
  560. } else if (fc_conff_old) {
  561. fprintf(stderr, _(" ==> Using current old file as you requested.\n"));
  562. cc = 'n';
  563. break;
  564. }
  565. }
  566. /* Force the default action (if there is one. */
  567. if (fc_conff_def) {
  568. if (what & cfof_keep) {
  569. fprintf(stderr, _(" ==> Keeping old config file as default.\n"));
  570. cc = 'n';
  571. break;
  572. } else if (what & cfof_install) {
  573. fprintf(stderr, _(" ==> Using new config file as default.\n"));
  574. cc = 'y';
  575. break;
  576. }
  577. }
  578. fprintf(stderr,
  579. _(" What would you like to do about it ? Your options are:\n"
  580. " Y or I : install the package maintainer's version\n"
  581. " N or O : keep your currently-installed version\n"
  582. " D : show the differences between the versions\n"
  583. " Z : start a shell to examine the situation\n"));
  584. if (what & cfof_keep)
  585. fprintf(stderr, _(" The default action is to keep your current version.\n"));
  586. else if (what & cfof_install)
  587. fprintf(stderr, _(" The default action is to install the new version.\n"));
  588. s = strrchr(cfgfile, '/');
  589. if (!s || !*++s)
  590. s = cfgfile;
  591. fprintf(stderr, "*** %s (Y/I/N/O/D/Z) %s ? ",
  592. s,
  593. (what & cfof_keep) ? _("[default=N]") :
  594. (what & cfof_install) ? _("[default=Y]") :
  595. _("[no default]"));
  596. if (ferror(stderr))
  597. ohshite(_("error writing to stderr, discovered before conffile prompt"));
  598. cc = 0;
  599. while ((c = getchar()) != EOF && c != '\n')
  600. if (!isspace(c) && !cc)
  601. cc = tolower(c);
  602. if (c == EOF) {
  603. if (ferror(stdin))
  604. ohshite(_("read error on stdin at conffile prompt"));
  605. ohshit(_("EOF on stdin at conffile prompt"));
  606. }
  607. if (!cc) {
  608. if (what & cfof_keep) {
  609. cc = 'n';
  610. break;
  611. } else if (what & cfof_install) {
  612. cc = 'y';
  613. break;
  614. }
  615. }
  616. /* FIXME: Say something if silently not install. */
  617. if (cc == 'd')
  618. showdiff(realold, realnew);
  619. if (cc == 'z')
  620. spawn_shell(realold, realnew);
  621. } while (!strchr("yino", cc));
  622. log_message("conffile %s %s", cfgfile,
  623. (cc == 'i' || cc == 'y') ? "install" : "keep");
  624. what &= cfof_userrmd;
  625. switch (cc) {
  626. case 'i':
  627. case 'y':
  628. what |= cfof_install | cfof_backup;
  629. break;
  630. case 'n':
  631. case 'o':
  632. what |= cfof_keep | cfof_backup;
  633. break;
  634. default:
  635. internerr("unknown response '%d'", cc);
  636. }
  637. return what;
  638. }