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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 292 - (hide annotations)
Sat Feb 11 16:32:44 2006 UTC (18 years, 2 months 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 frodo 290 /*
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 frodo 292 char *xauthfile;
49 frodo 290
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 frodo 292 if (! (xauthfile = getenv("XAUTHORITY")))
94     asprintf(&xauthfile,"~%s/.Xauthority",userdata->pw_name);
95 frodo 290 setuid(0);
96     setgid(0);
97 frodo 292 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 frodo 290 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