From 43d40df9621b9203a1b52af0d217dccfa475cff7 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Thu, 21 Oct 1999 10:38:38 +0000 Subject: [PATCH] * Fixed some compiler warnings * Make start-stop-daemon exit(1) when we don't find one of the pid's we are trying to kill, in accordance with the man page. * When running --configure on an already installed package, just say it's installed, and not that it is in an unconfigurable state * Bah, add all the prefix/datadir... stuff back to the install target in debian/rules (po/ doesn't use it) * Add function to libdpkg that dpkg can call to make sure it's compiled version matches that of the library. If it fails, complain loudly, but allow to proceed * Make dpkg check for uid 0 requirement, before checking the path since not being root, is probably the reason that the PATH is borked in the first place * Make -p short for --print-avail, and -P short for --purge * Fix typo in md5sum(1) man page * start-stop-daemon: Add --background and --make-pidfile options * update-alternatives: make sure we remove "old" symlinks when they are no longer pertinent. Add /etc/alternatives/README that refers to the update-alternatives(8) man page. * dpkg-divert: Add check for being able to write to the old/new destination before doing a rename. We fail on this, without changing the diversion registry * Fix bad regex in update-rc.d --- ChangeLog | 27 ++++++++ debian/changelog | 25 ++++++- debian/rules | 11 +++- dpkg-deb/build.c | 2 +- dselect/pkgdepcon.cc | 2 + dselect/pkglist.cc | 2 + include/dpkg.h.in | 1 + lib/dump.c | 2 + lib/parse.c | 2 +- lib/showcright.c | 5 ++ main/archives.c | 12 ++-- main/configure.c | 2 + main/dpkg.8 | 6 +- main/enquiry.c | 4 +- main/help.c | 22 +++++++ main/main.c | 52 ++++++++------- main/main.h | 1 + main/packages.c | 2 +- md5sum/md5sum.1 | 2 +- md5sum/md5sum.c | 2 +- scripts/Makefile.am | 3 +- scripts/README.alternatives | 2 + scripts/dpkg-divert.pl | 10 +++ scripts/update-alternatives.pl | 2 + scripts/update-rc.d.pl | 8 +-- utils/start-stop-daemon.8 | 22 +++++++ utils/start-stop-daemon.c | 117 ++++++++++++++++++++++++++------- 27 files changed, 276 insertions(+), 72 deletions(-) create mode 100644 scripts/README.alternatives diff --git a/ChangeLog b/ChangeLog index 89a2e86e..b738f192 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +Thu Oct 21 06:37:24 EDT 1999 Ben Collins + + * Fixed some compiler warnings + * Make start-stop-daemon exit(1) when we don't find one of the + pid's we are trying to kill, in accordance with the man page. + * When running --configure on an already installed package, just + say it's installed, and not that it is in an unconfigurable + state + * Bah, add all the prefix/datadir... stuff back to the install + target in debian/rules (po/ doesn't use it) + * Add function to libdpkg that dpkg can call to make sure it's + compiled version matches that of the library. If it fails, + complain loudly, but allow to proceed + * Make dpkg check for uid 0 requirement, before checking the path + since not being root, is probably the reason that the PATH is + borked in the first place + * Make -p short for --print-avail, and -P short for --purge + * Fix typo in md5sum(1) man page + * start-stop-daemon: Add --background and --make-pidfile options + * update-alternatives: make sure we remove "old" symlinks when they + are no longer pertinent. Add /etc/alternatives/README that refers + to the update-alternatives(8) man page. + * dpkg-divert: Add check for being able to write to the old/new + destination before doing a rename. We fail on this, without + changing the diversion registry + * Fix bad regex in update-rc.d + Tue Oct 19 18:07:28 EDT 1999 Ben Collins * Ok, TMPDIR usage is back in dpkg-deb and working diff --git a/debian/changelog b/debian/changelog index 5309f2f4..b303b6de 100644 --- a/debian/changelog +++ b/debian/changelog @@ -31,9 +31,6 @@ dpkg (1.4.1.17) unstable; urgency=low already generated anyway * Removed the ltconfig patch, and resort to a debian/rules fix to libtool itself after running configure - * Use DESTDIR when installing instead of specifying all our - dest dirs seperately in the make line. Also fix some of the - make files to use DESTDIR when installing files * Removed shlibs.default.i386. It's now a template for arch porting to Debian/dpkg, we install it still, if there exists a file matching the arch @@ -48,6 +45,28 @@ dpkg (1.4.1.17) unstable; urgency=low distclean and all that other stuff. Don't run "make dist", we simply copy the .tar.gz that dpkg-source creates for the byhand source. + * Make start-stop-daemon exit(1) when we don't find one of the + pid's we are trying to kill, in accordance with the man page. + * When running --configure on an already installed package, just + say it's installed, and not that it is in an unconfigurable + state + * Fixed some compiler warnings + * Add function to libdpkg that dpkg can call to make sure it's + compiled version matches that of the library. If it fails, + complain loudly, but allow to proceed + * Make dpkg check for uid 0 requirement, before checking the path + since not being root, is probably the reason that the PATH is + borked in the first place + * Make -p short for --print-avail, and -P short for --purge + * Fix typo in md5sum(1) man page + * start-stop-daemon: Add --background and --make-pidfile options + * update-alternatives: make sure we remove "old" symlinks when they + are no longer pertinent. Add /etc/alternatives/README that refers + to the update-alternatives(8) man page. + * dpkg-divert: Add check for being able to write to the old/new + destination before doing a rename. We fail on this, without + changing the diversion registry + * Fix bad regex in update-rc.d -- Wichert Akkerman UNRELEASED diff --git a/debian/rules b/debian/rules index fde8bfe4..90509917 100755 --- a/debian/rules +++ b/debian/rules @@ -62,7 +62,16 @@ binary-trees: build debian/tmp-dev/etc/dpkg/shlibs.default ; \ fi cp debian/{prerm,postinst} $(mcidir)/. - $(MAKE) -C $(BUILD) DESTDIR=$(DIR)/debian/tmp-main install + + $(MAKE) -C $(BUILD) install \ + prefix=$(DIR)/debian/tmp-main/usr \ + sysconfdir=$(DIR)/debian/tmp-main/etc \ + sharedstatedir=$(DIR)/debian/tmp-main/var/lib \ + localstatedir=$(DIR)/debian/tmp-main/var/lib \ + datadir=$(DIR)/debian/tmp-main/usr/share \ + mandir=$(DIR)/debian/tmp-main/usr/share/man \ + infodir=$(DIR)/debian/tmp-main/usr/share/info + install -m 755 debian/dev-postinst debian/tmp-dev/DEBIAN/postinst install -m 755 debian/dev-prerm debian/tmp-dev/DEBIAN/prerm install -d debian/tmp-dev/etc/emacs/site-start.d diff --git a/dpkg-deb/build.c b/dpkg-deb/build.c index 51f91acd..71c1c6b7 100644 --- a/dpkg-deb/build.c +++ b/dpkg-deb/build.c @@ -72,7 +72,7 @@ void do_build(const char *const *argv) { directory= *argv++; if (!directory) badusage(_("--build needs a directory argument")); /* template for our tempfiles */ if ((envbuf= getenv("TMPDIR")) == NULL) - envbuf= P_tmpdir; + envbuf= (char *)P_tmpdir; tfbuf = (char *)malloc(strlen(envbuf)+13); strcpy(tfbuf,envbuf); strcat(tfbuf,"/dpkg.XXXXXX"); diff --git a/dselect/pkgdepcon.cc b/dselect/pkgdepcon.cc index 9395b662..6b2b7fd3 100644 --- a/dselect/pkgdepcon.cc +++ b/dselect/pkgdepcon.cc @@ -333,6 +333,8 @@ int packagelist::resolvedepcon(dependency *depends) { default: internerr("unknown deptype"); } + /* never reached, make gcc happy */ + return 1; } int packagelist::deppossatisfied(deppossi *possi, perpackagestate **fixbyupgrade) { diff --git a/dselect/pkglist.cc b/dselect/pkglist.cc index 81f17109..a3987adc 100644 --- a/dselect/pkglist.cc +++ b/dselect/pkglist.cc @@ -78,6 +78,8 @@ int packagelist::compareentries(struct perpackagestate *a, default: internerr("unsorted or unknown in compareentries"); } + /* never reached, make gcc happy */ + return 1; } void packagelist::discardheadings() { diff --git a/include/dpkg.h.in b/include/dpkg.h.in index cef8dfb1..ecae1fa6 100644 --- a/include/dpkg.h.in +++ b/include/dpkg.h.in @@ -202,5 +202,6 @@ extern volatile int onerr_abort; struct cmdinfo; void showcopyright(const struct cmdinfo*, const char*); +char *libdpkgver(void); #endif /* DPKG_H */ diff --git a/lib/dump.c b/lib/dump.c index a43be264..53fb1bab 100644 --- a/lib/dump.c +++ b/lib/dump.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include diff --git a/lib/parse.c b/lib/parse.c index c1b4164a..258dc42d 100644 --- a/lib/parse.c +++ b/lib/parse.c @@ -200,7 +200,7 @@ int parsedb(const char *filename, enum parsedbflags flags, &newpifp->maintainer, "maintainer"); if (newpig.status != stat_halfinstalled) parsemustfield(file,filename,lno, warnto,warncount,&newpig,0, - &newpifp->version.version, "version"); + (char **)&newpifp->version.version, "version"); } if (flags & pdb_recordavailable) parsemustfield(file,filename,lno, warnto,warncount,&newpig,1, diff --git a/lib/showcright.c b/lib/showcright.c index c327076b..037c5dbc 100644 --- a/lib/showcright.c +++ b/lib/showcright.c @@ -24,6 +24,7 @@ #include #include +#include void showcopyright(const struct cmdinfo *c, const char *v) { int fd; @@ -33,3 +34,7 @@ void showcopyright(const struct cmdinfo *c, const char *v) { execlp(CAT,CAT,"-",(char*)0); ohshite(_("unable to exec cat for displaying GPL file")); } + +char *libdpkgver(void) { + return DPKG_VERSION; +} diff --git a/main/archives.c b/main/archives.c index 49ba456e..65fab3a2 100644 --- a/main/archives.c +++ b/main/archives.c @@ -698,6 +698,12 @@ void archivefiles(const char *const *argv) { const char **arglist; char *p; + modstatdb_init(admindir, + f_noact ? msdbrw_readonly + : cipaction->arg == act_avail ? msdbrw_write + : fc_nonroot ? msdbrw_write + : msdbrw_needsuperuser); + checkpath(); if (f_recursive) { @@ -770,12 +776,6 @@ void archivefiles(const char *const *argv) { } - modstatdb_init(admindir, - f_noact ? msdbrw_readonly - : cipaction->arg == act_avail ? msdbrw_write - : fc_nonroot ? msdbrw_write - : msdbrw_needsuperuser); - currenttime= time(0); varbufaddstr(&fnamevb,instdir); varbufaddc(&fnamevb,'/'); diff --git a/main/configure.c b/main/configure.c index 512f01bc..11ae1aaf 100644 --- a/main/configure.c +++ b/main/configure.c @@ -78,6 +78,8 @@ void deferred_configure(struct pkginfo *pkg) { if (pkg->status == stat_notinstalled) ohshit(_("no package named `%s' is installed, cannot configure"),pkg->name); + if (pkg->status == stat_installed) + ohshit(_("package %.250s is already installed and configured"), pkg->name); if (pkg->status != stat_unpacked && pkg->status != stat_halfconfigured) ohshit(_("package %.250s is not ready for configuration\n" " cannot configure (current status `%.250s')"), diff --git a/main/dpkg.8 b/main/dpkg.8 index c57a5c9d..09db76ca 100644 --- a/main/dpkg.8 +++ b/main/dpkg.8 @@ -147,12 +147,12 @@ something goes wrong. \fB2.\fP Run \fIpostinst\fP script, if provided by the package. .TP -\fBdpkg -r\fP | \fB--remove\fP | \fB --purge \fP\fIpackage\fP ... | \fB-a\fP | \fB--pending\fP +\fBdpkg -r\fP | \fB--remove\fP | \fB-P\fP | \fB--purge \fP\fIpackage\fP ... | \fB-a\fP | \fB--pending\fP Remove an installed package. \fB-r\fP or \fB--remove\fP remove everything except configuration files. This may avoid having to reconfigure the package if it is reinstalled later. (Configuration files are the files listed in the \fIdebian/conffiles\fP control -file). \fB--purge\fP removes everything, including configuration +file). \fB-P\fP or \fB--purge\fP removes everything, including configuration files. If \fB-a\fP or \fB--pending\fP is given instead of a package name, then all packages unpacked, but marked to be removed or purged in file \fI/var/lib/dpkg/status\fP, are removed or purged, @@ -170,7 +170,7 @@ Removing of a package consists of the following steps: \fB3.\fP Run \fIpostrm\fP script .br .TP -.BI "dpkg --print-avail " package +.BI "dpkg -p|--print-avail " package Display details about \fIpackage\fP, as found in \fI/var/lib/dpkg/available\fP. .TP diff --git a/main/enquiry.c b/main/enquiry.c index 43117ce0..65c19e5c 100644 --- a/main/enquiry.c +++ b/main/enquiry.c @@ -467,7 +467,7 @@ void enqperpackage(const char *const *argv) { } } -void assertversion(const char *const *argv, +static void assertversion(const char *const *argv, struct versionrevision *verrev_buf, const char *reqversion) { struct pkginfo *pkg; @@ -520,7 +520,7 @@ void predeppackage(const char *const *argv) { static struct varbuf vb; struct pkgiterator *it; - struct pkginfo *pkg, *startpkg, *trypkg; + struct pkginfo *pkg= 0, *startpkg, *trypkg; struct dependency *dep; struct deppossi *possi, *provider; diff --git a/main/help.c b/main/help.c index 762d77b4..0c33ccb4 100644 --- a/main/help.c +++ b/main/help.c @@ -31,6 +31,7 @@ #include #include +#include #include #include "filesdb.h" @@ -504,3 +505,24 @@ void ensure_pathname_nonexisting(const char *pathname) { debug(dbg_eachfile,"ensure_pathname_nonexisting running rm -rf"); waitsubproc(c1,"rm cleanup",0); } + +void check_libver (void) { + int c; + if (!strcmp(DPKG_VERSION, libdpkgver())) return; + /* ooh, we have a version mismatch with the library, + * continue, but warn LOUDLY about possible problems. + */ + fprintf(stderr, _("\ +WARNING: A mismatch between dpkg and libdpkg.so has\n\ +been detected. Somehow, your system has a different\n\ +version of dpkg than the library that is uses. This\n\ +may not cause any problems, but it does reflect a\n\ +serious condition. You should really reinstall the dpkg\n\ +package before continuing.\n\ +\n\ +Press 'Q' to exit, any other key to continue: ")); + c= getc(stdin); + if (c == 'q' || c == 'Q') + ohshite(_("Quitting at user request")); + return; +} diff --git a/main/main.c b/main/main.c index 75714793..86e3ecca 100644 --- a/main/main.c +++ b/main/main.c @@ -59,28 +59,28 @@ Usage: \n\ dpkg -i|--install <.deb file name> ... | -R|--recursive ...\n\ dpkg --unpack <.deb file name> ... | -R|--recursive ...\n\ dpkg -A|--record-avail <.deb file name> ... | -R|--recursive ...\n\ - dpkg --configure ... | -a|--pending\n\ - dpkg -r|--remove | --purge ... | -a|--pending\n\ - dpkg --get-selections [ ...] get list of selections to stdout\n\ - dpkg --set-selections set package selections from stdin\n\ - dpkg --update-avail replace available packages info\n\ - dpkg --merge-avail merge with info from file\n\ - dpkg --clear-avail erase existing available info\n\ - dpkg --forget-old-unavail forget uninstalled unavailable pkgs\n\ - dpkg -s|--status ... display package status details\n\ - dpkg --print-avail ... display available version details\n\ - dpkg -L|--listfiles ... list files `owned' by package(s)\n\ - dpkg -l|--list [ ...] list packages concisely\n\ - dpkg -S|--search ... find package(s) owning file(s)\n\ - dpkg -C|--audit check for broken package(s)\n\ - dpkg --abort-after abort after encountering errors\n\ - dpkg --print-architecture print target architecture (uses GCC)\n\ - dpkg --print-gnu-build-architecture print GNU version of target arch\n\ - dpkg --print-installation-architecture print host architecture (for inst'n)\n\ - dpkg --compare-versions compare version numbers - see below\n\ - dpkg --help | --version show this help / version number\n\ - dpkg --force-help | -Dh|--debug=help help on forcing resp. debugging\n\ - dpkg --licence print copyright licencing terms\n\ + dpkg --configure ... | -a|--pending\n\ + dpkg -r|--remove | -P|--purge ... | -a|--pending\n\ + dpkg --get-selections [ ...] get list of selections to stdout\n\ + dpkg --set-selections set package selections from stdin\n\ + dpkg --update-avail replace available packages info\n\ + dpkg --merge-avail merge with info from file\n\ + dpkg --clear-avail erase existing available info\n\ + dpkg --forget-old-unavail forget uninstalled unavailable pkgs\n\ + dpkg -s|--status ... display package status details\n\ + dpkg -p|--print-avail ... display available version details\n\ + dpkg -L|--listfiles ... list files `owned' by package(s)\n\ + dpkg -l|--list [ ...] list packages concisely\n\ + dpkg -S|--search ... find package(s) owning file(s)\n\ + dpkg -C|--audit check for broken package(s)\n\ + dpkg --abort-after abort after encountering errors\n\ + dpkg --print-architecture print target architecture (uses GCC)\n\ + dpkg --print-gnu-build-architecture print GNU version of target arch\n\ + dpkg --print-installation-architecture print host architecture (for inst'n)\n\ + dpkg --compare-versions compare version numbers - see below\n\ + dpkg --help | --version show this help / version number\n\ + dpkg --force-help | -Dh|--debug=help help on forcing resp. debugging\n\ + dpkg --licence print copyright licencing terms\n\ \n\ Use dpkg -b|--build|-c|--contents|-e|--control|-I|--info|-f|--field|\n\ -x|--extract|-X|--vextract|--fsys-tarfile on archives (type %s --help.)\n\ @@ -325,12 +325,12 @@ static const struct cmdinfo cmdinfos[]= { ACTION( "record-avail", 'A', act_avail, archivefiles ), ACTION( "configure", 0, act_configure, packages ), ACTION( "remove", 'r', act_remove, packages ), - ACTION( "purge", 0, act_purge, packages ), + ACTION( "purge", 'P', act_purge, packages ), ACTION( "listfiles", 'L', act_listfiles, enqperpackage ), ACTION( "status", 's', act_status, enqperpackage ), ACTION( "get-selections", 0, act_getselections, getselections ), ACTION( "set-selections", 0, act_setselections, setselections ), - ACTION( "print-avail", 0, act_printavail, enqperpackage ), + ACTION( "print-avail", 'p', act_printavail, enqperpackage ), ACTION( "update-avail", 0, act_avreplace, updateavailable ), ACTION( "merge-avail", 0, act_avmerge, updateavailable ), ACTION( "clear-avail", 0, act_avclear, updateavailable ), @@ -394,7 +394,9 @@ int main(int argc, const char *const *argv) { push_error_handler(&ejbuf,print_error_fatal,0); umask(022); /* Make sure all our status databases are readable. */ - + + check_libver(); + for (argvs=argv+1; (argp= *argvs) && *argp++=='-'; argvs++) { if (*argp++=='-') { if (!strcmp(argp,"-")) break; diff --git a/main/main.h b/main/main.h index 6ee114df..f41b51ab 100644 --- a/main/main.h +++ b/main/main.h @@ -203,6 +203,7 @@ enum debugflags { }; void debug(int which, const char *fmt, ...) PRINTFFORMAT(2,3); +void check_libver(void); /* from depcon.c */ diff --git a/main/packages.c b/main/packages.c index 3dea58bb..0cb6aaaa 100644 --- a/main/packages.c +++ b/main/packages.c @@ -67,11 +67,11 @@ void packages(const char *const *argv) { const char *thisarg; int l; - checkpath(); modstatdb_init(admindir, f_noact ? msdbrw_readonly : fc_nonroot ? msdbrw_write : msdbrw_needsuperuser); + checkpath(); if (f_pending) { diff --git a/md5sum/md5sum.1 b/md5sum/md5sum.1 index aa8cb7a4..df7c704f 100644 --- a/md5sum/md5sum.1 +++ b/md5sum/md5sum.1 @@ -65,7 +65,7 @@ with other manpages. .B md5sum does not accept standard options like -.BR -\-\help . +.BR --help . .SH AUTHOR diff --git a/md5sum/md5sum.c b/md5sum/md5sum.c index f5a0fdf8..2d103676 100644 --- a/md5sum/md5sum.c +++ b/md5sum/md5sum.c @@ -66,7 +66,7 @@ char *progname; int verbose = 0; int bin_mode = 0; -void +int main(int argc, char **argv) { int opt, rc = 0; diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 8cd049ad..a3e5ad29 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -43,7 +43,7 @@ EXTRA_DIST = update-rc.d.pl \ update-alternatives.pl install-info.pl dpkg-divert.pl \ cleanup-info.pl controllib.pl debian-changelog-mode.el \ cl-debian.pl dpkg-architecture.pl dpkg-scansources.pl \ - $(man_MANS) + $(man_MANS) README.alternatives noinst_DATA = cl-debian @@ -78,6 +78,7 @@ dpkg-scansources.8: dpkg-scansources.pl install-data-local: cl-debian $(mkinstalldirs) $(DESTDIR)$(altslocalstatedir) $(DESTDIR)$(altssysconfdir) + $(INSTALL_DATA) $(srcdir)/README.alternatives $(DESTDIR)$(altssysconfdir)/README set -e; for f in $(LSMANL); do ln -sf $(mandir)/man1/dpkg-source.1 $(DESTDIR)$(mandir)/man1/$$f.1; done $(mkinstalldirs) $(DESTDIR)$(parsechangelogdir) $(INSTALL_PROGRAM) cl-debian $(DESTDIR)$(parsechangelogdir)/debian diff --git a/scripts/README.alternatives b/scripts/README.alternatives new file mode 100644 index 00000000..54ef7400 --- /dev/null +++ b/scripts/README.alternatives @@ -0,0 +1,2 @@ +Please read the update-alternatives(8) man page for information on this +directory and its contents. diff --git a/scripts/dpkg-divert.pl b/scripts/dpkg-divert.pl index befe47d7..9728ec88 100755 --- a/scripts/dpkg-divert.pl +++ b/scripts/dpkg-divert.pl @@ -176,10 +176,20 @@ sub infol { sub checkrename { return unless $dorename; ($rsrc,$rdest) = @_; + my %exist; (@ssrc= lstat($rsrc)) || $! == &ENOENT || &quit("cannot stat old name \`$rsrc': $!"); + $exist{$rsrc} = 1 unless $! != &ENOENT; (@sdest= lstat($rdest)) || $! == &ENOENT || &quit("cannot stat new name \`$rdest': $!"); + $exist{$rdest} = 1 unless $! != &ENOENT; + foreach $file ($rsrc,$rdest) { + open (TMP, "a $file") || &quit("error checking \`$file': $!"); + close TMP; + if ($exist{$file} == 1) { + unlink ("$file"); + } + } if (@ssrc && @sdest && !($ssrc[0] == $sdest[0] && $ssrc[1] == $sdest[1])) { &quit("rename involves overwriting \`$rdest' with\n". diff --git a/scripts/update-alternatives.pl b/scripts/update-alternatives.pl index a34f488b..28392846 100755 --- a/scripts/update-alternatives.pl +++ b/scripts/update-alternatives.pl @@ -406,6 +406,8 @@ if ($manual eq 'auto') { &pr("Removing $sname ($slink), not appropriate with $best."); unlink("$altdir/$sname") || $! == &ENOENT || &quit("unable to remove $altdir/$sname: $!"); + unlink("$slink") || $! == &ENOENT || + &quit("unable to remove $slink: $!"); } else { if (defined($linkname= readlink("$altdir/$sname")) && $linkname eq $spath) { &pr("Leaving $sname ($slink) pointing to $spath."); diff --git a/scripts/update-rc.d.pl b/scripts/update-rc.d.pl index 4289ee63..a26f9876 100644 --- a/scripts/update-rc.d.pl +++ b/scripts/update-rc.d.pl @@ -52,10 +52,10 @@ if ($ARGV[0] ne 'remove') { } $_ = $ARGV[0]; -if (/^remove$/) { &checklinks ("remove"); } -elsif (/^defaults$/) { &defaults; &makelinks } -elsif (/^start|stop$/) { &startstop; &makelinks; } -else { &usage; } +if (/^remove$/) { &checklinks ("remove"); } +elsif (/^defaults$/) { &defaults; &makelinks } +elsif (/^(start|stop)$/) { &startstop; &makelinks; } +else { &usage; } exit (0); diff --git a/utils/start-stop-daemon.8 b/utils/start-stop-daemon.8 index faa7f68a..9e490f67 100644 --- a/utils/start-stop-daemon.8 +++ b/utils/start-stop-daemon.8 @@ -124,6 +124,28 @@ Do not print informational messages; only display error messages. .I -c|--chuid Change to this username/uid before starting the process .TP +.I -b|--background +Typically used with programs that don't detach on their own. This option +will force +.B start-stop-daemon +to fork before starting the process, and force it into the background. +.B WARNING: +start-stop-daemon +cannot check the exit status if the process fails to execute for +.B any +reason. This is a last resort, and is only meant for programs that either +make no sense forking on their own, or where it's not feasible to add the +code for it to do this itself. +.TP +.I -m|--make-pidfile +Used when starting a program that does not create its own pid file. This +option will make +.B start-stop-daemon +create the file referenced with +.B --pidfile +and place the pid into it just before executing the process. Note, it will +not be removed when stopping the program. +.TP .I -v|--verbose Print verbose informational messages. .TP diff --git a/utils/start-stop-daemon.c b/utils/start-stop-daemon.c index aac58f54..f21d23ce 100644 --- a/utils/start-stop-daemon.c +++ b/utils/start-stop-daemon.c @@ -9,7 +9,11 @@ * , to make output conform to the Debian * Console Message Standard, also placed in public domain. Minor * changes by Klee Dienes , also placed in the Public - * Domain. */ + * Domain. + * + * Changes by Ben Collins , added --chuid, --background + * and --make-pidfile options, placed in public domain aswell. + */ #include "config.h" #define _GNU_SOURCE @@ -40,6 +44,9 @@ #include #include #include +#include +#include +#include #ifdef HAVE_ERROR_H #include @@ -53,6 +60,8 @@ static int quietmode = 0; static int exitnodo = 1; static int start = 0; static int stop = 0; +static int background = 0; +static int mpidfile = 0; static int signal_nr = 15; static const char *signal_str = NULL; static int user_id = -1; @@ -88,7 +97,7 @@ static int pid_is_user(int pid, int uid); static int pid_is_cmd(int pid, const char *name); static void check(int pid); static void do_pidfile(const char *name); -static void do_stop(void); +static int do_stop(void); #if defined(OSLinux) static int pid_is_exec(int pid, const struct stat *esb); #endif @@ -165,6 +174,8 @@ Options (at least one of --exec|--pidfile|--user is required): -n|--name stop processes with this name\n\ -s|--signal signal to send (default TERM)\n\ -a|--startas program to start (default is )\n\ + -b|--background force the process to detach\n\ + -m|--make-pidfile create the pidfile before starting\n\ -t|--test test mode, don't do anything\n\ -o|--oknodo exit status 0 (not 1) if nothing done\n\ -q|--quiet be more quiet\n\ @@ -226,27 +237,29 @@ static void parse_options(int argc, char * const *argv) { static struct option longopts[] = { - { "help", 0, NULL, 'H'}, - { "stop", 0, NULL, 'K'}, - { "start", 0, NULL, 'S'}, - { "version", 0, NULL, 'V'}, - { "startas", 1, NULL, 'a'}, - { "name", 1, NULL, 'n'}, - { "oknodo", 0, NULL, 'o'}, - { "pidfile", 1, NULL, 'p'}, - { "quiet", 0, NULL, 'q'}, - { "signal", 1, NULL, 's'}, - { "test", 0, NULL, 't'}, - { "user", 1, NULL, 'u'}, - { "verbose", 0, NULL, 'v'}, - { "exec", 1, NULL, 'x'}, - { "chuid", 1, NULL, 'c'}, + { "help", 0, NULL, 'H'}, + { "stop", 0, NULL, 'K'}, + { "start", 0, NULL, 'S'}, + { "version", 0, NULL, 'V'}, + { "startas", 1, NULL, 'a'}, + { "name", 1, NULL, 'n'}, + { "oknodo", 0, NULL, 'o'}, + { "pidfile", 1, NULL, 'p'}, + { "quiet", 0, NULL, 'q'}, + { "signal", 1, NULL, 's'}, + { "test", 0, NULL, 't'}, + { "user", 1, NULL, 'u'}, + { "verbose", 0, NULL, 'v'}, + { "exec", 1, NULL, 'x'}, + { "chuid", 1, NULL, 'c'}, + { "background", 0, NULL, 'b'}, + { "make-pidfile", 0, NULL, 'm'}, { NULL, 0, NULL, 0} }; int c; for (;;) { - c = getopt_long(argc, argv, "HKSVa:n:op:qs:tu:vx:c:", + c = getopt_long(argc, argv, "HKSVa:n:op:qs:tu:vx:c:bm", longopts, (int *) 0); if (c == -1) break; @@ -296,6 +309,12 @@ parse_options(int argc, char * const *argv) case 'c': /* --chuid | */ changeuser = optarg; break; + case 'b': /* --background */ + background = 1; + break; + case 'm': /* --make-pidfile */ + mpidfile = 1; + break; default: badusage(NULL); /* message printed by getopt */ } @@ -320,6 +339,13 @@ parse_options(int argc, char * const *argv) if (start && !startas) badusage("--start needs --exec or --startas"); + + if (mpidfile && pidfile == NULL) + badusage("--make-pidfile is only relevant with --pidfile"); + + if (background && !start) + badusage("--background is only relevant with --start"); + } #if defined(OSLinux) @@ -497,12 +523,13 @@ do_psinit(void) } #endif /* OSHURD */ - -static void +/* return 1 on failure */ +static int do_stop(void) { char what[1024]; struct pid_list *p; + int retval = 0; if (cmdname) strcpy(what, cmdname); @@ -526,9 +553,11 @@ do_stop(void) signal_nr, p->pid); else if (kill(p->pid, signal_nr) == 0) push(&killed, p->pid); - else + else { printf("%s: warning: failed to kill %d: %s\n", progname, p->pid, strerror(errno)); + retval += 1; + } } if (quietmode < 0 && killed) { printf("Stopped %s (pid", what); @@ -536,6 +565,7 @@ do_stop(void) printf(" %d", p->pid); printf(").\n"); } + return retval; } @@ -577,7 +607,12 @@ main(int argc, char **argv) do_procinit(); if (stop) { - do_stop(); + int i = do_stop(); + if (i) { + if (quietmode <= 0) + printf("%d pids were not killed\n", i); + exit(1); + } exit(0); } @@ -590,6 +625,8 @@ main(int argc, char **argv) printf("Would start %s ", startas); while (argc-- > 0) printf("%s ", *argv++); + if (changeuser != NULL) + printf(" (as user %s[%d])", changeuser, runas_id); printf(".\n"); exit(0); } @@ -598,6 +635,42 @@ main(int argc, char **argv) *--argv = startas; if (changeuser != NULL && seteuid(runas_id)) fatal("Unable to set effective uid to %s", changeuser); + if (background) { /* ok, we need to detach this process */ + int i, fd; + if (quietmode < 0) + printf("Detatching to start %s...", startas); + i = fork(); + if (i<0) { + fatal("Unable to fork.\n"); + } + if (i) { /* parent */ + if (quietmode < 0) + printf("done.\n"); + exit(0); + } + /* child continues here */ + /* now close all extra fds */ + for (i=getdtablesize()-1; i>=0; --i) close(i); + /* change tty */ + fd = open("/dev/tty", O_RDWR); + ioctl(fd, TIOCNOTTY, 0); + close(fd); + chdir("/"); + umask(022); /* set a default for dumb programs */ + setpgrp(); /* set the process group */ + fd=open("/dev/null", O_RDWR); /* stdin */ + dup(fd); /* stdout */ + dup(fd); /* stderr */ + } + if (mpidfile && pidfile != NULL) { /* user wants _us_ to make the pidfile :) */ + FILE *pidf = fopen(pidfile, "w"); + pid_t pidt = getpid(); + if (pidf == NULL) + fatal("Unable to open pidfile `%s' for writing: %s", pidfile, + strerror(errno)); + fprintf(pidf, "%d\n", pidt); + fclose(pidf); + } execv(startas, argv); fatal("Unable to start %s: %s", startas, strerror(errno)); } -- 2.39.5