fakerunlevel.c (3041B)
1 // $Id$ 2 3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> 4 // based on fakerunlevel.cc by Jacques Gelinas 5 // 6 // This program is free software; you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation; either version 2, or (at your option) 9 // any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program; if not, write to the Free Software 18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 20 /* 21 This program add a RUNLEVEL record in a utmp file. 22 This is used when a vserver lack a private init process 23 so runlevel properly report the fake runlevel. 24 */ 25 #ifdef HAVE_CONFIG_H 26 # include <config.h> 27 #endif 28 29 #include "util.h" 30 31 #include <utmp.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <stdlib.h> 35 #include <errno.h> 36 #include <fcntl.h> 37 #include <grp.h> 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 41 #define ENSC_WRAPPERS_PREFIX "fakerunlevel: " 42 #define ENSC_WRAPPERS_UNISTD 1 43 #define ENSC_WRAPPERS_FCNTL 1 44 #include <wrappers.h> 45 46 int wrapper_exit_code = 1; 47 48 static void 49 showHelp(int fd, int exit_code) 50 { 51 WRITE_MSG(fd, 52 "Usage: fakerunlevel <runlevel> <utmp_file>\n\n" 53 "Put a runlevel record in file <utmp_file>\n\n" 54 "Please report bugs to " PACKAGE_BUGREPORT "\n"); 55 56 exit(exit_code); 57 } 58 59 static void 60 showVersion() 61 { 62 WRITE_MSG(1, 63 "fakerunlevel " VERSION "\n" 64 "This program is part of " PACKAGE_STRING "\n\n" 65 "Copyright (C) 2003 Enrico Scholz\n" 66 VERSION_COPYRIGHT_DISCLAIMER); 67 exit(0); 68 } 69 70 int main (int argc, char *argv[]) 71 { 72 if (argc==1) showHelp(2,1); 73 if (strcmp(argv[1], "--help")==0) showHelp(1,0); 74 if (strcmp(argv[1], "--version")==0) showVersion(); 75 if (argc!=3) showHelp(2,1); 76 77 { 78 int const runlevel = atoi(argv[1]); 79 char const * const fname = argv[2]; 80 int fd; 81 struct utmp ut; 82 83 gid_t gid; 84 char *gid_str = getenv("UTMP_GID"); 85 86 if (runlevel<0 || runlevel>9) showHelp(2,1); 87 88 Echroot("."); 89 Echdir("/"); 90 91 // Real NSS is too expensive/insecure in this state; therefore, use the 92 // value detected at ./configure stage or overridden by $UTMP_GID 93 // env-variable 94 gid = gid_str ? atoi(gid_str) : UTMP_GID; 95 Esetgroups(1, &gid); 96 Esetgid(gid); 97 98 if (getgid()!=gid) { 99 WRITE_MSG(2, "fakerunlevel: Failed to set group\n"); 100 return EXIT_FAILURE; 101 } 102 103 umask(002); 104 fd = EopenD(fname, O_WRONLY|O_CREAT|O_APPEND, 0664); 105 Eclose(fd); 106 107 utmpname (fname); 108 setutent(); 109 memset (&ut,0,sizeof(ut)); 110 ut.ut_type = RUN_LVL; 111 ut.ut_pid = ('#' << 8) + runlevel+'0'; 112 pututline (&ut); 113 endutent(); 114 } 115 116 return EXIT_SUCCESS; 117 }