fixing leak
[oweals/gnunet.git] / src / monkey / gdbmi_get_free_vt.c
1 /**[txh]********************************************************************
2
3   Copyright (c) 2004 by Salvador E. Tropea.
4   Covered by the GPL license.
5
6   Module: Linux VT.
7   Comments:
8   Helper to find a free VT. That's 100% Linux specific.@p
9   The code comes from "lconsole.c" from Allegro project and was originally
10 created by Marek Habersack and then modified by George Foot. I addapted it
11 to my needs and changed license from giftware to GPL.@p
12   
13 ***************************************************************************/
14
15 #define _GNU_SOURCE
16 #include <string.h>
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <sys/ioctl.h>
21 #ifdef __APPLE__
22 #include <util.h>
23 #endif /* __APPLE__ */
24
25 #include "gdbmi.h"
26
27 #if !defined(__linux__)
28
29 int mi_look_for_free_vt()
30 {
31  return -1;
32 }
33
34 mi_aux_term *gmi_look_for_free_vt()
35 {
36  return NULL;
37 }
38
39 #else
40
41 #include <linux/vt.h>
42
43 /**[txh]********************************************************************
44
45   Description:
46   Look for a free and usable Linux VT. Low level, use
47 @x{gmi_look_for_free_vt}.
48   
49   Return: The VT number or <0 on error.
50   
51 ***************************************************************************/
52
53 int mi_look_for_free_vt()
54 {/* Code from Allegro. */
55  int tty, console_fd, fd;
56  unsigned short mask;
57  char tty_name[16];
58  struct vt_stat vts; 
59
60  /* Now we need to find a VT we can use.  It must be readable and
61   * writable by us, if we're not setuid root.  VT_OPENQRY itself
62   * isn't too useful because it'll only ever come up with one 
63   * suggestion, with no guarrantee that we actually have access 
64   * to it.
65   *
66   * At some stage I think this is a candidate for config
67   * file overriding, but for now we'll stat the first N consoles
68   * to see which ones we can write to (hopefully at least one!),
69   * so that we can use that one to do ioctls.  We used to use 
70   * /dev/console for that purpose but it looks like it's not 
71   * always writable by enough people.
72   *
73   * Having found and opened a writable device, we query the state
74   * of the first sixteen (fifteen really) consoles, and try 
75   * opening each unused one in turn.
76   */
77
78  console_fd=open("/dev/console",O_WRONLY);
79  if (console_fd<0)
80    {
81     int n;
82     /* Try some ttys instead... */
83     for (n=1; n<=24; n++)
84        {
85         snprintf(tty_name,sizeof(tty_name),"/dev/tty%d",n);
86         console_fd=open(tty_name,O_WRONLY);
87         if (console_fd>=0)
88            break;
89        }
90     if (n>24)
91        return -1;
92    }
93
94  /* Get the state of the console -- in particular, the free VT field */
95  if (ioctl(console_fd,VT_GETSTATE,&vts)) {
96          close(console_fd);
97     return -2;
98  }
99  close(console_fd);
100
101  /* We attempt to set our euid to 0; if we were run with euid 0 to
102   * start with, we'll be able to do this now.  Otherwise, we'll just
103   * ignore the error returned since it might not be a problem if the
104   * ttys we look at are owned by the user running the program. */
105  seteuid(0);
106
107  /* tty0 is not really a console, so start counting at 2. */
108  fd=-1;
109  for (tty=1, mask=2; mask; tty++, mask<<=1)
110      if (!(vts.v_state & mask))
111        {
112         snprintf(tty_name,sizeof(tty_name),"/dev/tty%d",tty);
113         fd=open(tty_name,O_RDWR);
114         if (fd!=-1)
115           {
116            close(fd);
117            break;
118           }
119        }
120
121  seteuid(getuid());
122
123  if (!mask)
124     return -3;
125
126  return tty;
127 }
128
129 /**[txh]********************************************************************
130
131   Description:
132   Look for a free and usable Linux VT to be used by the child.
133   
134   Return: A new mi_aux_term structure, you can use @x{gmi_end_aux_term} to
135 release it.
136   
137 ***************************************************************************/
138
139 mi_aux_term *gmi_look_for_free_vt()
140 {
141  int ret;
142  int vt=mi_look_for_free_vt();
143  mi_aux_term *res;
144
145  if (vt<0)
146     return NULL;
147  res=(mi_aux_term *)malloc(sizeof(mi_aux_term));
148  if (!res)
149     return NULL;
150  res->pid=-1;
151  ret = asprintf(&res->tty,"/dev/tty%d",vt);
152  return res;
153 }
154
155 #endif
156