configure.c 22 KB

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