vuname.c (7868B)
1 // $Id$ --*- c -*-- 2 3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> 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 "vserver.h" 24 #include "util.h" 25 26 #include <getopt.h> 27 #include <stdlib.h> 28 #include <assert.h> 29 #include <stdio.h> 30 #include <libgen.h> 31 #include <errno.h> 32 #include <fcntl.h> 33 #include <ctype.h> 34 #include <strings.h> 35 36 #define ENSC_WRAPPERS_PREFIX "vuname: " 37 #define ENSC_WRAPPERS_UNISTD 1 38 #define ENSC_WRAPPERS_IO 1 39 #define ENSC_WRAPPERS_VSERVER 1 40 #include <wrappers.h> 41 42 #define CMD_HELP 0x1000 43 #define CMD_VERSION 0x1001 44 #define CMD_DIR 0x4007 45 #define CMD_MISSINGOK 0x4008 46 47 int wrapper_exit_code = 255; 48 49 static vc_uts_type const UTS_MAPPING[7] = { 50 vcVHI_CONTEXT, vcVHI_SYSNAME, vcVHI_NODENAME, 51 vcVHI_RELEASE, vcVHI_VERSION, vcVHI_MACHINE, 52 vcVHI_DOMAINNAME }; 53 54 #define DECL(UTS) [vcVHI_ ## UTS] = #UTS 55 static char const * const UTS_STRINGS[] = { 56 DECL(CONTEXT), DECL(SYSNAME), DECL(NODENAME), 57 DECL(RELEASE), DECL(VERSION), DECL(MACHINE), 58 DECL(DOMAINNAME) 59 }; 60 61 struct Tag { 62 bool is_set; 63 char const * value; 64 }; 65 66 struct Arguments { 67 struct Tag tags[DIM_OF(UTS_MAPPING)]; 68 xid_t xid; 69 bool do_set; 70 char const * dir; 71 bool is_missingok; 72 }; 73 74 static struct option const 75 CMDLINE_OPTIONS[] = { 76 { "help", no_argument, 0, CMD_HELP }, 77 { "version", no_argument, 0, CMD_VERSION }, 78 { "xid", required_argument, 0, 'x' }, 79 { "set", no_argument, 0, 's' }, 80 { "get", no_argument, 0, 'g' }, 81 { "dir", required_argument, 0, CMD_DIR }, 82 { "missingok", no_argument, 0, CMD_MISSINGOK }, 83 { 0,0,0,0 } 84 }; 85 86 static void 87 showHelp(int fd, char const *cmd, int res) 88 { 89 VSERVER_DECLARE_CMD(cmd); 90 91 WRITE_MSG(fd, "Usage: "); 92 WRITE_STR(fd, cmd); 93 WRITE_MSG(fd, 94 " [-g] --xid <xid> <TAG>*\n" 95 " or "); 96 WRITE_STR(fd, cmd); 97 WRITE_MSG(fd, 98 " -s --xid <xid> -t <TAG>=<VALUE> [--] [<command> <args>*]\n" 99 " or "); 100 WRITE_STR(fd, cmd); 101 WRITE_MSG(fd, 102 " --dir <dir> --xid <xid> [--missingok] [--] [<command> <args>*]\n\n" 103 " Options:\n" 104 " -g ... get and print the value\n" 105 " -s ... set the value\n\n" 106 " --xid <xid> ... operate on this context; 'self' means the current one\n" 107 " -t <TAG>=<VALUE>\n" 108 " ... set <TAG> to <VALUE>; this option can be repeated multiple time\n" 109 " --dir <dir> ... read values from files in <dir>. These files must\n" 110 " have a valid TAG as their name\n" 111 " --missingok ... do not fail when the <DIR> from '--dir' does not exist.\n" 112 "\n" 113 " Possible values for TAG are:\n" 114 " context, sysname, nodename, release, version, machine, domainname\n" 115 "\n" 116 "Please report bugs to " PACKAGE_BUGREPORT "\n"); 117 exit(res); 118 } 119 120 static void 121 showVersion() 122 { 123 WRITE_MSG(1, 124 "vuname " VERSION " -- modifies and shows uname entries of vserver contexts\n" 125 "This program is part of " PACKAGE_STRING "\n\n" 126 "Copyright (C) 2004 Enrico Scholz\n" 127 VERSION_COPYRIGHT_DISCLAIMER); 128 exit(0); 129 } 130 131 static void 132 setFromDir(char const *pathname, bool is_missingok, xid_t xid) 133 { 134 struct stat st; 135 size_t i; 136 size_t l_pathname = strlen(pathname); 137 char buf[l_pathname + sizeof("/domainname") + 32]; 138 139 if (stat(pathname, &st)==-1) { 140 if (errno==ENOENT && is_missingok) return; 141 PERROR_Q(ENSC_WRAPPERS_PREFIX "fstat", pathname); 142 exit(wrapper_exit_code); 143 } 144 145 memcpy(buf, pathname, l_pathname); 146 if (l_pathname>0 && pathname[l_pathname-1]!='/') 147 buf[l_pathname++] = '/'; 148 149 for (i=0; i<DIM_OF(UTS_STRINGS); ++i) { 150 char * ptr = buf+l_pathname; 151 int fd; 152 153 // ignore unimplemented uts-names 154 if (UTS_STRINGS[i]==0) continue; 155 strcpy(ptr, UTS_STRINGS[i]); 156 for (;*ptr;++ptr) *ptr = tolower(*ptr); 157 fd = open(buf, O_RDONLY); 158 if (fd!=-1) { 159 size_t l = Elseek(fd, 0, SEEK_END); 160 char name[l+1]; 161 Elseek(fd,0,SEEK_SET); 162 EreadAll(fd, name, l); 163 while (l>0 && name[l-1]=='\n') --l; 164 name[l] = '\0'; 165 Eclose(fd); 166 167 if (vc_set_vhi_name(xid, (vc_uts_type)(i), name, l)==-1) { 168 PERROR_U(ENSC_WRAPPERS_PREFIX "vc_set_vhi_name", UTS_STRINGS[i]); 169 exit(wrapper_exit_code); 170 } 171 } 172 } 173 } 174 175 static size_t 176 findUtsIdx(char const *str, size_t len) 177 { 178 size_t i; 179 for (i=0; i<DIM_OF(UTS_STRINGS); ++i) 180 if (UTS_STRINGS[i]!=0 && strncasecmp(UTS_STRINGS[i], str, len)==0) 181 return i; 182 183 WRITE_MSG(2, "Tag '"); 184 Vwrite (2, str, len); 185 WRITE_STR(2, "' not recognized\n"); 186 exit(wrapper_exit_code); 187 } 188 189 static void 190 registerValue(char const *str, struct Tag tags[DIM_OF(UTS_MAPPING)]) 191 { 192 char const * ptr = strchr(str, '='); 193 size_t idx; 194 195 if (ptr==0) ptr = str + strlen(str); 196 assert(*ptr=='=' || *ptr=='\0'); 197 198 idx = findUtsIdx(str, ptr-str); 199 200 if (*ptr=='=') ++ptr; 201 tags[idx].is_set = true; 202 tags[idx].value = ptr; 203 } 204 205 static void 206 printUtsValue(xid_t xid, int val) 207 { 208 char buf[128]; 209 if (vc_get_vhi_name(xid, val, buf, sizeof(buf)-1)==-1) 210 WRITE_MSG(1, "???"); 211 else 212 WRITE_STR(1, buf); 213 214 } 215 216 int main(int argc, char *argv[]) 217 { 218 struct Arguments args = { 219 .tags = { [0] = {false,0} }, 220 .do_set = false, 221 .dir = 0, 222 .is_missingok= false, 223 .xid = VC_NOCTX, 224 }; 225 size_t i; 226 227 assert(DIM_OF(UTS_MAPPING) == DIM_OF(args.tags)); 228 229 while (1) { 230 int c = getopt_long(argc, argv, "+gst:", CMDLINE_OPTIONS, 0); 231 if (c==-1) break; 232 233 switch (c) { 234 case CMD_HELP : showHelp(1, argv[0], 0); 235 case CMD_VERSION : showVersion(); 236 case CMD_DIR : args.dir = optarg; break; 237 case CMD_MISSINGOK: args.is_missingok = true; break; 238 case 'g' : args.do_set = false; break; 239 case 's' : args.do_set = true; break; 240 case 'x' : args.xid = Evc_xidopt2xid(optarg,true); break; 241 case 't' : registerValue(optarg, args.tags); break; 242 default : 243 WRITE_MSG(2, "Try '"); 244 WRITE_STR(2, argv[0]); 245 WRITE_MSG(2, " --help' for more information.\n"); 246 return EXIT_FAILURE; 247 break; 248 } 249 } 250 251 if (args.xid==VC_NOCTX) { 252 WRITE_MSG(2, "No context specified; try '--help' for more information\n"); 253 exit(wrapper_exit_code); 254 } 255 256 if (args.dir) 257 setFromDir(args.dir, args.is_missingok, args.xid); 258 else if (args.do_set) { 259 for (i=0; i<DIM_OF(args.tags); ++i) { 260 if (!args.tags[i].is_set) continue; 261 Evc_set_vhi_name(args.xid, i, args.tags[i].value, strlen(args.tags[i].value)); 262 } 263 } 264 else if (optind==argc) { 265 char const * delim = ""; 266 for (i=0; i<DIM_OF(UTS_MAPPING); ++i) { 267 WRITE_STR(1, delim); 268 printUtsValue(args.xid, i); 269 delim = " "; 270 } 271 WRITE_MSG(1, "\n"); 272 273 return EXIT_SUCCESS; 274 } 275 else { 276 char const * delim = ""; 277 while (optind <argc) { 278 int idx = findUtsIdx(argv[optind], strlen(argv[optind])); 279 WRITE_STR(1, delim); 280 printUtsValue(args.xid, idx); 281 delim = " "; 282 283 ++optind; 284 } 285 WRITE_MSG(1, "\n"); 286 287 return EXIT_SUCCESS; 288 } 289 290 if (optind<argc) 291 EexecvpD(argv[optind], argv+optind); 292 293 return EXIT_SUCCESS; 294 }