vsysctl.c (4537B)
1 // $Id$ --*- c -*-- 2 3 // Copyright (C) 2007 Daniel Hokka Zakrisson 4 // 5 // This program is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation; version 2 of the License. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program; if not, write to the Free Software 16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 18 19 #ifdef HAVE_CONFIG_H 20 # include <config.h> 21 #endif 22 23 #include "util.h" 24 #include <lib/internal.h> 25 26 #include <vserver.h> 27 28 #include <stdio.h> 29 #include <getopt.h> 30 #include <errno.h> 31 #include <fcntl.h> 32 #include <string.h> 33 #include <dirent.h> 34 35 #define ENSC_WRAPPERS_PREFIX "vsysctl: " 36 #define ENSC_WRAPPERS_UNISTD 1 37 #define ENSC_WRAPPERS_FCNTL 1 38 #define ENSC_WRAPPERS_DIRENT 1 39 #define ENSC_WRAPPERS_VSERVER 1 40 #define ENSC_WRAPPERS_IO 1 41 #include <wrappers.h> 42 43 44 #define PROC_SYS_DIRECTORY "/proc/sys" 45 46 47 #define CMD_HELP 0x1000 48 #define CMD_VERSION 0x1001 49 #define CMD_XID 0x4000 50 #define CMD_DIR 0x4001 51 #define CMD_MISSINGOK 0x4002 52 53 int wrapper_exit_code = 1; 54 55 struct option const 56 CMDLINE_OPTIONS[] = { 57 { "help", no_argument, 0, CMD_HELP }, 58 { "version", no_argument, 0, CMD_VERSION }, 59 { "xid", required_argument, 0, CMD_XID }, 60 { "dir", required_argument, 0, CMD_DIR }, 61 { "missingok", no_argument, 0, CMD_MISSINGOK }, 62 {0,0,0,0} 63 }; 64 65 static void 66 showHelp(int fd, char const *cmd) 67 { 68 WRITE_MSG(fd, "Usage: "); 69 WRITE_STR(fd, cmd); 70 WRITE_MSG(fd, 71 " --xid <xid> --dir <directory> [--missingok] -- <command> <args>*\n" 72 "\n" 73 "Please report bugs to " PACKAGE_BUGREPORT "\n"); 74 75 exit(0); 76 } 77 78 static void 79 showVersion() 80 { 81 WRITE_MSG(1, 82 "vsysctl " VERSION " -- sets sysctl values during guest boot\n" 83 "This program is part of " PACKAGE_STRING "\n\n" 84 "Copyright (C) 2007 Daniel Hokka Zakrisson\n" 85 VERSION_COPYRIGHT_DISCLAIMER); 86 exit(0); 87 } 88 89 void handle_setting(const char *dir, const char *name) 90 { 91 int len_dir = strlen(dir), len_name = strlen(name); 92 char filename[len_dir+1+len_name+sizeof("/setting")]; 93 char setting[128], value[128], *ptr; 94 int fd; 95 size_t setting_len, value_len; 96 97 strcpy(filename, dir); 98 *(filename+len_dir) = '/'; 99 strcpy(filename+len_dir+1, name); 100 101 #define READFILE(f) \ 102 strcpy(filename+len_dir+1+len_name, "/" #f); \ 103 fd = EopenD(filename, O_RDONLY, 0); \ 104 f##_len = Eread(fd, f, sizeof(f)); \ 105 if (f##_len == sizeof(f)) { \ 106 errno = EOVERFLOW; \ 107 perror(ENSC_WRAPPERS_PREFIX "read"); \ 108 exit(EXIT_FAILURE); \ 109 } \ 110 f[f##_len] = '\0'; \ 111 Eclose(fd); 112 113 READFILE(setting); 114 READFILE(value); 115 116 /* replace all . with / in setting to get a filename */ 117 for (ptr = strchr(setting, '.'); ptr; ptr = strchr(ptr, '.')) 118 *ptr = '/'; 119 120 /* we just want the first line, and not the linefeed */ 121 if ((ptr = strchr(setting, '\n')) != NULL) 122 *ptr = '\0'; 123 124 fd = EopenD(setting, O_WRONLY, 0); 125 EwriteAll(fd, value, value_len); 126 Eclose(fd); 127 } 128 129 int main(int argc, char *argv[]) 130 { 131 xid_t xid = VC_NOCTX; 132 const char *dir = NULL; 133 bool missing = false; 134 135 while (1) { 136 int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0); 137 if (c==-1) break; 138 139 switch (c) { 140 case CMD_HELP : showHelp(1, argv[0]); 141 case CMD_VERSION : showVersion(); 142 case CMD_XID : xid = Evc_xidopt2xid(optarg, true); break; 143 case CMD_DIR : dir = optarg; break; 144 case CMD_MISSINGOK: missing = true; break; 145 146 default : 147 WRITE_MSG(2, "Try '"); 148 WRITE_STR(2, argv[0]); 149 WRITE_MSG(2, " --help' for more information.\n"); 150 return EXIT_FAILURE; 151 break; 152 } 153 } 154 155 if (dir != NULL) { 156 int curdir = EopenD(".", O_RDONLY, 0); 157 DIR *dp; 158 struct dirent *de; 159 160 if (chdir(PROC_SYS_DIRECTORY) == -1) 161 goto exec; 162 163 dp = opendir(dir); 164 if (dp != NULL) { 165 while ((de = Ereaddir(dp)) != NULL) { 166 if (*de->d_name == '.') 167 continue; 168 handle_setting(dir, de->d_name); 169 } 170 Eclosedir(dp); 171 } 172 else if (!missing) { 173 perror(ENSC_WRAPPERS_PREFIX "opendir"); 174 exit(wrapper_exit_code); 175 } 176 177 Efchdir(curdir); 178 Eclose(curdir); 179 } 180 181 exec: 182 Eexecvp(argv[optind], argv+optind); 183 return EXIT_FAILURE; 184 }