# include <linux/serial.h>
# include <linux/major.h>
#endif
-#include <fcntl.h>
#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
#include <unistd.h>
#ifdef USE_SULOGIN_EMERGENCY_MOUNT
} while (0)
static inline void __attribute__ ((__format__ (__printf__, 1, 2)))
-dbgprint(const char *mesg, ...)
+dbgprint(const char * const mesg, ...)
{
va_list ap;
va_start(ap, mesg);
}
if (stat("/", &rt) != 0) {
- warn("can not get file status of root file system\n");
+ warn("cannot get file status of root file system\n");
return;
}
* the caller has to free the result
*/
static __attribute__((__nonnull__))
-char *oneline(const char *file)
+char *oneline(const char * const file)
{
FILE *fp;
char *ret = NULL;
DBG(dbgprint("reading %s", file));
- if (!(fp = fopen(file, "re")))
+ if (!(fp = fopen(file, "r" UL_CLOEXECSTR)))
return NULL;
len = getline(&ret, &dummy, fp);
if (len >= 0) {
* /sys/class/tty, the caller has to free the result.
*/
static __attribute__((__malloc__))
-char *actattr(const char *tty)
+char *actattr(const char * const tty)
{
char *ret, *path;
* /sys/class/tty.
*/
static
-dev_t devattr(const char *tty)
+dev_t devattr(const char * const tty)
{
dev_t dev = 0;
char *path, *value;
#endif /* __linux__ */
/*
- * Search below /dev for the characer device in `dev_t comparedev' variable.
+ * Search below /dev for the character device in `dev_t comparedev' variable.
+ * Note that realpath(3) is used here to avoid not existent devices due the
+ * strdup(3) used in our canonicalize_path()!
*/
static
#ifdef __GNUC__
__attribute__((__nonnull__,__malloc__,__hot__))
#endif
-char* scandev(DIR *dir, dev_t comparedev)
+char* scandev(DIR *dir, const dev_t comparedev)
{
+ char path[PATH_MAX];
char *name = NULL;
- struct dirent *dent;
- int fd;
+ const struct dirent *dent;
+ int len, fd;
DBG(dbgprint("scanning /dev for %u:%u", major(comparedev), minor(comparedev)));
+ /*
+ * Try udev links on character devices first.
+ */
+ if ((len = snprintf(path, sizeof(path),
+ "/dev/char/%u:%u", major(comparedev), minor(comparedev))) > 0 &&
+ (size_t)len < sizeof(path)) {
+
+ name = realpath(path, NULL);
+ if (name)
+ goto out;
+ }
+
fd = dirfd(dir);
rewinddir(dir);
while ((dent = readdir(dir))) {
- char path[PATH_MAX];
struct stat st;
#ifdef _DIRENT_HAVE_D_TYPE
continue;
if (comparedev != st.st_rdev)
continue;
- if ((size_t)snprintf(path, sizeof(path), "/dev/%s", dent->d_name) >= sizeof(path))
+ if ((len = snprintf(path, sizeof(path), "/dev/%s", dent->d_name)) < 0 ||
+ (size_t)len >= sizeof(path))
continue;
-#ifdef USE_SULOGIN_EMERGENCY_MOUNT
- if (emergency_flags & MNT_DEVTMPFS)
- mknod(path, S_IFCHR|S_IRUSR|S_IWUSR, comparedev);
-#endif
- name = canonicalize_path(path);
- break;
+ name = realpath(path, NULL);
+ if (name)
+ goto out;
}
+#ifdef USE_SULOGIN_EMERGENCY_MOUNT
+ /*
+ * There was no /dev mounted hence and no device was found hence we create our own.
+ */
+ if (!name && (emergency_flags & MNT_DEVTMPFS)) {
+
+ if ((len = snprintf(path, sizeof(path),
+ "/dev/tmp-%u:%u", major(comparedev), minor(comparedev))) < 0 ||
+ (size_t)len >= sizeof(path))
+ goto out;
+
+ if (mknod(path, S_IFCHR|S_IRUSR|S_IWUSR, comparedev) < 0 && errno != EEXIST)
+ goto out;
+
+ name = realpath(path, NULL);
+ }
+#endif
+out:
return name;
}
*/
static
#ifdef __GNUC__
-__attribute__((__nonnull__,__hot__))
+__attribute__((__hot__))
#endif
-int append_console(struct list_head *consoles, const char *name)
+int append_console(struct list_head *consoles, const char * const name)
{
struct console *restrict tail;
- struct console *last = NULL;
+ const struct console *last = NULL;
DBG(dbgprint("appenging %s", name));
tail->flags = 0;
tail->fd = -1;
tail->id = last ? last->id + 1 : 0;
- tail->pid = 0;
+ tail->pid = -1;
memset(&tail->tio, 0, sizeof(tail->tio));
return 0;
DBG(dbgprint("trying /proc"));
- fc = fopen("/proc/consoles", "re");
+ fc = fopen("/proc/consoles", "r" UL_CLOEXECSTR);
if (!fc) {
rc = 2;
goto done;
#ifdef TIOCGDEV
static int detect_consoles_from_tiocgdev(struct list_head *consoles,
- int fallback,
+ const int fallback,
const char *device)
{
unsigned int devnum;
* Returns 1 if stdout and stderr should be reconnected and 0
* otherwise or less than zero on error.
*/
-int detect_consoles(const char *device, int fallback, struct list_head *consoles)
+int detect_consoles(const char *device, const int fallback, struct list_head *consoles)
{
int fd, reconnect = 0, rc;
dev_t comparedev = 0;
struct stat st;
#ifdef TIOCGDEV
unsigned int devnum;
+#endif
+#ifdef __GNU__
+ /*
+ * The Hurd always gives st_rdev as 0, which causes this
+ * method to select the first terminal it finds.
+ */
+ close(fd);
+ goto fallback;
#endif
DBG(dbgprint("trying device/fallback file descriptor"));
#ifdef __linux__
console:
/*
- * Detection of devices used for Linux system consolei using
+ * Detection of devices used for Linux system console using
* the /proc/consoles API with kernel 2.6.38 and higher.
*/
rc = detect_consoles_from_proc(consoles);
{
char *name = NULL;
int fd, re;
- LIST_HEAD(consoles);
- struct list_head *p;
+ struct list_head *p, consoles;
if (argc == 2) {
name = argv[1];
if (!name)
errx(EXIT_FAILURE, "usage: %s [<tty>]\n", program_invocation_short_name);
+ INIT_LIST_HEAD(&consoles);
re = detect_consoles(name, fd, &consoles);
list_for_each(p, &consoles) {