diff --git a/README b/README index 348f5d4..e55b2dd 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is version 1.1.0 of nfs-utils, the Linux NFS utility package. +This is version 1.2.6 of nfs-utils, the Linux NFS utility package. 0. PROJECT RESOURCES diff --git a/aclocal/libcap.m4 b/aclocal/libcap.m4 index 68a624c..f8a0ed1 100644 --- a/aclocal/libcap.m4 +++ b/aclocal/libcap.m4 @@ -3,7 +3,7 @@ dnl AC_DEFUN([AC_LIBCAP], [ dnl look for prctl - AC_CHECK_FUNC([prctl], , ) + AC_CHECK_FUNC([prctl], , AC_MSG_ERROR([prctl syscall is not available])) AC_ARG_ENABLE([caps], [AS_HELP_STRING([--disable-caps], [Disable capabilities support])]) diff --git a/aclocal/libsqlite3.m4 b/aclocal/libsqlite3.m4 index 73d1e46..8c38993 100644 --- a/aclocal/libsqlite3.m4 +++ b/aclocal/libsqlite3.m4 @@ -29,5 +29,4 @@ AC_DEFUN([AC_SQLITE3_VERS], [ LIBS="$saved_LIBS"]) AC_MSG_RESULT($libsqlite3_cv_is_recent) - AM_CONDITIONAL(CONFIG_SQLITE3, [test "$libsqlite3_cv_is_recent" = "yes"]) ])dnl diff --git a/configure.ac b/configure.ac index 9ba53e2..18ee11a 100644 --- a/configure.ac +++ b/configure.ac @@ -278,8 +278,6 @@ if test "$enable_nfsv4" = yes; then fi fi - AM_CONDITIONAL(CONFIG_NFSDCLD, [test "$enable_nfsdcld" = "yes" ]) - dnl librpcsecgss already has a dependency on libgssapi, dnl but we need to make sure we get the right version if test "$enable_gss" = yes; then @@ -293,6 +291,7 @@ if test "$enable_nfsv41" = yes; then fi dnl enable nfsidmap when its support by libnfsidmap +AM_CONDITIONAL(CONFIG_NFSDCLD, [test "$enable_nfsdcld" = "yes" ]) AM_CONDITIONAL(CONFIG_NFSIDMAP, [test "$ac_cv_header_keyutils_h$ac_cv_lib_nfsidmap_nfs4_owner_to_uid" = "yesyes"]) @@ -393,7 +392,7 @@ AC_CHECK_FUNCS([alarm atexit dup2 fdatasync ftruncate getcwd \ gethostbyaddr gethostbyname gethostname getmntent \ getnameinfo getrpcbyname getifaddrs \ gettimeofday hasmntopt inet_ntoa innetgr memset mkdir pathconf \ - realpath rmdir select socket strcasecmp strchr strdup \ + ppoll realpath rmdir select socket strcasecmp strchr strdup \ strerror strrchr strtol strtoul sigprocmask]) diff --git a/support/include/nfs/debug.h b/support/include/nfs/debug.h index dbec5ba..80a1b1d 100644 --- a/support/include/nfs/debug.h +++ b/support/include/nfs/debug.h @@ -79,6 +79,7 @@ enum { #define NFSDBG_FSCACHE 0x0800 #define NFSDBG_PNFS 0x1000 #define NFSDBG_PNFS_LD 0x2000 +#define NFSDBG_STATE 0x4000 #define NFSDBG_ALL 0xFFFF #endif /* _NFS_DEBUG_H */ diff --git a/support/nsm/file.c b/support/nsm/file.c index 5dd52c1..4711c2c 100644 --- a/support/nsm/file.c +++ b/support/nsm/file.c @@ -338,10 +338,10 @@ nsm_is_default_parentdir(void) * * Returns true if successful, or false if some error occurred. */ +#ifdef HAVE_SYS_CAPABILITY_H static _Bool nsm_clear_capabilities(void) { -#ifdef HAVE_SYS_CAPABILITY_H cap_t caps; caps = cap_from_text("cap_net_bind_service=ep"); @@ -357,10 +357,60 @@ nsm_clear_capabilities(void) } (void)cap_free(caps); -#endif return true; } +#define CAP_BOUND_PROCFILE "/proc/sys/kernel/cap-bound" +static _Bool +prune_bounding_set(void) +{ +#ifdef PR_CAPBSET_DROP + int ret; + unsigned long i; + struct stat st; + + /* + * Prior to kernel 2.6.25, the capabilities bounding set was a global + * value. Check to see if /proc/sys/kernel/cap-bound exists and don't + * bother to clear the bounding set if it does. + */ + ret = stat(CAP_BOUND_PROCFILE, &st); + if (!ret) { + xlog(L_WARNING, "%s exists. Not attempting to clear " + "capabilities bounding set.", + CAP_BOUND_PROCFILE); + return true; + } else if (errno != ENOENT) { + /* Warn, but attempt to clear the bounding set anyway. */ + xlog(L_WARNING, "Unable to stat %s: %m", CAP_BOUND_PROCFILE); + } + + /* prune the bounding set to nothing */ + for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >=0 ; ++i) { + ret = prctl(PR_CAPBSET_DROP, i, 0, 0, 0); + if (ret) { + xlog(L_ERROR, "Unable to prune capability %lu from " + "bounding set: %m", i); + return false; + } + } +#endif /* PR_CAPBSET_DROP */ + return true; +} +#else /* !HAVE_SYS_CAPABILITY_H */ +static _Bool +nsm_clear_capabilities(void) +{ + return true; +} + +static _Bool +prune_bounding_set(void) +{ + return true; +} +#endif /* HAVE_SYS_CAPABILITY_H */ + /** * nsm_drop_privileges - drop root privileges * @pidfd: file descriptor of a pid file @@ -393,6 +443,9 @@ nsm_drop_privileges(const int pidfd) return false; } + if (!prune_bounding_set()) + return false; + if (st.st_uid == 0) { xlog_warn("Running as root. " "chown %s to choose different user", nsm_base_dirname); diff --git a/tests/nsm_client/Makefile.am b/tests/nsm_client/Makefile.am index 4bf0a45..4c15346 100644 --- a/tests/nsm_client/Makefile.am +++ b/tests/nsm_client/Makefile.am @@ -13,7 +13,7 @@ nsm_client_SOURCES = $(GENFILES) nsm_client.c BUILT_SOURCES = $(GENFILES) nsm_client_LDADD = ../../support/nfs/libnfs.a \ - ../../support/nsm/libnsm.a $(LIBCAP) + ../../support/nsm/libnsm.a $(LIBCAP) $(LIBTIRPC) if CONFIG_RPCGEN RPCGEN = $(top_builddir)/tools/rpcgen/rpcgen diff --git a/tools/rpcdebug/rpcdebug.c b/tools/rpcdebug/rpcdebug.c index 444616d..d6e10d3 100644 --- a/tools/rpcdebug/rpcdebug.c +++ b/tools/rpcdebug/rpcdebug.c @@ -170,6 +170,7 @@ static struct flagmap { FLAG(NFS, FSCACHE), FLAG(NFS, PNFS), FLAG(NFS, PNFS_LD), + FLAG(NFS, STATE), FLAG(NFS, ALL), /* nfsd */ diff --git a/utils/blkmapd/device-process.c b/utils/blkmapd/device-process.c index 652a7a8..5fe3dff 100644 --- a/utils/blkmapd/device-process.c +++ b/utils/blkmapd/device-process.c @@ -49,28 +49,6 @@ #include "device-discovery.h" -static char *pretty_sig(char *sig, uint32_t siglen) -{ - static char rs[100]; - uint64_t sigval; - unsigned int i; - - if (siglen <= sizeof(sigval)) { - sigval = 0; - for (i = 0; i < siglen; i++) - sigval |= ((unsigned char *)sig)[i] << (i * 8); - sprintf(rs, "0x%0llx", (unsigned long long) sigval); - } else { - if (siglen > sizeof rs - 4) { - siglen = sizeof rs - 4; - sprintf(&rs[siglen], "..."); - } else - rs[siglen] = '\0'; - memcpy(rs, sig, siglen); - } - return rs; -} - uint32_t *blk_overflow(uint32_t * p, uint32_t * end, size_t nbytes) { uint32_t *q = p + ((nbytes + 3) >> 2); @@ -109,9 +87,6 @@ static int decode_blk_signature(uint32_t **pp, uint32_t * end, * for mapping, then thrown away. */ comp->bs_string = (char *)p; - BL_LOG_INFO("%s: si_comps[%d]: bs_length %d, bs_string %s\n", - __func__, i, siglen, - pretty_sig(comp->bs_string, siglen)); p += ((siglen + 3) >> 2); } *pp = p; @@ -152,10 +127,6 @@ read_cmp_blk_sig(struct bl_disk *disk, int fd, struct bl_sig_comp *comp) } ret = memcmp(sig, comp->bs_string, siglen); - if (!ret) - BL_LOG_INFO("%s: %s sig %s at %lld\n", __func__, dev_name, - pretty_sig(sig, siglen), - (long long)comp->bs_offset); out: if (sig) diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c index a3323d7..9f79541 100644 --- a/utils/exportfs/exportfs.c +++ b/utils/exportfs/exportfs.c @@ -40,7 +40,7 @@ static void unexportfs(char *arg, int verbose); static void exports_update(int verbose); static void dump(int verbose); static void error(nfs_export *exp, int err); -static void usage(const char *progname); +static void usage(const char *progname, int n); static void validate_export(nfs_export *exp); static int matchhostname(const char *hostname1, const char *hostname2); static void export_d_read(const char *dname); @@ -105,11 +105,17 @@ main(int argc, char **argv) export_errno = 0; - while ((c = getopt(argc, argv, "aio:ruvf")) != EOF) { + while ((c = getopt(argc, argv, "afhio:ruv")) != EOF) { switch(c) { case 'a': f_all = 1; break; + case 'f': + force_flush = 1; + break; + case 'h': + usage(progname, 0); + break; case 'i': f_ignore = 1; break; @@ -126,11 +132,8 @@ main(int argc, char **argv) case 'v': f_verbose = 1; break; - case 'f': - force_flush = 1; - break; default: - usage(progname); + usage(progname, 1); break; } } @@ -723,8 +726,8 @@ error(nfs_export *exp, int err) } static void -usage(const char *progname) +usage(const char *progname, int n) { - fprintf(stderr, "usage: %s [-aruv] [host:/path]\n", progname); - exit(1); + fprintf(stderr, "usage: %s [-afhioruv] [host:/path]\n", progname); + exit(n); } diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h index 28a8206..71a140b 100644 --- a/utils/gssd/gssd.h +++ b/utils/gssd/gssd.h @@ -81,8 +81,10 @@ struct clnt_info { char *protocol; int krb5_fd; int krb5_poll_index; + int krb5_close_me; int gssd_fd; int gssd_poll_index; + int gssd_close_me; struct sockaddr_storage addr; }; diff --git a/utils/gssd/gssd_main_loop.c b/utils/gssd/gssd_main_loop.c index cec09ea..ccf7fe5 100644 --- a/utils/gssd/gssd_main_loop.c +++ b/utils/gssd/gssd_main_loop.c @@ -55,16 +55,14 @@ #include "err_util.h" extern struct pollfd *pollarray; -extern int pollsize; +extern unsigned long pollsize; #define POLL_MILLISECS 500 static volatile int dir_changed = 1; -static void dir_notify_handler(int sig, siginfo_t *si, void *data) +static void dir_notify_handler(__attribute__((unused))int sig) { - printerr(2, "dir_notify_handler: sig %d si %p data %p\n", sig, si, data); - dir_changed = 1; } @@ -78,8 +76,10 @@ scan_poll_results(int ret) { i = clp->gssd_poll_index; if (i >= 0 && pollarray[i].revents) { - if (pollarray[i].revents & POLLHUP) + if (pollarray[i].revents & POLLHUP) { + clp->gssd_close_me = 1; dir_changed = 1; + } if (pollarray[i].revents & POLLIN) handle_gssd_upcall(clp); pollarray[clp->gssd_poll_index].revents = 0; @@ -89,8 +89,10 @@ scan_poll_results(int ret) } i = clp->krb5_poll_index; if (i >= 0 && pollarray[i].revents) { - if (pollarray[i].revents & POLLHUP) + if (pollarray[i].revents & POLLHUP) { + clp->krb5_close_me = 1; dir_changed = 1; + } if (pollarray[i].revents & POLLIN) handle_krb5_upcall(clp); pollarray[clp->krb5_poll_index].revents = 0; @@ -99,7 +101,7 @@ scan_poll_results(int ret) break; } } -}; +} static int topdirs_add_entry(struct dirent *dent) @@ -119,11 +121,13 @@ topdirs_add_entry(struct dirent *dent) } snprintf(tdi->dirname, PATH_MAX, "%s/%s", pipefs_dir, dent->d_name); tdi->fd = open(tdi->dirname, O_RDONLY); - if (tdi->fd != -1) { - fcntl(tdi->fd, F_SETSIG, DNOTIFY_SIGNAL); - fcntl(tdi->fd, F_NOTIFY, - DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT); + if (tdi->fd == -1) { + printerr(0, "ERROR: failed to open %s\n", tdi->dirname); + free(tdi); + return -1; } + fcntl(tdi->fd, F_SETSIG, DNOTIFY_SIGNAL); + fcntl(tdi->fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT); TAILQ_INSERT_HEAD(&topdirs_list, tdi, list); return 0; @@ -175,17 +179,52 @@ out_err: return -1; } +#ifdef HAVE_PPOLL +static void gssd_poll(struct pollfd *fds, unsigned long nfds) +{ + sigset_t emptyset; + int ret; + + sigemptyset(&emptyset); + ret = ppoll(fds, nfds, NULL, &emptyset); + if (ret < 0) { + if (errno != EINTR) + printerr(0, "WARNING: error return from poll\n"); + } else if (ret == 0) { + printerr(0, "WARNING: unexpected timeout\n"); + } else { + scan_poll_results(ret); + } +} +#else /* !HAVE_PPOLL */ +static void gssd_poll(struct pollfd *fds, unsigned long nfds) +{ + int ret; + + /* race condition here: dir_changed could be set before we + * enter the poll, and we'd never notice if it weren't for the + * timeout. */ + ret = poll(fds, nfds, POLL_MILLISECS); + if (ret < 0) { + if (errno != EINTR) + printerr(0, "WARNING: error return from poll\n"); + } else if (ret == 0) { + /* timeout */ + } else { /* ret > 0 */ + scan_poll_results(ret); + } +} +#endif /* !HAVE_PPOLL */ + void gssd_run() { - int ret; - struct sigaction dn_act; + struct sigaction dn_act = { + .sa_handler = dir_notify_handler + }; sigset_t set; - /* Taken from linux/Documentation/dnotify.txt: */ - dn_act.sa_sigaction = dir_notify_handler; sigemptyset(&dn_act.sa_mask); - dn_act.sa_flags = SA_SIGINFO; sigaction(DNOTIFY_SIGNAL, &dn_act, NULL); /* just in case the signal is blocked... */ @@ -207,19 +246,7 @@ gssd_run() exit(1); } } - /* race condition here: dir_changed could be set before we - * enter the poll, and we'd never notice if it weren't for the - * timeout. */ - ret = poll(pollarray, pollsize, POLL_MILLISECS); - if (ret < 0) { - if (errno != EINTR) - printerr(0, - "WARNING: error return from poll\n"); - } else if (ret == 0) { - /* timeout */ - } else { /* ret > 0 */ - scan_poll_results(ret); - } + gssd_poll(pollarray, pollsize); } topdirs_free_list(); diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c index aa39435..e393d59 100644 --- a/utils/gssd/gssd_proc.c +++ b/utils/gssd/gssd_proc.c @@ -104,7 +104,7 @@ struct pollfd * pollarray; -int pollsize; /* the size of pollaray (in pollfd's) */ +unsigned long pollsize; /* the size of pollaray (in pollfd's) */ /* * convert a presentation address string to a sockaddr_storage struct. Returns @@ -340,6 +340,25 @@ process_clnt_dir_files(struct clnt_info * clp) char gname[PATH_MAX]; char info_file_name[PATH_MAX]; + if (clp->gssd_close_me) { + printerr(2, "Closing 'gssd' pipe for %s\n", clp->dirname); + close(clp->gssd_fd); + memset(&pollarray[clp->gssd_poll_index], 0, + sizeof(struct pollfd)); + clp->gssd_fd = -1; + clp->gssd_poll_index = -1; + clp->gssd_close_me = 0; + } + if (clp->krb5_close_me) { + printerr(2, "Closing 'krb5' pipe for %s\n", clp->dirname); + close(clp->krb5_fd); + memset(&pollarray[clp->krb5_poll_index], 0, + sizeof(struct pollfd)); + clp->krb5_fd = -1; + clp->krb5_poll_index = -1; + clp->krb5_close_me = 0; + } + if (clp->gssd_fd == -1) { snprintf(gname, sizeof(gname), "%s/gssd", clp->dirname); clp->gssd_fd = open(gname, O_RDWR); diff --git a/utils/mount/Makefile.am b/utils/mount/Makefile.am index 7627854..5810936 100644 --- a/utils/mount/Makefile.am +++ b/utils/mount/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in # These binaries go in /sbin (not /usr/sbin), and that cannot be -# overriden at config time. +# overridden at config time. sbindir = /sbin man8_MANS = mount.nfs.man umount.nfs.man diff --git a/utils/mount/mount_libmount.c b/utils/mount/mount_libmount.c index e8f17a9..701d41e 100644 --- a/utils/mount/mount_libmount.c +++ b/utils/mount/mount_libmount.c @@ -140,14 +140,14 @@ static int try_mount(struct libmnt_context *cxt, int bg) return ret; } -/* returns: error = -1, success = 0 , unknown = 1 */ +/* returns: error = -1, success = 1 , not vers4 == 0 */ static int is_vers4(struct libmnt_context *cxt) { struct libmnt_fs *fs = mnt_context_get_fs(cxt); struct libmnt_table *tb = NULL; const char *src = mnt_context_get_source(cxt), *tgt = mnt_context_get_target(cxt); - int rc = 1; + int rc = 0; if (!src || !tgt) return -1; @@ -163,7 +163,7 @@ static int is_vers4(struct libmnt_context *cxt) if (fs) { const char *type = mnt_fs_get_fstype(fs); if (type && strcmp(type, "nfs4") == 0) - rc = 0; + rc = 1; } mnt_free_table(tb); return rc; @@ -173,6 +173,7 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) { int rc, c; char *spec = NULL, *opts = NULL; + int ret = EX_FAIL; static const struct option longopts[] = { { "force", 0, 0, 'f' }, @@ -209,8 +210,6 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) if (mnt_context_set_target(cxt, spec)) goto err; - if (mnt_context_set_fstype_pattern(cxt, "nfs,nfs4")) /* restrict filesystems */ - goto err; /* read mtab/fstab, evaluate permissions, etc. */ rc = mnt_context_prepare_umount(cxt); @@ -220,6 +219,14 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) goto err; } + if (mnt_context_get_fstype(cxt) && + !mnt_match_fstype(mnt_context_get_fstype(cxt), "nfs,nfs4")) { + + nfs_error(_("%s: %s: is not an NFS filesystem"), progname, spec); + ret = EX_USAGE; + goto err; + } + opts = retrieve_mount_options(mnt_context_get_fs(cxt)); if (!mnt_context_is_lazy(cxt)) { @@ -244,6 +251,7 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) nfs_umount23(spec, "tcp,v3"); } + ret = EX_FILEIO; rc = mnt_context_do_umount(cxt); /* call umount(2) syscall */ mnt_context_finalize_mount(cxt); /* mtab update */ @@ -252,12 +260,10 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) umount_error(rc, spec); goto err; } - - free(opts); - return EX_SUCCESS; + ret = EX_SUCCESS; err: free(opts); - return EX_FAIL; + return ret; } static int mount_main(struct libmnt_context *cxt, int argc, char **argv) diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c index e09aa7c..0aa9a75 100644 --- a/utils/mount/stropts.c +++ b/utils/mount/stropts.c @@ -665,6 +665,7 @@ static int nfs_try_mount_v3v2(struct nfsmount_info *mi) case ECONNREFUSED: case EOPNOTSUPP: case EHOSTUNREACH: + case ETIMEDOUT: continue; default: goto out; @@ -752,6 +753,7 @@ static int nfs_try_mount_v4(struct nfsmount_info *mi) switch (errno) { case ECONNREFUSED: case EHOSTUNREACH: + case ETIMEDOUT: continue; default: goto out; diff --git a/utils/mountd/v4root.c b/utils/mountd/v4root.c index 708eb61..726b50d 100644 --- a/utils/mountd/v4root.c +++ b/utils/mountd/v4root.c @@ -62,6 +62,8 @@ void set_pseudofs_security(struct exportent *pseudo, struct exportent *source) if (source->e_flags & NFSEXP_INSECURE_PORT) pseudo->e_flags |= NFSEXP_INSECURE_PORT; + if ((source->e_flags & NFSEXP_ROOTSQUASH) == 0) + pseudo->e_flags &= ~NFSEXP_ROOTSQUASH; for (se = source->e_secinfo; se->flav; se++) { struct sec_entry *new; @@ -92,7 +94,8 @@ v4root_create(char *path, nfs_export *export) exp = export_create(&eep, 0); if (exp == NULL) return NULL; - xlog(D_CALL, "v4root_create: path '%s'", exp->m_export.e_path); + xlog(D_CALL, "v4root_create: path '%s' flags 0x%x", + exp->m_export.e_path, exp->m_export.e_flags); return &exp->m_export; } diff --git a/utils/nfsdcld/nfsdcld.c b/utils/nfsdcld/nfsdcld.c index e7af4e3..473d069 100644 --- a/utils/nfsdcld/nfsdcld.c +++ b/utils/nfsdcld/nfsdcld.c @@ -102,8 +102,8 @@ cld_set_caps(void) } /* prune the bounding set to nothing */ - for (i = 0; i <= CAP_LAST_CAP; ++i) { - ret = prctl(PR_CAPBSET_DROP, i); + for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0 ; ++i) { + ret = prctl(PR_CAPBSET_DROP, i, 0, 0, 0); if (ret) { xlog(L_ERROR, "Unable to prune capability %lu from " "bounding set: %m", i); diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c index cf11551..e14543c 100644 --- a/utils/nfsidmap/nfsidmap.c +++ b/utils/nfsidmap/nfsidmap.c @@ -12,6 +12,7 @@ #include #include "xlog.h" +#include "conffile.h" int verbose = 0; char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]"; @@ -26,6 +27,10 @@ char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]"; #define DEFAULT_KEYRING "id_resolver" #endif +#ifndef PATH_IDMAPDCONF +#define PATH_IDMAPDCONF "/etc/idmapd.conf" +#endif + static int keyring_clear(char *keyring); #define UIDKEYS 0x1 @@ -267,6 +272,13 @@ int main(int argc, char **argv) } } + if (nfs4_init_name_mapping(PATH_IDMAPDCONF)) { + xlog_err("Unable to create name to user id mappings."); + return 1; + } + if (!verbose) + verbose = conf_get_num("General", "Verbosity", 0); + if (keystr) { rc = key_revoke(keystr, keymask); return rc; diff --git a/utils/osd_login/Makefile.am b/utils/osd_login/Makefile.am index adc493a..20c2d8c 100644 --- a/utils/osd_login/Makefile.am +++ b/utils/osd_login/Makefile.am @@ -1,12 +1,9 @@ ## Process this file with automake to produce Makefile.in -OSD_LOGIN_FILES= osd_login +# These binaries go in /sbin (not /usr/sbin), and that cannot be +# overridden at config time. +sbindir = /sbin -EXTRA_DIST= $(OSD_LOGIN_FILES) - -all-local: $(OSD_LOGIN_FILES) - -install-data-hook: - $(INSTALL) --mode 755 osd_login $(DESTDIR)/sbin/osd_login +sbin_SCRIPTS = osd_login MAINTAINERCLEANFILES = Makefile.in