+Thu Oct 21 06:37:24 EDT 1999 Ben Collins <bcollins.debian.org>
+
+ * 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 <bcollins.debian.org>
* Ok, TMPDIR usage is back in dpkg-deb and working
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
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 <wakkerma@debian.org> UNRELEASED
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
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");
default:
internerr("unknown deptype");
}
+ /* never reached, make gcc happy */
+ return 1;
}
int packagelist::deppossatisfied(deppossi *possi, perpackagestate **fixbyupgrade) {
default:
internerr("unsorted or unknown in compareentries");
}
+ /* never reached, make gcc happy */
+ return 1;
}
void packagelist::discardheadings() {
struct cmdinfo;
void showcopyright(const struct cmdinfo*, const char*);
+char *libdpkgver(void);
#endif /* DPKG_H */
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <config.h>
#include <dpkg.h>
&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,
#include <config.h>
#include <dpkg.h>
+#include <version.h>
void showcopyright(const struct cmdinfo *c, const char *v) {
int fd;
execlp(CAT,CAT,"-",(char*)0);
ohshite(_("unable to exec cat for displaying GPL file"));
}
+
+char *libdpkgver(void) {
+ return DPKG_VERSION;
+}
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) {
}
- 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,'/');
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')"),
\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,
\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
}
}
-void assertversion(const char *const *argv,
+static void assertversion(const char *const *argv,
struct versionrevision *verrev_buf,
const char *reqversion) {
struct pkginfo *pkg;
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;
#include <config.h>
#include <dpkg.h>
+#include <version.h>
#include <dpkg-db.h>
#include "filesdb.h"
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;
+}
dpkg -i|--install <.deb file name> ... | -R|--recursive <dir> ...\n\
dpkg --unpack <.deb file name> ... | -R|--recursive <dir> ...\n\
dpkg -A|--record-avail <.deb file name> ... | -R|--recursive <dir> ...\n\
- dpkg --configure <package name> ... | -a|--pending\n\
- dpkg -r|--remove | --purge <package name> ... | -a|--pending\n\
- dpkg --get-selections [<pattern> ...] get list of selections to stdout\n\
- dpkg --set-selections set package selections from stdin\n\
- dpkg --update-avail <Packages-file> replace available packages info\n\
- dpkg --merge-avail <Packages-file> 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 <package-name> ... display package status details\n\
- dpkg --print-avail <package-name> ... display available version details\n\
- dpkg -L|--listfiles <package-name> ... list files `owned' by package(s)\n\
- dpkg -l|--list [<pattern> ...] list packages concisely\n\
- dpkg -S|--search <pattern> ... find package(s) owning file(s)\n\
- dpkg -C|--audit check for broken package(s)\n\
- dpkg --abort-after <n> abort after encountering <n> 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 <a> <rel> <b> 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 <package name> ... | -a|--pending\n\
+ dpkg -r|--remove | -P|--purge <package name> ... | -a|--pending\n\
+ dpkg --get-selections [<pattern> ...] get list of selections to stdout\n\
+ dpkg --set-selections set package selections from stdin\n\
+ dpkg --update-avail <Packages-file> replace available packages info\n\
+ dpkg --merge-avail <Packages-file> 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 <package-name> ... display package status details\n\
+ dpkg -p|--print-avail <package-name> ... display available version details\n\
+ dpkg -L|--listfiles <package-name> ... list files `owned' by package(s)\n\
+ dpkg -l|--list [<pattern> ...] list packages concisely\n\
+ dpkg -S|--search <pattern> ... find package(s) owning file(s)\n\
+ dpkg -C|--audit check for broken package(s)\n\
+ dpkg --abort-after <n> abort after encountering <n> 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 <a> <rel> <b> 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\
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 ),
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;
};
void debug(int which, const char *fmt, ...) PRINTFFORMAT(2,3);
+void check_libver(void);
/* from depcon.c */
const char *thisarg;
int l;
- checkpath();
modstatdb_init(admindir,
f_noact ? msdbrw_readonly
: fc_nonroot ? msdbrw_write
: msdbrw_needsuperuser);
+ checkpath();
if (f_pending) {
.B md5sum
does not accept standard options like
-.BR -\-\help .
+.BR --help .
.SH AUTHOR
int verbose = 0;
int bin_mode = 0;
-void
+int
main(int argc, char **argv)
{
int opt, rc = 0;
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
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
--- /dev/null
+Please read the update-alternatives(8) man page for information on this
+directory and its contents.
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".
&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.");
}
$_ = $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);
.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
* <schwarz@monet.m.isar.de>, to make output conform to the Debian
* Console Message Standard, also placed in public domain. Minor
* changes by Klee Dienes <klee@debian.org>, also placed in the Public
- * Domain. */
+ * Domain.
+ *
+ * Changes by Ben Collins <bcollins@debian.org>, added --chuid, --background
+ * and --make-pidfile options, placed in public domain aswell.
+ */
#include "config.h"
#define _GNU_SOURCE
#include <unistd.h>
#include <getopt.h>
#include <pwd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <fcntl.h>
#ifdef HAVE_ERROR_H
#include <error.h>
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;
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
-n|--name <process-name> stop processes with this name\n\
-s|--signal <signal> signal to send (default TERM)\n\
-a|--startas <pathname> program to start (default is <executable>)\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\
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;
case 'c': /* --chuid <username>|<uid> */
changeuser = optarg;
break;
+ case 'b': /* --background */
+ background = 1;
+ break;
+ case 'm': /* --make-pidfile */
+ mpidfile = 1;
+ break;
default:
badusage(NULL); /* message printed by getopt */
}
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)
}
#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);
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);
printf(" %d", p->pid);
printf(").\n");
}
+ return retval;
}
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);
}
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);
}
*--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));
}