Procházet zdrojové kódy

Make all command line action functions return int

This will allow using type-safe function pointers instead of casting
them around. Replace all exit(3) calls with return statements. Remove
DPKG_ATTR_NORET from function declarations, all functions are expected
to return now.
Guillem Jover před 15 roky
rodič
revize
ba372a8c55

+ 4 - 2
dpkg-deb/build.c

@@ -384,7 +384,9 @@ pkg_get_pathname(const char *dir, struct pkginfo *pkg)
 /**
 /**
  * Overly complex function that builds a .deb file.
  * Overly complex function that builds a .deb file.
  */
  */
-void do_build(const char *const *argv) {
+int
+do_build(const char *const *argv)
+{
   const char *debar, *dir;
   const char *debar, *dir;
   bool subdir;
   bool subdir;
   char *tfbuf;
   char *tfbuf;
@@ -593,5 +595,5 @@ void do_build(const char *const *argv) {
   if (close(arfd))
   if (close(arfd))
     ohshite(_("unable to close file '%s'"), debar);
     ohshite(_("unable to close file '%s'"), debar);
 
 
-  exit(0);
+  return 0;
 }
 }

+ 2 - 2
dpkg-deb/dpkg-deb.h

@@ -21,8 +21,8 @@
 #ifndef DPKG_DEB_H
 #ifndef DPKG_DEB_H
 #define DPKG_DEB_H
 #define DPKG_DEB_H
 
 
-typedef void dofunction(const char *const *argv);
-dofunction do_build DPKG_ATTR_NORET;
+typedef int dofunction(const char *const *argv);
+dofunction do_build;
 dofunction do_contents, do_control, do_showinfo;
 dofunction do_contents, do_control, do_showinfo;
 dofunction do_info, do_field, do_extract, do_vextract, do_fsystarfile;
 dofunction do_info, do_field, do_extract, do_vextract, do_fsystarfile;
 
 

+ 28 - 7
dpkg-deb/extract.c

@@ -327,9 +327,10 @@ extracthalf(const char *debar, const char *dir, const char *taroption,
   }
   }
 }
 }
 
 
-static void controlextractvextract(int admin,
-                                   const char *taroptions,
-                                   const char *const *argv) {
+static int
+controlextractvextract(int admin, const char *taroptions,
+                       const char *const *argv)
+{
   const char *debar, *dir;
   const char *debar, *dir;
 
 
   if (!(debar= *argv++))
   if (!(debar= *argv++))
@@ -344,9 +345,13 @@ static void controlextractvextract(int admin,
     badusage(_("--%s takes at most two arguments (.deb and directory)"),cipaction->olong);
     badusage(_("--%s takes at most two arguments (.deb and directory)"),cipaction->olong);
   }
   }
   extracthalf(debar, dir, taroptions, admin);
   extracthalf(debar, dir, taroptions, admin);
+
+  return 0;
 }
 }
 
 
-void do_fsystarfile(const char *const *argv) {
+int
+do_fsystarfile(const char *const *argv)
+{
   const char *debar;
   const char *debar;
 
 
   if (!(debar= *argv++))
   if (!(debar= *argv++))
@@ -354,8 +359,24 @@ void do_fsystarfile(const char *const *argv) {
   if (*argv)
   if (*argv)
     badusage(_("--%s takes only one argument (.deb filename)"),cipaction->olong);
     badusage(_("--%s takes only one argument (.deb filename)"),cipaction->olong);
   extracthalf(debar, NULL, NULL, 0);
   extracthalf(debar, NULL, NULL, 0);
+
+  return 0;
+}
+
+int
+do_control(const char *const *argv)
+{
+  return controlextractvextract(1, "x", argv);
+}
+
+int
+do_extract(const char *const *argv)
+{
+  return controlextractvextract(0, "xp", argv);
 }
 }
 
 
-void do_control(const char *const *argv) { controlextractvextract(1, "x", argv); }
-void do_extract(const char *const *argv) { controlextractvextract(0, "xp", argv); }
-void do_vextract(const char *const *argv) { controlextractvextract(0, "xpv", argv); }
+int
+do_vextract(const char *const *argv)
+{
+  return controlextractvextract(0, "xpv", argv);
+}

+ 20 - 5
dpkg-deb/info.c

@@ -254,7 +254,9 @@ info_field(const char *debar, const char *dir, const char *const *fields,
   m_output(stdout, _("<standard output>"));
   m_output(stdout, _("<standard output>"));
 }
 }
 
 
-void do_showinfo(const char* const* argv) {
+int
+do_showinfo(const char *const *argv)
+{
   const char *debar, *dir;
   const char *debar, *dir;
   struct pkginfo *pkg;
   struct pkginfo *pkg;
   struct pkg_format_node *fmt = pkg_format_parse(showformat);
   struct pkg_format_node *fmt = pkg_format_parse(showformat);
@@ -267,10 +269,13 @@ void do_showinfo(const char* const* argv) {
   parsedb(CONTROLFILE, pdb_recordavailable | pdb_rejectstatus | pdb_ignorefiles,
   parsedb(CONTROLFILE, pdb_recordavailable | pdb_rejectstatus | pdb_ignorefiles,
           &pkg);
           &pkg);
   pkg_format_show(fmt, pkg, &pkg->available);
   pkg_format_show(fmt, pkg, &pkg->available);
-}
 
 
+  return 0;
+}
 
 
-void do_info(const char *const *argv) {
+int
+do_info(const char *const *argv)
+{
   const char *debar, *dir;
   const char *debar, *dir;
 
 
   if (*argv && argv[1]) {
   if (*argv && argv[1]) {
@@ -280,9 +285,13 @@ void do_info(const char *const *argv) {
     info_prepare(&argv, &debar, &dir, 2);
     info_prepare(&argv, &debar, &dir, 2);
     info_list(debar, dir);
     info_list(debar, dir);
   }
   }
+
+  return 0;
 }
 }
 
 
-void do_field(const char *const *argv) {
+int
+do_field(const char *const *argv)
+{
   const char *debar, *dir;
   const char *debar, *dir;
 
 
   info_prepare(&argv, &debar, &dir, 1);
   info_prepare(&argv, &debar, &dir, 1);
@@ -292,13 +301,19 @@ void do_field(const char *const *argv) {
     static const char *const controlonly[] = { "control", NULL };
     static const char *const controlonly[] = { "control", NULL };
     info_spew(debar, dir, controlonly);
     info_spew(debar, dir, controlonly);
   }
   }
+
+  return 0;
 }
 }
 
 
-void do_contents(const char *const *argv) {
+int
+do_contents(const char *const *argv)
+{
   const char *debar;
   const char *debar;
 
 
   if (!(debar= *argv++) || *argv) badusage(_("--contents takes exactly one argument"));
   if (!(debar= *argv++) || *argv) badusage(_("--contents takes exactly one argument"));
   extracthalf(debar, NULL, "tv", 0);
   extracthalf(debar, NULL, "tv", 0);
+
+  return 0;
 }
 }
 /* vi: sw=2
 /* vi: sw=2
  */
  */

+ 5 - 2
dpkg-deb/main.c

@@ -183,6 +183,7 @@ static const struct cmdinfo cmdinfos[]= {
 
 
 int main(int argc, const char *const *argv) {
 int main(int argc, const char *const *argv) {
   dofunction *action;
   dofunction *action;
+  int ret;
 
 
   setlocale(LC_NUMERIC, "POSIX");
   setlocale(LC_NUMERIC, "POSIX");
   setlocale(LC_ALL, "");
   setlocale(LC_ALL, "");
@@ -196,9 +197,11 @@ int main(int argc, const char *const *argv) {
 
 
   unsetenv("GZIP");
   unsetenv("GZIP");
   action = (dofunction *)cipaction->arg_func;
   action = (dofunction *)cipaction->arg_func;
-  action(argv);
+  ret = action(argv);
+
   standard_shutdown();
   standard_shutdown();
-  exit(0);
+
+  return ret;
 }
 }
 
 
 /* vi: sw=2
 /* vi: sw=2

+ 2 - 2
dpkg-split/dpkg-split.h

@@ -21,8 +21,8 @@
 #ifndef DPKG_SPLIT_H
 #ifndef DPKG_SPLIT_H
 #define DPKG_SPLIT_H
 #define DPKG_SPLIT_H
 
 
-typedef void dofunction(const char *const *argv);
-dofunction do_split DPKG_ATTR_NORET;
+typedef int dofunction(const char *const *argv);
+dofunction do_split;
 dofunction do_join, do_info, do_auto, do_queue, do_discard;
 dofunction do_join, do_info, do_auto, do_queue, do_discard;
 
 
 struct partinfo {
 struct partinfo {

+ 5 - 1
dpkg-split/info.c

@@ -224,7 +224,9 @@ void print_info(const struct partinfo *pi) {
          (intmax_t)pi->filesize);
          (intmax_t)pi->filesize);
 }
 }
 
 
-void do_info(const char *const *argv) {
+int
+do_info(const char *const *argv)
+{
   const char *thisarg;
   const char *thisarg;
   struct partinfo *pi, ps;
   struct partinfo *pi, ps;
   FILE *part;
   FILE *part;
@@ -245,4 +247,6 @@ void do_info(const char *const *argv) {
     }
     }
     m_output(stdout, _("<standard output>"));
     m_output(stdout, _("<standard output>"));
   }
   }
+
+  return 0;
 }
 }

+ 5 - 1
dpkg-split/join.c

@@ -92,7 +92,9 @@ void addtopartlist(struct partinfo **partlist,
   partlist[i]= pi;
   partlist[i]= pi;
 }
 }
 
 
-void do_join(const char *const *argv) {
+int
+do_join(const char *const *argv)
+{
   const char *thisarg;
   const char *thisarg;
   struct partqueue *pq;
   struct partqueue *pq;
   struct partinfo *refi, **partlist;
   struct partinfo *refi, **partlist;
@@ -136,4 +138,6 @@ void do_join(const char *const *argv) {
     opt_outputfile = p;
     opt_outputfile = p;
   }
   }
   reassemble(partlist, opt_outputfile);
   reassemble(partlist, opt_outputfile);
+
+  return 0;
 }
 }

+ 4 - 2
dpkg-split/main.c

@@ -145,6 +145,7 @@ static const struct cmdinfo cmdinfos[]= {
 };
 };
 
 
 int main(int argc, const char *const *argv) {
 int main(int argc, const char *const *argv) {
+  int ret;
   int l;
   int l;
   char *p;
   char *p;
   dofunction *action;
   dofunction *action;
@@ -168,10 +169,11 @@ int main(int argc, const char *const *argv) {
 
 
   setvbuf(stdout,NULL,_IONBF,0);
   setvbuf(stdout,NULL,_IONBF,0);
   action = (dofunction *)cipaction->arg_func;
   action = (dofunction *)cipaction->arg_func;
-  action(argv);
+  ret = action(argv);
 
 
   m_output(stderr, _("<standard error>"));
   m_output(stderr, _("<standard error>"));
 
 
   standard_shutdown();
   standard_shutdown();
-  exit(0);
+
+  return ret;
 }
 }

+ 16 - 4
dpkg-split/queue.c

@@ -120,7 +120,9 @@ partmatches(struct partinfo *pi, struct partinfo *refi)
           pi->maxpartlen == refi->maxpartlen);
           pi->maxpartlen == refi->maxpartlen);
 }
 }
 
 
-void do_auto(const char *const *argv) {
+int
+do_auto(const char *const *argv)
+{
   const char *partfile;
   const char *partfile;
   struct partinfo *refi, **partlist, *otherthispart;
   struct partinfo *refi, **partlist, *otherthispart;
   struct partqueue *pq;
   struct partqueue *pq;
@@ -140,7 +142,7 @@ void do_auto(const char *const *argv) {
     if (!opt_npquiet)
     if (!opt_npquiet)
       printf(_("File `%.250s' is not part of a multipart archive.\n"),partfile);
       printf(_("File `%.250s' is not part of a multipart archive.\n"),partfile);
     m_output(stdout, _("<standard output>"));
     m_output(stdout, _("<standard output>"));
-    exit(1);
+    return 1;
   }
   }
   fclose(part);
   fclose(part);
   scandepot();
   scandepot();
@@ -214,9 +216,13 @@ void do_auto(const char *const *argv) {
   }
   }
 
 
   m_output(stderr, _("<standard error>"));
   m_output(stderr, _("<standard error>"));
+
+  return 0;
 }
 }
 
 
-void do_queue(const char *const *argv) {
+int
+do_queue(const char *const *argv)
+{
   struct partqueue *pq;
   struct partqueue *pq;
   const char *head;
   const char *head;
   struct stat stab;
   struct stat stab;
@@ -272,6 +278,8 @@ void do_queue(const char *const *argv) {
     printf(_("(total %jd bytes)\n"), (intmax_t)bytes);
     printf(_("(total %jd bytes)\n"), (intmax_t)bytes);
   }
   }
   m_output(stdout, _("<standard output>"));
   m_output(stdout, _("<standard output>"));
+
+  return 0;
 }
 }
 
 
 enum discardwhich { ds_junk, ds_package, ds_all };
 enum discardwhich { ds_junk, ds_package, ds_all };
@@ -298,7 +306,9 @@ static void discardsome(enum discardwhich which, const char *package) {
   }
   }
 }
 }
 
 
-void do_discard(const char *const *argv) {
+int
+do_discard(const char *const *argv)
+{
   const char *thisarg;
   const char *thisarg;
   struct partqueue *pq;
   struct partqueue *pq;
 
 
@@ -312,4 +322,6 @@ void do_discard(const char *const *argv) {
   } else {
   } else {
     discardsome(ds_all,NULL);
     discardsome(ds_all,NULL);
   }
   }
+
+  return 0;
 }
 }

+ 2 - 2
dpkg-split/split.c

@@ -237,7 +237,7 @@ mksplit(const char *file_src, const char *prefix, off_t maxpartsize,
 	return 0;
 	return 0;
 }
 }
 
 
-void
+int
 do_split(const char *const *argv)
 do_split(const char *const *argv)
 {
 {
 	const char *sourcefile, *prefix;
 	const char *sourcefile, *prefix;
@@ -264,5 +264,5 @@ do_split(const char *const *argv)
 
 
 	mksplit(sourcefile, prefix, opt_maxpartsize, opt_msdos);
 	mksplit(sourcefile, prefix, opt_maxpartsize, opt_msdos);
 
 
-	exit(0);
+	return 0;
 }
 }

+ 5 - 1
src/archives.c

@@ -1183,7 +1183,9 @@ void cu_fileslist(int argc, void **argv) {
   destroyobstack();
   destroyobstack();
 }
 }
 
 
-void archivefiles(const char *const *argv) {
+int
+archivefiles(const char *const *argv)
+{
   const char *volatile thisarg;
   const char *volatile thisarg;
   const char *const *volatile argp;
   const char *const *volatile argp;
   jmp_buf ejbuf;
   jmp_buf ejbuf;
@@ -1321,6 +1323,8 @@ void archivefiles(const char *const *argv) {
 
 
   trigproc_run_deferred();
   trigproc_run_deferred();
   modstatdb_shutdown();
   modstatdb_shutdown();
+
+  return 0;
 }
 }
 
 
 /**
 /**

+ 62 - 27
src/enquiry.c

@@ -127,7 +127,9 @@ static void describebriefly(struct pkginfo *pkg) {
   printf(" %-20s %.*s\n",pkg->name,l,pdesc);
   printf(" %-20s %.*s\n",pkg->name,l,pdesc);
 }
 }
 
 
-void audit(const char *const *argv) {
+int
+audit(const char *const *argv)
+{
   const struct badstatinfo *bsi;
   const struct badstatinfo *bsi;
   bool head_running = false;
   bool head_running = false;
 
 
@@ -162,6 +164,8 @@ void audit(const char *const *argv) {
   }
   }
 
 
   m_output(stdout, _("<standard output>"));
   m_output(stdout, _("<standard output>"));
+
+  return 0;
 }
 }
 
 
 struct sectionentry {
 struct sectionentry {
@@ -192,7 +196,9 @@ yettobeunpacked(struct pkginfo *pkg, const char **thissect)
   return false;
   return false;
 }
 }
 
 
-void unpackchk(const char *const *argv) {
+int
+unpackchk(const char *const *argv)
+{
   int totalcount, sects;
   int totalcount, sects;
   struct sectionentry *sectionentries, *se, **sep;
   struct sectionentry *sectionentries, *se, **sep;
   struct pkgiterator *it;
   struct pkgiterator *it;
@@ -228,7 +234,8 @@ void unpackchk(const char *const *argv) {
   }
   }
   pkg_db_iter_free(it);
   pkg_db_iter_free(it);
 
 
-  if (totalcount == 0) exit(0);
+  if (totalcount == 0)
+    return 0;
 
 
   if (totalcount <= 12) {
   if (totalcount <= 12) {
     it = pkg_db_iter_new();
     it = pkg_db_iter_new();
@@ -270,9 +277,11 @@ void unpackchk(const char *const *argv) {
   }
   }
 
 
   m_output(stdout, _("<standard output>"));
   m_output(stdout, _("<standard output>"));
+
+  return 0;
 }
 }
 
 
-static void
+static int
 assert_version_support(const char *const *argv,
 assert_version_support(const char *const *argv,
                        struct versionrevision *version,
                        struct versionrevision *version,
                        const char *feature_name)
                        const char *feature_name)
@@ -288,40 +297,53 @@ assert_version_support(const char *const *argv,
   switch (pkg->status) {
   switch (pkg->status) {
   case stat_installed:
   case stat_installed:
   case stat_triggerspending:
   case stat_triggerspending:
-    break;
+    return 0;
   case stat_unpacked: case stat_halfconfigured: case stat_halfinstalled:
   case stat_unpacked: case stat_halfconfigured: case stat_halfinstalled:
   case stat_triggersawaited:
   case stat_triggersawaited:
     if (versionsatisfied3(&pkg->configversion, version, dvr_laterequal))
     if (versionsatisfied3(&pkg->configversion, version, dvr_laterequal))
-      break;
+      return 0;
     printf(_("Version of dpkg with working %s support not yet configured.\n"
     printf(_("Version of dpkg with working %s support not yet configured.\n"
              " Please use 'dpkg --configure dpkg', and then try again.\n"),
              " Please use 'dpkg --configure dpkg', and then try again.\n"),
            feature_name);
            feature_name);
-    exit(1);
+    return 1;
   default:
   default:
     printf(_("dpkg not recorded as installed, cannot check for %s support!\n"),
     printf(_("dpkg not recorded as installed, cannot check for %s support!\n"),
            feature_name);
            feature_name);
-    exit(1);
+    return 1;
   }
   }
 }
 }
 
 
-void assertpredep(const char *const *argv) {
+int
+assertpredep(const char *const *argv)
+{
   struct versionrevision version = { 0, "1.1.0", NULL };
   struct versionrevision version = { 0, "1.1.0", NULL };
-  assert_version_support(argv, &version, _("Pre-Depends field"));
+
+  return assert_version_support(argv, &version, _("Pre-Depends field"));
 }
 }
 
 
-void assertepoch(const char *const *argv) {
+int
+assertepoch(const char *const *argv)
+{
   struct versionrevision version = { 0, "1.4.0.7", NULL };
   struct versionrevision version = { 0, "1.4.0.7", NULL };
-  assert_version_support(argv, &version, _("epoch"));
+
+  return assert_version_support(argv, &version, _("epoch"));
 }
 }
 
 
-void assertlongfilenames(const char *const *argv) {
+int
+assertlongfilenames(const char *const *argv)
+{
   struct versionrevision version = { 0, "1.4.1.17", NULL };
   struct versionrevision version = { 0, "1.4.1.17", NULL };
-  assert_version_support(argv, &version, _("long filenames"));
+
+  return assert_version_support(argv, &version, _("long filenames"));
 }
 }
 
 
-void assertmulticonrep(const char *const *argv) {
+int
+assertmulticonrep(const char *const *argv)
+{
   struct versionrevision version = { 0, "1.4.1.19", NULL };
   struct versionrevision version = { 0, "1.4.1.19", NULL };
-  assert_version_support(argv, &version, _("multiple Conflicts and Replaces"));
+
+  return assert_version_support(argv, &version,
+                                _("multiple Conflicts and Replaces"));
 }
 }
 
 
 /**
 /**
@@ -337,7 +359,9 @@ void assertmulticonrep(const char *const *argv) {
  *  1 = no suitable package available
  *  1 = no suitable package available
  *  2 = error
  *  2 = error
  */
  */
-void predeppackage(const char *const *argv) {
+int
+predeppackage(const char *const *argv)
+{
   static struct varbuf vb;
   static struct varbuf vb;
 
 
   struct pkgiterator *it;
   struct pkgiterator *it;
@@ -375,7 +399,7 @@ void predeppackage(const char *const *argv) {
   pkg_db_iter_free(it);
   pkg_db_iter_free(it);
 
 
   if (!dep)
   if (!dep)
-    exit(1); /* Not found. */
+    return 1; /* Not found. */
   assert(pkg);
   assert(pkg);
   startpkg= pkg;
   startpkg= pkg;
   pkg->clientdata->istobe= itb_preinstall;
   pkg->clientdata->istobe= itb_preinstall;
@@ -425,26 +449,34 @@ void predeppackage(const char *const *argv) {
   writerecord(stdout, _("<standard output>"), pkg, &pkg->available);
   writerecord(stdout, _("<standard output>"), pkg, &pkg->available);
 
 
   m_output(stdout, _("<standard output>"));
   m_output(stdout, _("<standard output>"));
+
+  return 0;
 }
 }
 
 
-void printarch(const char *const *argv) {
+int
+printarch(const char *const *argv)
+{
   if (*argv)
   if (*argv)
     badusage(_("--%s takes no arguments"), cipaction->olong);
     badusage(_("--%s takes no arguments"), cipaction->olong);
 
 
   printf("%s\n", native_arch);
   printf("%s\n", native_arch);
 
 
   m_output(stdout, _("<standard output>"));
   m_output(stdout, _("<standard output>"));
+
+  return 0;
 }
 }
 
 
-void
+int
 printinstarch(const char *const *argv)
 printinstarch(const char *const *argv)
 {
 {
   warning(_("obsolete option '--%s', please use '--%s' instead."),
   warning(_("obsolete option '--%s', please use '--%s' instead."),
           "print-installation-architecture", "print-architecture");
           "print-installation-architecture", "print-architecture");
-  printarch(argv);
+  return printarch(argv);
 }
 }
 
 
-void cmpversions(const char *const *argv) {
+int
+cmpversions(const char *const *argv)
+{
   struct relationinfo {
   struct relationinfo {
     const char *string;
     const char *string;
     /* These values are exit status codes, so 0 = true, 1 = false. */
     /* These values are exit status codes, so 0 = true, 1 = false. */
@@ -506,16 +538,19 @@ void cmpversions(const char *const *argv) {
     blankversion(&b);
     blankversion(&b);
   }
   }
   if (!informativeversion(&a)) {
   if (!informativeversion(&a)) {
-    exit(informativeversion(&b) ? rip->if_none_a : rip->if_none_both);
+    return informativeversion(&b) ? rip->if_none_a : rip->if_none_both;
   } else if (!informativeversion(&b)) {
   } else if (!informativeversion(&b)) {
-    exit(rip->if_none_b);
+    return rip->if_none_b;
   }
   }
   r= versioncompare(&a,&b);
   r= versioncompare(&a,&b);
   debug(dbg_general,"cmpversions a=`%s' b=`%s' r=%d",
   debug(dbg_general,"cmpversions a=`%s' b=`%s' r=%d",
         versiondescribe(&a,vdew_always),
         versiondescribe(&a,vdew_always),
         versiondescribe(&b,vdew_always),
         versiondescribe(&b,vdew_always),
         r);
         r);
-  if (r>0) exit(rip->if_greater);
-  else if (r<0) exit(rip->if_lesser);
-  else exit(rip->if_equal);
+  if (r > 0)
+    return rip->if_greater;
+  else if (r < 0)
+    return rip->if_lesser;
+  else
+    return rip->if_equal;
 }
 }

+ 19 - 11
src/main.c

@@ -516,8 +516,8 @@ static void setforce(const struct cmdinfo *cip, const char *value) {
   }
   }
 }
 }
 
 
-void execbackend(const char *const *argv) DPKG_ATTR_NORET;
-void commandfd(const char *const *argv);
+int execbackend(const char *const *argv) DPKG_ATTR_NORET;
+int commandfd(const char *const *argv);
 
 
 /* This table has both the action entries in it and the normal options.
 /* This table has both the action entries in it and the normal options.
  * The action entries are made with the ACTION macro, as they all
  * The action entries are made with the ACTION macro, as they all
@@ -605,7 +605,9 @@ static const struct cmdinfo cmdinfos[]= {
   { NULL,                0,   0, NULL,          NULL,      NULL,          0 }
   { NULL,                0,   0, NULL,          NULL,      NULL,          0 }
 };
 };
 
 
-void execbackend(const char *const *argv) {
+int
+execbackend(const char *const *argv)
+{
   struct command cmd;
   struct command cmd;
   char *arg;
   char *arg;
 
 
@@ -623,16 +625,19 @@ void execbackend(const char *const *argv) {
   command_exec(&cmd);
   command_exec(&cmd);
 }
 }
 
 
-void commandfd(const char *const *argv) {
+int
+commandfd(const char *const *argv)
+{
   struct varbuf linevb = VARBUF_INIT;
   struct varbuf linevb = VARBUF_INIT;
   const char * pipein;
   const char * pipein;
   const char **newargs = NULL;
   const char **newargs = NULL;
   char *ptr, *endptr;
   char *ptr, *endptr;
   FILE *in;
   FILE *in;
   unsigned long infd;
   unsigned long infd;
+  int ret = 0;
   int c, lno, i;
   int c, lno, i;
   bool skipchar;
   bool skipchar;
-  void (*actionfunction)(const char *const *argv);
+  int (*actionfunction)(const char *const *argv);
 
 
   pipein = *argv++;
   pipein = *argv++;
   if (pipein == NULL)
   if (pipein == NULL)
@@ -714,15 +719,18 @@ void commandfd(const char *const *argv) {
     myopt((const char *const**)&newargs,cmdinfos);
     myopt((const char *const**)&newargs,cmdinfos);
     if (!cipaction) badusage(_("need an action option"));
     if (!cipaction) badusage(_("need an action option"));
 
 
-    actionfunction = (void (*)(const char *const *))cipaction->arg_func;
-    actionfunction(newargs);
+    actionfunction = (int (*)(const char *const *))cipaction->arg_func;
+    ret |= actionfunction(newargs);
 
 
     pop_error_context(ehflag_normaltidy);
     pop_error_context(ehflag_normaltidy);
   }
   }
+
+  return ret;
 }
 }
 
 
 int main(int argc, const char *const *argv) {
 int main(int argc, const char *const *argv) {
-  void (*actionfunction)(const char *const *argv);
+  int (*actionfunction)(const char *const *argv);
+  int ret;
 
 
   setlocale(LC_ALL, "");
   setlocale(LC_ALL, "");
   bindtextdomain(PACKAGE, LOCALEDIR);
   bindtextdomain(PACKAGE, LOCALEDIR);
@@ -752,14 +760,14 @@ int main(int argc, const char *const *argv) {
 
 
   filesdbinit();
   filesdbinit();
 
 
-  actionfunction = (void (*)(const char *const *))cipaction->arg_func;
+  actionfunction = (int (*)(const char *const *))cipaction->arg_func;
 
 
-  actionfunction(argv);
+  ret = actionfunction(argv);
 
 
   if (is_invoke_action(cipaction->arg_int))
   if (is_invoke_action(cipaction->arg_int))
     run_invoke_hooks(cipaction->olong, post_invoke_hooks);
     run_invoke_hooks(cipaction->olong, post_invoke_hooks);
 
 
   standard_shutdown();
   standard_shutdown();
 
 
-  return reportbroken_retexitstatus(0);
+  return reportbroken_retexitstatus(ret);
 }
 }

+ 17 - 17
src/main.h

@@ -147,7 +147,7 @@ struct invoke_hook {
 
 
 /* from archives.c */
 /* from archives.c */
 
 
-void archivefiles(const char *const *argv);
+int archivefiles(const char *const *argv);
 void process_archive(const char *filename);
 void process_archive(const char *filename);
 bool wanttoinstall(struct pkginfo *pkg);
 bool wanttoinstall(struct pkginfo *pkg);
 struct fileinlist *newconff_append(struct fileinlist ***newconffileslastp_io,
 struct fileinlist *newconff_append(struct fileinlist ***newconffileslastp_io,
@@ -155,33 +155,33 @@ struct fileinlist *newconff_append(struct fileinlist ***newconffileslastp_io,
 
 
 /* from update.c */
 /* from update.c */
 
 
-void forgetold(const char *const *argv);
-void updateavailable(const char *const *argv);
+int forgetold(const char *const *argv);
+int updateavailable(const char *const *argv);
 
 
 /* from enquiry.c */
 /* from enquiry.c */
 
 
-void audit(const char *const *argv);
-void unpackchk(const char *const *argv);
-void assertepoch(const char *const *argv);
-void assertpredep(const char *const *argv);
-void assertlongfilenames(const char *const *argv);
-void assertmulticonrep(const char *const *argv);
-void predeppackage(const char *const *argv);
-void printarch(const char *const *argv);
-void printinstarch(const char *const *argv);
-void cmpversions(const char *const *argv) DPKG_ATTR_NORET;
+int audit(const char *const *argv);
+int unpackchk(const char *const *argv);
+int assertepoch(const char *const *argv);
+int assertpredep(const char *const *argv);
+int assertlongfilenames(const char *const *argv);
+int assertmulticonrep(const char *const *argv);
+int predeppackage(const char *const *argv);
+int printarch(const char *const *argv);
+int printinstarch(const char *const *argv);
+int cmpversions(const char *const *argv);
 
 
 /* from select.c */
 /* from select.c */
 
 
-void getselections(const char *const *argv);
-void setselections(const char *const *argv);
-void clearselections(const char *const *argv);
+int getselections(const char *const *argv);
+int setselections(const char *const *argv);
+int clearselections(const char *const *argv);
 
 
 /* from packages.c, remove.c and configure.c */
 /* from packages.c, remove.c and configure.c */
 
 
 void add_to_queue(struct pkginfo *pkg);
 void add_to_queue(struct pkginfo *pkg);
 void process_queue(void);
 void process_queue(void);
-void packages(const char *const *argv);
+int packages(const char *const *argv);
 void removal_bulk(struct pkginfo *pkg);
 void removal_bulk(struct pkginfo *pkg);
 int conffderef(struct pkginfo *pkg, struct varbuf *result, const char *in);
 int conffderef(struct pkginfo *pkg, struct varbuf *result, const char *in);
 
 

+ 3 - 1
src/packages.c

@@ -117,7 +117,7 @@ enqueue_specified(const char *const *argv)
   }
   }
 }
 }
 
 
-void
+int
 packages(const char *const *argv)
 packages(const char *const *argv)
 {
 {
   trigproc_install_hooks();
   trigproc_install_hooks();
@@ -146,6 +146,8 @@ packages(const char *const *argv)
   trigproc_run_deferred();
   trigproc_run_deferred();
 
 
   modstatdb_shutdown();
   modstatdb_shutdown();
+
+  return 0;
 }
 }
 
 
 void process_queue(void) {
 void process_queue(void) {

+ 14 - 3
src/select.c

@@ -44,7 +44,9 @@ static void getsel1package(struct pkginfo *pkg) {
   printf("%s%.*s%s\n",pkg->name,l,"\t\t\t\t\t\t",wantinfos[pkg->want].name);
   printf("%s%.*s%s\n",pkg->name,l,"\t\t\t\t\t\t",wantinfos[pkg->want].name);
 }
 }
 
 
-void getselections(const char *const *argv) {
+int
+getselections(const char *const *argv)
+{
   struct pkg_array array;
   struct pkg_array array;
   struct pkginfo *pkg;
   struct pkginfo *pkg;
   const char *thisarg;
   const char *thisarg;
@@ -78,9 +80,13 @@ void getselections(const char *const *argv) {
   m_output(stderr, _("<standard error>"));
   m_output(stderr, _("<standard error>"));
 
 
   pkg_array_destroy(&array);
   pkg_array_destroy(&array);
+
+  return 0;
 }
 }
 
 
-void setselections(const char *const *argv) {
+int
+setselections(const char *const *argv)
+{
   const struct namevalue *nv;
   const struct namevalue *nv;
   struct pkginfo *pkg;
   struct pkginfo *pkg;
   const char *e;
   const char *e;
@@ -144,9 +150,12 @@ void setselections(const char *const *argv) {
   modstatdb_shutdown();
   modstatdb_shutdown();
   varbuf_destroy(&namevb);
   varbuf_destroy(&namevb);
   varbuf_destroy(&selvb);
   varbuf_destroy(&selvb);
+
+  return 0;
 }
 }
 
 
-void clearselections(const char *const *argv)
+int
+clearselections(const char *const *argv)
 {
 {
   struct pkgiterator *it;
   struct pkgiterator *it;
   struct pkginfo *pkg;
   struct pkginfo *pkg;
@@ -164,5 +173,7 @@ void clearselections(const char *const *argv)
   pkg_db_iter_free(it);
   pkg_db_iter_free(it);
 
 
   modstatdb_shutdown();
   modstatdb_shutdown();
+
+  return 0;
 }
 }
 
 

+ 2 - 2
src/statcmd.c

@@ -294,9 +294,9 @@ statoverride_remove(const char *const *argv)
 		if (opt_verbose)
 		if (opt_verbose)
 			warning(_("No override present."));
 			warning(_("No override present."));
 		if (opt_force)
 		if (opt_force)
-			exit(0);
+			return 0;
 		else
 		else
-			exit(2);
+			return 2;
 	}
 	}
 
 
 	if (opt_update && opt_verbose)
 	if (opt_update && opt_verbose)

+ 10 - 2
src/update.c

@@ -34,7 +34,9 @@
 
 
 #include "main.h"
 #include "main.h"
 
 
-void updateavailable(const char *const *argv) {
+int
+updateavailable(const char *const *argv)
+{
   const char *sourcefile= argv[0];
   const char *sourcefile= argv[0];
   char *availfile;
   char *availfile;
   int count= 0;
   int count= 0;
@@ -99,12 +101,18 @@ void updateavailable(const char *const *argv) {
               "Information about %d packages was updated.\n", count), count);
               "Information about %d packages was updated.\n", count), count);
 
 
   modstatdb_done();
   modstatdb_done();
+
+  return 0;
 }
 }
 
 
-void forgetold(const char *const *argv) {
+int
+forgetold(const char *const *argv)
+{
   if (*argv)
   if (*argv)
     badusage(_("--%s takes no arguments"), cipaction->olong);
     badusage(_("--%s takes no arguments"), cipaction->olong);
 
 
   warning(_("obsolete '--%s' option, unavailable packages are automatically cleaned up."),
   warning(_("obsolete '--%s' option, unavailable packages are automatically cleaned up."),
           cipaction->olong);
           cipaction->olong);
+
+  return 0;
 }
 }