/[public]/qemu-start/trunk/qemu-start.c
ViewVC logotype

Contents of /qemu-start/trunk/qemu-start.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 292 - (show annotations)
Sat Feb 11 16:32:44 2006 UTC (18 years, 1 month ago) by frodo
File MIME type: text/plain
File size: 4006 byte(s)
(Frodo) Updated docs; fixed bug in qemu-start regarding xauth data

1 /*
2 qemu-start.c - Part of qemu-start, a package to start qemu nicely.
3 Copyright (c) 2006 Frodo Looijaard <frodo@frodo.looijaard.name>
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; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #define _GNU_SOURCE /* asprintf */
21 #include <stdio.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <pwd.h>
25 #include <grp.h>
26 #include <sys/stat.h>
27 #include <sys/ioctl.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <net/if.h>
32 #include <linux/if_tun.h>
33
34 #define QEMU "/usr/bin/qemu"
35 #define USER "qemu"
36
37 /* Tiny code to open tap/tun device, and hand the fd to qemu.
38 Run as root, drops to given user. */
39 int main(int argc, char *argv[])
40 {
41 struct ifreq ifr;
42 struct passwd *userdata;
43 char *newargs[argc + 2];
44 int i,fd,vlan,tapnr;
45 char *ptr;
46 char *command;
47 char *display;
48 char *xauthfile;
49
50 /* Check parameters */
51 if (argc < 4) {
52 fprintf(stderr, "Usage: qemu-start TAPDEVNR VLAN SYSTEM <qemu options>...\n");
53 fprintf(stderr, " A device tapTAPDEVNR must have been configured.\n");
54 fprintf(stderr, " VLAN is the Virtual LAN number (just use 0 if unsure).\n");
55 fprintf(stderr, " SYSTEM is the system to emulate. Use \"\" for the current architecture\n");
56 fprintf(stderr, " (uses /usr/bin/qemm); else a binary /usr/bin/qemu-system-SYSTEM is used.\n");
57 exit(1);
58 }
59
60 /* First parameter: TAPDEVNR */
61 tapnr = strtol(argv[1],&ptr,0);
62 if (*ptr) {
63 fprintf(stderr, "Invalid value for TAPDEVNR parameter (use a number!)\n");
64 exit(1);
65 }
66
67 /* Second parameter: VLAN */
68 vlan = strtol(argv[2],&ptr,0);
69 if (*ptr) {
70 fprintf(stderr, "Invalid value for VLAN parameter (use a number!)\n");
71 exit(1);
72 }
73
74 /* Open /dev/net/tun */
75 fd = open("/dev/net/tun", O_RDWR);
76 if (fd < 0) {
77 perror("Could not open /dev/net/tun");
78 exit(1);
79 }
80
81 /* Bind to the right tap device */
82 memset(&ifr, 0, sizeof(ifr));
83 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
84 snprintf(ifr.ifr_name,IFNAMSIZ,"tap%d",tapnr);
85
86 if (ioctl(fd, TUNSETIFF, (void *) &ifr) != 0) {
87 perror("Could not get tap device");
88 exit(1);
89 }
90
91 /* Fix X-display */
92 userdata = getpwuid(getuid());
93 if (! (xauthfile = getenv("XAUTHORITY")))
94 asprintf(&xauthfile,"~%s/.Xauthority",userdata->pw_name);
95 setuid(0);
96 setgid(0);
97 asprintf(&command,"xauth -f %s extract - $(echo $DISPLAY|sed \"s,^localhost,$(hostname)/unix,\") | xauth -f ~%s/.Xauthority merge -; chown %s: ~%s/.Xauthority",xauthfile,USER,USER,USER);
98 fprintf(stderr,"%s\n",command);
99 system(command);
100
101 /* Set correct userid. */
102 userdata = getpwnam(USER);
103 if (!userdata) {
104 fprintf(stderr, "No user '%s'\n", USER);
105 exit(1);
106 }
107 setgroups(0, NULL);
108 setgid(userdata->pw_gid);
109 if (setuid(userdata->pw_uid) != 0) {
110 perror("setting uid");
111 exit(1);
112 }
113
114 /* Clean the environment */
115 display=getenv("DISPLAY");
116 clearenv();
117 setenv("HOME",userdata->pw_dir,1);
118 setenv("DISPLAY",display,1);
119 setenv("PATH","/usr/bin:/bin:/usr/local/bin",1);
120 setenv("LOGNAME",userdata->pw_name,1);
121 setenv("USER",userdata->pw_name,1);
122
123 /* Create the right qemu invocation */
124 if (!strlen(argv[3]))
125 newargs[0] = QEMU;
126 else
127 asprintf(&newargs[0],"%s-system-%s",QEMU,argv[3]);
128 newargs[1] = "-net";
129 asprintf(&newargs[2],"nic,vlan=%d",vlan);
130 newargs[3] = "-net";
131 asprintf(&newargs[4],"tap,fd=%d,vlan=%d",fd,vlan);
132 for (i = 4; i <= argc; i++)
133 newargs[i+1] = argv[i];
134
135 execvp(newargs[0], newargs);
136 exit(1);
137 }

frodo@frodo.looijaard.name
ViewVC Help
Powered by ViewVC 1.1.26