Merge branch 'misc' of git://github.com/kerolasa/lelux-utiliteetit

* 'misc' of git://github.com/kerolasa/lelux-utiliteetit:
  textual: share crypt() error message in sulogin and newgrp
  newgrp: avoid use of obsolete getpass() function
  newgrp: use libc function to read gshadow if it is available
  setarch: use personality() system call when it is available
  setarch: reindent code
  hwclock: remove referal to deprecated keyboard interface
  eject: make open_device() and select_speed() to use struct eject_control
  eject: add struct eject_control to remove global variables
  mountpoint: simplify if statement
  mkfs.minix: fix couple compiler warnings
  mountpoint: add struct mountpoint_control
  last: improve code readability by renaming variable names
  last: make is_phantom() when kernel config does not include audit support
  lib: remove xgetpass()
  include: simplify fputc_careful() in carefulputc.h
  libuuid: add extern qualifiers to uuid/uuid.h system header
This commit is contained in:
Karel Zak 2014-09-22 14:55:37 +02:00
commit 286f1e229b
17 changed files with 627 additions and 813 deletions

View File

@ -310,6 +310,7 @@ AC_CHECK_FUNCS([ \
getexecname \ getexecname \
getmntinfo \ getmntinfo \
getrlimit \ getrlimit \
getsgnam \
inotify_init \ inotify_init \
inotify_init1 \ inotify_init1 \
jrand48 \ jrand48 \

View File

@ -362,9 +362,11 @@ static void make_bad_inode_v2_v3 (void)
static void make_bad_inode(void) static void make_bad_inode(void)
{ {
if (fs_version < 2) if (fs_version < 2) {
return make_bad_inode_v1(); make_bad_inode_v1();
return make_bad_inode_v2_v3(); return;
}
make_bad_inode_v2_v3();
} }
static void make_root_inode_v1(void) { static void make_root_inode_v1(void) {
@ -412,9 +414,11 @@ static void make_root_inode_v2_v3 (void) {
static void make_root_inode(void) static void make_root_inode(void)
{ {
if (fs_version < 2) if (fs_version < 2) {
return make_root_inode_v1(); make_root_inode_v1();
return make_root_inode_v2_v3(); return;
}
make_root_inode_v2_v3();
} }
static void super_set_nzones(void) static void super_set_nzones(void)

View File

@ -49,7 +49,6 @@ dist_noinst_HEADERS += \
include/ttyutils.h \ include/ttyutils.h \
include/widechar.h \ include/widechar.h \
include/xalloc.h \ include/xalloc.h \
include/xgetpass.h \
include/pt-sgi.h \ include/pt-sgi.h \
include/pt-bsd.h \ include/pt-bsd.h \
include/pt-mbr.h \ include/pt-mbr.h \

View File

@ -10,26 +10,22 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#define iso8859x_iscntrl(c) \ static inline int fputc_careful(int c, FILE *fp, const char fail)
(((c) & 0x7f) < 0x20 || (c) == 0x7f) {
static inline int fputc_careful(int c, FILE *fp, const char fail) {
int ret; int ret;
if (c == '\007' || c == '\t' || c == '\r' || c == '\n' || if (isprint(c) || c == '\a' || c == '\t' || c == '\r' || c == '\n')
(!iso8859x_iscntrl(c) && (isprint(c) || isspace(c))))
ret = putc(c, fp); ret = putc(c, fp);
else if ((c & 0x80) || !isprint(c^0x40)) else if (!isascii(c))
ret = fprintf(fp, "\\%3o", (unsigned char) c); ret = fprintf(fp, "\\%3o", (unsigned char)c);
else { else {
ret = putc(fail, fp); ret = putc(fail, fp);
if (ret != EOF) if (ret != EOF)
ret = putc(c^0x40, fp); ret = putc(c ^ 0x40, fp);
} }
return (ret < 0) ? EOF : 0; return (ret < 0) ? EOF : 0;
} }
static inline void fputs_quoted(const char *data, FILE *out) static inline void fputs_quoted(const char *data, FILE *out)
{ {
const char *p; const char *p;

View File

@ -1,6 +0,0 @@
#ifndef UTIL_LINUX_XGETPASS_H
#define UTIL_LINUX_XGETPASS_H
extern char *xgetpass(int pfd, const char *prompt);
#endif /* UTIL_LINUX_XGETPASS_H */

View File

@ -24,7 +24,6 @@ libcommon_la_SOURCES = \
lib/sysfs.c \ lib/sysfs.c \
lib/timeutils.c \ lib/timeutils.c \
lib/ttyutils.c \ lib/ttyutils.c \
lib/xgetpass.c \
lib/exec_shell.c \ lib/exec_shell.c \
lib/readutmp.c lib/readutmp.c

View File

@ -1,46 +0,0 @@
/*
* A function to read the passphrase either from the terminal or from
* an open file descriptor.
*
* Public domain.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include "c.h"
#include "xgetpass.h"
char *xgetpass(int pfd, const char *prompt)
{
char *pass = NULL;
int len = 0, i;
if (pfd < 0) /* terminal */
return getpass(prompt);
for (i=0; ; i++) {
if (i >= len-1) {
char *tmppass = pass;
len += 128;
pass = realloc(tmppass, len);
if (!pass) {
pass = tmppass; /* the old buffer hasn't changed */
break;
}
}
if (pass && (read(pfd, pass + i, 1) != 1 ||
pass[i] == '\n' || pass[i] == 0))
break;
}
if (pass)
pass[i] = '\0';
return pass;
}

View File

@ -67,35 +67,35 @@ extern "C" {
#endif #endif
/* clear.c */ /* clear.c */
void uuid_clear(uuid_t uu); extern void uuid_clear(uuid_t uu);
/* compare.c */ /* compare.c */
int uuid_compare(const uuid_t uu1, const uuid_t uu2); extern int uuid_compare(const uuid_t uu1, const uuid_t uu2);
/* copy.c */ /* copy.c */
void uuid_copy(uuid_t dst, const uuid_t src); extern void uuid_copy(uuid_t dst, const uuid_t src);
/* gen_uuid.c */ /* gen_uuid.c */
void uuid_generate(uuid_t out); extern void uuid_generate(uuid_t out);
void uuid_generate_random(uuid_t out); extern void uuid_generate_random(uuid_t out);
void uuid_generate_time(uuid_t out); extern void uuid_generate_time(uuid_t out);
int uuid_generate_time_safe(uuid_t out); extern int uuid_generate_time_safe(uuid_t out);
/* isnull.c */ /* isnull.c */
int uuid_is_null(const uuid_t uu); extern int uuid_is_null(const uuid_t uu);
/* parse.c */ /* parse.c */
int uuid_parse(const char *in, uuid_t uu); extern int uuid_parse(const char *in, uuid_t uu);
/* unparse.c */ /* unparse.c */
void uuid_unparse(const uuid_t uu, char *out); extern void uuid_unparse(const uuid_t uu, char *out);
void uuid_unparse_lower(const uuid_t uu, char *out); extern void uuid_unparse_lower(const uuid_t uu, char *out);
void uuid_unparse_upper(const uuid_t uu, char *out); extern void uuid_unparse_upper(const uuid_t uu, char *out);
/* uuid_time.c */ /* uuid_time.c */
time_t uuid_time(const uuid_t uu, struct timeval *ret_tv); extern time_t uuid_time(const uuid_t uu, struct timeval *ret_tv);
int uuid_type(const uuid_t uu); extern int uuid_type(const uuid_t uu);
int uuid_variant(const uuid_t uu); extern int uuid_variant(const uuid_t uu);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -376,9 +376,9 @@ static void trim_trailing_spaces(char *s)
/* /*
* Show one line of information on screen * Show one line of information on screen
*/ */
static int list(const struct last_control *ctl, struct utmp *p, time_t t, int what) static int list(const struct last_control *ctl, struct utmp *p, time_t logout_time, int what)
{ {
time_t secs, tmp, epoch; time_t secs, utmp_time, now;
char logintime[LAST_TIMESTAMP_LEN]; char logintime[LAST_TIMESTAMP_LEN];
char logouttime[LAST_TIMESTAMP_LEN]; char logouttime[LAST_TIMESTAMP_LEN];
char length[LAST_TIMESTAMP_LEN]; char length[LAST_TIMESTAMP_LEN];
@ -417,22 +417,25 @@ static int list(const struct last_control *ctl, struct utmp *p, time_t t, int wh
/* /*
* Calculate times * Calculate times
*/ */
tmp = p->UL_UT_TIME; utmp_time = p->UL_UT_TIME;
if (ctl->present && (ctl->present < tmp || (0 < t && t < ctl->present))) if (ctl->present) {
return 0; if (ctl->present < utmp_time)
return 0;
if (time_formatter(ctl, &logintime[0], sizeof(logintime), &tmp, 0) < 0 || if (0 < logout_time && logout_time < ctl->present)
time_formatter(ctl, &logouttime[0], sizeof(logouttime), &t, 1) < 0) return 0;
}
if (time_formatter(ctl, &logintime[0], sizeof(logintime), &utmp_time, 0) < 0 ||
time_formatter(ctl, &logouttime[0], sizeof(logouttime), &logout_time, 1) < 0)
errx(EXIT_FAILURE, _("preallocation size exceeded")); errx(EXIT_FAILURE, _("preallocation size exceeded"));
secs = t - p->UL_UT_TIME; secs = logout_time - utmp_time;
mins = (secs / 60) % 60; mins = (secs / 60) % 60;
hours = (secs / 3600) % 24; hours = (secs / 3600) % 24;
days = secs / 86400; days = secs / 86400;
epoch = time(NULL); now = time(NULL);
if (t == epoch) { if (logout_time == now) {
if (ctl->time_fmt > LAST_TIMEFTM_SHORT_CTIME) { if (ctl->time_fmt > LAST_TIMEFTM_SHORT_CTIME) {
sprintf(logouttime, " still running"); sprintf(logouttime, " still running");
length[0] = 0; length[0] = 0;
@ -582,8 +585,6 @@ static int is_phantom(const struct last_control *ctl, struct utmp *ut)
{ {
struct passwd *pw; struct passwd *pw;
char path[32]; char path[32];
FILE *f = NULL;
unsigned int loginuid;
int ret = 0; int ret = 0;
if (ut->UL_UT_TIME < ctl->boot_time.tv_sec) if (ut->UL_UT_TIME < ctl->boot_time.tv_sec)
@ -592,14 +593,26 @@ static int is_phantom(const struct last_control *ctl, struct utmp *ut)
if (!pw) if (!pw)
return 1; return 1;
sprintf(path, "/proc/%u/loginuid", ut->ut_pid); sprintf(path, "/proc/%u/loginuid", ut->ut_pid);
if (access(path, R_OK) != 0 || !(f = fopen(path, "r"))) if (access(path, R_OK) == 0) {
return 1; unsigned int loginuid;
FILE *f = NULL;
if (fscanf(f, "%u", &loginuid) != 1) if (!(f = fopen(path, "r")))
ret = 1; return 1;
fclose(f); if (fscanf(f, "%u", &loginuid) != 1)
if (!ret && pw->pw_uid != loginuid) ret = 1;
return 1; fclose(f);
if (!ret && pw->pw_uid != loginuid)
return 1;
} else {
struct stat st;
sprintf(path, "/dev/%s", ut->ut_line);
if (stat(path, &st))
return 1;
if (pw->pw_uid != st.st_uid)
return 1;
}
return ret; return ret;
} }

View File

@ -22,21 +22,75 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <termios.h>
#include <unistd.h> #include <unistd.h>
#ifdef HAVE_CRYPT_H #ifdef HAVE_CRYPT_H
# include <crypt.h> # include <crypt.h>
#endif #endif
#ifdef HAVE_GETSGNAM
# include <gshadow.h>
#endif
#include "c.h" #include "c.h"
#include "closestream.h" #include "closestream.h"
#include "nls.h" #include "nls.h"
#include "pathnames.h" #include "pathnames.h"
#include "xalloc.h" #include "xalloc.h"
static char *xgetpass(FILE *input, const char *prompt)
{
char *pass = NULL;
struct termios saved, no_echo;
const int fd = fileno(input);
size_t dummy = 0;
ssize_t len;
fputs(prompt, stdout);
if (isatty(fd)) {
/* disable echo */
tcgetattr(fd, &saved);
no_echo = saved;
no_echo.c_lflag &= ~ECHO;
no_echo.c_lflag |= ECHONL;
if (tcsetattr(fd, TCSANOW, &no_echo))
err(EXIT_FAILURE, _("could not set terminal attributes"));
}
len = getline(&pass, &dummy, input);
if (isatty(fd))
/* restore terminal */
if (tcsetattr(fd, TCSANOW, &saved))
err(EXIT_FAILURE, _("could not set terminal attributes"));
if (len < 0)
err(EXIT_FAILURE, _("could not getline"));
if (0 < len && *(pass + len - 1) == '\n')
*(pass + len - 1) = '\0';
return pass;
}
/* Ensure memory is set to value c without compiler optimization getting
* into way that could happen with memset(3). */
static int memset_s(void *v, size_t sz, const int c)
{
volatile unsigned char *p = v;
if (v == NULL)
return EINVAL;
while (sz--)
*p++ = c;
return 0;
}
/* try to read password from gshadow */ /* try to read password from gshadow */
static char *get_gshadow_pwd(char *groupname) static char *get_gshadow_pwd(char *groupname)
{ {
#ifdef HAVE_GETSGNAM
struct sgrp *sgrp;
sgrp = getsgnam(groupname);
return sgrp ? xstrdup(sgrp->sg_passwd) : NULL;
#else
char buf[BUFSIZ]; char buf[BUFSIZ];
char *pwd = NULL; char *pwd = NULL;
FILE *f; FILE *f;
@ -69,6 +123,7 @@ static char *get_gshadow_pwd(char *groupname)
} }
fclose(f); fclose(f);
return pwd ? xstrdup(pwd) : NULL; return pwd ? xstrdup(pwd) : NULL;
#endif /* HAVE_GETSGNAM */
} }
static int allow_setgid(struct passwd *pe, struct group *ge) static int allow_setgid(struct passwd *pe, struct group *ge)
@ -99,11 +154,13 @@ static int allow_setgid(struct passwd *pe, struct group *ge)
if (!(pwd = get_gshadow_pwd(ge->gr_name))) if (!(pwd = get_gshadow_pwd(ge->gr_name)))
pwd = ge->gr_passwd; pwd = ge->gr_passwd;
if (pwd && *pwd && (xpwd = getpass(_("Password: ")))) { if (pwd && *pwd && (xpwd = xgetpass(stdin, _("Password: ")))) {
char *cbuf = crypt(xpwd, pwd); char *cbuf = crypt(xpwd, pwd);
memset_s(xpwd, strlen(xpwd), 0);
free(xpwd);
if (!cbuf) if (!cbuf)
warn(_("crypt() failed")); warn(_("crypt failed"));
else if (strcmp(pwd, cbuf) == 0) else if (strcmp(pwd, cbuf) == 0)
return TRUE; return TRUE;
} }

View File

@ -359,8 +359,7 @@ PATHFILES += sys-utils/hwclock.8
hwclock_SOURCES = \ hwclock_SOURCES = \
sys-utils/hwclock.c \ sys-utils/hwclock.c \
sys-utils/hwclock.h \ sys-utils/hwclock.h \
sys-utils/hwclock-cmos.c \ sys-utils/hwclock-cmos.c
sys-utils/hwclock-kd.c
if LINUX if LINUX
hwclock_SOURCES += sys-utils/hwclock-rtc.c hwclock_SOURCES += sys-utils/hwclock-rtc.c
endif endif

View File

@ -81,31 +81,34 @@ static const char * const hotplug_subsystems[] = {
"ccw" "ccw"
}; };
/* Global Variables */ struct eject_control {
static int a_option; /* command flags and arguments */ struct libmnt_table *mtab;
static int c_option; char *device; /* device or mount point to be ejected */
static int d_option; int fd; /* file descriptor for device */
static int f_option; unsigned int /* command flags and arguments */
static int F_option; a_option:1,
static int n_option; c_option:1,
static int q_option; d_option:1,
static int r_option; F_option:1,
static int s_option; f_option:1,
static int t_option; i_option:1,
static int T_option; M_option:1,
static int X_option; m_option:1,
static int v_option; n_option:1,
static int x_option; p_option:1,
static int p_option; q_option:1,
static int m_option; r_option:1,
static int M_option; s_option:1,
static int i_option; T_option:1,
static int a_arg; t_option:1,
static int i_arg; v_option:1,
static long int c_arg; X_option:1,
static long int x_arg; x_option:1,
a_arg:1,
struct libmnt_table *mtab; i_arg:1;
long int c_arg; /* changer slot number */
long int x_arg; /* cd speed */
};
static void vinfo(const char *fmt, va_list va) static void vinfo(const char *fmt, va_list va)
{ {
@ -114,11 +117,11 @@ static void vinfo(const char *fmt, va_list va)
fputc('\n', stdout); fputc('\n', stdout);
} }
static inline void verbose(const char *fmt, ...) static inline void verbose(const struct eject_control *ctl, const char *fmt, ...)
{ {
va_list va; va_list va;
if (!v_option) if (!ctl->v_option)
return; return;
va_start(va, fmt); va_start(va, fmt);
@ -174,7 +177,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
/* Handle command line options. */ /* Handle command line options. */
static void parse_args(int argc, char **argv, char **device) static void parse_args(struct eject_control *ctl, int argc, char **argv)
{ {
static const struct option long_opts[] = static const struct option long_opts[] =
{ {
@ -206,75 +209,75 @@ static void parse_args(int argc, char **argv, char **device)
"a:c:i:x:dfFhnqrstTXvVpmM", long_opts, NULL)) != -1) { "a:c:i:x:dfFhnqrstTXvVpmM", long_opts, NULL)) != -1) {
switch (c) { switch (c) {
case 'a': case 'a':
a_option = 1; ctl->a_option = 1;
if (!strcmp(optarg, "0") || !strcmp(optarg, "off")) if (!strcmp(optarg, "0") || !strcmp(optarg, "off"))
a_arg = 0; ctl->a_arg = 0;
else if (!strcmp(optarg, "1") || !strcmp(optarg, "on")) else if (!strcmp(optarg, "1") || !strcmp(optarg, "on"))
a_arg = 1; ctl->a_arg = 1;
else else
errx(EXIT_FAILURE, _("invalid argument to --auto/-a option")); errx(EXIT_FAILURE, _("invalid argument to --auto/-a option"));
break; break;
case 'c': case 'c':
c_option = 1; ctl->c_option = 1;
c_arg = strtoul_or_err(optarg, _("invalid argument to --changerslot/-c option")); ctl->c_arg = strtoul_or_err(optarg, _("invalid argument to --changerslot/-c option"));
break; break;
case 'x': case 'x':
x_option = 1; ctl->x_option = 1;
x_arg = strtoul_or_err(optarg, _("invalid argument to --cdspeed/-x option")); ctl->x_arg = strtoul_or_err(optarg, _("invalid argument to --cdspeed/-x option"));
break; break;
case 'd': case 'd':
d_option = 1; ctl->d_option = 1;
break; break;
case 'f': case 'f':
f_option = 1; ctl->f_option = 1;
break; break;
case 'F': case 'F':
F_option = 1; ctl->F_option = 1;
break; break;
case 'h': case 'h':
usage(stdout); usage(stdout);
break; break;
case 'i': case 'i':
i_option = 1; ctl->i_option = 1;
if (!strcmp(optarg, "0") || !strcmp(optarg, "off")) if (!strcmp(optarg, "0") || !strcmp(optarg, "off"))
i_arg = 0; ctl->i_arg = 0;
else if (!strcmp(optarg, "1") || !strcmp(optarg, "on")) else if (!strcmp(optarg, "1") || !strcmp(optarg, "on"))
i_arg = 1; ctl->i_arg = 1;
else else
errx(EXIT_FAILURE, _("invalid argument to --manualeject/-i option")); errx(EXIT_FAILURE, _("invalid argument to --manualeject/-i option"));
break; break;
case 'm': case 'm':
m_option = 1; ctl->m_option = 1;
break; break;
case 'M': case 'M':
M_option = 1; ctl->M_option = 1;
break; break;
case 'n': case 'n':
n_option = 1; ctl->n_option = 1;
break; break;
case 'p': case 'p':
p_option = 1; ctl->p_option = 1;
break; break;
case 'q': case 'q':
q_option = 1; ctl->q_option = 1;
break; break;
case 'r': case 'r':
r_option = 1; ctl->r_option = 1;
break; break;
case 's': case 's':
s_option = 1; ctl->s_option = 1;
break; break;
case 't': case 't':
t_option = 1; ctl->t_option = 1;
break; break;
case 'T': case 'T':
T_option = 1; ctl->T_option = 1;
break; break;
case 'X': case 'X':
X_option = 1; ctl->X_option = 1;
break; break;
case 'v': case 'v':
v_option = 1; ctl->v_option = 1;
break; break;
case 'V': case 'V':
printf(UTIL_LINUX_VERSION); printf(UTIL_LINUX_VERSION);
@ -292,7 +295,7 @@ static void parse_args(int argc, char **argv, char **device)
errx(EXIT_FAILURE, _("too many arguments")); errx(EXIT_FAILURE, _("too many arguments"));
if ((argc - optind) == 1) if ((argc - optind) == 1)
*device = xstrdup(argv[optind]); ctl->device = xstrdup(argv[optind]);
} }
/* /*
@ -323,15 +326,15 @@ static char *find_device(const char *name)
} }
/* Set or clear auto-eject mode. */ /* Set or clear auto-eject mode. */
static void auto_eject(int fd, int on) static void auto_eject(const struct eject_control *ctl)
{ {
int status = -1; int status = -1;
#if defined(CDROM_SET_OPTIONS) && defined(CDROM_CLEAR_OPTIONS) #if defined(CDROM_SET_OPTIONS) && defined(CDROM_CLEAR_OPTIONS)
if (on) if (ctl->a_arg)
status = ioctl(fd, CDROM_SET_OPTIONS, CDO_AUTO_EJECT); status = ioctl(ctl->fd, CDROM_SET_OPTIONS, CDO_AUTO_EJECT);
else else
status = ioctl(fd, CDROM_CLEAR_OPTIONS, CDO_AUTO_EJECT); status = ioctl(ctl->fd, CDROM_CLEAR_OPTIONS, CDO_AUTO_EJECT);
#else #else
errno = ENOSYS; errno = ENOSYS;
#endif #endif
@ -350,12 +353,12 @@ static void auto_eject(int fd, int on)
* EBUSY Attempt to unlock when multiple users * EBUSY Attempt to unlock when multiple users
* have the drive open and not CAP_SYS_ADMIN * have the drive open and not CAP_SYS_ADMIN
*/ */
static void manual_eject(int fd, int on) static void manual_eject(const struct eject_control *ctl)
{ {
if (ioctl(fd, CDROM_LOCKDOOR, on) < 0) if (ioctl(ctl->fd, CDROM_LOCKDOOR, ctl->i_arg) < 0)
err(EXIT_FAILURE, _("CD-ROM lock door command failed")); err(EXIT_FAILURE, _("CD-ROM lock door command failed"));
if (on) if (ctl->i_arg)
info(_("CD-Drive may NOT be ejected with device button")); info(_("CD-Drive may NOT be ejected with device button"));
else else
info(_("CD-Drive may be ejected with device button")); info(_("CD-Drive may be ejected with device button"));
@ -365,14 +368,14 @@ static void manual_eject(int fd, int on)
* Changer select. CDROM_SELECT_DISC is preferred, older kernels used * Changer select. CDROM_SELECT_DISC is preferred, older kernels used
* CDROMLOADFROMSLOT. * CDROMLOADFROMSLOT.
*/ */
static void changer_select(int fd, int slot) static void changer_select(const struct eject_control *ctl)
{ {
#ifdef CDROM_SELECT_DISC #ifdef CDROM_SELECT_DISC
if (ioctl(fd, CDROM_SELECT_DISC, slot) < 0) if (ioctl(ctl->fd, CDROM_SELECT_DISC, ctl->c_arg) < 0)
err(EXIT_FAILURE, _("CD-ROM select disc command failed")); err(EXIT_FAILURE, _("CD-ROM select disc command failed"));
#elif defined CDROMLOADFROMSLOT #elif defined CDROMLOADFROMSLOT
if (ioctl(fd, CDROMLOADFROMSLOT, slot) != 0) if (ioctl(ctl->fd, CDROMLOADFROMSLOT, ctl->c_arg) != 0)
err(EXIT_FAILURE, _("CD-ROM load from slot command failed")); err(EXIT_FAILURE, _("CD-ROM load from slot command failed"));
#else #else
warnx(_("IDE/ATAPI CD-ROM changer not supported by this kernel\n") ); warnx(_("IDE/ATAPI CD-ROM changer not supported by this kernel\n") );
@ -485,10 +488,10 @@ static void toggle_tray(int fd)
* Thanks to Roland Krivanek (krivanek@fmph.uniba.sk) * Thanks to Roland Krivanek (krivanek@fmph.uniba.sk)
* http://dmpc.dbp.fmph.uniba.sk/~krivanek/cdrom_speed/ * http://dmpc.dbp.fmph.uniba.sk/~krivanek/cdrom_speed/
*/ */
static void select_speed(int fd, int speed) static void select_speed(const struct eject_control *ctl)
{ {
#ifdef CDROM_SELECT_SPEED #ifdef CDROM_SELECT_SPEED
if (ioctl(fd, CDROM_SELECT_SPEED, speed) != 0) if (ioctl(ctl->fd, CDROM_SELECT_SPEED, ctl->x_arg) != 0)
err(EXIT_FAILURE, _("CD-ROM select speed command failed")); err(EXIT_FAILURE, _("CD-ROM select speed command failed"));
#else #else
warnx(_("CD-ROM select speed command not supported by this kernel")); warnx(_("CD-ROM select speed command not supported by this kernel"));
@ -557,22 +560,22 @@ static int read_speed(const char *devname)
/* /*
* List Speed of CD-ROM drive. * List Speed of CD-ROM drive.
*/ */
static void list_speeds(const char *name, int fd) static void list_speeds(struct eject_control *ctl)
{ {
#ifdef CDROM_SELECT_SPEED #ifdef CDROM_SELECT_SPEED
int max_speed, curr_speed = 0, prev_speed; int max_speed, curr_speed = 0;
select_speed(fd, 0); select_speed(ctl);
max_speed = read_speed(name); max_speed = read_speed(ctl->device);
while (curr_speed < max_speed) { while (curr_speed < max_speed) {
prev_speed = curr_speed; ctl->x_arg = curr_speed + 1;
select_speed(fd, prev_speed + 1); select_speed(ctl);
curr_speed = read_speed(name); curr_speed = read_speed(ctl->device);
if (curr_speed > prev_speed) if (ctl->x_arg < curr_speed)
printf("%d ", curr_speed); printf("%d ", curr_speed);
else else
curr_speed = prev_speed + 1; curr_speed = ctl->x_arg + 1;
} }
printf("\n"); printf("\n");
@ -584,7 +587,7 @@ static void list_speeds(const char *name, int fd)
/* /*
* Eject using SCSI SG_IO commands. Return 1 if successful, 0 otherwise. * Eject using SCSI SG_IO commands. Return 1 if successful, 0 otherwise.
*/ */
static int eject_scsi(int fd) static int eject_scsi(const struct eject_control *ctl)
{ {
int status, k; int status, k;
sg_io_hdr_t io_hdr; sg_io_hdr_t io_hdr;
@ -594,8 +597,8 @@ static int eject_scsi(int fd)
unsigned char inqBuff[2]; unsigned char inqBuff[2];
unsigned char sense_buffer[32]; unsigned char sense_buffer[32];
if ((ioctl(fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) { if ((ioctl(ctl->fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
verbose(_("not an sg device, or old sg driver")); verbose(ctl, _("not an sg device, or old sg driver"));
return 0; return 0;
} }
@ -610,12 +613,12 @@ static int eject_scsi(int fd)
io_hdr.timeout = 10000; io_hdr.timeout = 10000;
io_hdr.cmdp = allowRmBlk; io_hdr.cmdp = allowRmBlk;
status = ioctl(fd, SG_IO, (void *)&io_hdr); status = ioctl(ctl->fd, SG_IO, (void *)&io_hdr);
if (status < 0 || io_hdr.host_status || io_hdr.driver_status) if (status < 0 || io_hdr.host_status || io_hdr.driver_status)
return 0; return 0;
io_hdr.cmdp = startStop1Blk; io_hdr.cmdp = startStop1Blk;
status = ioctl(fd, SG_IO, (void *)&io_hdr); status = ioctl(ctl->fd, SG_IO, (void *)&io_hdr);
if (status < 0 || io_hdr.host_status) if (status < 0 || io_hdr.host_status)
return 0; return 0;
@ -630,12 +633,12 @@ static int eject_scsi(int fd)
return 0; return 0;
io_hdr.cmdp = startStop2Blk; io_hdr.cmdp = startStop2Blk;
status = ioctl(fd, SG_IO, (void *)&io_hdr); status = ioctl(ctl->fd, SG_IO, (void *)&io_hdr);
if (status < 0 || io_hdr.host_status || io_hdr.driver_status) if (status < 0 || io_hdr.host_status || io_hdr.driver_status)
return 0; return 0;
/* force kernel to reread partition table when new disc inserted */ /* force kernel to reread partition table when new disc inserted */
ioctl(fd, BLKRRPART); ioctl(ctl->fd, BLKRRPART);
return 1; return 1;
} }
@ -660,14 +663,14 @@ static int eject_tape(int fd)
/* umount a device. */ /* umount a device. */
static void umount_one(const char *name) static void umount_one(const struct eject_control *ctl, const char *name)
{ {
int status; int status;
if (!name) if (!name)
return; return;
verbose(_("%s: unmounting"), name); verbose(ctl, _("%s: unmounting"), name);
switch (fork()) { switch (fork()) {
case 0: /* child */ case 0: /* child */
@ -677,7 +680,7 @@ static void umount_one(const char *name)
if (setuid(getuid()) < 0) if (setuid(getuid()) < 0)
err(EXIT_FAILURE, _("cannot set user id")); err(EXIT_FAILURE, _("cannot set user id"));
if (p_option) if (ctl->p_option)
execl("/bin/umount", "/bin/umount", name, "-n", NULL); execl("/bin/umount", "/bin/umount", name, "-n", NULL);
else else
execl("/bin/umount", "/bin/umount", name, NULL); execl("/bin/umount", "/bin/umount", name, NULL);
@ -701,51 +704,49 @@ static void umount_one(const char *name)
} }
/* Open a device file. */ /* Open a device file. */
static int open_device(const char *name) static void open_device(struct eject_control *ctl)
{ {
int fd = open(name, O_RDWR|O_NONBLOCK); ctl->fd = open(ctl->device, O_RDWR | O_NONBLOCK);
if (ctl->fd < 0)
if (fd < 0) ctl->fd = open(ctl->device, O_RDONLY | O_NONBLOCK);
fd = open(name, O_RDONLY|O_NONBLOCK); if (ctl->fd == -1)
if (fd == -1) err(EXIT_FAILURE, _("cannot open %s"), ctl->device);
err(EXIT_FAILURE, _("cannot open %s"), name);
return fd;
} }
/* /*
* See if device has been mounted by looking in mount table. If so, set * See if device has been mounted by looking in mount table. If so, set
* device name and mount point name, and return 1, otherwise return 0. * device name and mount point name, and return 1, otherwise return 0.
*/ */
static int device_get_mountpoint(char **devname, char **mnt) static int device_get_mountpoint(struct eject_control *ctl, char **devname, char **mnt)
{ {
struct libmnt_fs *fs; struct libmnt_fs *fs;
int rc; int rc;
*mnt = NULL; *mnt = NULL;
if (!mtab) { if (!ctl->mtab) {
struct libmnt_cache *cache; struct libmnt_cache *cache;
mtab = mnt_new_table(); ctl->mtab = mnt_new_table();
if (!mtab) if (!ctl->mtab)
err(EXIT_FAILURE, _("failed to initialize libmount table")); err(EXIT_FAILURE, _("failed to initialize libmount table"));
cache = mnt_new_cache(); cache = mnt_new_cache();
mnt_table_set_cache(mtab, cache); mnt_table_set_cache(ctl->mtab, cache);
mnt_unref_cache(cache); mnt_unref_cache(cache);
if (p_option) if (ctl->p_option)
rc = mnt_table_parse_file(mtab, _PATH_PROC_MOUNTINFO); rc = mnt_table_parse_file(ctl->mtab, _PATH_PROC_MOUNTINFO);
else else
rc = mnt_table_parse_mtab(mtab, NULL); rc = mnt_table_parse_mtab(ctl->mtab, NULL);
if (rc) if (rc)
err(EXIT_FAILURE, _("failed to parse mount table")); err(EXIT_FAILURE, _("failed to parse mount table"));
} }
fs = mnt_table_find_source(mtab, *devname, MNT_ITER_BACKWARD); fs = mnt_table_find_source(ctl->mtab, *devname, MNT_ITER_BACKWARD);
if (!fs) { if (!fs) {
/* maybe 'devname' is mountpoint rather than a real device */ /* maybe 'devname' is mountpoint rather than a real device */
fs = mnt_table_find_target(mtab, *devname, MNT_ITER_BACKWARD); fs = mnt_table_find_target(ctl->mtab, *devname, MNT_ITER_BACKWARD);
if (fs) { if (fs) {
free(*devname); free(*devname);
*devname = xstrdup(mnt_fs_get_source(fs)); *devname = xstrdup(mnt_fs_get_source(fs));
@ -774,7 +775,7 @@ static char *get_disk_devname(const char *device)
return st.st_rdev == diskno ? NULL : find_device(diskname); return st.st_rdev == diskno ? NULL : find_device(diskname);
} }
static int umount_partitions(const char *disk, int checkonly) static int umount_partitions(struct eject_control *ctl)
{ {
struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY; struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY;
dev_t devno; dev_t devno;
@ -782,7 +783,7 @@ static int umount_partitions(const char *disk, int checkonly)
struct dirent *d; struct dirent *d;
int count = 0; int count = 0;
devno = sysfs_devname_to_devno(disk, NULL); devno = sysfs_devname_to_devno(ctl->device, NULL);
if (sysfs_init(&cxt, devno, NULL) != 0) if (sysfs_init(&cxt, devno, NULL) != 0)
return 0; return 0;
@ -795,14 +796,14 @@ static int umount_partitions(const char *disk, int checkonly)
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue; continue;
if (sysfs_is_partition_dirent(dir, d, disk)) { if (sysfs_is_partition_dirent(dir, d, ctl->device)) {
char *mnt = NULL; char *mnt = NULL;
char *dev = find_device(d->d_name); char *dev = find_device(d->d_name);
if (dev && device_get_mountpoint(&dev, &mnt) == 0) { if (dev && device_get_mountpoint(ctl, &dev, &mnt) == 0) {
verbose(_("%s: mounted on %s"), dev, mnt); verbose(ctl, _("%s: mounted on %s"), dev, mnt);
if (!checkonly) if (!ctl->M_option)
umount_one(mnt); umount_one(ctl, mnt);
count++; count++;
} }
free(dev); free(dev);
@ -881,7 +882,7 @@ static char *get_subsystem(char *chain, char *buf, size_t bufsz)
return NULL; return NULL;
} }
static int is_hotpluggable(const char* device) static int is_hotpluggable(const struct eject_control *ctl)
{ {
struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY; struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY;
char devchain[PATH_MAX]; char devchain[PATH_MAX];
@ -891,13 +892,13 @@ static int is_hotpluggable(const char* device)
ssize_t sz; ssize_t sz;
char *sub; char *sub;
devno = sysfs_devname_to_devno(device, NULL); devno = sysfs_devname_to_devno(ctl->device, NULL);
if (sysfs_init(&cxt, devno, NULL) != 0) if (sysfs_init(&cxt, devno, NULL) != 0)
return 0; return 0;
/* check /sys/dev/block/<maj>:<min>/removable attribute */ /* check /sys/dev/block/<maj>:<min>/removable attribute */
if (sysfs_read_int(&cxt, "removable", &rc) == 0 && rc == 1) { if (sysfs_read_int(&cxt, "removable", &rc) == 0 && rc == 1) {
verbose(_("%s: is removable device"), device); verbose(ctl, _("%s: is removable device"), ctl->device);
goto done; goto done;
} }
@ -916,8 +917,8 @@ static int is_hotpluggable(const char* device)
while ((sub = get_subsystem(devchain, subbuf, sizeof(subbuf)))) { while ((sub = get_subsystem(devchain, subbuf, sizeof(subbuf)))) {
rc = is_hotpluggable_subsystem(sub); rc = is_hotpluggable_subsystem(sub);
if (rc) { if (rc) {
verbose(_("%s: connected by hotplug subsystem: %s"), verbose(ctl, _("%s: connected by hotplug subsystem: %s"),
device, sub); ctl->device, sub);
break; break;
} }
} }
@ -929,20 +930,18 @@ done:
/* handle -x option */ /* handle -x option */
static void set_device_speed(char *name) static void set_device_speed(struct eject_control *ctl)
{ {
int fd; if (!ctl->x_option)
if (!x_option)
return; return;
if (x_arg == 0) if (ctl->x_arg == 0)
verbose(_("setting CD-ROM speed to auto")); verbose(ctl, _("setting CD-ROM speed to auto"));
else else
verbose(_("setting CD-ROM speed to %ldX"), x_arg); verbose(ctl, _("setting CD-ROM speed to %ldX"), ctl->x_arg);
fd = open_device(name); open_device(ctl);
select_speed(fd, x_arg); select_speed(ctl);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
@ -950,11 +949,10 @@ static void set_device_speed(char *name)
/* main program */ /* main program */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
char *device = NULL;
char *disk = NULL; char *disk = NULL;
char *mountpoint = NULL; char *mountpoint = NULL;
int worked = 0; /* set to 1 when successfully ejected */ int worked = 0; /* set to 1 when successfully ejected */
int fd; /* file descriptor for device */ struct eject_control ctl = { 0 };
setlocale(LC_ALL,""); setlocale(LC_ALL,"");
bindtextdomain(PACKAGE, LOCALEDIR); bindtextdomain(PACKAGE, LOCALEDIR);
@ -962,118 +960,118 @@ int main(int argc, char **argv)
atexit(close_stdout); atexit(close_stdout);
/* parse the command line arguments */ /* parse the command line arguments */
parse_args(argc, argv, &device); parse_args(&ctl, argc, argv);
/* handle -d option */ /* handle -d option */
if (d_option) { if (ctl.d_option) {
info(_("default device: `%s'"), EJECT_DEFAULT_DEVICE); info(_("default device: `%s'"), EJECT_DEFAULT_DEVICE);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
if (!device) { if (!ctl.device) {
device = mnt_resolve_path(EJECT_DEFAULT_DEVICE, NULL); ctl.device = mnt_resolve_path(EJECT_DEFAULT_DEVICE, NULL);
verbose(_("using default device `%s'"), device); verbose(&ctl, _("using default device `%s'"), ctl.device);
} else { } else {
char *p; char *p;
if (device[strlen(device)-1] == '/') if (ctl.device[strlen(ctl.device) - 1] == '/')
device[strlen(device)-1] = '\0'; ctl.device[strlen(ctl.device) - 1] = '\0';
/* figure out full device or mount point name */ /* figure out full device or mount point name */
p = find_device(device); p = find_device(ctl.device);
if (p) if (p)
free(device); free(ctl.device);
else else
p = device; p = ctl.device;
device = mnt_resolve_spec(p, NULL); ctl.device = mnt_resolve_spec(p, NULL);
free(p); free(p);
} }
if (!device) if (!ctl.device)
errx(EXIT_FAILURE, _("%s: unable to find device"), device); errx(EXIT_FAILURE, _("%s: unable to find device"), ctl.device);
verbose(_("device name is `%s'"), device); verbose(&ctl, _("device name is `%s'"), ctl.device);
device_get_mountpoint(&device, &mountpoint); device_get_mountpoint(&ctl, &ctl.device, &mountpoint);
if (mountpoint) if (mountpoint)
verbose(_("%s: mounted on %s"), device, mountpoint); verbose(&ctl, _("%s: mounted on %s"), ctl.device, mountpoint);
else else
verbose(_("%s: not mounted"), device); verbose(&ctl, _("%s: not mounted"), ctl.device);
disk = get_disk_devname(device); disk = get_disk_devname(ctl.device);
if (disk) { if (disk) {
verbose(_("%s: disc device: %s (disk device will be used for eject)"), device, disk); verbose(&ctl, _("%s: disc device: %s (disk device will be used for eject)"), ctl.device, disk);
free(device); free(ctl.device);
device = disk; ctl.device = disk;
disk = NULL; disk = NULL;
} else { } else {
struct stat st; struct stat st;
if (stat(device, &st) != 0 || !S_ISBLK(st.st_mode)) if (stat(ctl.device, &st) != 0 || !S_ISBLK(st.st_mode))
errx(EXIT_FAILURE, _("%s: not found mountpoint or device " errx(EXIT_FAILURE, _("%s: not found mountpoint or device "
"with the given name"), device); "with the given name"), ctl.device);
verbose(_("%s: is whole-disk device"), device); verbose(&ctl, _("%s: is whole-disk device"), ctl.device);
} }
if (F_option == 0 && is_hotpluggable(device) == 0) if (ctl.F_option == 0 && is_hotpluggable(&ctl) == 0)
errx(EXIT_FAILURE, _("%s: is not hot-pluggable device"), device); errx(EXIT_FAILURE, _("%s: is not hot-pluggable device"), ctl.device);
/* handle -n option */ /* handle -n option */
if (n_option) { if (ctl.n_option) {
info(_("device is `%s'"), device); info(_("device is `%s'"), ctl.device);
verbose(_("exiting due to -n/--noop option")); verbose(&ctl, _("exiting due to -n/--noop option"));
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* handle -i option */ /* handle -i option */
if (i_option) { if (ctl.i_option) {
fd = open_device(device); open_device(&ctl);
manual_eject(fd, i_arg); manual_eject(&ctl);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* handle -a option */ /* handle -a option */
if (a_option) { if (ctl.a_option) {
if (a_arg) if (ctl.a_arg)
verbose(_("%s: enabling auto-eject mode"), device); verbose(&ctl, _("%s: enabling auto-eject mode"), ctl.device);
else else
verbose(_("%s: disabling auto-eject mode"), device); verbose(&ctl, _("%s: disabling auto-eject mode"), ctl.device);
fd = open_device(device); open_device(&ctl);
auto_eject(fd, a_arg); auto_eject(&ctl);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* handle -t option */ /* handle -t option */
if (t_option) { if (ctl.t_option) {
verbose(_("%s: closing tray"), device); verbose(&ctl, _("%s: closing tray"), ctl.device);
fd = open_device(device); open_device(&ctl);
close_tray(fd); close_tray(ctl.fd);
set_device_speed(device); set_device_speed(&ctl);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* handle -T option */ /* handle -T option */
if (T_option) { if (ctl.T_option) {
verbose(_("%s: toggling tray"), device); verbose(&ctl, _("%s: toggling tray"), ctl.device);
fd = open_device(device); open_device(&ctl);
toggle_tray(fd); toggle_tray(ctl.fd);
set_device_speed(device); set_device_speed(&ctl);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* handle -X option */ /* handle -X option */
if (X_option) { if (ctl.X_option) {
verbose(_("%s: listing CD-ROM speed"), device); verbose(&ctl, _("%s: listing CD-ROM speed"), ctl.device);
fd = open_device(device); open_device(&ctl);
list_speeds(device, fd); list_speeds(&ctl);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* handle -x option only */ /* handle -x option only */
if (!c_option) if (!ctl.c_option)
set_device_speed(device); set_device_speed(&ctl);
/* /*
@ -1081,62 +1079,62 @@ int main(int argc, char **argv)
* mountpoint if -M is specified, otherwise print error of another * mountpoint if -M is specified, otherwise print error of another
* partition is mounted. * partition is mounted.
*/ */
if (!m_option) { if (!ctl.m_option) {
int ct = umount_partitions(device, M_option); int ct = umount_partitions(&ctl);
if (ct == 0 && mountpoint) if (ct == 0 && mountpoint)
umount_one(mountpoint); /* probably whole-device */ umount_one(&ctl, mountpoint); /* probably whole-device */
if (M_option) { if (ctl.M_option) {
if (ct == 1 && mountpoint) if (ct == 1 && mountpoint)
umount_one(mountpoint); umount_one(&ctl, mountpoint);
else if (ct) else if (ct)
errx(EXIT_FAILURE, _("error: %s: device in use"), device); errx(EXIT_FAILURE, _("error: %s: device in use"), ctl.device);
} }
} }
/* handle -c option */ /* handle -c option */
if (c_option) { if (ctl.c_option) {
verbose(_("%s: selecting CD-ROM disc #%ld"), device, c_arg); verbose(&ctl, _("%s: selecting CD-ROM disc #%ld"), ctl.device, ctl.c_arg);
fd = open_device(device); open_device(&ctl);
changer_select(fd, c_arg); changer_select(&ctl);
set_device_speed(device); set_device_speed(&ctl);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* if user did not specify type of eject, try all four methods */ /* if user did not specify type of eject, try all four methods */
if (r_option + s_option + f_option + q_option == 0) if (ctl.r_option + ctl.s_option + ctl.f_option + ctl.q_option == 0)
r_option = s_option = f_option = q_option = 1; ctl.r_option = ctl.s_option = ctl.f_option = ctl.q_option = 1;
/* open device */ /* open device */
fd = open_device(device); open_device(&ctl);
/* try various methods of ejecting until it works */ /* try various methods of ejecting until it works */
if (r_option) { if (ctl.r_option) {
verbose(_("%s: trying to eject using CD-ROM eject command"), device); verbose(&ctl, _("%s: trying to eject using CD-ROM eject command"), ctl.device);
worked = eject_cdrom(fd); worked = eject_cdrom(ctl.fd);
verbose(worked ? _("CD-ROM eject command succeeded") : verbose(&ctl, worked ? _("CD-ROM eject command succeeded") :
_("CD-ROM eject command failed")); _("CD-ROM eject command failed"));
} }
if (s_option && !worked) { if (ctl.s_option && !worked) {
verbose(_("%s: trying to eject using SCSI commands"), device); verbose(&ctl, _("%s: trying to eject using SCSI commands"), ctl.device);
worked = eject_scsi(fd); worked = eject_scsi(&ctl);
verbose(worked ? _("SCSI eject succeeded") : verbose(&ctl, worked ? _("SCSI eject succeeded") :
_("SCSI eject failed")); _("SCSI eject failed"));
} }
if (f_option && !worked) { if (ctl.f_option && !worked) {
verbose(_("%s: trying to eject using floppy eject command"), device); verbose(&ctl, _("%s: trying to eject using floppy eject command"), ctl.device);
worked = eject_floppy(fd); worked = eject_floppy(ctl.fd);
verbose(worked ? _("floppy eject command succeeded") : verbose(&ctl, worked ? _("floppy eject command succeeded") :
_("floppy eject command failed")); _("floppy eject command failed"));
} }
if (q_option && !worked) { if (ctl.q_option && !worked) {
verbose(_("%s: trying to eject using tape offline command"), device); verbose(&ctl, _("%s: trying to eject using tape offline command"), ctl.device);
worked = eject_tape(fd); worked = eject_tape(ctl.fd);
verbose(worked ? _("tape offline command succeeded") : verbose(&ctl, worked ? _("tape offline command succeeded") :
_("tape offline command failed")); _("tape offline command failed"));
} }
@ -1144,11 +1142,11 @@ int main(int argc, char **argv)
errx(EXIT_FAILURE, _("unable to eject")); errx(EXIT_FAILURE, _("unable to eject"));
/* cleanup */ /* cleanup */
close(fd); close(ctl.fd);
free(device); free(ctl.device);
free(mountpoint); free(mountpoint);
mnt_unref_table(mtab); mnt_unref_table(ctl.mtab);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -1,180 +0,0 @@
/*
* kd.c - KDGHWCLK stuff, possibly m68k only, likely to be deprecated
*/
#include "hwclock.h"
#ifdef __m68k__
# include <fcntl.h>
# include <sysexits.h>
# include <sys/ioctl.h>
# include <unistd.h>
# include "nls.h"
/* Get defines for KDGHWCLK and KDSHWCLK (m68k) */
# include <linux/kd.h>
/* Even on m68k, if KDGHWCLK (antique) is not defined, don't build this */
#endif
#if !defined(__m68k__) || !defined(KDGHWCLK)
#include <stddef.h>
struct clock_ops *probe_for_kd_clock(void)
{
return NULL;
}
#else /* __m68k__ && KDGHWCLK */
/* Opened by probe_for_kd_clock(), and never closed. */
static int con_fd = -1;
static char *con_fd_filename; /* usually "/dev/tty1" */
/*
* Wait for the top of a clock tick by calling KDGHWCLK in a busy loop until
* we see it.
*/
static int synchronize_to_clock_tick_kd(void)
{
/* The time when we were called (and started waiting) */
struct hwclk_time start_time, nowtime;
struct timeval begin, now;
if (debug)
printf(_("Waiting in loop for time from KDGHWCLK to change\n"));
if (ioctl(con_fd, KDGHWCLK, &start_time) == -1) {
warn(_("KDGHWCLK ioctl to read time failed"));
return 3;
}
/*
* Wait for change. Should be within a second, but in case something
* weird happens, we have a time limit (1.5s) on this loop to reduce
* the impact of this failure.
*/
gettimeofday(&begin, NULL);
do {
/*
* Added by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
*
* "The culprit is the fast loop with KDGHWCLK ioctls. It
* seems the kernel gets confused by those on Amigas with
* A2000 RTCs and simply hangs after some time. Inserting a
* sleep helps."
*/
xusleep(1);
if (ioctl(con_fd, KDGHWCLK, &nowtime) == -1) {
warn(_("KDGHWCLK ioctl to read time failed in loop"));
return 3;
}
if (start_time.tm_sec != nowtime.tm_sec)
break;
gettimeofday(&now, NULL);
if (time_diff(now, begin) > 1.5) {
warnx(_("Timed out waiting for time change."));
return 2;
}
} while (1);
return 0;
}
/*
* Read the hardware clock and return the current time via <tm> argument.
* Use ioctls to /dev/tty1 on what we assume is an m68k machine.
*
* Note that we don't use /dev/console here. That might be a serial console.
*/
static int read_hardware_clock_kd(struct tm *tm)
{
struct hwclk_time t;
if (ioctl(con_fd, KDGHWCLK, &t) == -1) {
warn(_("ioctl() failed to read time from %s"),
con_fd_filename);
hwclock_exit(EX_IOERR);
}
tm->tm_sec = t.sec;
tm->tm_min = t.min;
tm->tm_hour = t.hour;
tm->tm_mday = t.day;
tm->tm_mon = t.mon;
tm->tm_year = t.year;
tm->tm_wday = t.wday;
tm->tm_isdst = -1; /* Don't know if it's Daylight Savings Time */
return 0;
}
/*
* Set the Hardware Clock to the time <new_broken_time>. Use ioctls to
* /dev/tty1 on what we assume is an m68k machine.
*
* Note that we don't use /dev/console here. That might be a serial console.
*/
static int set_hardware_clock_kd(const struct tm *new_broken_time)
{
struct hwclk_time t;
t.sec = new_broken_time->tm_sec;
t.min = new_broken_time->tm_min;
t.hour = new_broken_time->tm_hour;
t.day = new_broken_time->tm_mday;
t.mon = new_broken_time->tm_mon;
t.year = new_broken_time->tm_year;
t.wday = new_broken_time->tm_wday;
if (ioctl(con_fd, KDSHWCLK, &t) == -1) {
warn(_("ioctl KDSHWCLK failed"));
hwclock_exit(EX_IOERR);
}
return 0;
}
static int get_permissions_kd(void)
{
return 0;
}
static struct clock_ops kd = {
N_("Using the KDGHWCLK interface to m68k clock."),
get_permissions_kd,
read_hardware_clock_kd,
set_hardware_clock_kd,
synchronize_to_clock_tick_kd,
};
/* return &kd if KDGHWCLK works, NULL otherwise */
struct clock_ops *probe_for_kd_clock()
{
struct clock_ops *ret = NULL;
struct hwclk_time t;
if (con_fd < 0) { /* first time here */
con_fd_filename = "/dev/tty1";
con_fd = open(con_fd_filename, O_RDONLY);
}
if (con_fd < 0) {
/* perhaps they are using devfs? */
con_fd_filename = "/dev/vc/1";
con_fd = open(con_fd_filename, O_RDONLY);
}
if (con_fd < 0) {
/* probably KDGHWCLK exists on m68k only */
warn(_("Can't open /dev/tty1 or /dev/vc/1"));
} else {
if (ioctl(con_fd, KDGHWCLK, &t) == -1) {
if (errno != EINVAL)
warn(_("KDGHWCLK ioctl failed"));
} else
ret = &kd;
}
return ret;
}
#endif /* __m68k__ && KDGHWCLK */

View File

@ -1256,9 +1256,6 @@ static void determine_clock_access_method(const bool user_requests_ISA)
ur = probe_for_rtc_clock(); ur = probe_for_rtc_clock();
#endif #endif
if (!ur)
ur = probe_for_kd_clock();
if (!ur && !user_requests_ISA) if (!ur && !user_requests_ISA)
ur = probe_for_cmos_clock(); ur = probe_for_cmos_clock();

View File

@ -19,7 +19,6 @@ struct clock_ops {
extern struct clock_ops *probe_for_cmos_clock(void); extern struct clock_ops *probe_for_cmos_clock(void);
extern struct clock_ops *probe_for_rtc_clock(void); extern struct clock_ops *probe_for_rtc_clock(void);
extern struct clock_ops *probe_for_kd_clock(void);
typedef int bool; typedef int bool;

View File

@ -40,9 +40,17 @@
#include "closestream.h" #include "closestream.h"
#include "pathnames.h" #include "pathnames.h"
static int quiet; struct mountpoint_control {
char *path;
dev_t dev;
struct stat st;
unsigned int
dev_devno:1,
fs_devno:1,
quiet:1;
};
static int dir_to_device(const char *spec, dev_t *dev) static int dir_to_device(struct mountpoint_control *ctl)
{ {
struct libmnt_table *tb = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO); struct libmnt_table *tb = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO);
struct libmnt_fs *fs; struct libmnt_fs *fs;
@ -54,16 +62,13 @@ static int dir_to_device(const char *spec, dev_t *dev)
* Fallback. Traditional way to detect mountpoints. This way * Fallback. Traditional way to detect mountpoints. This way
* is independent on /proc, but not able to detect bind mounts. * is independent on /proc, but not able to detect bind mounts.
*/ */
struct stat pst, st; struct stat pst;
char buf[PATH_MAX], *cn; char buf[PATH_MAX], *cn;
int len; int len;
if (stat(spec, &st) != 0) cn = mnt_resolve_path(ctl->path, NULL); /* canonicalize */
return -1;
cn = mnt_resolve_path(spec, NULL); /* canonicalize */ len = snprintf(buf, sizeof(buf), "%s/..", cn ? cn : ctl->path);
len = snprintf(buf, sizeof(buf), "%s/..", cn ? cn : spec);
free(cn); free(cn);
if (len < 0 || (size_t) len + 1 > sizeof(buf)) if (len < 0 || (size_t) len + 1 > sizeof(buf))
@ -71,9 +76,9 @@ static int dir_to_device(const char *spec, dev_t *dev)
if (stat(buf, &pst) !=0) if (stat(buf, &pst) !=0)
return -1; return -1;
if ((st.st_dev != pst.st_dev) || if ((ctl->st.st_dev != pst.st_dev) ||
(st.st_dev == pst.st_dev && st.st_ino == pst.st_ino)) { (ctl->st.st_dev == pst.st_dev && ctl->st.st_ino == pst.st_ino)) {
*dev = st.st_dev; ctl->dev = ctl->st.st_dev;
return 0; return 0;
} }
@ -85,9 +90,9 @@ static int dir_to_device(const char *spec, dev_t *dev)
mnt_table_set_cache(tb, cache); mnt_table_set_cache(tb, cache);
mnt_unref_cache(cache); mnt_unref_cache(cache);
fs = mnt_table_find_target(tb, spec, MNT_ITER_BACKWARD); fs = mnt_table_find_target(tb, ctl->path, MNT_ITER_BACKWARD);
if (fs && mnt_fs_get_target(fs)) { if (fs && mnt_fs_get_target(fs)) {
*dev = mnt_fs_get_devno(fs); ctl->dev = mnt_fs_get_devno(fs);
rc = 0; rc = 0;
} }
@ -95,20 +100,14 @@ static int dir_to_device(const char *spec, dev_t *dev)
return rc; return rc;
} }
static int print_devno(const char *devname, struct stat *st) static int print_devno(const struct mountpoint_control *ctl)
{ {
struct stat stbuf; if (!S_ISBLK(ctl->st.st_mode)) {
if (!ctl->quiet)
if (!st && stat(devname, &stbuf) == 0) warnx(_("%s: not a block device"), ctl->path);
st = &stbuf;
if (!st)
return -1;
if (!S_ISBLK(st->st_mode)) {
if (!quiet)
warnx(_("%s: not a block device"), devname);
return -1; return -1;
} }
printf("%u:%u\n", major(st->st_rdev), minor(st->st_rdev)); printf("%u:%u\n", major(ctl->st.st_rdev), minor(ctl->st.st_rdev));
return 0; return 0;
} }
@ -133,9 +132,8 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int c, fs_devno = 0, dev_devno = 0, rc = 0; int c;
char *spec; struct mountpoint_control ctl = { 0 };
struct stat st;
static const struct option longopts[] = { static const struct option longopts[] = {
{ "quiet", 0, 0, 'q' }, { "quiet", 0, 0, 'q' },
@ -157,13 +155,13 @@ int main(int argc, char **argv)
switch(c) { switch(c) {
case 'q': case 'q':
quiet = 1; ctl.quiet = 1;
break; break;
case 'd': case 'd':
fs_devno = 1; ctl.fs_devno = 1;
break; break;
case 'x': case 'x':
dev_devno = 1; ctl.dev_devno = 1;
break; break;
case 'h': case 'h':
usage(stdout); usage(stdout);
@ -180,28 +178,23 @@ int main(int argc, char **argv)
if (optind + 1 != argc) if (optind + 1 != argc)
usage(stderr); usage(stderr);
spec = argv[optind++]; ctl.path = argv[optind];
if (stat(spec, &st)) { if (stat(ctl.path, &ctl.st)) {
if (!quiet) if (!ctl.quiet)
err(EXIT_FAILURE, "%s", spec); err(EXIT_FAILURE, "%s", ctl.path);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (dev_devno) if (ctl.dev_devno)
rc = print_devno(spec, &st); return print_devno(&ctl) ? EXIT_FAILURE : EXIT_SUCCESS;
else { if (dir_to_device(&ctl)) {
dev_t src; if (!ctl.quiet)
printf(_("%s is not a mountpoint\n"), ctl.path);
if ( dir_to_device(spec, &src)) { return EXIT_FAILURE;
if (!quiet)
printf(_("%s is not a mountpoint\n"), spec);
return EXIT_FAILURE;
}
if (fs_devno)
printf("%u:%u\n", major(src), minor(src));
else if (!quiet)
printf(_("%s is a mountpoint\n"), spec);
} }
if (ctl.fs_devno)
return rc ? EXIT_FAILURE : EXIT_SUCCESS; printf("%u:%u\n", major(ctl.dev), minor(ctl.dev));
else if (!ctl.quiet)
printf(_("%s is a mountpoint\n"), ctl.path);
return EXIT_SUCCESS;
} }

View File

@ -24,8 +24,7 @@
* sparc32 util by Jakub Jelinek (1998, 1999) * sparc32 util by Jakub Jelinek (1998, 1999)
*/ */
#include <syscall.h> #include <sys/personality.h>
#include <linux/personality.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -37,11 +36,14 @@
#include "c.h" #include "c.h"
#include "closestream.h" #include "closestream.h"
#define set_pers(pers) ((long)syscall(SYS_personality, pers)) #ifndef HAVE_PERSONALITY
# include <syscall.h>
# define personality(pers) ((long)syscall(SYS_personality, pers))
#endif
/* Options without equivalent short options */ /* Options without equivalent short options */
enum { enum {
OPT_4GB = CHAR_MAX + 1, OPT_4GB = CHAR_MAX + 1,
OPT_UNAME26 OPT_UNAME26
}; };
@ -52,7 +54,6 @@ enum {
printf(_("Switching on %s.\n"), #_flag); \ printf(_("Switching on %s.\n"), #_flag); \
} while(0) } while(0)
#ifndef UNAME26 #ifndef UNAME26
# define UNAME26 0x0020000 # define UNAME26 0x0020000
#endif #endif
@ -87,301 +88,291 @@ enum {
# define ADDR_LIMIT_3GB 0x8000000 # define ADDR_LIMIT_3GB 0x8000000
#endif #endif
static void __attribute__((__noreturn__)) static void __attribute__((__noreturn__)) show_help(void)
show_help(void)
{ {
fputs(USAGE_HEADER, stdout); fputs(USAGE_HEADER, stdout);
printf(_(" %s%s [options] [program [program arguments]]\n"), printf(_(" %s%s [options] [program [program arguments]]\n"),
program_invocation_short_name, program_invocation_short_name,
!strcmp(program_invocation_short_name, "setarch") ? " <arch>" : ""); !strcmp(program_invocation_short_name, "setarch") ? " <arch>" : "");
fputs(USAGE_OPTIONS, stdout);
fputs(_(" -v, --verbose says what options are being switched on\n"), stdout);
fputs(_(" -R, --addr-no-randomize disables randomization of the virtual address space\n"), stdout);
fputs(_(" -F, --fdpic-funcptrs makes function pointers point to descriptors\n"), stdout);
fputs(_(" -Z, --mmap-page-zero turns on MMAP_PAGE_ZERO\n"), stdout);
fputs(_(" -L, --addr-compat-layout changes the way virtual memory is allocated\n"), stdout);
fputs(_(" -X, --read-implies-exec turns on READ_IMPLIES_EXEC\n"), stdout);
fputs(_(" -B, --32bit turns on ADDR_LIMIT_32BIT\n"), stdout);
fputs(_(" -I, --short-inode turns on SHORT_INODE\n"), stdout);
fputs(_(" -S, --whole-seconds turns on WHOLE_SECONDS\n"), stdout);
fputs(_(" -T, --sticky-timeouts turns on STICKY_TIMEOUTS\n"), stdout);
fputs(_(" -3, --3gb limits the used address space to a maximum of 3 GB\n"), stdout);
fputs(_(" --4gb ignored (for backward compatibility only)\n"), stdout);
fputs(_(" --uname-2.6 turns on UNAME26\n"), stdout);
fputs(_(" --list list settable architectures, and exit\n"), stdout);
fputs(USAGE_SEPARATOR, stdout);
fputs(USAGE_HELP, stdout);
fputs(USAGE_VERSION, stdout);
printf(USAGE_MAN_TAIL("setarch(8)"));
exit(EXIT_SUCCESS);
}
fputs(USAGE_OPTIONS, stdout); static void __attribute__((__noreturn__)) show_usage(const char *s)
fputs(_(" -v, --verbose says what options are being switched on\n"), stdout); {
fputs(_(" -R, --addr-no-randomize disables randomization of the virtual address space\n"), stdout); if (s)
fputs(_(" -F, --fdpic-funcptrs makes function pointers point to descriptors\n"), stdout); errx(EXIT_FAILURE,
fputs(_(" -Z, --mmap-page-zero turns on MMAP_PAGE_ZERO\n"), stdout); _("%s\nTry `%s --help' for more information."), s,
fputs(_(" -L, --addr-compat-layout changes the way virtual memory is allocated\n"), stdout); program_invocation_short_name);
fputs(_(" -X, --read-implies-exec turns on READ_IMPLIES_EXEC\n"), stdout); else
fputs(_(" -B, --32bit turns on ADDR_LIMIT_32BIT\n"), stdout); errx(EXIT_FAILURE, _("Try `%s --help' for more information."),
fputs(_(" -I, --short-inode turns on SHORT_INODE\n"), stdout); program_invocation_short_name);
fputs(_(" -S, --whole-seconds turns on WHOLE_SECONDS\n"), stdout);
fputs(_(" -T, --sticky-timeouts turns on STICKY_TIMEOUTS\n"), stdout);
fputs(_(" -3, --3gb limits the used address space to a maximum of 3 GB\n"), stdout);
fputs(_(" --4gb ignored (for backward compatibility only)\n"), stdout);
fputs(_(" --uname-2.6 turns on UNAME26\n"), stdout);
fputs(_(" --list list settable architectures, and exit\n"), stdout);
fputs(USAGE_SEPARATOR, stdout);
fputs(USAGE_HELP, stdout);
fputs(USAGE_VERSION, stdout);
printf(USAGE_MAN_TAIL("setarch(8)"));
exit(EXIT_SUCCESS);
} }
static void __attribute__((__noreturn__)) static void __attribute__((__noreturn__))
show_usage(const char *s) show_version(void)
{ {
if (s) printf(UTIL_LINUX_VERSION);
errx(EXIT_FAILURE, _("%s\nTry `%s --help' for more information."), s, program_invocation_short_name); exit(EXIT_SUCCESS);
else
errx(EXIT_FAILURE, _("Try `%s --help' for more information."), program_invocation_short_name);
} }
static void __attribute__((__noreturn__)) static int set_arch(const char *pers, unsigned long options, int list)
show_version(void)
{ {
printf(UTIL_LINUX_VERSION); struct utsname un;
exit(EXIT_SUCCESS); int i;
} unsigned long pers_value;
static int struct {
set_arch(const char *pers, unsigned long options, int list) int perval;
{ const char *target_arch, *result_arch;
struct utsname un; } transitions[] = {
int i; {UNAME26, "uname26", NULL},
unsigned long pers_value; {PER_LINUX32, "linux32", NULL},
{PER_LINUX, "linux64", NULL},
struct {
int perval;
const char *target_arch, *result_arch;
} transitions[] = {
{UNAME26, "uname26", NULL},
{PER_LINUX32, "linux32", NULL},
{PER_LINUX, "linux64", NULL},
#if defined(__powerpc__) || defined(__powerpc64__) #if defined(__powerpc__) || defined(__powerpc64__)
#ifdef __BIG_ENDIAN__ # ifdef __BIG_ENDIAN__
{PER_LINUX32, "ppc32", "ppc"}, {PER_LINUX32, "ppc32", "ppc"},
{PER_LINUX32, "ppc", "ppc"}, {PER_LINUX32, "ppc", "ppc"},
{PER_LINUX, "ppc64", "ppc64"}, {PER_LINUX, "ppc64", "ppc64"},
{PER_LINUX, "ppc64pseries", "ppc64"}, {PER_LINUX, "ppc64pseries", "ppc64"},
{PER_LINUX, "ppc64iseries", "ppc64"}, {PER_LINUX, "ppc64iseries", "ppc64"},
#else # else
{PER_LINUX32, "ppc32le", "ppcle"}, PER_LINUX32, "ppc32le", "ppcle"},
{PER_LINUX32, "ppcle", "ppcle"}, PER_LINUX32, "ppcle", "ppcle"},
{PER_LINUX, "ppc64le", "ppc64le"}, PER_LINUX, "ppc64le", "ppc64le"},
#endif # endif
#endif #endif
#if defined(__x86_64__) || defined(__i386__) || defined(__ia64__) #if defined(__x86_64__) || defined(__i386__) || defined(__ia64__)
{PER_LINUX32, "i386", "i386"}, {PER_LINUX32, "i386", "i386"},
{PER_LINUX32, "i486", "i386"}, {PER_LINUX32, "i486", "i386"},
{PER_LINUX32, "i586", "i386"}, {PER_LINUX32, "i586", "i386"},
{PER_LINUX32, "i686", "i386"}, {PER_LINUX32, "i686", "i386"},
{PER_LINUX32, "athlon", "i386"}, {PER_LINUX32, "athlon", "i386"},
#endif #endif
#if defined(__x86_64__) || defined(__i386__) #if defined(__x86_64__) || defined(__i386__)
{PER_LINUX, "x86_64", "x86_64"}, {PER_LINUX, "x86_64", "x86_64"},
#endif #endif
#if defined(__ia64__) || defined(__i386__) #if defined(__ia64__) || defined(__i386__)
{PER_LINUX, "ia64", "ia64"}, {PER_LINUX, "ia64", "ia64"},
#endif #endif
#if defined(__hppa__) #if defined(__hppa__)
{PER_LINUX32, "parisc32", "parisc"}, {PER_LINUX32, "parisc32", "parisc"},
{PER_LINUX32, "parisc", "parisc"}, {PER_LINUX32, "parisc", "parisc"},
{PER_LINUX, "parisc64", "parisc64"}, {PER_LINUX, "parisc64", "parisc64"},
#endif #endif
#if defined(__s390x__) || defined(__s390__) #if defined(__s390x__) || defined(__s390__)
{PER_LINUX32, "s390", "s390"}, {PER_LINUX32, "s390", "s390"},
{PER_LINUX, "s390x", "s390x"}, {PER_LINUX, "s390x", "s390x"},
#endif #endif
#if defined(__sparc64__) || defined(__sparc__) #if defined(__sparc64__) || defined(__sparc__)
{PER_LINUX32, "sparc", "sparc"}, {PER_LINUX32, "sparc", "sparc"},
{PER_LINUX32, "sparc32bash", "sparc"}, {PER_LINUX32, "sparc32bash", "sparc"},
{PER_LINUX32, "sparc32", "sparc"}, {PER_LINUX32, "sparc32", "sparc"},
{PER_LINUX, "sparc64", "sparc64"}, {PER_LINUX, "sparc64", "sparc64"},
#endif #endif
#if defined(__mips64__) || defined(__mips__) #if defined(__mips64__) || defined(__mips__)
{PER_LINUX32, "mips32", "mips"}, {PER_LINUX32, "mips32", "mips"},
{PER_LINUX32, "mips", "mips"}, {PER_LINUX32, "mips", "mips"},
{PER_LINUX, "mips64", "mips64"}, {PER_LINUX, "mips64", "mips64"},
#endif #endif
#if defined(__alpha__) #if defined(__alpha__)
{PER_LINUX, "alpha", "alpha"}, {PER_LINUX, "alpha", "alpha"},
{PER_LINUX, "alphaev5", "alpha"}, {PER_LINUX, "alphaev5", "alpha"},
{PER_LINUX, "alphaev56", "alpha"}, {PER_LINUX, "alphaev56", "alpha"},
{PER_LINUX, "alphaev6", "alpha"}, {PER_LINUX, "alphaev6", "alpha"},
{PER_LINUX, "alphaev67", "alpha"}, {PER_LINUX, "alphaev67", "alpha"},
#endif #endif
{-1, NULL, NULL}, /* place holder, eventually filled up at runtime */ /* place holder, will be filled up at runtime */
{-1, NULL, NULL} {-1, NULL, NULL},
}; {-1, NULL, NULL}
};
/* Add the trivial transition {PER_LINUX, machine, machine} if no such /* Add the trivial transition {PER_LINUX, machine, machine} if no
target_arch is hardcoded yet. */ * such target_arch is hardcoded yet. */
uname(&un); uname(&un);
for (i = 0; transitions[i].perval >= 0; i++) for (i = 0; transitions[i].perval >= 0; i++)
if(!strcmp(un.machine, transitions[i].target_arch)) if (!strcmp(un.machine, transitions[i].target_arch))
break; break;
if (transitions[i].perval < 0) { if (transitions[i].perval < 0) {
unsigned long wrdsz = CHAR_BIT * sizeof(void*); unsigned long wrdsz = CHAR_BIT * sizeof(void *);
if (wrdsz == 32 || wrdsz == 64) { if (wrdsz == 32 || wrdsz == 64) {
transitions[i].perval = wrdsz == 32 ? PER_LINUX32 : PER_LINUX; /* fill up the place holder */
transitions[i].target_arch = un.machine; transitions[i].perval = wrdsz == 32 ? PER_LINUX32 : PER_LINUX;
transitions[i].result_arch = un.machine; transitions[i].target_arch = un.machine;
transitions[i].result_arch = un.machine;
}
} }
} if (list) {
for (i = 0; transitions[i].target_arch != NULL; i++)
if (list) { printf("%s\n", transitions[i].target_arch);
for(i = 0; transitions[i].target_arch != NULL; i++) return 0;
printf("%s\n", transitions[i].target_arch); }
return 0; for (i = 0; transitions[i].perval >= 0; i++)
} if (!strcmp(pers, transitions[i].target_arch))
break;
for(i = 0; transitions[i].perval >= 0; i++) if (transitions[i].perval < 0)
if(!strcmp(pers, transitions[i].target_arch)) errx(EXIT_FAILURE, _("%s: Unrecognized architecture"), pers);
break; pers_value = transitions[i].perval | options;
if (personality(pers_value) == -EINVAL)
if(transitions[i].perval < 0) return 1;
errx(EXIT_FAILURE, _("%s: Unrecognized architecture"), pers); uname(&un);
if (transitions[i].result_arch && strcmp(un.machine, transitions[i].result_arch)) {
pers_value = transitions[i].perval | options; if (strcmp(transitions[i].result_arch, "i386")
if (set_pers(pers_value) == -EINVAL) || (strcmp(un.machine, "i486")
return 1; && strcmp(un.machine, "i586")
&& strcmp(un.machine, "i686")
uname(&un); && strcmp(un.machine, "athlon")))
if(transitions[i].result_arch && errx(EXIT_FAILURE, _("%s: Unrecognized architecture"), pers);
strcmp(un.machine, transitions[i].result_arch)) }
{ return 0;
if(strcmp(transitions[i].result_arch, "i386")
|| (strcmp(un.machine, "i486")
&& strcmp(un.machine, "i586")
&& strcmp(un.machine, "i686")
&& strcmp(un.machine, "athlon")))
errx(EXIT_FAILURE, _("%s: Unrecognized architecture"), pers);
}
return 0;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
const char *p; const char *p;
unsigned long options = 0; unsigned long options = 0;
int verbose = 0; int verbose = 0;
int c; int c;
/* Options --3gb and --4gb are for compatibitity with an old Debian setarch /* Options --3gb and --4gb are for compatibitity with an old
implementation. */ * Debian setarch implementation. */
static const struct option longopts[] = static const struct option longopts[] = {
{ {"help", no_argument, NULL, 'h'},
{ "help", 0, 0, 'h' }, {"version", no_argument, NULL, 'V'},
{ "version", 0, 0, 'V' }, {"verbose", no_argument, NULL, 'v'},
{ "verbose", 0, 0, 'v' }, {"addr-no-randomize", no_argument, NULL, 'R'},
{ "addr-no-randomize", 0, 0, 'R' }, {"fdpic-funcptrs", no_argument, NULL, 'F'},
{ "fdpic-funcptrs", 0, 0, 'F' }, {"mmap-page-zero", no_argument, NULL, 'Z'},
{ "mmap-page-zero", 0, 0, 'Z' }, {"addr-compat-layout", no_argument, NULL, 'L'},
{ "addr-compat-layout", 0, 0, 'L' }, {"read-implies-exec", no_argument, NULL, 'X'},
{ "read-implies-exec", 0, 0, 'X' }, {"32bit", no_argument, NULL, 'B'},
{ "32bit", 0, 0, 'B' }, {"short-inode", no_argument, NULL, 'I'},
{ "short-inode", 0, 0, 'I' }, {"whole-seconds", no_argument, NULL, 'S'},
{ "whole-seconds", 0, 0, 'S' }, {"sticky-timeouts", no_argument, NULL, 'T'},
{ "sticky-timeouts", 0, 0, 'T' }, {"3gb", no_argument, NULL, '3'},
{ "3gb", 0, 0, '3' }, {"4gb", no_argument, NULL, OPT_4GB},
{ "4gb", 0, 0, OPT_4GB }, {"uname-2.6", no_argument, NULL, OPT_UNAME26},
{ "uname-2.6", 0, 0, OPT_UNAME26 }, {NULL, 0, NULL, 0}
{ NULL, 0, 0, 0 } };
};
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR); bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE); textdomain(PACKAGE);
atexit(close_stdout); atexit(close_stdout);
if (argc < 1) if (argc < 1)
show_usage(_("Not enough arguments")); show_usage(_("Not enough arguments"));
p = program_invocation_short_name; p = program_invocation_short_name;
if (!strcmp(p, "setarch")) { if (!strcmp(p, "setarch")) {
argc--; argc--;
if (argc < 1) if (argc < 1)
show_usage(_("Not enough arguments")); show_usage(_("Not enough arguments"));
p = argv[1]; p = argv[1];
argv[1] = argv[0]; /* for getopt_long() to get the program name */ argv[1] = argv[0]; /* for getopt_long() to get the program name */
argv++; argv++;
if (!strcmp(p, "-h") || !strcmp(p, "--help")) if (!strcmp(p, "-h") || !strcmp(p, "--help"))
show_help(); show_help();
else if (!strcmp(p, "-V") || !strcmp(p, "--version")) else if (!strcmp(p, "-V") || !strcmp(p, "--version"))
show_version(); show_version();
else if (!strcmp(p, "--list")) { else if (!strcmp(p, "--list")) {
set_arch(argv[0], 0L, 1); set_arch(argv[0], 0L, 1);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
} }
#if defined(__sparc64__) || defined(__sparc__) #if defined(__sparc64__) || defined(__sparc__)
if (!strcmp(p, "sparc32bash")) { if (!strcmp(p, "sparc32bash")) {
if (set_arch(p, 0L, 0)) if (set_arch(p, 0L, 0))
err(EXIT_FAILURE, _("Failed to set personality to %s"), p); err(EXIT_FAILURE, _("Failed to set personality to %s"), p);
execl("/bin/bash", NULL); execl("/bin/bash", NULL);
err(EXIT_FAILURE, _("failed to execute %s"), "/bin/bash"); err(EXIT_FAILURE, _("failed to execute %s"), "/bin/bash");
} }
#endif #endif
while ((c = getopt_long(argc, argv, "+hVv3BFILRSTXZ", longopts, NULL)) != -1) { while ((c = getopt_long(argc, argv, "+hVv3BFILRSTXZ", longopts, NULL)) != -1) {
switch (c) { switch (c) {
case 'h': case 'h':
show_help(); show_help();
break; break;
case 'V': case 'V':
show_version(); show_version();
break; break;
case 'v': case 'v':
verbose = 1; verbose = 1;
break; break;
case 'R': case 'R':
turn_on(ADDR_NO_RANDOMIZE, options); turn_on(ADDR_NO_RANDOMIZE, options);
break; break;
case 'F': case 'F':
turn_on(FDPIC_FUNCPTRS, options); turn_on(FDPIC_FUNCPTRS, options);
break; break;
case 'Z': case 'Z':
turn_on(MMAP_PAGE_ZERO, options); turn_on(MMAP_PAGE_ZERO, options);
break; break;
case 'L': case 'L':
turn_on(ADDR_COMPAT_LAYOUT, options); turn_on(ADDR_COMPAT_LAYOUT, options);
break; break;
case 'X': case 'X':
turn_on(READ_IMPLIES_EXEC, options); turn_on(READ_IMPLIES_EXEC, options);
break; break;
case 'B': case 'B':
turn_on(ADDR_LIMIT_32BIT, options); turn_on(ADDR_LIMIT_32BIT, options);
break; break;
case 'I': case 'I':
turn_on(SHORT_INODE, options); turn_on(SHORT_INODE, options);
break; break;
case 'S': case 'S':
turn_on(WHOLE_SECONDS, options); turn_on(WHOLE_SECONDS, options);
break; break;
case 'T': case 'T':
turn_on(STICKY_TIMEOUTS, options); turn_on(STICKY_TIMEOUTS, options);
break; break;
case '3': case '3':
turn_on(ADDR_LIMIT_3GB, options); turn_on(ADDR_LIMIT_3GB, options);
break; break;
case OPT_4GB: /* just ignore this one */ case OPT_4GB: /* just ignore this one */
break; break;
case OPT_UNAME26: case OPT_UNAME26:
turn_on(UNAME26, options); turn_on(UNAME26, options);
break; break;
default: default:
show_usage(NULL); show_usage(NULL);
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (set_arch(p, options, 0)) if (set_arch(p, options, 0))
err(EXIT_FAILURE, _("Failed to set personality to %s"), p); err(EXIT_FAILURE, _("Failed to set personality to %s"), p);
/* flush all output streams before exec */ /* flush all output streams before exec */
fflush(NULL); fflush(NULL);
if (!argc) { if (!argc) {
execl("/bin/sh", "-sh", NULL); execl("/bin/sh", "-sh", NULL);
err(EXIT_FAILURE, _("failed to execute %s"), "/bin/sh"); err(EXIT_FAILURE, _("failed to execute %s"), "/bin/sh");
} }
execvp(argv[0], argv); execvp(argv[0], argv);
err(EXIT_FAILURE, "%s", argv[0]); err(EXIT_FAILURE, "%s", argv[0]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }