/[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 290 - (hide annotations)
Sat Feb 11 16:27:15 2006 UTC (18 years, 9 months ago) by frodo
File MIME type: text/plain
File size: 3874 byte(s)
Imported sources

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    
49     /* Check parameters */
50     if (argc < 4) {
51     fprintf(stderr, "Usage: qemu-start TAPDEVNR VLAN SYSTEM <qemu options>...\n");
52     fprintf(stderr, " A device tapTAPDEVNR must have been configured.\n");
53     fprintf(stderr, " VLAN is the Virtual LAN number (just use 0 if unsure).\n");
54     fprintf(stderr, " SYSTEM is the system to emulate. Use \"\" for the current architecture\n");
55     fprintf(stderr, " (uses /usr/bin/qemm); else a binary /usr/bin/qemu-system-SYSTEM is used.\n");
56     exit(1);
57     }
58    
59     /* First parameter: TAPDEVNR */
60     tapnr = strtol(argv[1],&ptr,0);
61     if (*ptr) {
62     fprintf(stderr, "Invalid value for TAPDEVNR parameter (use a number!)\n");
63     exit(1);
64     }
65    
66     /* Second parameter: VLAN */
67     vlan = strtol(argv[2],&ptr,0);
68     if (*ptr) {
69     fprintf(stderr, "Invalid value for VLAN parameter (use a number!)\n");
70     exit(1);
71     }
72    
73     /* Open /dev/net/tun */
74     fd = open("/dev/net/tun", O_RDWR);
75     if (fd < 0) {
76     perror("Could not open /dev/net/tun");
77     exit(1);
78     }
79    
80     /* Bind to the right tap device */
81     memset(&ifr, 0, sizeof(ifr));
82     ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
83     snprintf(ifr.ifr_name,IFNAMSIZ,"tap%d",tapnr);
84    
85     if (ioctl(fd, TUNSETIFF, (void *) &ifr) != 0) {
86     perror("Could not get tap device");
87     exit(1);
88     }
89    
90     /* Fix X-display */
91     userdata = getpwuid(getuid());
92     setuid(0);
93     setgid(0);
94     asprintf(&command,"xauth -f ~%s/.Xauthority extract - $(echo $DISPLAY|sed \"s,^localhost,$(hostname)/unix,\") | xauth -f ~%s/.Xauthority merge -; chown %s: ~%s/.Xauthority",userdata->pw_name,USER,USER,USER);
95     system(command);
96    
97     /* Set correct userid. */
98     userdata = getpwnam(USER);
99     if (!userdata) {
100     fprintf(stderr, "No user '%s'\n", USER);
101     exit(1);
102     }
103     setgroups(0, NULL);
104     setgid(userdata->pw_gid);
105     if (setuid(userdata->pw_uid) != 0) {
106     perror("setting uid");
107     exit(1);
108     }
109    
110     /* Clean the environment */
111     display=getenv("DISPLAY");
112     clearenv();
113     setenv("HOME",userdata->pw_dir,1);
114     setenv("DISPLAY",display,1);
115     setenv("PATH","/usr/bin:/bin:/usr/local/bin",1);
116     setenv("LOGNAME",userdata->pw_name,1);
117     setenv("USER",userdata->pw_name,1);
118    
119     /* Create the right qemu invocation */
120     if (!strlen(argv[3]))
121     newargs[0] = QEMU;
122     else
123     asprintf(&newargs[0],"%s-system-%s",QEMU,argv[3]);
124     newargs[1] = "-net";
125     asprintf(&newargs[2],"nic,vlan=%d",vlan);
126     newargs[3] = "-net";
127     asprintf(&newargs[4],"tap,fd=%d,vlan=%d",fd,vlan);
128     for (i = 4; i <= argc; i++)
129     newargs[i+1] = argv[i];
130    
131     execvp(newargs[0], newargs);
132     exit(1);
133     }

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