configure.c 20 KB

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