21866339 pkgrepo (and other pkg tools that need many fds) should increase soft fd limit s12b109
authorMingrui Lyu <mingrui.lyu@oracle.com>
Mon, 26 Sep 2016 11:52:18 -0700
changeset 3447 c7bfb19c6b1a
parent 3446 06756ef34a2d
child 3448 3cc8ebe07f88
21866339 pkgrepo (and other pkg tools that need many fds) should increase soft fd limit 24681766 pkg cli tools should use pkgdefs constants
src/client.py
src/modules/misc.py
src/pkgdep.py
src/pkgrepo.py
src/po/de.po
src/po/es.po
src/po/fr.po
src/po/it.po
src/po/ja.po
src/po/ko.po
src/po/pt_BR.po
src/po/zh_CN.po
src/po/zh_HK.po
src/po/zh_TW.po
src/publish.py
src/pull.py
src/sign.py
src/util/publish/pkgdiff.py
src/util/publish/pkgfmt.py
src/util/publish/pkglint.py
src/util/publish/pkgmerge.py
src/util/publish/pkgmogrify.py
src/util/publish/pkgsurf.py
--- a/src/client.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/client.py	Mon Sep 26 11:52:18 2016 -0700
@@ -5769,6 +5769,7 @@
         misc.setlocale(locale.LC_ALL, "", error)
         gettext.install("pkg", "/usr/share/locale",
             codeset=locale.getpreferredencoding())
+        misc.set_fd_limits(printer=error)
 
         # Make all warnings be errors.
         import warnings
--- a/src/modules/misc.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/modules/misc.py	Mon Sep 26 11:52:18 2016 -0700
@@ -82,6 +82,7 @@
 from pkg.client.debugvalues import DebugValues
 from pkg.client.imagetypes import img_type_names, IMG_NONE
 from pkg.pkggzip import PkgGzipFile
+from pkg.client.pkgdefs import EXIT_OOPS
 
 # Default path where the temporary directories will be created.
 DEFAULT_TEMP_PATH = "/var/tmp"
@@ -3049,3 +3050,20 @@
                         kuse_sign = e.value.key_cert_sign
 
         return kuse_sign is not False and bconst_ca
+
+FILE_DESCRIPTOR_LIMIT = 4096
+
+def set_fd_limits(printer=None):
+        """Set the open file descriptor soft limit."""
+        if printer is None:
+                printer = emsg
+        try:
+                (soft, hard) = resource.getrlimit(resource.RLIMIT_NOFILE)
+                soft = max(hard, FILE_DESCRIPTOR_LIMIT)
+                resource.setrlimit(resource.RLIMIT_NOFILE, (soft, hard))
+        except (OSError, ValueError) as e:
+                printer(_("unable to set open file limit to {0}; please "
+                    "increase the open file limit using 'ulimit -n'"
+                    " and try the requested operation again: {1}")\
+                    .format(soft, e))
+                sys.exit(EXIT_OOPS)
--- a/src/pkgdep.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/pkgdep.py	Mon Sep 26 11:52:18 2016 -0700
@@ -43,6 +43,7 @@
 import pkg.misc as misc
 import pkg.publish.dependencies as dependencies
 from pkg.misc import msg, emsg, PipeError
+from pkg.client.pkgdefs import EXIT_OK, EXIT_OOPS, EXIT_BADOPT
 
 CLIENT_API_VERSION = 82
 PKG_CLIENT_NAME = "pkgdepend"
@@ -77,7 +78,7 @@
         # program name on all platforms.
         emsg(ws + "pkgdepend: " + text_nows)
 
-def usage(usage_error=None, cmd=None, retcode=2):
+def usage(usage_error=None, cmd=None, retcode=EXIT_BADOPT):
         """Emit a usage message and optionally prefix it with a more specific
         error message.  Causes program to exit."""
 
@@ -124,7 +125,7 @@
                 if opt == "-d":
                         if not os.path.isdir(arg):
                                 usage(_("The proto directory {0} could not be "
-                                    "found.".format(arg)), retcode=2)
+                                    "found.".format(arg)), retcode=EXIT_BADOPT)
                         proto_dirs.append(os.path.abspath(arg))
                 elif opt == "-D":
                         try:
@@ -147,7 +148,7 @@
                 elif opt in ("--help", "-?"):
                         show_usage = True
         if show_usage:
-                usage(retcode=0)
+                usage(retcode=EXIT_OK)
         if len(pargs) > 2 or len(pargs) < 1:
                 usage(_("Generate only accepts one or two arguments."))
 
@@ -155,22 +156,22 @@
                 usage(_("ORIGIN may not be specified using -D. It will be "
                     "inferred from the\ninstall paths of the files."))
 
-        retcode = 0
+        retcode = EXIT_OK
 
         manf = pargs[0]
 
         if not os.path.isfile(manf):
                 usage(_("The manifest file {0} could not be found.").format(manf),
-                    retcode=2)
+                    retcode=EXIT_BADOPT)
 
         if len(pargs) > 1:
                 if not os.path.isdir(pargs[1]):
                         usage(_("The proto directory {0} could not be found.").format(
-                            pargs[1]), retcode=2)
+                            pargs[1]), retcode=EXIT_BADOPT)
                 proto_dirs.insert(0, os.path.abspath(pargs[1]))
         if not proto_dirs:
                 usage(_("At least one proto directory must be provided."),
-                    retcode=2)
+                    retcode=EXIT_BADOPT)
 
         try:
                 ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(manf,
@@ -179,10 +180,10 @@
                 error(_("Could not parse manifest {manifest} because of the "
                     "following line:\n{line}").format(manifest=manf,
                     line=e.actionstr))
-                return 1
+                return EXIT_OOPS
         except api_errors.ApiException as e:
                 error(e)
-                return 1
+                return EXIT_OOPS
 
         if echo_manf:
                 fh = open(manf, "r")
@@ -202,7 +203,7 @@
 
         for e in es:
                 emsg(e)
-                retcode = 1
+                retcode = EXIT_OOPS
         return retcode
 
 def resolve(args, img_dir):
@@ -247,13 +248,13 @@
         for manifest in manifest_paths:
                 if not os.path.isfile(manifest):
                         usage(_("The manifest file {0} could not be found.").format(
-                            manifest), retcode=2)
+                            manifest), retcode=EXIT_BADOPT)
 
         if out_dir:
                 out_dir = os.path.abspath(out_dir)
                 if not os.path.isdir(out_dir):
                         usage(_("The output directory {0} is not a directory.").format(
-                            out_dir), retcode=2)
+                            out_dir), retcode=EXIT_BADOPT)
 
         provided_image_dir = True
         pkg_image_used = False
@@ -276,7 +277,7 @@
         if not img_dir:
                 error(_("Could not find image.  Use the -R option or set "
                     "$PKG_IMAGE to the\nlocation of an image."))
-                return 1
+                return EXIT_OOPS
 
         system_patterns = misc.EmptyI
         if constraint_files:
@@ -294,12 +295,12 @@
                                         error("{0}: '{1}'".format(
                                             e.args[1], e.filename),
                                             cmd="resolve")
-                                        return 1
+                                        return EXIT_OOPS
                                 raise api_errors._convert_error(e)
                 if not system_patterns:
                         error(_("External package list files were provided but "
                             "did not contain any fmri patterns."))
-                        return 1
+                        return EXIT_OOPS
         elif use_system_to_resolve:
                 system_patterns = ["*"]
 
@@ -320,14 +321,14 @@
                                     e.user_dir))
                 else:
                         error(_("No image found."))
-                return 1
+                return EXIT_OOPS
         except api_errors.PermissionsException as e:
                 error(e)
-                return 1
+                return EXIT_OOPS
         except api_errors.ImageFormatUpdateNeeded as e:
                 # This should be a very rare error case.
                 format_update_error(e)
-                return 1
+                return EXIT_OOPS
 
         try:
                 pkg_deps, errs, warnings, unused_fmris, external_deps = \
@@ -336,14 +337,14 @@
         except (actions.MalformedActionError, actions.UnknownActionError) as e:
                 error(_("Could not parse one or more manifests because of "
                     "the following line:\n{0}").format(e.actionstr))
-                return 1
+                return EXIT_OOPS
         except dependencies.DependencyError as e:
                 error(e)
-                return 1
+                return EXIT_OOPS
         except api_errors.ApiException as e:
                 error(e)
-                return 1
-        ret_code = 0
+                return EXIT_OOPS
+        ret_code = EXIT_OK
 
         if output_to_screen:
                 ret_code = pkgdeps_to_screen(pkg_deps, manifest_paths,
@@ -369,8 +370,8 @@
                                 msg("\t{0}".format(pfmri))
 
         for e in errs:
-                if ret_code == 0:
-                        ret_code = 1
+                if ret_code == EXIT_OK:
+                        ret_code = EXIT_OOPS
                 emsg(e)
         for w in warnings:
                 emsg(w)
@@ -413,7 +414,7 @@
                                         text += "\n"
                                 out_func(text)
         except EnvironmentError:
-                ret_code = 1
+                ret_code = EXIT_OOPS
                 emsg(_("Could not open {0} to echo manifest").format(
                     manifest_path))
 
@@ -429,7 +430,7 @@
         'echo_manifest' is a boolean which determines whether the original
         manifest will be written out or not."""
 
-        ret_code = 0
+        ret_code = EXIT_OK
         first = True
         for p in manifest_paths:
                 if not first:
@@ -456,11 +457,11 @@
         'manifest_path' the path to the manifest which generated the
         dependencies."""
 
-        ret_code = 0
+        ret_code = EXIT_OK
         try:
                 out_fh = open(out_file, "w")
         except EnvironmentError:
-                ret_code = 1
+                ret_code = EXIT_OOPS
                 emsg(_("Could not open output file {0} for writing").format(
                     out_file))
                 return ret_code
@@ -489,7 +490,7 @@
         'echo_manifest' is a boolean which determines whether the original
         manifest will be written out or not."""
 
-        ret_code = 0
+        ret_code = EXIT_OK
         if not os.path.exists(out_dir):
                 try:
                         os.makedirs(out_dir)
@@ -501,7 +502,7 @@
                                 e_dic["err"] = e.args[0]
                         emsg(_("Out dir {out_dir} does not exist and could "
                             "not be created. Error is: {err}").format(**e_dic))
-                        return 1
+                        return EXIT_OOPS
         if suffix and suffix[0] != ".":
                 suffix = "." + suffix
         for p in manifest_paths:
@@ -531,7 +532,7 @@
         'echo_manifest' is a boolean which determines whether the original
         manifest will be written out or not."""
 
-        ret_code = 0
+        ret_code = EXIT_OK
         if not suffix:
                 suffix = DEFAULT_SUFFIX
         if suffix[0] != ".":
@@ -544,10 +545,6 @@
         return ret_code
 
 def main_func():
-        misc.setlocale(locale.LC_ALL, "", error)
-        gettext.install("pkg", "/usr/share/locale",
-            codeset=locale.getpreferredencoding())
-
         try:
                 opts, pargs = getopt.getopt(sys.argv[1:], "R:?",
                     ["help"])
@@ -569,7 +566,7 @@
                         show_usage = True
 
         if show_usage:
-                usage(retcode=0)
+                usage(retcode=EXIT_OK)
         elif not subcommand:
                 usage()
 
@@ -587,6 +584,10 @@
 # so that we can more easily detect these in testing of the CLI commands.
 #
 if __name__ == "__main__":
+        misc.setlocale(locale.LC_ALL, "", error)
+        gettext.install("pkg", "/usr/share/locale",
+            codeset=locale.getpreferredencoding())
+        misc.set_fd_limits(printer=error)
 
         # Make all warnings be errors.
         warnings.simplefilter('error')
@@ -598,7 +599,7 @@
                 __ret = main_func()
         except api_errors.MissingFileArgumentException as e:
                 error("The manifest file {0} could not be found.".format(e.path))
-                __ret = 1
+                __ret = EXIT_OOPS
         except api_errors.VersionException as __e:
                 error(_("The {cmd} command appears out of sync with the lib"
                     "raries provided\nby pkg:/package/pkg. The client version "
@@ -607,17 +608,17 @@
                     client=__e.received_version,
                     api=__e.expected_version
                     ))
-                __ret = 1
+                __ret = EXIT_OOPS
         except api_errors.ApiException as e:
                 error(e)
-                __ret = 1
+                __ret = EXIT_OOPS
         except RuntimeError as _e:
                 emsg("{0}: {1}".format(PKG_CLIENT_NAME, _e))
-                __ret = 1
+                __ret = EXIT_OOPS
         except (PipeError, KeyboardInterrupt):
                 # We don't want to display any messages here to prevent
                 # possible further broken pipe (EPIPE) errors.
-                __ret = 1
+                __ret = EXIT_OOPS
         except SystemExit as _e:
                 raise _e
         except:
--- a/src/pkgrepo.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/pkgrepo.py	Mon Sep 26 11:52:18 2016 -0700
@@ -2364,6 +2364,7 @@
         misc.setlocale(locale.LC_ALL, "", error)
         gettext.install("pkg", "/usr/share/locale",
             codeset=locale.getpreferredencoding())
+        misc.set_fd_limits(printer=error)
 
         # Make all warnings be errors.
         warnings.simplefilter('error')
--- a/src/po/de.po	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/po/de.po	Mon Sep 26 11:52:18 2016 -0700
@@ -9525,7 +9525,7 @@
 "\n"
 "Options:\n"
 "        -c pattern      Treat every package whose FMRI matches 'pattern' "
-"as \n"
+"as\n"
 "                        changed and do not reversion it. Can be specified\n"
 "                        multiple times.\n"
 "\n"
@@ -9546,7 +9546,7 @@
 "                        filesystem-based repository.\n"
 "\n"
 "        -?/--help       Print this message.\n"
-msgstr "Syntax:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\nOptionen:\n        -c pattern      Behandelt jedes Package, bei dem FMRI mit 'pattern' übereinstimmt als \n                        geändert und führt keine Reversionierung aus. Kann mehrmals\n                        angegeben werden.\n\n        -i name         Ignoriert set-Aktionen mit dem Namensfeld 'name' zur\n                        Bestimmung der Inhaltsänderung. Kann mehrmals\n                        angegeben werden.\n\n        -n              Führt einen Probelauf aus, ohne Änderungen vorzunehmen\n\n        -p publisher    Führt den Vorgang nur mit dem angegebenen Herausgeber aus. Kann mehrmals\n                        angegeben werden.\n\n        -r ref_uri      URI des Referenz-Repositorys.\n\n        -s target_path  Pfad zum Ziel-Repository. Repository darf nur\n                        eine Version jedes Packages enthalten. Muss ein\n                        dateisystembasiertes Repository sein.\n\n        -?/--help       Druckt diese Meldung.\n"
+msgstr "Syntax:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\nOptionen:\n        -c pattern      Behandelt jedes Package, bei dem FMRI mit 'pattern' übereinstimmt als\n                        geändert und führt keine Reversionierung aus. Kann mehrmals\n                        angegeben werden.\n\n        -i name         Ignoriert set-Aktionen mit dem Namensfeld 'name' zur\n                        Bestimmung der Inhaltsänderung. Kann mehrmals\n                        angegeben werden.\n\n        -n              Führt einen Probelauf aus, ohne Änderungen vorzunehmen\n\n        -p publisher    Führt den Vorgang nur mit dem angegebenen Herausgeber aus. Kann mehrmals\n                        angegeben werden.\n\n        -r ref_uri      URI des Referenz-Repositorys.\n\n        -s target_path  Pfad zum Ziel-Repository. Repository darf nur\n                        eine Version jedes Packages enthalten. Muss ein\n                        dateisystembasiertes Repository sein.\n\n        -?/--help       Druckt diese Meldung.\n"
 
 #: ../util/publish/pkgsurf.py:230
 msgid ""
--- a/src/po/es.po	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/po/es.po	Mon Sep 26 11:52:18 2016 -0700
@@ -9525,7 +9525,7 @@
 "\n"
 "Options:\n"
 "        -c pattern      Treat every package whose FMRI matches 'pattern' "
-"as \n"
+"as\n"
 "                        changed and do not reversion it. Can be specified\n"
 "                        multiple times.\n"
 "\n"
@@ -9546,7 +9546,7 @@
 "                        filesystem-based repository.\n"
 "\n"
 "        -?/--help       Print this message.\n"
-msgstr "Sintaxis:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\nOpciones:\n        -c pattern      Trata todos los paquetes cuyo FMRI coincida con 'pattern' como \n                        cambiado y realiza una reversión. Se puede especificar\n                        varias veces.\n\n        -i name         Ignora el conjunto de acciones con el campo de nombre definido en 'name' para\n                        la determinación de cambio de contenido.  Se puede especificar\n                        varias veces.\n\n        -n              Realiza una ejecución de prueba sin cambios realizados.\n\n        -p publisher    Sólo funciona en un operador dado. Se puede especificar\n                        varias veces.\n\n        -r ref_uri      URI de repositorio de referencia.\n\n        -s target_path  Ruta para el repositorio de referencia. El repositorio sólo\n                        debe contener una versión de cada paquete. Debe ser un\n                        repositorio basado en sistema de archivos.\n\n        -?/--help       Imprime este mensaje.\n"
+msgstr "Sintaxis:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\nOpciones:\n        -c pattern      Trata todos los paquetes cuyo FMRI coincida con 'pattern' como\n                        cambiado y realiza una reversión. Se puede especificar\n                        varias veces.\n\n        -i name         Ignora el conjunto de acciones con el campo de nombre definido en 'name' para\n                        la determinación de cambio de contenido.  Se puede especificar\n                        varias veces.\n\n        -n              Realiza una ejecución de prueba sin cambios realizados.\n\n        -p publisher    Sólo funciona en un operador dado. Se puede especificar\n                        varias veces.\n\n        -r ref_uri      URI de repositorio de referencia.\n\n        -s target_path  Ruta para el repositorio de referencia. El repositorio sólo\n                        debe contener una versión de cada paquete. Debe ser un\n                        repositorio basado en sistema de archivos.\n\n        -?/--help       Imprime este mensaje.\n"
 
 #: ../util/publish/pkgsurf.py:230
 msgid ""
--- a/src/po/fr.po	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/po/fr.po	Mon Sep 26 11:52:18 2016 -0700
@@ -9525,7 +9525,7 @@
 "\n"
 "Options:\n"
 "        -c pattern      Treat every package whose FMRI matches 'pattern' "
-"as \n"
+"as\n"
 "                        changed and do not reversion it. Can be specified\n"
 "                        multiple times.\n"
 "\n"
@@ -9546,7 +9546,7 @@
 "                        filesystem-based repository.\n"
 "\n"
 "        -?/--help       Print this message.\n"
-msgstr "Syntaxe :\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\nOptions :\n        -c pattern      Traiter chaque package dont le FMRI correspond à 'pattern' comme \n                        modifié et ne pas en modifier le versionnage. Peut être spécifié\n                        plusieurs fois.\n\n        -i name         Ignorer les actions définies dont le champ de nom est réglé sur 'name' lors\n                        de la détermination de la modification du contenu.  Peut être spécifié\n                        plusieurs fois.\n\n        -n              Effectuer une série de tests sans avoir apporté de modifications.\n\n        -p publisher    Appliquer uniquement à l'éditeur spécifié. Peut être spécifié\n                        plusieurs fois.\n\n        -r ref_uri      URI du référentiel de référence.\n\n        -s target_path  Chemin d'accès au référentiel cible. Le référentiel ne doit\n                        contenir qu'une version de chaque package. Il doit être\n                        basé sur un système de fichiers.\n\n        -?/--help       Imprimer ce message.\n"
+msgstr "Syntaxe :\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\nOptions :\n        -c pattern      Traiter chaque package dont le FMRI correspond à 'pattern' comme\n                        modifié et ne pas en modifier le versionnage. Peut être spécifié\n                        plusieurs fois.\n\n        -i name         Ignorer les actions définies dont le champ de nom est réglé sur 'name' lors\n                        de la détermination de la modification du contenu.  Peut être spécifié\n                        plusieurs fois.\n\n        -n              Effectuer une série de tests sans avoir apporté de modifications.\n\n        -p publisher    Appliquer uniquement à l'éditeur spécifié. Peut être spécifié\n                        plusieurs fois.\n\n        -r ref_uri      URI du référentiel de référence.\n\n        -s target_path  Chemin d'accès au référentiel cible. Le référentiel ne doit\n                        contenir qu'une version de chaque package. Il doit être\n                        basé sur un système de fichiers.\n\n        -?/--help       Imprimer ce message.\n"
 
 #: ../util/publish/pkgsurf.py:230
 msgid ""
--- a/src/po/it.po	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/po/it.po	Mon Sep 26 11:52:18 2016 -0700
@@ -9525,7 +9525,7 @@
 "\n"
 "Options:\n"
 "        -c pattern      Treat every package whose FMRI matches 'pattern' "
-"as \n"
+"as\n"
 "                        changed and do not reversion it. Can be specified\n"
 "                        multiple times.\n"
 "\n"
@@ -9546,7 +9546,7 @@
 "                        filesystem-based repository.\n"
 "\n"
 "        -?/--help       Print this message.\n"
-msgstr "Uso:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\nOpzioni:\n        -c pattern      Considera ogni pacchetto il cui FMRI corrisponde a 'pattern' come \n                        modificato e non crea una nuova versione. Può essere specificata\n                        più volte.\n\n        -i name         Ignora le azioni impostate il cui campo del nome è impostato su 'name' per\n                        determinare la modifica del contenuto. Può essere specificata\n                        più volte.\n\n        -n              Effettua un'esecuzione di prova se le modifiche apportate.\n\n        -p publisher    Funziona solo sul publisher indicato. Può essere specificata\n                        più volte.\n\n        -r ref_uri      URI del repository di riferimento.\n\n        -s target_path  Percorso del repository di destinazione. Il repository deve\n                        contenere una sola versione di ogni pacchetto. Deve essere un\n                        repository basato su file system.\n\n        -?/--help       Stampa questo messaggio.\n"
+msgstr "Uso:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\nOpzioni:\n        -c pattern      Considera ogni pacchetto il cui FMRI corrisponde a 'pattern' come\n                        modificato e non crea una nuova versione. Può essere specificata\n                        più volte.\n\n        -i name         Ignora le azioni impostate il cui campo del nome è impostato su 'name' per\n                        determinare la modifica del contenuto. Può essere specificata\n                        più volte.\n\n        -n              Effettua un'esecuzione di prova se le modifiche apportate.\n\n        -p publisher    Funziona solo sul publisher indicato. Può essere specificata\n                        più volte.\n\n        -r ref_uri      URI del repository di riferimento.\n\n        -s target_path  Percorso del repository di destinazione. Il repository deve\n                        contenere una sola versione di ogni pacchetto. Deve essere un\n                        repository basato su file system.\n\n        -?/--help       Stampa questo messaggio.\n"
 
 #: ../util/publish/pkgsurf.py:230
 msgid ""
--- a/src/po/ja.po	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/po/ja.po	Mon Sep 26 11:52:18 2016 -0700
@@ -9525,7 +9525,7 @@
 "\n"
 "Options:\n"
 "        -c pattern      Treat every package whose FMRI matches 'pattern' "
-"as \n"
+"as\n"
 "                        changed and do not reversion it. Can be specified\n"
 "                        multiple times.\n"
 "\n"
--- a/src/po/ko.po	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/po/ko.po	Mon Sep 26 11:52:18 2016 -0700
@@ -9525,7 +9525,7 @@
 "\n"
 "Options:\n"
 "        -c pattern      Treat every package whose FMRI matches 'pattern' "
-"as \n"
+"as\n"
 "                        changed and do not reversion it. Can be specified\n"
 "                        multiple times.\n"
 "\n"
@@ -9546,7 +9546,7 @@
 "                        filesystem-based repository.\n"
 "\n"
 "        -?/--help       Print this message.\n"
-msgstr "사용법:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\n옵션:\n        -c pattern      해당 FMRI가 'pattern'과 일치하는 모든 패키지를 \n                        변경된 것으로 취급하고 복원하지 않습니다. 여러 번 지정할\n                        수 있습니다.\n\n        -i name         컨텐츠 변경 확인을 위해 이름 필드가 'name'으로\n                        설정된 세트 작업을 무시합니다. 여러 번 지정할\n                        수 있습니다.\n\n        -n              변경사항 없이 테스트 실행을 수행합니다.\n\n        -p publisher    제공된 게시자에서만 작업을 수행합니다. 여러 번 지정할\n                        수 있습니다.\n\n        -r ref_uri      참조 저장소의 URI입니다.\n\n        -s target_path  대상 저장소에 대한 경로입니다. 저장소에는 각 패키지의 버전이\n                        하나만 포함되어야 합니다. 파일 시스템\n                        기반 저장소여야 합니다.\n\n        -?/--help       이 메시지를 출력합니다.\n"
+msgstr "사용법:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\n옵션:\n        -c pattern      해당 FMRI가 'pattern'과 일치하는 모든 패키지를\n                        변경된 것으로 취급하고 복원하지 않습니다. 여러 번 지정할\n                        수 있습니다.\n\n        -i name         컨텐츠 변경 확인을 위해 이름 필드가 'name'으로\n                        설정된 세트 작업을 무시합니다. 여러 번 지정할\n                        수 있습니다.\n\n        -n              변경사항 없이 테스트 실행을 수행합니다.\n\n        -p publisher    제공된 게시자에서만 작업을 수행합니다. 여러 번 지정할\n                        수 있습니다.\n\n        -r ref_uri      참조 저장소의 URI입니다.\n\n        -s target_path  대상 저장소에 대한 경로입니다. 저장소에는 각 패키지의 버전이\n                        하나만 포함되어야 합니다. 파일 시스템\n                        기반 저장소여야 합니다.\n\n        -?/--help       이 메시지를 출력합니다.\n"
 
 #: ../util/publish/pkgsurf.py:230
 msgid ""
--- a/src/po/pt_BR.po	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/po/pt_BR.po	Mon Sep 26 11:52:18 2016 -0700
@@ -9525,7 +9525,7 @@
 "\n"
 "Options:\n"
 "        -c pattern      Treat every package whose FMRI matches 'pattern' "
-"as \n"
+"as\n"
 "                        changed and do not reversion it. Can be specified\n"
 "                        multiple times.\n"
 "\n"
@@ -9546,7 +9546,7 @@
 "                        filesystem-based repository.\n"
 "\n"
 "        -?/--help       Print this message.\n"
-msgstr "Uso:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\nOpções:\n        -c pattern      Trata cada pacote cujo FMRI combina o 'padrão' como \n                        alterado e não o reverte. Pode ser especificado\n                        várias vezes.\n\n        -i name         Ignora as ações definidas com o campo de nome definido para 'nome' para\n                        determinação de alteração de conteúdo.  Pode ser especificado\n                        várias vezes.\n\n        -n              Realiza uma execução de teste sem alterações feitas.\n\n        -p publisher    Opera apenas no editor especificado. Pode ser especificado\n                        várias vezes.\n\n        -r ref_uri      URI do repositório de referência.\n\n        -s target_path  Caminho para o repositório de destino. O repositório só deve\n                        conter uma versão de cada pacote. Deve ser um\n                        repositório baseado no sistema de arquivos.\n\n        -?/--help       Imprime esta mensagem.\n"
+msgstr "Uso:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\nOpções:\n        -c pattern      Trata cada pacote cujo FMRI combina o 'padrão' como\n                        alterado e não o reverte. Pode ser especificado\n                        várias vezes.\n\n        -i name         Ignora as ações definidas com o campo de nome definido para 'nome' para\n                        determinação de alteração de conteúdo.  Pode ser especificado\n                        várias vezes.\n\n        -n              Realiza uma execução de teste sem alterações feitas.\n\n        -p publisher    Opera apenas no editor especificado. Pode ser especificado\n                        várias vezes.\n\n        -r ref_uri      URI do repositório de referência.\n\n        -s target_path  Caminho para o repositório de destino. O repositório só deve\n                        conter uma versão de cada pacote. Deve ser um\n                        repositório baseado no sistema de arquivos.\n\n        -?/--help       Imprime esta mensagem.\n"
 
 #: ../util/publish/pkgsurf.py:230
 msgid ""
--- a/src/po/zh_CN.po	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/po/zh_CN.po	Mon Sep 26 11:52:18 2016 -0700
@@ -9525,7 +9525,7 @@
 "\n"
 "Options:\n"
 "        -c pattern      Treat every package whose FMRI matches 'pattern' "
-"as \n"
+"as\n"
 "                        changed and do not reversion it. Can be specified\n"
 "                        multiple times.\n"
 "\n"
--- a/src/po/zh_HK.po	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/po/zh_HK.po	Mon Sep 26 11:52:18 2016 -0700
@@ -9525,7 +9525,7 @@
 "\n"
 "Options:\n"
 "        -c pattern      Treat every package whose FMRI matches 'pattern' "
-"as \n"
+"as\n"
 "                        changed and do not reversion it. Can be specified\n"
 "                        multiple times.\n"
 "\n"
@@ -9546,7 +9546,7 @@
 "                        filesystem-based repository.\n"
 "\n"
 "        -?/--help       Print this message.\n"
-msgstr "用法:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\n選項:\n        -c pattern      將其 FMRI 符合 'pattern' 的所有套裝軟體均視為 \n                        已變更且不執行回復。\n                        可多次指定。\n\n        -i name         忽略名稱欄位設為 'name' 的設定作業\n                        以供判斷內容變更。\n                        可多次指定。\n\n        -n              執行不會做任何變更的試驗執行。\n\n        -p publisher    僅對指定的發佈者執行。\n                        可多次指定。\n\n        -r ref_uri      參照儲存庫的 URI。\n\n        -s target_path  目標儲存庫的路徑。\n                        儲存庫中每個套裝軟體只能有一個版本。\n                        必須是以檔案系統為基礎的儲存庫。\n\n        -?/--help       列印此訊息。\n"
+msgstr "用法:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\n選項:\n        -c pattern      將其 FMRI 符合 'pattern' 的所有套裝軟體均視為\n                        已變更且不執行回復。\n                        可多次指定。\n\n        -i name         忽略名稱欄位設為 'name' 的設定作業\n                        以供判斷內容變更。\n                        可多次指定。\n\n        -n              執行不會做任何變更的試驗執行。\n\n        -p publisher    僅對指定的發佈者執行。\n                        可多次指定。\n\n        -r ref_uri      參照儲存庫的 URI。\n\n        -s target_path  目標儲存庫的路徑。\n                        儲存庫中每個套裝軟體只能有一個版本。\n                        必須是以檔案系統為基礎的儲存庫。\n\n        -?/--help       列印此訊息。\n"
 
 #: ../util/publish/pkgsurf.py:230
 msgid ""
--- a/src/po/zh_TW.po	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/po/zh_TW.po	Mon Sep 26 11:52:18 2016 -0700
@@ -9525,7 +9525,7 @@
 "\n"
 "Options:\n"
 "        -c pattern      Treat every package whose FMRI matches 'pattern' "
-"as \n"
+"as\n"
 "                        changed and do not reversion it. Can be specified\n"
 "                        multiple times.\n"
 "\n"
@@ -9546,7 +9546,7 @@
 "                        filesystem-based repository.\n"
 "\n"
 "        -?/--help       Print this message.\n"
-msgstr "用法:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\n選項:\n        -c pattern      將其 FMRI 符合 'pattern' 的所有套裝軟體均視為 \n                        已變更且不執行回復。\n                        可多次指定。\n\n        -i name         忽略名稱欄位設為 'name' 的設定作業\n                        以供判斷內容變更。\n                        可多次指定。\n\n        -n              執行不會做任何變更的試驗執行。\n\n        -p publisher    僅對指定的發佈者執行。\n                        可多次指定。\n\n        -r ref_uri      參照儲存庫的 URI。\n\n        -s target_path  目標儲存庫的路徑。\n                        儲存庫中每個套裝軟體只能有一個版本。\n                        必須是以檔案系統為基礎的儲存庫。\n\n        -?/--help       列印此訊息。\n"
+msgstr "用法:\n        pkgsurf -s target_path -r ref_uri [-n] [-p publisher ...] [-i name ...]\n            [-c pattern ...]\n\n選項:\n        -c pattern      將其 FMRI 符合 'pattern' 的所有套裝軟體均視為\n                        已變更且不執行回復。\n                        可多次指定。\n\n        -i name         忽略名稱欄位設為 'name' 的設定作業\n                        以供判斷內容變更。\n                        可多次指定。\n\n        -n              執行不會做任何變更的試驗執行。\n\n        -p publisher    僅對指定的發佈者執行。\n                        可多次指定。\n\n        -r ref_uri      參照儲存庫的 URI。\n\n        -s target_path  目標儲存庫的路徑。\n                        儲存庫中每個套裝軟體只能有一個版本。\n                        必須是以檔案系統為基礎的儲存庫。\n\n        -?/--help       列印此訊息。\n"
 
 #: ../util/publish/pkgsurf.py:230
 msgid ""
--- a/src/publish.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/publish.py	Mon Sep 26 11:52:18 2016 -0700
@@ -35,6 +35,8 @@
 import traceback
 import warnings
 import errno
+from pkg.client.pkgdefs import EXIT_OOPS, EXIT_OK, EXIT_PARTIAL, EXIT_BADOPT
+
 if sys.version_info[:2] >= (3, 4):
         from importlib import reload
 else:
@@ -88,7 +90,7 @@
         # program name on all platforms.
         emsg(ws + pkg_cmd + text_nows)
 
-def usage(usage_error=None, cmd=None, retcode=2):
+def usage(usage_error=None, cmd=None, retcode=EXIT_BADOPT):
         """Emit a usage message and optionally prefix it with a more specific
         error message.  Causes program to exit."""
 
@@ -186,8 +188,8 @@
                     "values using the --set-property option."))
         except trans.TransactionError as e:
                 error(e, cmd="create-repository")
-                return 1
-        return 0
+                return EXIT_OOPS
+        return EXIT_OK
 
 def trans_open(repo_uri, args):
         """DEPRECATED"""
@@ -217,7 +219,7 @@
         else:
                 msg(t.open())
 
-        return 0
+        return EXIT_OK
 
 def trans_append(repo_uri, args):
         """DEPRECATED"""
@@ -247,7 +249,7 @@
         else:
                 msg(t.append())
 
-        return 0
+        return EXIT_OK
 
 def trans_close(repo_uri, args):
         """DEPRECATED"""
@@ -281,7 +283,7 @@
         for val in (pkg_state, pkg_fmri):
                 if val is not None:
                         msg(val)
-        return 0
+        return EXIT_OK
 
 def trans_add(repo_uri, args):
         """DEPRECATED"""
@@ -300,13 +302,13 @@
         if action.name in nopub_actions:
                 error(_("invalid action for publication: {0}").format(action),
                     cmd="add")
-                return 1
+                return EXIT_OOPS
 
         xport, pub = setup_transport_and_pubs(repo_uri)
         t = trans.Transaction(repo_uri, trans_id=trans_id, xport=xport,
             pub=pub)
         t.add(action)
-        return 0
+        return EXIT_OK
 
 def trans_publish(repo_uri, fargs):
         """Publish packages in a single step using provided manifest data and
@@ -352,7 +354,7 @@
                         filelist = [(f, open(f)) for f in pargs]
                 except IOError as e:
                         error(e, cmd="publish")
-                        return 1
+                        return EXIT_OOPS
 
         lines = ""      # giant string of all input files concatenated together
         linecnts = []   # tuples of starting line number, ending line number
@@ -363,7 +365,7 @@
                         data = f.read()
                 except IOError as e:
                         error(e, cmd="publish")
-                        return 1
+                        return EXIT_OOPS
                 lines += data
                 linecnt = len(data.splitlines())
                 linecnts.append((linecounter, linecounter + linecnt))
@@ -388,7 +390,7 @@
                 error(_("File {filename} line {lineno}: {err}").format(
                     filename=filename, lineno=lineno, err=e),
                     cmd="publish")
-                return 1
+                return EXIT_OOPS
 
         try:
                 pfmri = pkg.fmri.PkgFmri(m["pkg.fmri"])
@@ -397,14 +399,14 @@
                         error(_("The pkg.fmri attribute '{0}' in the package "
                             "manifest must include a version.").format(pfmri),
                             cmd="publish")
-                        return 1
+                        return EXIT_OOPS
                 if not DebugValues["allow-timestamp"]:
                         # If not debugging, timestamps are ignored.
                         pfmri.version.timestr = None
                 pkg_name = pfmri.get_fmri()
         except KeyError:
                 error(_("Manifest does not set pkg.fmri"))
-                return 1
+                return EXIT_OOPS
 
         xport, pub = setup_transport_and_pubs(repo_uri, ssl_key=key,
             ssl_cert=cert)
@@ -447,7 +449,7 @@
                         error(_("invalid action for publication: {0}").format(
                             action), cmd="publish")
                         t.close(abandon=True)
-                        return 1
+                        return EXIT_OOPS
                 if a.name == "file":
                         basename = os.path.basename(a.attrs["path"])
                         for pattern in timestamp_files:
@@ -471,7 +473,7 @@
         for val in (pkg_state, pkg_fmri):
                 if val is not None:
                         msg(val)
-        return 0
+        return EXIT_OK
 
 def trans_include(repo_uri, fargs, transaction=None):
         """DEPRECATED"""
@@ -506,7 +508,7 @@
                         filelist = [(f, open(f)) for f in pargs]
                 except IOError as e:
                         error(e, cmd="include")
-                        return 1
+                        return EXIT_OOPS
 
         lines = []      # giant string of all input files concatenated together
         linecnts = []   # tuples of starting line number, ending line number
@@ -517,7 +519,7 @@
                         data = f.read()
                 except IOError as e:
                         error(e, cmd="include")
-                        return 1
+                        return EXIT_OOPS
                 lines.append(data)
                 linecnt = len(data.splitlines())
                 linecnts.append((linecounter, linecounter + linecnt))
@@ -541,7 +543,7 @@
                 error(_("File {filename} line {lineno}: {err}").format(
                     filename=filename, lineno=lineno, err=e),
                     cmd="include")
-                return 1
+                return EXIT_OOPS
 
         invalid_action = False
 
@@ -569,9 +571,9 @@
                         t.add(a)
 
         if invalid_action:
-                return 3
+                return EXIT_PARTIAL
         else:
-                return 0
+                return EXIT_OK
 
 def gen_actions(files, timestamp_files, target_files, minimal=False, visitors=[],
     use_default_owner=True):
@@ -633,7 +635,7 @@
         xport, pub = setup_transport_and_pubs(repo_uri)
         t = trans.Transaction(repo_uri, trans_id=trans_id, xport=xport, pub=pub)
 
-        ret = 0
+        ret = EXIT_OK
         abandon = False
         try:
                 for action, err in gen_actions(pargs, timestamp_files,
@@ -647,19 +649,19 @@
                                         t.add(action)
         except TypeError as e:
                 error(e, cmd="import")
-                return 1
+                return EXIT_OOPS
         except EnvironmentError as e:
                 if e.errno == errno.ENOENT:
                         error("{0}: '{1}'".format(e.args[1], e.filename),
                             cmd="import")
-                        return 1
+                        return EXIT_OOPS
                 else:
                         raise
 
         for visitor in visitors:
                 if visitor.errors:
                         abandon = True
-                        ret = 1
+                        ret = EXIT_OOPS
         if abandon:
                 error("Abandoning transaction due to errors.")
                 t.close(abandon=True)
@@ -696,16 +698,16 @@
                         print(action)
         except TypeError as e:
                 error(e, cmd="generate")
-                return 1
+                return EXIT_OOPS
         except EnvironmentError as e:
                 if e.errno == errno.ENOENT:
                         error("{0}: '{1}'".format(e.args[1], e.filename),
                             cmd="generate")
-                        return 1
+                        return EXIT_OOPS
                 else:
                         raise
 
-        return 0
+        return EXIT_OK
 
 def trans_refresh_index(repo_uri, args):
         """DEPRECATED"""
@@ -720,8 +722,8 @@
                     pub=pub).refresh_index()
         except trans.TransactionError as e:
                 error(e, cmd="refresh-index")
-                return 1
-        return 0
+                return EXIT_OOPS
+        return EXIT_OK
 
 def setup_transport_and_pubs(repo_uri, remote=True, ssl_key=None,
     ssl_cert=None):
@@ -737,8 +739,6 @@
         return xport, targ_pub
 
 def main_func():
-        gettext.install("pkg", "/usr/share/locale",
-            codeset=locale.getpreferredencoding())
 
         repo_uri = os.getenv("PKG_REPO", None)
 
@@ -788,7 +788,7 @@
                     "using -s."), cmd=subcommand)
 
         visitors = [SolarisBundleVisitor()]
-        ret = 0
+        ret = EXIT_OK
         try:
                 if subcommand == "create-repository":
                         ret = trans_create_repository(repo_uri, pargs)
@@ -828,10 +828,10 @@
                                         print("")
                                         printed_space = True
                                 error(err, cmd=subcommand)
-                                ret = 1
+                                ret = EXIT_OOPS
         except pkg.bundle.InvalidBundleException as e:
                 error(e, cmd=subcommand)
-                ret = 1
+                ret = EXIT_OOPS
         except getopt.GetoptError as e:
                 usage(_("illegal {cmd} option -- {opt}").format(
                     cmd=subcommand, opt=e.opt))
@@ -843,6 +843,10 @@
 # so that we can more easily detect these in testing of the CLI commands.
 #
 if __name__ == "__main__":
+        misc.setlocale(locale.LC_ALL, "", error)
+        gettext.install("pkg", "/usr/share/locale",
+            codeset=locale.getpreferredencoding())
+        misc.set_fd_limits(printer=error)
 
         # Make all warnings be errors.
         warnings.simplefilter('error')
@@ -855,7 +859,7 @@
         except (PipeError, KeyboardInterrupt):
                 # We don't want to display any messages here to prevent
                 # possible further broken pipe (EPIPE) errors.
-                __ret = 1
+                __ret = EXIT_OOPS
         except (pkg.actions.ActionError, trans.TransactionError,
             EnvironmentError, RuntimeError, pkg.fmri.FmriError,
             apx.ApiException) as _e:
@@ -866,10 +870,10 @@
                         # Only print message if failure wasn't due to
                         # broken pipe (EPIPE) error.
                         print("pkgsend: {0}".format(_e), file=sys.stderr)
-                __ret = 1
+                __ret = EXIT_OOPS
         except MemoryError:
                 error("\n" + misc.out_of_memory())
-                __ret = 1
+                __ret = EXIT_OOPS
         except SystemExit as _e:
                 raise _e
         except:
--- a/src/pull.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/pull.py	Mon Sep 26 11:52:18 2016 -0700
@@ -422,9 +422,6 @@
 
         temp_root = misc.config_temp_root()
 
-        gettext.install("pkg", "/usr/share/locale",
-            codeset=locale.getpreferredencoding())
-
         # set process limits for memory consumption to 8GB
         misc.set_memory_limit(8 * 1024 * 1024 * 1024)
 
@@ -1727,6 +1724,10 @@
         return pkgdefs.EXIT_OK
 
 if __name__ == "__main__":
+        misc.setlocale(locale.LC_ALL, "", error)
+        gettext.install("pkg", "/usr/share/locale",
+            codeset=locale.getpreferredencoding())
+        misc.set_fd_limits(printer=error)
 
         # Make all warnings be errors.
         warnings.simplefilter('error')
--- a/src/sign.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/sign.py	Mon Sep 26 11:52:18 2016 -0700
@@ -127,9 +127,6 @@
         return fp
 
 def main_func():
-        misc.setlocale(locale.LC_ALL, "", error)
-        gettext.install("pkg", "/usr/share/locale",
-            codeset=locale.getpreferredencoding())
         global_settings.client_name = "pkgsign"
 
         try:
@@ -388,6 +385,11 @@
 # so that we can more easily detect these in testing of the CLI commands.
 #
 if __name__ == "__main__":
+        misc.setlocale(locale.LC_ALL, "", error)
+        gettext.install("pkg", "/usr/share/locale",
+            codeset=locale.getpreferredencoding())
+        misc.set_fd_limits(printer=error)
+
         try:
                 __ret = main_func()
         except (PipeError, KeyboardInterrupt):
--- a/src/util/publish/pkgdiff.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/util/publish/pkgdiff.py	Mon Sep 26 11:52:18 2016 -0700
@@ -42,8 +42,9 @@
 from pkg.misc import PipeError, CMP_UNSIGNED, CMP_ALL
 from collections import defaultdict
 from itertools import product
+from pkg.client.pkgdefs import EXIT_OK, EXIT_OOPS, EXIT_BADOPT, EXIT_PARTIAL
 
-def usage(errmsg="", exitcode=2):
+def usage(errmsg="", exitcode=EXIT_BADOPT):
         """Emit a usage message and optionally prefix it with a more specific
         error message.  Causes program to exit."""
 
@@ -57,7 +58,7 @@
             [-v name=value]... (file1 | -) (file2 | -)"""))
         sys.exit(exitcode)
 
-def error(text, exitcode=3):
+def error(text, exitcode=EXIT_PARTIAL):
         """Emit an error message prefixed by the command name """
 
         print("pkgdiff: {0}".format(text), file=sys.stderr)
@@ -66,8 +67,6 @@
                 sys.exit(exitcode)
 
 def main_func():
-        gettext.install("pkg", "/usr/share/locale",
-            codeset=locale.getpreferredencoding())
 
         ignoreattrs = []
         onlyattrs = []
@@ -95,7 +94,7 @@
                                         args[0] = "variant." + args[0]
                                 varattrs[args[0]].add(args[1])
                         elif opt in ("--help", "-?"):
-                                usage(exitcode=0)
+                                usage(exitcode=EXIT_OK)
 
         except getopt.GetoptError as e:
                 usage(_("illegal global option -- {0}").format(e.opt))
@@ -363,13 +362,18 @@
         return int(different)
 
 if __name__ == "__main__":
+        misc.setlocale(locale.LC_ALL, "", error)
+        gettext.install("pkg", "/usr/share/locale",
+            codeset=locale.getpreferredencoding())
+        misc.set_fd_limits(printer=error)
+
         if six.PY3:
                 # disable ResourceWarning: unclosed file
                 warnings.filterwarnings("ignore", category=ResourceWarning)
         try:
                 exit_code = main_func()
         except (PipeError, KeyboardInterrupt):
-                exit_code = 1
+                exit_code = EXIT_OOPS
         except SystemExit as __e:
                 exit_code = __e
         except Exception as __e:
--- a/src/util/publish/pkgfmt.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/util/publish/pkgfmt.py	Mon Sep 26 11:52:18 2016 -0700
@@ -78,9 +78,11 @@
         from pkg.misc import emsg, PipeError
         from pkg.actions.generic import quote_attr_value
         from pkg.actions.depend import known_types as dep_types
+        from pkg.client.pkgdefs import (EXIT_OK, EXIT_OOPS, EXIT_BADOPT,
+            EXIT_PARTIAL)
 except KeyboardInterrupt:
         import sys
-        sys.exit(1)
+        sys.exit(EXIT_OOPS)
 
 FMT_V1 = "v1"
 FMT_V2 = "v2"
@@ -91,7 +93,7 @@
 opt_format = FMT_V2
 orig_opt_format = None
 
-def usage(errmsg="", exitcode=2):
+def usage(errmsg="", exitcode=EXIT_BADOPT):
         """Emit a usage message and optionally prefix it with a more specific
         error message.  Causes program to exit."""
 
@@ -105,7 +107,7 @@
 
         sys.exit(exitcode)
 
-def error(text, exitcode=1):
+def error(text, exitcode=EXIT_OOPS):
         """Emit an error message prefixed by the command name """
 
         # If we get passed something like an Exception, we can convert
@@ -519,8 +521,6 @@
         print(output, file=fileobj)
 
 def main_func():
-        gettext.install("pkg", "/usr/share/locale",
-            codeset=locale.getpreferredencoding())
         global opt_unwrap
         global opt_check
         global opt_diffs
@@ -548,7 +548,7 @@
                         elif opt == "-u":
                                 opt_unwrap = True
                         elif opt in ("--help", "-?"):
-                                usage(exitcode=0)
+                                usage(exitcode=EXIT_OK)
         except getopt.GetoptError as e:
                 usage(_("illegal global option -- {0}").format(e.opt))
         if len(opt_set - set(["-f"])) > 1:
@@ -666,9 +666,9 @@
                                 os.chmod(tname, mode)
                                 os.rename(tname, fname)
                         except EnvironmentError as e:
-                                error(str(e), exitcode=1)
+                                error(str(e), exitcode=EXIT_OOPS)
                 except (EnvironmentError, IOError) as e:
-                        error(str(e), exitcode=1)
+                        error(str(e), exitcode=EXIT_OOPS)
                 finally:
                         if tname:
                                 try:
@@ -714,6 +714,11 @@
 
 
 if __name__ == "__main__":
+        misc.setlocale(locale.LC_ALL, "", error)
+        gettext.install("pkg", "/usr/share/locale",
+            codeset=locale.getpreferredencoding())
+        misc.set_fd_limits(printer=error)
+
         if six.PY3:
                 # disable ResourceWarning: unclosed file
                 warnings.filterwarnings("ignore", category=ResourceWarning)
--- a/src/util/publish/pkglint.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/util/publish/pkglint.py	Mon Sep 26 11:52:18 2016 -0700
@@ -37,6 +37,7 @@
 from pkg.client.api_errors import InvalidPackageErrors
 from pkg import VERSION
 from pkg.misc import PipeError
+from pkg.client.pkgdefs import EXIT_OK, EXIT_OOPS, EXIT_BADOPT
 
 import pkg.lint.engine as engine
 import pkg.lint.log as log
@@ -48,8 +49,12 @@
 
 logger = None
 
-def error(message):
-        logger.error(_("Error: {0}").format(message))
+def error(message=""):
+        """Emit an error message prefixed by the command name. """
+        misc.emsg("pkglint: {0}".format(message))
+
+        if logger is not None:
+                logger.error(_("Error: {0}").format(message))
 
 def msg(message):
         logger.info(message)
@@ -60,9 +65,6 @@
 def main_func():
         """Start pkglint."""
 
-        gettext.install("pkg", "/usr/share/locale",
-            codeset=locale.getpreferredencoding())
-
         global logger
 
         usage = \
@@ -128,7 +130,7 @@
                 if opts.list_checks:
                         list_checks(lint_engine.checkers,
                             lint_engine.excluded_checkers, opts.verbose)
-                        return 0
+                        return EXIT_OK
 
                 if (opts.lint_uris or opts.ref_uris) and not opts.cache:
                         parser.error(
@@ -141,7 +143,7 @@
                         if None in manifests or \
                             lint_logger.produced_lint_msgs():
                                 error(_("Fatal error in manifest - exiting."))
-                                return 1
+                                return EXIT_OOPS
                 lint_engine.setup(ref_uris=opts.ref_uris,
                     lint_uris=opts.lint_uris,
                     lint_manifests=manifests,
@@ -159,16 +161,16 @@
                 # errors during setup are likely to be caused by bad
                 # input or configuration, not lint errors in manifests.
                 error(err)
-                return 2
+                return EXIT_BADOPT
 
         except engine.LintEngineException as err:
                 error(err)
-                return 1
+                return EXIT_OOPS
 
         if lint_logger.produced_lint_msgs():
-                return 1
+                return EXIT_OOPS
         else:
-                return 0
+                return EXIT_OK
 
 def list_checks(checkers, exclude, verbose=False):
         """Prints a human-readable version of configured checks."""
@@ -315,6 +317,11 @@
 
 
 if __name__ == "__main__":
+        misc.setlocale(locale.LC_ALL, "", error)
+        gettext.install("pkg", "/usr/share/locale",
+            codeset=locale.getpreferredencoding())
+        misc.set_fd_limits(printer=error)
+
         if six.PY3:
                 # disable ResourceWarning: unclosed file
                 warnings.filterwarnings("ignore", category=ResourceWarning)
@@ -323,12 +330,12 @@
         except (PipeError, KeyboardInterrupt):
                 # We don't want to display any messages here to prevent
                 # possible further broken pipe (EPIPE) errors.
-                __ret = 2
+                __ret = EXIT_BADOPT
         except SystemExit as __e:
                 __ret = __e.code
         except (apx.InvalidDepotResponseException, tx.TransportFailures) as __e:
                 error(__e)
-                __ret = 2
+                __ret = EXIT_BADOPT
         except:
                 traceback.print_exc()
                 error(misc.get_traceback_message())
--- a/src/util/publish/pkgmerge.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/util/publish/pkgmerge.py	Mon Sep 26 11:52:18 2016 -0700
@@ -52,9 +52,11 @@
         from functools import reduce
         from pkg.misc import PipeError, emsg, msg
         from six.moves.urllib.parse import quote
+        from pkg.client.pkgdefs import (EXIT_OK, EXIT_OOPS, EXIT_BADOPT,
+            EXIT_PARTIAL)
 except KeyboardInterrupt:
         import sys
-        sys.exit(1)
+        sys.exit(EXIT_OOPS)
 
 class PkgmergeException(Exception):
         """An exception raised if something goes wrong during the merging
@@ -140,7 +142,7 @@
 
         sys.exit(exitcode)
 
-def error(text, exitcode=1):
+def error(text, exitcode=EXIT_OOPS):
         """Emit an error message prefixed by the command name """
 
         emsg("pkgmerge: {0}".format(text))
@@ -450,9 +452,9 @@
         for message in errors:
                 error(message, exitcode=None)
         if errors:
-                exit(1)
+                exit(EXIT_OOPS)
 
-        return 0
+        return EXIT_OK
 
 def republish_packages(pub, target_pub, processdict, source_list, variant_list,
         variants, tracker, xport, dest_repo, dest_xport, pkg_tmpdir,
@@ -968,6 +970,7 @@
         misc.setlocale(locale.LC_ALL, "", error)
         gettext.install("pkg", "/usr/share/locale",
             codeset=locale.getpreferredencoding())
+        misc.set_fd_limits(printer=error)
 
         # Make all warnings be errors.
         import warnings
@@ -980,9 +983,9 @@
         except (pkg.actions.ActionError, trans.TransactionError,
             RuntimeError, pkg.fmri.FmriError, apx.ApiException) as __e:
                 print("pkgmerge: {0}".format(__e), file=sys.stderr)
-                __ret = 1
+                __ret = EXIT_OOPS
         except (PipeError, KeyboardInterrupt):
-                __ret = 1
+                __ret = EXIT_OOPS
         except SystemExit as __e:
                 raise __e
         except Exception as __e:
--- a/src/util/publish/pkgmogrify.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/util/publish/pkgmogrify.py	Mon Sep 26 11:52:18 2016 -0700
@@ -35,9 +35,10 @@
 import pkg.misc as misc
 import pkg.mogrify as mog
 from pkg.misc import PipeError
+from pkg.client.pkgdefs import EXIT_OK, EXIT_OOPS, EXIT_BADOPT, EXIT_PARTIAL
 
 
-def usage(errmsg="", exitcode=2):
+def usage(errmsg="", exitcode=EXIT_BADOPT):
         """Emit a usage message and optionally prefix it with a more specific
         error message.  Causes program to exit."""
 
@@ -50,7 +51,7 @@
             [-O outputfile] [-P printfile] [inputfile ...]"""))
         sys.exit(exitcode)
 
-def error(text, exitcode=1):
+def error(text, exitcode=EXIT_OOPS):
         """Emit an error message prefixed by the command name """
 
         print("pkgmogrify: {0}".format(text), file=sys.stderr)
@@ -58,9 +59,6 @@
                 sys.exit(exitcode)
 
 def main_func():
-        gettext.install("pkg", "/usr/share/locale",
-            codeset=locale.getpreferredencoding())
-
         outfilename = None
         printfilename = None
         verbose = False
@@ -91,7 +89,7 @@
                         if opt == "-v":
                                 verbose = True
                         if opt in ("--help", "-?"):
-                                usage(exitcode=0)
+                                usage(exitcode=EXIT_OK)
 
         except getopt.GetoptError as e:
                 usage(_("illegal global option -- {0}").format(e.opt))
@@ -100,7 +98,7 @@
                 mog.process_mog(pargs, ignoreincludes, verbose, includes,
                     macros, printinfo, output, error_cb=error)
         except RuntimeError as e:
-                sys.exit(1)
+                sys.exit(EXIT_OOPS)
 
         try:
                 if printfilename == None:
@@ -148,6 +146,10 @@
         return 0
 
 if __name__ == "__main__":
+        misc.setlocale(locale.LC_ALL, "", error)
+        gettext.install("pkg", "/usr/share/locale",
+            codeset=locale.getpreferredencoding())
+        misc.set_fd_limits(printer=error)
 
         # Make all warnings be errors.
         warnings.simplefilter('error')
@@ -157,7 +159,7 @@
         try:
                 exit_code = main_func()
         except (PipeError, KeyboardInterrupt):
-                exit_code = 1
+                exit_code = EXIT_OOPS
         except SystemExit as __e:
                 exit_code = __e
         except Exception as __e:
--- a/src/util/publish/pkgsurf.py	Mon Sep 26 11:23:30 2016 -0700
+++ b/src/util/publish/pkgsurf.py	Mon Sep 26 11:52:18 2016 -0700
@@ -30,7 +30,7 @@
 # After determining the packages present in the target repo, pkgsurf tries to
 # find the associated version of each package in the reference repo. Packages
 # which can't be found in the reference are ignored (not reversioned). Only the
-# latest version of the reference packages are considered. 
+# latest version of the reference packages are considered.
 # We then compare the target and ref manifest for content changes. Any
 # difference in the manifests' actions is considered a content change unless
 # they differ in:
@@ -38,7 +38,7 @@
 #  - a set action whose name attribute is specified with -i/--ignore
 #  - a signature action (signature will change when FMRI changes)
 #  - a depend action (see below)
-#   
+#
 # Changes in depend actions are not considered a content change, however,
 # further analysis is required since the package can only be reversioned if the
 # dependency package didn't have a content change and its dependencies didn't
@@ -64,7 +64,7 @@
 # pkgsurf deletes and inserts manifests in place for the target repo. File data
 # does not need to be modified since we only operate on packages with no content
 # change. It runs a catalog rebuild as the last step to regain catalog integrity
-# within the repo. 
+# within the repo.
 
 import getopt
 import gettext
@@ -153,7 +153,7 @@
             [-i name ...] [-c pattern ...]
 
 Options:
-        -c pattern      Treat every package whose FMRI matches 'pattern' as 
+        -c pattern      Treat every package whose FMRI matches 'pattern' as
                         changed and do not reversion it. Can be specified
                         multiple times.
 
@@ -298,7 +298,7 @@
 
         # Dep package hasn't been changed, no adjustment necessary.
         if dpfmri.get_pkg_stem() not in reversioned_pkgs:
-                return fmri_str                
+                return fmri_str
 
         # Find the dependency action of the reference package
         # and replace the current version with it.
@@ -380,7 +380,7 @@
         if a.name == "set" and "name" in a.attrs:
                 if a.attrs["name"] in ignores:
                         return True
-                # We ignore the pkg FMRI because this is what 
+                # We ignore the pkg FMRI because this is what
                 # will always change.
                 if a.attrs["name"] == "pkg.fmri":
                         return True
@@ -487,13 +487,13 @@
                     or not all(use_ref(a, rdeps, ignores) for a in ra):
                         continue
 
-                # Both dep lists should be equally long in case deps have just 
+                # Both dep lists should be equally long in case deps have just
                 # changed. If not, it means a dep has been added or removed and
                 # that means content change.
                 if len(tdeps) != len(rdeps):
                         continue
 
-                # If len is not different we still have to make sure that 
+                # If len is not different we still have to make sure that
                 # entries have the same pkg stem. The test above just saves time
                 # in some cases.
                 if not all(td in rdeps for td in tdeps):
@@ -515,15 +515,15 @@
                 """Determine if a package or any of its dependencies has
                 changed.
                 Function will check if a dependency had a content change. If it
-                only had a dependency change, analyze its dependencies 
+                only had a dependency change, analyze its dependencies
                 recursively. Only if the whole dependency chain didn't have any
-                content change it is safe to reversion the package. 
+                content change it is safe to reversion the package.
 
-                Note about circular dependencies: The function keeps track of 
+                Note about circular dependencies: The function keeps track of
                 pkgs it already processed by stuffing them into the set 'seen'.
-                However, 'seen' gets updated before the child dependencies of 
+                However, 'seen' gets updated before the child dependencies of
                 the current pkg are examined. This works if 'seen' is only used
-                for one dependency chain since the function immediately comes 
+                for one dependency chain since the function immediately comes
                 back with a True result if a pkg has changed further down the
                 tree. However, if 'seen' is re-used between runs, it will
                 return prematurely, likely returning wrong results. """
@@ -648,7 +648,7 @@
                                     err=str(e)))
                         continue
 
-                # For packages we don't reversion we have to check if they 
+                # For packages we don't reversion we have to check if they
                 # depend on a reversioned package.
                 # Since the version of this dependency might be removed from the
                 # repo, we have to adjust the dep version to the one of the
@@ -681,9 +681,6 @@
         global temp_root, repo_modified, repo_finished, repo_uri, tracker
         global dry_run
 
-        misc.setlocale(locale.LC_ALL, "", error)
-        gettext.install("pkg", "/usr/share/locale",
-            codeset=locale.getpreferredencoding())
         global_settings.client_name = PKG_CLIENT_NAME
 
         try:
@@ -798,6 +795,11 @@
 # so that we can more easily detect these in testing of the CLI commands.
 #
 if __name__ == "__main__":
+        misc.setlocale(locale.LC_ALL, "", error)
+        gettext.install("pkg", "/usr/share/locale",
+            codeset=locale.getpreferredencoding())
+        misc.set_fd_limits(printer=error)
+
         if six.PY3:
                 # disable ResourceWarning: unclosed file
                 warnings.filterwarnings("ignore", category=ResourceWarning)