]>
git.wh0rd.org - sysvinit.git/blob - src/consoles.c
2 * consoles.c Routines to detect the system consoles
4 * Copyright (c) 2011 SuSE LINUX Products GmbH, All rights reserved.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program (see the file COPYING); if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 * Author: Werner Fink <werner@suse.de>
28 #include <sys/types.h>
30 #include <sys/ioctl.h>
35 # include <linux/serial.h>
44 # include <linux/major.h>
47 #if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
49 # define typeof __typeof__
52 # define restrict __restrict__
56 #define alignof(type) ((sizeof(type)+(sizeof(void*)-1)) & ~(sizeof(void*)-1))
58 struct console
*consoles
;
61 * Read and allocate one line from file,
62 * the caller has to free the result
66 __attribute__((__nonnull__
))
68 char *oneline(const char *file
)
71 char *ret
= (char*)0, *nl
;
74 if ((fp
= fopen(file
, "re")) == (FILE*)0)
76 if (getline(&ret
, &len
, fp
) < 0)
80 if ((nl
= strchr(ret
, '\n')))
90 * Read and determine active attribute for tty,
91 * the caller has to free the result.
94 __attribute__((__malloc__
))
95 char *actattr(const char *tty
)
100 if (!tty
|| *tty
== '\0')
103 if (asprintf(&path
, "/sys/class/tty/%s/active", tty
) < 0)
106 if ((ret
= oneline(path
)) == (char*)0)
114 /* Read and determine device attribute for tty */
116 dev_t
devattr(const char *tty
)
118 unsigned int maj
, min
;
122 if (!tty
|| *tty
== '\0')
125 if (asprintf(&path
, "/sys/class/tty/%s/dev", tty
) < 0)
128 if ((value
= oneline(path
)) == (char*)0)
131 if (sscanf(value
, "%u:%u", &maj
, &min
) == 2)
132 dev
= makedev(maj
, min
);
139 #endif /* __linux__ */
141 static dev_t comparedev
;
144 __attribute__((__nonnull__
,__malloc__
,__hot__
))
146 char* scandev(DIR *dir
)
148 char *name
= (char*)0;
154 while ((dent
= readdir(dir
))) {
157 if (fstatat(fd
, dent
->d_name
, &st
, 0) < 0)
159 if (!S_ISCHR(st
.st_mode
))
161 if (comparedev
!= st
.st_rdev
)
163 if ((size_t)snprintf(path
, sizeof(path
), "/dev/%s", dent
->d_name
) >= sizeof(path
))
165 name
= realpath(path
, NULL
);
172 struct chardata initcp
= {
179 static int concount
; /* Counter for console IDs */
183 __attribute__((__nonnull__
,__hot__
))
185 void consalloc(char * name
)
187 struct console
*restrict tail
;
189 if (posix_memalign((void*)&tail
, sizeof(void*), alignof(typeof(struct console
))) != 0)
190 perror("memory allocation");
192 tail
->next
= (struct console
*)0;
195 tail
->file
= (FILE*)0;
198 tail
->id
= concount
++;
200 memset(&tail
->tio
, 0, sizeof(tail
->tio
));
201 memcpy(&tail
->cp
, &initcp
, sizeof(struct chardata
));
206 consoles
->next
= tail
;
209 void detect_consoles(const char *console
, int fallback
)
212 char *attrib
, *cmdline
;
215 if ((fc
= fopen("/proc/consoles", "re"))) {
219 dir
= opendir("/dev");
222 while ((fscanf(fc
, "%*s %*s (%[^)]) %d:%d", &fbuf
[0], &maj
, &min
) == 3)) {
225 if (!strchr(fbuf
, 'E'))
227 comparedev
= makedev(maj
, min
);
240 if ((attrib
= actattr("console"))) {
241 char *words
= attrib
, *token
;
244 dir
= opendir("/dev");
247 while ((token
= strsep(&words
, " \t\r\n"))) {
252 comparedev
= devattr(token
);
253 if (comparedev
== makedev(TTY_MAJOR
, 0)) {
254 char *tmp
= actattr(token
);
257 comparedev
= devattr(tmp
);
273 if ((cmdline
= oneline("/proc/cmdline"))) {
274 char *words
= cmdline
, *token
;
277 dir
= opendir("/dev");
280 while ((token
= strsep(&words
, " \t\r\n"))) {
293 if (strncmp(token
, "console=", 8) != 0)
297 if (strcmp(token
, "brl") == 0)
299 if ((colon
= strchr(token
, ',')))
302 if (asprintf(&name
, "/dev/%s", token
) < 0)
305 if ((fd
= open(name
, O_RDWR
|O_NONBLOCK
|O_NOCTTY
|O_CLOEXEC
)) < 0) {
311 if (ioctl (fd
, TIOCGDEV
, &devnum
) < 0) {
315 comparedev
= (dev_t
)devnum
;
317 if (fstat(fd
, &st
) < 0) {
321 comparedev
= st
.st_rdev
;
322 if (comparedev
== makedev(TTY_MAJOR
, 0)) {
323 if (ioctl(fd
, VT_GETSTATE
, &vt
) < 0) {
327 comparedev
= makedev(TTY_MAJOR
, (int)vt
.v_active
);
342 #endif /* __linux __ */
343 if (console
&& *console
) {
356 if ((fd
= open(console
, O_RDWR
|O_NONBLOCK
|O_NOCTTY
|O_CLOEXEC
)) < 0)
359 if (ioctl (fd
, TIOCGDEV
, &devnum
) < 0) {
363 comparedev
= (dev_t
)devnum
;
365 if (fstat(fd
, &st
) < 0) {
370 comparedev
= st
.st_rdev
;
371 if (comparedev
== makedev(TTY_MAJOR
, 0)) {
372 if (ioctl(fd
, VT_GETSTATE
, &vt
) < 0) {
376 comparedev
= makedev(TTY_MAJOR
, (int)vt
.v_active
);
381 dir
= opendir("/dev");
392 const char *name
= ttyname(fallback
);
394 name
= "/dev/console";
395 consalloc(strdup(name
));
397 consoles
->fd
= fallback
;