Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Mar 2011 12:40:35 +0000 (UTC)
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r219304 - in head: include lib/libc/sys lib/libutil sys/compat/freebsd32 sys/conf sys/kern sys/sys usr.bin/id
Message-ID:  <201103051240.p25CeZYc054670@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: trasz
Date: Sat Mar  5 12:40:35 2011
New Revision: 219304
URL: http://svn.freebsd.org/changeset/base/219304

Log:
  Add two new system calls, setloginclass(2) and getloginclass(2).  This makes
  it possible for the kernel to track login class the process is assigned to,
  which is required for RCTL.  This change also make setusercontext(3) call
  setloginclass(2) and makes it possible to retrieve current login class using
  id(1).
  
  Reviewed by:	kib (as part of a larger patch)

Added:
  head/sys/kern/kern_loginclass.c   (contents, props changed)
  head/sys/sys/loginclass.h   (contents, props changed)
Modified:
  head/include/unistd.h
  head/lib/libc/sys/Symbol.map
  head/lib/libutil/login_cap.h
  head/lib/libutil/login_class.c
  head/sys/compat/freebsd32/syscalls.master
  head/sys/conf/files
  head/sys/kern/init_main.c
  head/sys/kern/kern_jail.c
  head/sys/kern/kern_prot.c
  head/sys/kern/syscalls.master
  head/sys/sys/priv.h
  head/sys/sys/ucred.h
  head/usr.bin/id/id.1
  head/usr.bin/id/id.c

Modified: head/include/unistd.h
==============================================================================
--- head/include/unistd.h	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/include/unistd.h	Sat Mar  5 12:40:35 2011	(r219304)
@@ -500,6 +500,7 @@ int	 feature_present(const char *);
 char	*fflagstostr(u_long);
 int	 getdomainname(char *, int);
 int	 getgrouplist(const char *, gid_t, gid_t *, int *);
+int	 getloginclass(char *, size_t);
 mode_t	 getmode(const void *, mode_t);
 int	 getosreldate(void);
 int	 getpeereid(int, uid_t *, gid_t *);
@@ -560,6 +561,7 @@ int	 setkey(const char *);
 #define	_SETKEY_DECLARED
 #endif
 int	 setlogin(const char *);
+int	 setloginclass(const char *);
 void	*setmode(const char *);
 void	 setproctitle(const char *_fmt, ...) __printf0like(1, 2);
 int	 setresgid(gid_t, gid_t, gid_t);

Modified: head/lib/libc/sys/Symbol.map
==============================================================================
--- head/lib/libc/sys/Symbol.map	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/lib/libc/sys/Symbol.map	Sat Mar  5 12:40:35 2011	(r219304)
@@ -344,6 +344,7 @@ FBSD_1.1 {
 	fexecve;
 	fstatat;
 	futimesat;
+	getloginclass;
 	jail_get;
 	jail_set;
 	jail_remove;
@@ -357,6 +358,7 @@ FBSD_1.1 {
 	readlinkat;
 	renameat;
 	setfib;
+	setloginclass;
 	shmctl;
 	symlinkat;
 	unlinkat;

Modified: head/lib/libutil/login_cap.h
==============================================================================
--- head/lib/libutil/login_cap.h	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/lib/libutil/login_cap.h	Sat Mar  5 12:40:35 2011	(r219304)
@@ -49,7 +49,8 @@
 #define LOGIN_SETENV		0x0080		/* set user environment */
 #define LOGIN_SETMAC		0x0100		/* set user default MAC label */
 #define LOGIN_SETCPUMASK	0x0200		/* set user cpumask */
-#define LOGIN_SETALL		0x03ff		/* set everything */
+#define LOGIN_SETLOGINCLASS	0x0400		/* set login class in the kernel */
+#define LOGIN_SETALL		0x07ff		/* set everything */
 
 #define BI_AUTH		"authorize"		/* accepted authentication */
 #define BI_REJECT	"reject"		/* rejected authentication */

Modified: head/lib/libutil/login_class.c
==============================================================================
--- head/lib/libutil/login_class.c	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/lib/libutil/login_class.c	Sat Mar  5 12:40:35 2011	(r219304)
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
 #include <login_cap.h>
 #include <paths.h>
 #include <pwd.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -425,6 +426,7 @@ setusercontext(login_cap_t *lc, const st
     quad_t	p;
     mode_t	mymask;
     login_cap_t *llc = NULL;
+    struct sigaction sa, prevsa;
     struct rtprio rtp;
     int error;
 
@@ -512,6 +514,27 @@ setusercontext(login_cap_t *lc, const st
 	return (-1);
     }
 
+    /* Inform the kernel about current login class */
+    if (lc != NULL && lc->lc_class != NULL && (flags & LOGIN_SETLOGINCLASS)) {
+	/*
+	 * XXX: This is a workaround to fail gracefully in case the kernel
+	 *      does not support setloginclass(2).
+	 */
+	bzero(&sa, sizeof(sa));
+	sa.sa_handler = SIG_IGN;
+	sigfillset(&sa.sa_mask);
+	sigaction(SIGSYS, &sa, &prevsa);
+	error = setloginclass(lc->lc_class);
+	sigaction(SIGSYS, &prevsa, NULL);
+	if (error != 0) {
+	    syslog(LOG_ERR, "setloginclass(%s): %m", lc->lc_class);
+#ifdef notyet
+	    login_close(llc);
+	    return (-1);
+#endif
+	}
+    }
+
     mymask = (flags & LOGIN_SETUMASK) ? umask(LOGIN_DEFUMASK) : 0;
     mymask = setlogincontext(lc, pwd, mymask, flags);
     login_close(llc);

Modified: head/sys/compat/freebsd32/syscalls.master
==============================================================================
--- head/sys/compat/freebsd32/syscalls.master	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/sys/compat/freebsd32/syscalls.master	Sat Mar  5 12:40:35 2011	(r219304)
@@ -962,3 +962,6 @@
 				    fd_set *ou, fd_set *ex, \
 				    const struct timespec32 *ts, \
 				    const sigset_t *sm); }
+523	AUE_NULL	NOPROTO	{ int getloginclass(char *namebuf, \
+				    size_t namelen); }
+524	AUE_NULL	NOPROTO	{ int setloginclass(const char *namebuf); }

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/sys/conf/files	Sat Mar  5 12:40:35 2011	(r219304)
@@ -2190,6 +2190,7 @@ kern/kern_linker.c		standard
 kern/kern_lock.c		standard
 kern/kern_lockf.c		standard
 kern/kern_lockstat.c		optional kdtrace_hooks
+kern/kern_loginclass.c		standard
 kern/kern_malloc.c		standard
 kern/kern_mbuf.c		standard
 kern/kern_mib.c			standard

Modified: head/sys/kern/init_main.c
==============================================================================
--- head/sys/kern/init_main.c	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/sys/kern/init_main.c	Sat Mar  5 12:40:35 2011	(r219304)
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/jail.h>
 #include <sys/ktr.h>
 #include <sys/lock.h>
+#include <sys/loginclass.h>
 #include <sys/mount.h>
 #include <sys/mutex.h>
 #include <sys/syscallsubr.h>
@@ -484,6 +485,7 @@ proc0_init(void *dummy __unused)
 	p->p_ucred->cr_uidinfo = uifind(0);
 	p->p_ucred->cr_ruidinfo = uifind(0);
 	p->p_ucred->cr_prison = &prison0;
+	p->p_ucred->cr_loginclass = loginclass_find("default");
 #ifdef AUDIT
 	audit_cred_kproc0(p->p_ucred);
 #endif

Modified: head/sys/kern/kern_jail.c
==============================================================================
--- head/sys/kern/kern_jail.c	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/sys/kern/kern_jail.c	Sat Mar  5 12:40:35 2011	(r219304)
@@ -3874,6 +3874,12 @@ prison_priv_check(struct ucred *cred, in
 	case PRIV_NETINET_GETCRED:
 		return (0);
 
+		/*
+		 * Allow jailed root to set loginclass.
+		 */
+	case PRIV_PROC_SETLOGINCLASS:
+		return (0);
+
 	default:
 		/*
 		 * In all remaining cases, deny the privilege request.  This

Added: head/sys/kern/kern_loginclass.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/kern/kern_loginclass.c	Sat Mar  5 12:40:35 2011	(r219304)
@@ -0,0 +1,220 @@
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Edward Tomasz Napierala under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Processes may set login class name using setloginclass(2).  This
+ * is usually done through call to setusercontext(3), by programs
+ * such as login(1), based on information from master.passwd(5).  Kernel
+ * uses this information to enforce per-class resource limits.  Current
+ * login class can be determined using id(1).  Login class is inherited
+ * from the parent process during fork(2).  If not set, it defaults
+ * to "default".
+ *
+ * Code in this file implements setloginclass(2) and getloginclass(2)
+ * system calls, and maintains class name storage and retrieval.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/eventhandler.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/loginclass.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/types.h>
+#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+#include <sys/refcount.h>
+#include <sys/sysproto.h>
+#include <sys/systm.h>
+
+static MALLOC_DEFINE(M_LOGINCLASS, "loginclass", "loginclass structures");
+
+LIST_HEAD(, loginclass)	loginclasses;
+
+/*
+ * Lock protecting loginclasses list.
+ */
+static struct mtx loginclasses_lock;
+
+static void lc_init(void);
+SYSINIT(loginclass, SI_SUB_CPU, SI_ORDER_FIRST, lc_init, NULL);
+
+void
+loginclass_hold(struct loginclass *lc)
+{
+
+	refcount_acquire(&lc->lc_refcount);
+}
+
+void
+loginclass_free(struct loginclass *lc)
+{
+	int old;
+
+	old = lc->lc_refcount;
+	if (old > 1 && atomic_cmpset_int(&lc->lc_refcount, old, old - 1))
+		return;
+
+	mtx_lock(&loginclasses_lock);
+	if (refcount_release(&lc->lc_refcount)) {
+		LIST_REMOVE(lc, lc_next);
+		mtx_unlock(&loginclasses_lock);
+		free(lc, M_LOGINCLASS);
+
+		return;
+	}
+	mtx_unlock(&loginclasses_lock);
+}
+
+/*
+ * Return loginclass structure with a corresponding name.  Not
+ * performance critical, as it's used mainly by setloginclass(2),
+ * which happens once per login session.  Caller has to use
+ * loginclass_free() on the returned value when it's no longer
+ * needed.
+ */
+struct loginclass *
+loginclass_find(const char *name)
+{
+	struct loginclass *lc, *newlc;
+
+	if (name[0] == '\0' || strlen(name) >= MAXLOGNAME)
+		return (NULL);
+
+	newlc = malloc(sizeof(*newlc), M_LOGINCLASS, M_ZERO | M_WAITOK);
+
+	mtx_lock(&loginclasses_lock);
+	LIST_FOREACH(lc, &loginclasses, lc_next) {
+		if (strcmp(name, lc->lc_name) != 0)
+			continue;
+
+		/* Found loginclass with a matching name? */
+		loginclass_hold(lc);
+		mtx_unlock(&loginclasses_lock);
+		free(newlc, M_LOGINCLASS);
+		return (lc);
+	}
+
+	/* Add new loginclass. */
+	strcpy(newlc->lc_name, name);
+	refcount_init(&newlc->lc_refcount, 1);
+	LIST_INSERT_HEAD(&loginclasses, newlc, lc_next);
+	mtx_unlock(&loginclasses_lock);
+
+	return (newlc);
+}
+
+/*
+ * Get login class name.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct getloginclass_args {
+	char	*namebuf;
+	size_t	namelen;
+};
+#endif
+/* ARGSUSED */
+int
+getloginclass(struct thread *td, struct getloginclass_args *uap)
+{
+	int error = 0;
+	size_t lcnamelen;
+	struct proc *p;
+	struct loginclass *lc;
+
+	p = td->td_proc;
+	PROC_LOCK(p);
+	lc = p->p_ucred->cr_loginclass;
+	loginclass_hold(lc);
+	PROC_UNLOCK(p);
+
+	lcnamelen = strlen(lc->lc_name) + 1;
+	if (lcnamelen > uap->namelen)
+		error = ERANGE;
+	if (error == 0)
+		error = copyout(lc->lc_name, uap->namebuf, lcnamelen);
+	loginclass_free(lc);
+	return (error);
+}
+
+/*
+ * Set login class name.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct setloginclass_args {
+	const char	*namebuf;
+};
+#endif
+/* ARGSUSED */
+int
+setloginclass(struct thread *td, struct setloginclass_args *uap)
+{
+	struct proc *p = td->td_proc;
+	int error;
+	char lcname[MAXLOGNAME];
+	struct loginclass *newlc;
+	struct ucred *newcred, *oldcred;
+
+	error = priv_check(td, PRIV_PROC_SETLOGINCLASS);
+	if (error != 0)
+		return (error);
+	error = copyinstr(uap->namebuf, lcname, sizeof(lcname), NULL);
+	if (error != 0)
+		return (error);
+
+	newlc = loginclass_find(lcname);
+	if (newlc == NULL)
+		return (EINVAL);
+	newcred = crget();
+
+	PROC_LOCK(p);
+	oldcred = crcopysafe(p, newcred);
+	newcred->cr_loginclass = newlc;
+	p->p_ucred = newcred;
+	PROC_UNLOCK(p);
+
+	loginclass_free(oldcred->cr_loginclass);
+	crfree(oldcred);
+
+	return (0);
+}
+
+static void
+lc_init(void)
+{
+
+	mtx_init(&loginclasses_lock, "loginclasses lock", NULL, MTX_DEF);
+}

Modified: head/sys/kern/kern_prot.c
==============================================================================
--- head/sys/kern/kern_prot.c	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/sys/kern/kern_prot.c	Sat Mar  5 12:40:35 2011	(r219304)
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/kdb.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
+#include <sys/loginclass.h>
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/refcount.h>
@@ -1842,6 +1843,8 @@ crfree(struct ucred *cr)
 		 */
 		if (cr->cr_prison != NULL)
 			prison_free(cr->cr_prison);
+		if (cr->cr_loginclass != NULL)
+			loginclass_free(cr->cr_loginclass);
 #ifdef AUDIT
 		audit_cred_destroy(cr);
 #endif
@@ -1878,6 +1881,7 @@ crcopy(struct ucred *dest, struct ucred 
 	uihold(dest->cr_uidinfo);
 	uihold(dest->cr_ruidinfo);
 	prison_hold(dest->cr_prison);
+	loginclass_hold(dest->cr_loginclass);
 #ifdef AUDIT
 	audit_cred_copy(src, dest);
 #endif

Modified: head/sys/kern/syscalls.master
==============================================================================
--- head/sys/kern/syscalls.master	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/sys/kern/syscalls.master	Sat Mar  5 12:40:35 2011	(r219304)
@@ -926,5 +926,8 @@
 				    fd_set *ou, fd_set *ex, \
 				    const struct timespec *ts, \
 				    const sigset_t *sm); }
+523	AUE_NULL	STD	{ int getloginclass(char *namebuf, \
+				    size_t namelen); }
+524	AUE_NULL	STD	{ int setloginclass(const char *namebuf); }
 ; Please copy any additions and changes to the following compatability tables:
 ; sys/compat/freebsd32/syscalls.master

Added: head/sys/sys/loginclass.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/sys/loginclass.h	Sat Mar  5 12:40:35 2011	(r219304)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Edward Tomasz Napierala under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_LOGINCLASS_H_
+#define	_SYS_LOGINCLASS_H_
+
+/*
+ * Exactly one of these structures exists per login class.
+ */
+struct loginclass {
+	LIST_ENTRY(loginclass)	lc_next;
+	char			lc_name[MAXLOGNAME];
+	u_int			lc_refcount;
+};
+
+void	loginclass_hold(struct loginclass *lc);
+void	loginclass_free(struct loginclass *lc);
+struct loginclass	*loginclass_find(const char *name);
+
+#endif /* !_SYS_LOGINCLASS_H_ */
+

Modified: head/sys/sys/priv.h
==============================================================================
--- head/sys/sys/priv.h	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/sys/sys/priv.h	Sat Mar  5 12:40:35 2011	(r219304)
@@ -156,6 +156,7 @@
 #define	PRIV_PROC_LIMIT		160	/* Exceed user process limit. */
 #define	PRIV_PROC_SETLOGIN	161	/* Can call setlogin. */
 #define	PRIV_PROC_SETRLIMIT	162	/* Can raise resources limits. */
+#define	PRIV_PROC_SETLOGINCLASS	163	/* Can call setloginclass(2). */
 
 /* System V IPC privileges.
  */

Modified: head/sys/sys/ucred.h
==============================================================================
--- head/sys/sys/ucred.h	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/sys/sys/ucred.h	Sat Mar  5 12:40:35 2011	(r219304)
@@ -35,6 +35,8 @@
 
 #include <bsm/audit.h>
 
+struct loginclass;
+
 /*
  * Credentials.
  *
@@ -54,7 +56,7 @@ struct ucred {
 	struct uidinfo	*cr_uidinfo;	/* per euid resource consumption */
 	struct uidinfo	*cr_ruidinfo;	/* per ruid resource consumption */
 	struct prison	*cr_prison;	/* jail(2) */
-	void		*cr_pspare;	/* general use */
+	struct loginclass	*cr_loginclass; /* login class */
 	u_int		cr_flags;	/* credential flags */
 	void 		*cr_pspare2[2];	/* general use 2 */
 #define	cr_endcopy	cr_label

Modified: head/usr.bin/id/id.1
==============================================================================
--- head/usr.bin/id/id.1	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/usr.bin/id/id.1	Sat Mar  5 12:40:35 2011	(r219304)
@@ -31,7 +31,7 @@
 .\"	@(#)id.1	8.1 (Berkeley) 6/6/93
 .\" $FreeBSD$
 .\"
-.Dd September 26, 2006
+.Dd March 5, 2011
 .Dt ID 1
 .Os
 .Sh NAME
@@ -51,6 +51,8 @@
 .Fl P
 .Op Ar user
 .Nm
+.Fl c
+.Nm
 .Fl g Op Fl nr
 .Op Ar user
 .Nm
@@ -89,6 +91,8 @@ Display the id as a password file entry.
 Ignored for compatibility with other
 .Nm
 implementations.
+.It Fl c
+Display current login class.
 .It Fl g
 Display the effective group ID as a number.
 .It Fl n

Modified: head/usr.bin/id/id.c
==============================================================================
--- head/usr.bin/id/id.c	Sat Mar  5 09:42:00 2011	(r219303)
+++ head/usr.bin/id/id.c	Sat Mar  5 12:40:35 2011	(r219304)
@@ -74,11 +74,13 @@ main(int argc, char *argv[])
 	struct group *gr;
 	struct passwd *pw;
 	int Gflag, Mflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag;
-	int Aflag;
+	int Aflag, cflag;
+	int error;
 	const char *myname;
+	char loginclass[MAXLOGNAME];
 
 	Gflag = Mflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0;
-	Aflag = 0;
+	Aflag = cflag = 0;
 
 	myname = strrchr(argv[0], '/');
 	myname = (myname != NULL) ? myname + 1 : argv[0];
@@ -92,7 +94,7 @@ main(int argc, char *argv[])
 	}
 
 	while ((ch = getopt(argc, argv,
-	    (isgroups || iswhoami) ? "" : "APGMagnpru")) != -1)
+	    (isgroups || iswhoami) ? "" : "APGMacgnpru")) != -1)
 		switch(ch) {
 #ifdef USE_BSM_AUDIT
 		case 'A':
@@ -110,6 +112,9 @@ main(int argc, char *argv[])
 			break;
 		case 'a':
 			break;
+		case 'c':
+			cflag = 1;
+			break;
 		case 'g':
 			gflag = 1;
 			break;
@@ -158,6 +163,14 @@ main(int argc, char *argv[])
 	}
 #endif
 
+	if (cflag) {
+		error = getloginclass(loginclass, sizeof(loginclass));
+		if (error != 0)
+			err(1, "loginclass");
+		(void)printf("%s\n", loginclass);
+		exit(0);
+	}
+
 	if (gflag) {
 		id = pw ? pw->pw_gid : rflag ? getgid() : getegid();
 		if (nflag && (gr = getgrgid(id)))
@@ -467,7 +480,7 @@ usage(void)
 	else if (iswhoami)
 		(void)fprintf(stderr, "usage: whoami\n");
 	else
-		(void)fprintf(stderr, "%s\n%s%s\n%s\n%s\n%s\n%s\n%s\n",
+		(void)fprintf(stderr, "%s\n%s%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
 		    "usage: id [user]",
 #ifdef USE_BSM_AUDIT
 		    "       id -A\n",
@@ -477,6 +490,7 @@ usage(void)
 		    "       id -G [-n] [user]",
 		    "       id -M",
 		    "       id -P [user]",
+		    "       id -c",
 		    "       id -g [-nr] [user]",
 		    "       id -p [user]",
 		    "       id -u [-nr] [user]");



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103051240.p25CeZYc054670>