{
    "content": [
        {
            "type": "text",
            "text": "# ucf(1) (man)\n\n**Summary:** ucf - Update Configuration File:  preserve user changes in configuration files\n\n**Synopsis:** ucf [options] <New File> <Destination>\nucf [options] --purge <Destination>\n\n## Flags\n\n| Flag | Long | Arg | Description |\n|------|------|-----|-------------|\n| -h | --help | — | Print a short usage message |\n| -n | --no-action | — | Dry run. Print the actions that would be taken if the script is invoked, but take no action. |\n| — | --debug | [n | Set the debug level to the (optional) level n (n defaults to 1). Please note there must be no spaces before the optional |\n| -p | --purge | — | Removes all vestiges of the file from the state hashfile. This is required to allow a package to be reinstalled after it |\n| -v | --verbose | — | Make the script be very verbose about setting internal variables. |\n| -P | --package | — | Don't follow dpkg-divert diversions by package foo when updating configuration files. |\n| -s | --src-dir | — | Set the source directory (historical md5sums are expected to live in files and sub di‐ rectories of this directory) to f |\n| — | --sum-file | — | Force the historical md5sums to be read from this file, rather than defaulting to liv‐ ing in the source directory. Sett |\n| — | --three-way | — | This turns on the option, during installation, for the user to be offered a chance to see a merge of the changes between |\n| — | --debconf-ok | — | Indicate that it is ok for ucf to use an already running debconf instance for prompt‐ ing (it has always been ok to use  |\n| — | --debconf-template | — | Instruct ucf to use the named multiselect debconf template instead of the normal ucf- provided debconf template. The cal |\n| — | --state-dir | — | Set the state directory to /path/to/dir instead of the default /var/lib/ucf. Used mostly for testing. |\n| -Z | — | — |  |\n\n## Examples\n\n- `If  the  package  foo  wants  to  use  ucf  to handle user interaction for configuration file`\n- `foo.conf, a version of which is provided in the package  as  /usr/share/foo/configuration,  a`\n- `simple invocation of ucf in the post inst file is all that is needed:`\n- `ucf /usr/share/foo/configuration /etc/foo.conf`\n- `On  purge,  one  should  tell  ucf  to  forget  about  the  file  (see  detailed  examples in`\n- `/usr/share/doc/ucf/examples):`\n- `ucf --purge /etc/foo.conf Please note that purge can also be used to make ucf forget the pre‐`\n- `vious state of the files, and when the package is next installed or updated, ucf will ask the`\n- `user to replace the current cofiguration file. Do this if you want to change your decision to`\n- `not update to a maintainer provided version of the configuration file.`\n- `The  motivation  for  this  script  was to provide conffile like handling for start files for`\n- `emacs lisp packages (for example,  /etc/emacs21/site-start.d/50psgml-init.el  )  These  start`\n- `files are not shipped with the package, instead, they are installed during the post installa‐`\n- `tion configuration phase by the script  /usr/lib/emacsen-common/emacs-package-install  $pack‐`\n- `agename.`\n- `This  script  is  meant to be invoked by the packages install script at /usr/lib/emacsen-com‐`\n- `mon/packages/install/$packagename for each flavour of installed emacsen by calling  it  with`\n- `the  proper  values  of  new file ( /usr/share/emacs/site-lisp/<pkg>/<pkg-init.el ), and dest`\n- `file ( /etc/emacs21/site-start.d/50<pkg-init.el ), and it should do the rest.`\n\n## See Also\n\n- ucf.conf(5)\n- ucfr(1)\n- ucfq(1)\n- diff3(1)\n\n## Section Outline\n\n- **NAME** (2 lines)\n- **SYNOPSIS** (4 lines)\n- **DESCRIPTION** (33 lines)\n- **OPTIONS** (1 lines) — 13 subsections\n  - -h, --help (2 lines)\n  - -n, --no-action (3 lines)\n  - -d[n], --debug=[n] (4 lines)\n  - -p, --purge (9 lines)\n  - -v, --verbose (2 lines)\n  - -P foo, --package foo (2 lines)\n  - -s foo, --src-dir  foo (6 lines)\n  - --sum-file  foo (5 lines)\n  - --three-way (10 lines)\n  - --debconf-ok (4 lines)\n  - --debconf-template  foo (7 lines)\n  - --state-dir /path/to/dir (3 lines)\n  - -Z (1 lines)\n- **USAGE** (27 lines) — 1 subsections\n  - The default historical md5sum (17 lines)\n- **ENVIRONMENT VARIABLES** (8 lines)\n- **FILES** (8 lines)\n- **EXAMPLES** (25 lines)\n- **SEE ALSO** (3 lines)\n- **AUTHOR** (6 lines)\n\n## Full Content\n\n### NAME\n\nucf - Update Configuration File:  preserve user changes in configuration files\n\n### SYNOPSIS\n\nucf [options] <New File> <Destination>\n\nucf [options] --purge <Destination>\n\n### DESCRIPTION\n\nThis  utility  provides  a  means of asking the user whether or not to accept new versions of\nconfiguration files provided by the package maintainer, with various heuristics  designed  to\nminimize  interaction  time. It uses debconf to interact with the user, as per Debian policy.\nIn the SYNOPSIS above, New file is the configuration file as provided by the package  (either\nshipped with the package, or generated by the maintainer scripts on the fly), and Destination\nis the location (usually under /etc) where the real configuration file lives, and  is  poten‐\ntially  modified  by  the end user.  Since the files edited would be real files, and not sym‐\nbolic links, ucf follows and resolves symbolic links before acting. As far as  possible,  ucf\nattempts  to preserve the ownership and permission of the New file as it is copied to the new\nlocation.\n\nThis script attempts to provide conffile like handling for files  installed  under  /etc  not\nshipped  in a Debian package, but handled by the postinst instead.  Debian policy states that\nfiles under /etc which are configuration files must preserve user changes, and  this  applies\nto  files  handled  by maintainer scripts as well. Using ucf, one may ship a bunch of default\nconfiguration files somewhere in /usr ( /usr/share/<pkg> is a good  location),  and  maintain\nfiles  in /etc, preserving user changes and in general offering the same facilities while up‐\ngrading that dpkg normally provides for “conffiles”\n\nAdditionally, this script provides facilities for transitioning a file that had not been pro‐\nvided  conffile like protection to come under this schema, and attempts to minimize questions\nasked at install time. Indeed, the transitioning facility is better than the one  offered  by\ndpkg  while  transitioning  a file from a non-conffile to conffile status. The second form in\nthe SYNOPSIS above is for purging information about the configuration file when  the  package\nis purged; and is critical for allowing smooth reinstallations.\n\nDuring  the  course of operations, when working with configuration files, ucf optionally cre‐\nates copies of versions of the configuration file in question. For example, a file  with  the\nsuffix  ucf-old  holds the old version of a configuration file replaced by ucf.  Also, copies\nof the configuration file with the suffixes ucf-new and ucf-dist  may  be  created;  and  the\nmaintainer scripts should consider purging copies of the configuration file with these exten‐\nsions during purge.\n\n### OPTIONS\n\n#### -h, --help\n\nPrint a short usage message\n\n#### -n, --no-action\n\nDry run. Print the actions that would be taken if the script is invoked, but  take  no\naction.\n\n#### -d[n], --debug=[n]\n\nSet  the  debug  level  to the (optional) level n (n defaults to 1). Please note there\nmust be no spaces before the optional digit n. This turns on copious debugging  infor‐\nmation.\n\n#### -p, --purge\n\nRemoves  all vestiges of the file from the state hashfile. This is required to allow a\npackage to be reinstalled after it is purged; since otherwise, the real  configuration\nfile is removed, but it remains in the hash file; and on reinstall no action is taken,\nsince the md5sum of the new file matches that in the hashfile.  In short, remember  to\nuse  this  option  in  the postrm for every configuration file managed by ucf when the\npackage is being purged (assuming ucf itself exists).  Note:  ucf  does  not  actually\ntouch the file on disk in this operation, so any file removals are still the responsi‐\nbility of the calling package.\n\n#### -v, --verbose\n\nMake the script be very verbose about setting internal variables.\n\n#### -P foo, --package foo\n\nDon't follow dpkg-divert diversions by package foo when updating configuration files.\n\n#### -s foo, --src-dir  foo\n\nSet the source directory (historical md5sums are expected to live in files and sub di‐\nrectories  of  this directory) to foo. By default, the directory the newfile lives in\nis assumed to be the source directory. Setting this option overrides settings  in  the\nenvironment   variable  UCFSOURCEDIR,  and  in  the   configuration   file  variable\nconfsourcedir.\n\n#### --sum-file  foo\n\nForce the historical md5sums to be read from this file, rather than defaulting to liv‐\ning  in  the source directory.  Setting this option overrides settings in the environ‐\nment  variable  UCFOLDMDSUMFILE,  and  in   the    configuration    file   variable\nconfoldmdsumfile.\n\n#### --three-way\n\nThis  turns on the option, during installation, for the user to be offered a chance to\nsee a merge of the changes between old maintainer version and the new maintainer  ver‐\nsion  into  the local copy of the configuration file. If the user likes what they see,\nthey can ask to have these changes merged in. This allows  one  to  get  new  upstream\nchanges  merged in even while retaining local modifications to the configuration file.\nThis is accomplished by taking the configuration file and stashing it in a cache  area\nduring  registration,  and  using diff3 during the install (the stashed file name is a\nmunged version of the full  path  of  the  configuration  file  to  avoid  name  space\nclashes).\n\n#### --debconf-ok\n\nIndicate  that it is ok for ucf to use an already running debconf instance for prompt‐\ning (it has always been ok to use ucf when debconf is not running -- it  shall  invoke\ndebconf as needed).\n\n#### --debconf-template  foo\n\nInstruct  ucf to use the named multiselect debconf template instead of the normal ucf-\nprovided debconf template.  The caller is responsible for ensuring that the named tem‐\nplate  exists  and  has a list of choices matching those for the default ucf template,\nand should set Choices-C: ${CHOICES} to ensure the returned values  match  those  from\nthe  default  template.   Note that the choices must be different according to whether\nthe --three-way option is also set.\n\n#### --state-dir /path/to/dir\n\nSet the state directory to /path/to/dir instead of  the  default  /var/lib/ucf.   Used\nmostly for testing.\n\n#### -Z\n\n### USAGE\n\nThe most common case usage is pretty simple: a single line invocation in the postinst on con‐\nfigure, and another single line in the postrm to tell ucf to forget about  the  configuration\nfile on purge (using the  --purge option) is all that is needed (assuming ucf is still on the\nsystem).\n\nIt is recommended that you also register any file being managed by ucf with the ucf registry;\nthis  associates  the  configuration file with the package it belongs to. This is done with a\nsimple call to ucfr.  Users may then query the association between a configuration  file  and\nthe package using the tool ucfq.  Please see the appropriate manual pages for details.\n\nIf  a  file maintained by maintainer scripts is being transitioned from an unprotected status\nto the protection afforded by the script, the maintainer can help ease the transition by  re‐\nducing  the  questions that may be asked at installation time. Specifically, questions should\nnot be asked if the file in question is an unmodified version that was one shipped in a  pre‐\nvious  version  of  this package; and the maintainer can help by telling the script about the\nhistorical md5sums that published versions of this file contained.\n\nThe way to do this is to either create a file called <New file>.md5sum, with  one  md5sum  on\neach  line, (the file names you use are ignored, except for the entry named default), or cre‐\nate a directory, called <New file>.md5sum.d, which should contain any number of  files,  each\ncontaining  a single line, namely, the md5sum of a previous version of <New file>.  The names\nof these files are not important, with one exception: The file called default is treated spe‐\ncially.   For  example,  the author personally uses either package version numbers or release\ncode names, like 7.6.3, or potato.  If none of the historical md5sums match,  we  are  almost\ncertain that either the historical record of md5sums is not complete, or the user has changed\nthe configuration file.\n\n#### The default historical md5sum\n\nThe exception to the rule about names mentioned earlier is that if no md5sums match,  and  if\nthe file <New file>.md5sum.d/default exists, or if there is a line corresponding to a default\nfile in <New file>.md5sum, it shall be used as the default md5sum of the previous version  of\nthe package assumed to have been installed on this machine.  As you can see, unless there are\nlimited number of previously released packages (like just one), the maintainer is also making\nan informed guess, but the option is provided to the maintainer.\n\nIf  the  file <New file>.md5sum, or the directory <New file>.md5sum.d does not exist, or none\nof the md5sums match, we test the installed <Destination> file to see whether it is the  same\nas the <New file>.  If not, we ask the user whether they want us to replace the file.\n\nAn  additional  facility  is  also  offered: optionally, ucf can store one old version of the\nmaintainers copy of the configuration file, and, on upgrade, calculate the  changes  made  in\nthe  maintainers version of the configuration file, and apply that patch to the local version\nof the file (on user request, of course). There is also a preview facility where the user can\ninspect the results of such a merge, before asking the action to be taken.\n\n### ENVIRONMENT VARIABLES\n\nThe  variable  UCFFORCECONFFNEW,  if  set,  forces the new file to always overwrite the in‐\nstalled destination file, while the variable UCFFORCECONFFOLD, if set silently retains  the\ninstalled  file.   UCFFORCECONFFMISS is only applicable when the installed destination file\ndoes not exist (perhaps due to user removal),and forces ucf to recreate the missing file (the\ndefault  behaviour  is  to honor the users wishes and not recreate the locally deleted file).\nAdditionally, when ucf creates an inferior shell, it populates the variables UCFCONFFILENEW\nand UCFCONFFILEOLD which are useful for inspecting the changes.\n\n### FILES\n\nThis  script  creates  the file newfile.md5sum, and it may copy the file (presumably shipped\nwith the package) <New file> to its destination, <Destination>.\n\n/var/lib/ucf/hashfile, and /var/lib/ucf/hashfile.X, where X is a small integer, where  previ‐\nous versions of the hashfile are stored.\n\n/etc/ucf.conf\n\n### EXAMPLES\n\nIf  the  package  foo  wants  to  use  ucf  to handle user interaction for configuration file\nfoo.conf, a version of which is provided in the package  as  /usr/share/foo/configuration,  a\nsimple invocation of ucf in the post inst file is all that is needed:\n\nucf /usr/share/foo/configuration /etc/foo.conf\n\nOn  purge,  one  should  tell  ucf  to  forget  about  the  file  (see  detailed  examples in\n/usr/share/doc/ucf/examples):\n\nucf --purge /etc/foo.conf Please note that purge can also be used to make ucf forget the pre‐\nvious state of the files, and when the package is next installed or updated, ucf will ask the\nuser to replace the current cofiguration file. Do this if you want to change your decision to\nnot update to a maintainer provided version of the configuration file.\n\nThe  motivation  for  this  script  was to provide conffile like handling for start files for\nemacs lisp packages (for example,  /etc/emacs21/site-start.d/50psgml-init.el  )  These  start\nfiles are not shipped with the package, instead, they are installed during the post installa‐\ntion configuration phase by the script  /usr/lib/emacsen-common/emacs-package-install  $pack‐\nagename.\n\nThis  script  is  meant to be invoked by the packages install script at /usr/lib/emacsen-com‐\nmon/packages/install/$packagename for each flavour of installed emacsen by calling  it  with\nthe  proper  values  of  new file ( /usr/share/emacs/site-lisp/<pkg>/<pkg-init.el ), and dest\nfile ( /etc/emacs21/site-start.d/50<pkg-init.el ), and it should do the rest.\n\n### SEE ALSO\n\nucf.conf(5), ucfr(1), ucfq(1), and diff3(1).  The Debian Emacs policy, shipped with the pack‐\nage emacsen-common.\n\n### AUTHOR\n\nThis manual page was written Manoj Srivastava <srivasta@debian.org>, for the Debian GNU/Linux\nsystem.\n\n\n\nDebian                                       May 30 2008                                      UCF(1)\n\n"
        }
    ],
    "structuredContent": {
        "command": "ucf",
        "section": "1",
        "mode": "man",
        "summary": "ucf - Update Configuration File:  preserve user changes in configuration files",
        "synopsis": "ucf [options] <New File> <Destination>\nucf [options] --purge <Destination>",
        "flags": [
            {
                "flag": "-h",
                "long": "--help",
                "arg": null,
                "description": "Print a short usage message"
            },
            {
                "flag": "-n",
                "long": "--no-action",
                "arg": null,
                "description": "Dry run. Print the actions that would be taken if the script is invoked, but take no action."
            },
            {
                "flag": "",
                "long": "--debug",
                "arg": "[n",
                "description": "Set the debug level to the (optional) level n (n defaults to 1). Please note there must be no spaces before the optional digit n. This turns on copious debugging infor‐ mation."
            },
            {
                "flag": "-p",
                "long": "--purge",
                "arg": null,
                "description": "Removes all vestiges of the file from the state hashfile. This is required to allow a package to be reinstalled after it is purged; since otherwise, the real configuration file is removed, but it remains in the hash file; and on reinstall no action is taken, since the md5sum of the new file matches that in the hashfile. In short, remember to use this option in the postrm for every configuration file managed by ucf when the package is being purged (assuming ucf itself exists). Note: ucf does not actually touch the file on disk in this operation, so any file removals are still the responsi‐ bility of the calling package."
            },
            {
                "flag": "-v",
                "long": "--verbose",
                "arg": null,
                "description": "Make the script be very verbose about setting internal variables."
            },
            {
                "flag": "-P",
                "long": "--package",
                "arg": null,
                "description": "Don't follow dpkg-divert diversions by package foo when updating configuration files."
            },
            {
                "flag": "-s",
                "long": "--src-dir",
                "arg": null,
                "description": "Set the source directory (historical md5sums are expected to live in files and sub di‐ rectories of this directory) to foo. By default, the directory the newfile lives in is assumed to be the source directory. Setting this option overrides settings in the environment variable UCFSOURCEDIR, and in the configuration file variable confsourcedir."
            },
            {
                "flag": "",
                "long": "--sum-file",
                "arg": null,
                "description": "Force the historical md5sums to be read from this file, rather than defaulting to liv‐ ing in the source directory. Setting this option overrides settings in the environ‐ ment variable UCFOLDMDSUMFILE, and in the configuration file variable confoldmdsumfile."
            },
            {
                "flag": "",
                "long": "--three-way",
                "arg": null,
                "description": "This turns on the option, during installation, for the user to be offered a chance to see a merge of the changes between old maintainer version and the new maintainer ver‐ sion into the local copy of the configuration file. If the user likes what they see, they can ask to have these changes merged in. This allows one to get new upstream changes merged in even while retaining local modifications to the configuration file. This is accomplished by taking the configuration file and stashing it in a cache area during registration, and using diff3 during the install (the stashed file name is a munged version of the full path of the configuration file to avoid name space clashes)."
            },
            {
                "flag": "",
                "long": "--debconf-ok",
                "arg": null,
                "description": "Indicate that it is ok for ucf to use an already running debconf instance for prompt‐ ing (it has always been ok to use ucf when debconf is not running -- it shall invoke debconf as needed)."
            },
            {
                "flag": "",
                "long": "--debconf-template",
                "arg": null,
                "description": "Instruct ucf to use the named multiselect debconf template instead of the normal ucf- provided debconf template. The caller is responsible for ensuring that the named tem‐ plate exists and has a list of choices matching those for the default ucf template, and should set Choices-C: ${CHOICES} to ensure the returned values match those from the default template. Note that the choices must be different according to whether the --three-way option is also set."
            },
            {
                "flag": "",
                "long": "--state-dir",
                "arg": null,
                "description": "Set the state directory to /path/to/dir instead of the default /var/lib/ucf. Used mostly for testing."
            },
            {
                "flag": "-Z",
                "long": null,
                "arg": null,
                "description": ""
            }
        ],
        "examples": [
            "If  the  package  foo  wants  to  use  ucf  to handle user interaction for configuration file",
            "foo.conf, a version of which is provided in the package  as  /usr/share/foo/configuration,  a",
            "simple invocation of ucf in the post inst file is all that is needed:",
            "ucf /usr/share/foo/configuration /etc/foo.conf",
            "On  purge,  one  should  tell  ucf  to  forget  about  the  file  (see  detailed  examples in",
            "/usr/share/doc/ucf/examples):",
            "ucf --purge /etc/foo.conf Please note that purge can also be used to make ucf forget the pre‐",
            "vious state of the files, and when the package is next installed or updated, ucf will ask the",
            "user to replace the current cofiguration file. Do this if you want to change your decision to",
            "not update to a maintainer provided version of the configuration file.",
            "The  motivation  for  this  script  was to provide conffile like handling for start files for",
            "emacs lisp packages (for example,  /etc/emacs21/site-start.d/50psgml-init.el  )  These  start",
            "files are not shipped with the package, instead, they are installed during the post installa‐",
            "tion configuration phase by the script  /usr/lib/emacsen-common/emacs-package-install  $pack‐",
            "agename.",
            "This  script  is  meant to be invoked by the packages install script at /usr/lib/emacsen-com‐",
            "mon/packages/install/$packagename for each flavour of installed emacsen by calling  it  with",
            "the  proper  values  of  new file ( /usr/share/emacs/site-lisp/<pkg>/<pkg-init.el ), and dest",
            "file ( /etc/emacs21/site-start.d/50<pkg-init.el ), and it should do the rest."
        ],
        "see_also": [
            {
                "name": "ucf.conf",
                "section": "5",
                "url": "https://www.chedong.com/phpMan.php/man/ucf.conf/5/json"
            },
            {
                "name": "ucfr",
                "section": "1",
                "url": "https://www.chedong.com/phpMan.php/man/ucfr/1/json"
            },
            {
                "name": "ucfq",
                "section": "1",
                "url": "https://www.chedong.com/phpMan.php/man/ucfq/1/json"
            },
            {
                "name": "diff3",
                "section": "1",
                "url": "https://www.chedong.com/phpMan.php/man/diff3/1/json"
            }
        ],
        "section_outline": [
            {
                "name": "NAME",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "SYNOPSIS",
                "lines": 4,
                "subsections": []
            },
            {
                "name": "DESCRIPTION",
                "lines": 33,
                "subsections": []
            },
            {
                "name": "OPTIONS",
                "lines": 1,
                "subsections": [
                    {
                        "name": "-h, --help",
                        "lines": 2,
                        "flag": "-h",
                        "long": "--help"
                    },
                    {
                        "name": "-n, --no-action",
                        "lines": 3,
                        "flag": "-n",
                        "long": "--no-action"
                    },
                    {
                        "name": "-d[n], --debug=[n]",
                        "lines": 4,
                        "long": "--debug",
                        "arg": "[n]"
                    },
                    {
                        "name": "-p, --purge",
                        "lines": 9,
                        "flag": "-p",
                        "long": "--purge"
                    },
                    {
                        "name": "-v, --verbose",
                        "lines": 2,
                        "flag": "-v",
                        "long": "--verbose"
                    },
                    {
                        "name": "-P foo, --package foo",
                        "lines": 2,
                        "flag": "-P",
                        "long": "--package"
                    },
                    {
                        "name": "-s foo, --src-dir  foo",
                        "lines": 6,
                        "flag": "-s",
                        "long": "--src-dir"
                    },
                    {
                        "name": "--sum-file  foo",
                        "lines": 5,
                        "long": "--sum-file"
                    },
                    {
                        "name": "--three-way",
                        "lines": 10,
                        "long": "--three-way"
                    },
                    {
                        "name": "--debconf-ok",
                        "lines": 4,
                        "long": "--debconf-ok"
                    },
                    {
                        "name": "--debconf-template  foo",
                        "lines": 7,
                        "long": "--debconf-template"
                    },
                    {
                        "name": "--state-dir /path/to/dir",
                        "lines": 3,
                        "long": "--state-dir"
                    },
                    {
                        "name": "-Z",
                        "lines": 1,
                        "flag": "-Z"
                    }
                ]
            },
            {
                "name": "USAGE",
                "lines": 27,
                "subsections": [
                    {
                        "name": "The default historical md5sum",
                        "lines": 17
                    }
                ]
            },
            {
                "name": "ENVIRONMENT VARIABLES",
                "lines": 8,
                "subsections": []
            },
            {
                "name": "FILES",
                "lines": 8,
                "subsections": []
            },
            {
                "name": "EXAMPLES",
                "lines": 25,
                "subsections": []
            },
            {
                "name": "SEE ALSO",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "AUTHOR",
                "lines": 6,
                "subsections": []
            }
        ]
    }
}