-// $Id: fakerunlevel.c,v 1.1 2003/09/29 22:01:57 ensc Exp $
+// $Id: fakerunlevel.c,v 1.6 2004/02/27 04:42:10 ensc Exp $
// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
// based on fakerunlevel.cc by Jacques Gelinas
This is used when a vserver lack a private init process
so runlevel properly report the fake runlevel.
*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "util.h"
+
#include <utmp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define ENSC_WRAPPERS_PREFIX "fakerunlevel: "
+#define ENSC_WRAPPERS_UNISTD 1
+#define ENSC_WRAPPERS_FCNTL 1
+#include <wrappers.h>
+
+int wrapper_exit_code = 1;
-static void usage()
+static void
+showHelp(int fd, int exit_code)
{
- fprintf (stderr,"fakerunlevel version %s\n",VERSION);
- fprintf (stderr
- ,"\n"
- "fakerunlevel runlevel utmp_file\n"
- "\n"
- "Put a runlevel record in file utmp_file\n");
+ WRITE_MSG(fd,
+ "Usage: fakerunlevel <runlevel> <utmp_file>\n\n"
+ "Put a runlevel record in file <utmp_file>\n\n"
+ "Please report bugs to " PACKAGE_BUGREPORT "\n");
+
+ exit(exit_code);
}
-int main (int argc, char *argv[])
+static void
+showVersion()
{
- if (argc != 3){
- usage();
- }else{
- int runlevel = atoi(argv[1]);
- const char *fname = argv[2];
- if (runlevel < 1 || runlevel > 5){
- usage();
- }else{
- // Make sure the file exist
- FILE *fout = fopen (fname,"a");
- if (fout == NULL){
- fprintf (stderr,"Can't open file %s (%s)\n",fname
- ,strerror(errno));
- }else{
- struct utmp ut;
-
- fclose (fout);
- utmpname (fname);
- setutent();
- memset (&ut,0,sizeof(ut));
- ut.ut_type = RUN_LVL;
- ut.ut_pid = ('#' << 8) + runlevel+'0';
- pututline (&ut);
- endutent();
- }
- }
- }
-
- return 0;
+ WRITE_MSG(1,
+ "fakerunlevel " VERSION "\n"
+ "This program is part of " PACKAGE_STRING "\n\n"
+ "Copyright (C) 2003 Enrico Scholz\n"
+ VERSION_COPYRIGHT_DISCLAIMER);
+ exit(0);
}
+int main (int argc, char *argv[])
+{
+ if (argc==1) showHelp(2,1);
+ if (strcmp(argv[1], "--help")==0) showHelp(1,0);
+ if (strcmp(argv[1], "--version")==0) showVersion();
+ if (argc!=3) showHelp(2,1);
+
+ {
+ int const runlevel = atoi(argv[1]);
+ char const * const fname = argv[2];
+ int fd;
+ struct utmp ut;
+
+ gid_t gid;
+ char *gid_str = getenv("UTMP_GID");
+
+ if (runlevel<0 || runlevel>6) showHelp(2,1);
+
+ Echroot(".");
+ Echdir("/");
+
+ // Real NSS is too expensive/insecure in this state; therefore, use the
+ // value detected at ./configure stage or overridden by $UTMP_GID
+ // env-variable
+ gid = gid_str ? atoi(gid_str) : UTMP_GID;
+ Esetgroups(1, &gid);
+ Esetgid(gid);
+
+ if (getgid()!=gid) {
+ WRITE_MSG(2, "fakerunlevel: Failed to set group\n");
+ return EXIT_FAILURE;
+ }
+
+ umask(002);
+ fd = EopenD(fname, O_WRONLY|O_CREAT|O_APPEND, 0664);
+ Eclose(fd);
+
+ utmpname (fname);
+ setutent();
+ memset (&ut,0,sizeof(ut));
+ ut.ut_type = RUN_LVL;
+ ut.ut_pid = ('#' << 8) + runlevel+'0';
+ pututline (&ut);
+ endutent();
+ }
+
+ return EXIT_SUCCESS;
+}