kern/180719: Compatibility enhancement - sigsend() (function) and sigsendset() (system call)

Jukka Ukkonen jau at iki.fi
Sun Jul 21 13:10:00 UTC 2013


>Number:         180719
>Category:       kern
>Synopsis:       Compatibility enhancement - sigsend() (function) and sigsendset() (system call)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jul 21 13:10:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Jukka Ukkonen
>Release:        9.2-BETA1
>Organization:
----
>Environment:
FreeBSD sleipnir 9.2-BETA1 FreeBSD 9.2-BETA1 #0 r253515M: Sun Jul 21 14:43:43 EEST 2013     root at sleipnir:/usr/obj/usr/src/sys/Sleipnir  amd64
>Description:
These call interfaces allow sending signals to much more varied groups of
processes than the traditional kill().
They have been present in multiple commercial UNIX variants including at least
SunOS/Solaris, HP-UX, IRIX, and Tru64, but they are not required by any standard.
These call interfaces provide a nice parallel to the extended wait*() family
functions waitid() [standard requirement] and wait6() [freebsd extension].
Supporting them also improves compatibility and portability between several
commercial UNIX flavors and FreeBSD.
On the down side actively using them in ones own code will most likely cause
problems when trying to port such code to systems like Linux and AIX which
apparently do not provide these interfaces.

Solaris manual page for these APIs can be found also in the FreeBSD web manual
pages...
http://www.freebsd.org/cgi/man.cgi?query=sigsendset&apropos=0&sektion=0&manpath=SunOS+5.10&arch=default&format=html

Notice!
The attached patch will move idtype_t definition out of <sys/wait.h> to its own
header file <sys/_idtype.h> to make it easier to include idtype_t definitions
only where it is needed. When the patch has been applied <sys/_idtype.h> and
another new header <sys/procset.h> will be included also right at the end of
<signal.h> to complete the declarations of sigsend() and sigsendset().

>How-To-Repeat:
No problem, just improved convenience, compatibility, and portability.
>Fix:
Apply the attached patch.

Remember to run

make sysent

in /usr/src/sys/kern and /usr/src/sys/compat/freebsd32 when the patch
has been applied.



Patch attached with submission follows:

Index: lib/libc/sys/Makefile.inc
===================================================================
--- lib/libc/sys/Makefile.inc	(revision 253336)
+++ lib/libc/sys/Makefile.inc	(working copy)
@@ -114,7 +114,8 @@
 	setgroups.2 setpgid.2 setregid.2 setresuid.2 setreuid.2 setsid.2 \
 	setuid.2 shmat.2 shmctl.2 shmget.2 shm_open.2 shutdown.2 \
 	sigaction.2 sigaltstack.2 sigpending.2 sigprocmask.2 sigqueue.2 \
-	sigreturn.2 sigstack.2 sigsuspend.2 sigwait.2 sigwaitinfo.2 \
+	sigreturn.2 sigsendset.2 sigstack.2 sigsuspend.2 \
+	sigwait.2 sigwaitinfo.2 \
 	socket.2 socketpair.2 stat.2 statfs.2 \
 	swapon.2 symlink.2 sync.2 sysarch.2 syscall.2 \
 	timer_create.2 timer_delete.2 timer_settime.2 \
@@ -132,7 +133,7 @@
 MLINKS+=clock_gettime.2 clock_getres.2 clock_gettime.2 clock_settime.2
 MLINKS+=cpuset.2 cpuset_getid.2 cpuset.2 cpuset_setid.2
 MLINKS+=cpuset_getaffinity.2 cpuset_setaffinity.2
-MLINKS+=dup.2 dup2.2
+MLINKS+=dup.2 dup2.2 dup.2 dup3.2
 MLINKS+=execve.2 fexecve.2
 MLINKS+=extattr_get_file.2 extattr.2 \
 	extattr_get_file.2 extattr_delete_fd.2 \
@@ -204,6 +205,7 @@
 MLINKS+=setuid.2 setegid.2 setuid.2 seteuid.2 setuid.2 setgid.2
 MLINKS+=shmat.2 shmdt.2
 MLINKS+=shm_open.2 shm_unlink.2
+MLINKS+=sigsendset.2 sigsend.2
 MLINKS+=sigwaitinfo.2 sigtimedwait.2
 MLINKS+=stat.2 fstat.2 stat.2 fstatat.2 stat.2 lstat.2
 MLINKS+=statfs.2 fstatfs.2
Index: lib/libc/gen/Symbol.map
===================================================================
--- lib/libc/gen/Symbol.map	(revision 253336)
+++ lib/libc/gen/Symbol.map	(working copy)
@@ -382,11 +382,12 @@
 FBSD_1.3 {
 	 fdlopen;
 	__FreeBSD_libc_enter_restricted_mode;
 	getcontextx;
 	gid_from_group;
 	nvis;
 	pwcache_userdb;
 	pwcache_groupdb;
+	sigsend;
 	snvis;
 	strenvisx;
 	strnunvis;
Index: lib/libc/gen/Makefile.inc
===================================================================
--- lib/libc/gen/Makefile.inc	(revision 253336)
+++ lib/libc/gen/Makefile.inc	(working copy)
@@ -29,7 +29,8 @@
 	scandir.c seed48.c seekdir.c semctl.c \
 	setdomainname.c sethostname.c setjmperr.c setmode.c \
 	setproctitle.c setprogname.c siginterrupt.c siglist.c signal.c \
-	sigsetops.c sleep.c srand48.c statvfs.c stringlist.c strtofflags.c \
+	sigsend.c sigsetops.c sleep.c \
+	srand48.c statvfs.c stringlist.c strtofflags.c \
 	sysconf.c sysctl.c sysctlbyname.c sysctlnametomib.c \
 	syslog.c telldir.c termios.c time.c times.c timezone.c tls.c \
 	ttyname.c ttyslot.c ualarm.c ulimit.c uname.c unvis-compat.c \
Index: lib/libc/include/namespace.h
===================================================================
--- lib/libc/include/namespace.h	(revision 253336)
+++ lib/libc/include/namespace.h	(working copy)
@@ -224,6 +224,7 @@
 #define		setsockopt			_setsockopt
 /*#define		sigaction			_sigaction*/
 #define		sigprocmask			_sigprocmask
+#define		sigsendset			_sigsendset
 #define		sigsuspend			_sigsuspend
 #define		socket				_socket
 #define		socketpair			_socketpair
Index: lib/libc/include/un-namespace.h
===================================================================
--- lib/libc/include/un-namespace.h	(revision 253336)
+++ lib/libc/include/un-namespace.h	(working copy)
@@ -205,6 +205,7 @@
 #undef		setsockopt
 #undef		sigaction
 #undef		sigprocmask
+#undef		sigsendset
 #undef		sigsuspend
 #undef		socket
 #undef		socketpair
Index: sys/bsm/audit_kevents.h
===================================================================
--- sys/bsm/audit_kevents.h	(revision 253336)
+++ sys/bsm/audit_kevents.h	(working copy)
@@ -603,6 +603,7 @@
 #define	AUE_PDGETPID		43199	/* FreeBSD. */
 #define	AUE_PDWAIT		43200	/* FreeBSD. */
 #define	AUE_WAIT6		43201	/* FreeBSD. */
+#define	AUE_SIGSENDSET		43202	/* FreeBSD. */
 
 /*
  * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
Index: sys/kern/makesyscalls.sh
===================================================================
--- sys/kern/makesyscalls.sh	(revision 253336)
+++ sys/kern/makesyscalls.sh	(working copy)
@@ -153,6 +153,7 @@
 		printf "#include <sys/acl.h>\n" > sysarg
 		printf "#include <sys/cpuset.h>\n" > sysarg
 		printf "#include <sys/_semaphore.h>\n" > sysarg
+		printf "#include <sys/procset.h>\n" > sysarg
 		printf "#include <sys/ucontext.h>\n\n" > sysarg
 		printf "#include <bsm/audit_kevents.h>\n\n" > sysarg
 		printf "struct proc;\n\n" > sysarg
Index: sys/kern/syscalls.master
===================================================================
--- sys/kern/syscalls.master	(revision 253336)
+++ sys/kern/syscalls.master	(working copy)
@@ -952,5 +952,7 @@
 				    int *status, int options, \
 				    struct __wrusage *wrusage, \
 				    siginfo_t *info); }
+533	AUE_SIGSENDSET	STD	{ int sigsendset(procset_t *psp, int sig); }
+
 ; Please copy any additions and changes to the following compatability tables:
 ; sys/compat/freebsd32/syscalls.master
Index: sys/sys/syscallsubr.h
===================================================================
--- sys/sys/syscallsubr.h	(revision 253336)
+++ sys/sys/syscallsubr.h	(working copy)
@@ -55,6 +55,7 @@
 struct stat;
 struct thr_param;
 struct __wrusage;
+struct __procset;
 
 int	kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg,
 	    u_int buflen);
@@ -206,6 +207,7 @@
 int	kern_sigaltstack(struct thread *td, stack_t *ss, stack_t *oss);
 int	kern_sigprocmask(struct thread *td, int how,
 	    sigset_t *set, sigset_t *oset, int flags);
+int	kern_sigsendset (struct thread *td, struct __procset *ps, int sign);
 int	kern_sigsuspend(struct thread *td, sigset_t mask);
 int	kern_sigtimedwait(struct thread *td, sigset_t waitset,
 	    struct ksiginfo *ksi, struct timespec *timeout);
Index: sys/compat/freebsd32/syscalls.master
===================================================================
--- sys/compat/freebsd32/syscalls.master	(revision 253336)
+++ sys/compat/freebsd32/syscalls.master	(working copy)
@@ -49,6 +49,7 @@
 #include <sys/sysproto.h>
 #include <sys/mount.h>
 #include <sys/socket.h>
+#include <sys/procset.h>
 #include <compat/freebsd32/freebsd32.h>
 #include <compat/freebsd32/freebsd32_proto.h>
 
@@ -1019,3 +1020,5 @@
 				    struct wrusage32 *wrusage, \
 				    siginfo_t *info); }
 #endif
+533	AUE_SIGSENDSET	STD	{ int freebsd32_sigsendset(struct procset32 *psp, \
+				    int sig); }
Index: include/signal.h
===================================================================
--- include/signal.h	(revision 253336)
+++ include/signal.h	(working copy)
@@ -120,6 +120,14 @@
 int	sigstack(const struct sigstack *, struct sigstack *);
 int	sigvec(int, struct sigvec *, struct sigvec *);
 #endif
+
+#if __BSD_VISIBLE
+#include <sys/procset.h>
+
+int	sigsend(idtype_t idtype, id_t id, int sig);
+int	sigsendset(procset_t *psetptr, int sig);
+#endif
+
 __END_DECLS
 
 #endif /* !_SIGNAL_H_ */
Index: sys/sys/wait.h
===================================================================
--- sys/sys/wait.h	(revision 253336)
+++ sys/sys/wait.h	(working copy)
@@ -88,46 +88,8 @@
 #define	WLINUXCLONE 0x80000000	/* Wait for kthread spawned from linux_clone. */
 #endif
 
-#ifndef _IDTYPE_T_DECLARED
-typedef enum
-#if __BSD_VISIBLE
-	idtype		/* pollutes XPG4.2 namespace */
-#endif
-		{
-	/*
-	 * These names were mostly lifted from Solaris source code and
-	 * still use Solaris style naming to avoid breaking any
-	 * OpenSolaris code which has been ported to FreeBSD.  There
-	 * is no clear FreeBSD counterpart for all of the names, but
-	 * some have a clear correspondence to FreeBSD entities.
-	 *
-	 * The numerical values are kept synchronized with the Solaris
-	 * values.
-	 */
-	P_PID,			/* A process identifier. */
-	P_PPID,			/* A parent process identifier.	*/
-	P_PGID,			/* A process group identifier. */
-	P_SID,			/* A session identifier. */
-	P_CID,			/* A scheduling class identifier. */
-	P_UID,			/* A user identifier. */
-	P_GID,			/* A group identifier. */
-	P_ALL,			/* All processes. */
-	P_LWPID,		/* An LWP identifier. */
-	P_TASKID,		/* A task identifier. */
-	P_PROJID,		/* A project identifier. */
-	P_POOLID,		/* A pool identifier. */
-	P_JAILID,		/* A zone identifier. */
-	P_CTID,			/* A (process) contract identifier. */
-	P_CPUID,		/* CPU identifier. */
-	P_PSETID		/* Processor set identifier. */
-} idtype_t;			/* The type of id_t we are using. */
+#include <sys/_idtype.h>
 
-#if __BSD_VISIBLE
-#define	P_ZONEID	P_JAILID
-#endif
-#define	_IDTYPE_T_DECLARED
-#endif
-
 /*
  * Tokens for special values of the "pid" parameter to wait4.
  * Extended struct __wrusage to collect rusage for both the target
Index: sys/kern/kern_sig.c
===================================================================
--- sys/kern/kern_sig.c	(revision 253336)
+++ sys/kern/kern_sig.c	(working copy)
@@ -1714,7 +1714,281 @@
 	/* NOTREACHED */
 }
 
+/*
+ * This shall be called only while holding both
+ * PROC_LOCK(me) and PROC_LOCK(p).
+ */
+static int
+pr_matches_id (me, p, idtype, id)
+	struct proc *me;
+	struct proc *p;
+	idtype_t    idtype;
+	id_t	    id;
+{
+	int ret = 0;		/* Assume no match. */
+
+	switch (idtype) {
+	case P_ALL:
+		ret = 1;
+		break;
+	case P_PID:
+		if (id == P_MYID)
+		    id = (id_t)me->p_pid;
+		ret = (p->p_pid == (pid_t)id) ? 1 : 0;
+		break;
+	case P_PGID:
+		if (id == P_MYID)
+		    id = (id_t)me->p_pgid;
+		ret = (p->p_pgid == (pid_t)id) ? 1 : 0;
+		break;
+	case P_SID:
+		if (id == P_MYID)
+		    id = (id_t)me->p_session->s_sid;
+		ret = (p->p_session->s_sid == (pid_t)id) ? 1 : 0;
+		break;
+	case P_UID:
+		if (id == P_MYID)
+		    id = (id_t)me->p_ucred->cr_uid;
+		ret = (p->p_ucred->cr_uid == (uid_t)id) ? 1 : 0;
+		break;
+	case P_GID:
+		if (id == P_MYID)
+		    id = (id_t)me->p_ucred->cr_gid;
+		ret = (p->p_ucred->cr_gid == (gid_t)id) ? 1 : 0;
+		break;
+	case P_JAILID:
+		if (p->p_ucred->cr_prison == NULL)
+			return (0);
+		if (id == P_MYID) {
+			if (me->p_ucred->cr_prison == NULL)
+				return (0);
+			id = (id_t) me->p_ucred->cr_prison->pr_id;
+		}
+		ret = (p->p_ucred->cr_prison->pr_id == (int)id) ? 1 : 0;
+		break;
+	default:
+		/*
+		 * Currently no support for
+		 * P_CID, P_CPUID, P_PSETID, P_POOLID,
+		 * P_LWPID, P_CTID, P_TASKID, P_PROJID,
+		 * usw.
+		 */
+		return (0);
+		break;
+	}
+	return (ret);
+}
+
+static int
+supported_sigsend_idtype (idtype)
+	idtype_t idtype;
+{
+	switch (idtype) {
+	case P_ALL:
+	case P_PID:
+	case P_PGID:
+	case P_SID:
+	case P_UID:
+	case P_GID:
+	case P_JAILID:
+		return (1);
+		break;
+	default:
+		/*
+		 * Currently no support for
+		 * P_CID, P_CPUID, P_PSETID, P_POOLID,
+		 * P_LWPID, P_CTID, P_TASKID, P_PROJID,
+		 * usw.
+		 */
+		break;
+	}
+	return (0);
+}
+
 int
+kern_sigsendset (td, ps, sig)
+	struct thread *td;
+	procset_t *ps;
+	int sig;
+{
+	ksiginfo_t ksi;
+	struct proc *p;
+	struct proc *me;
+	int error;
+	int ret;
+	int lmatch;
+	int rmatch;
+
+	if ((u_int)sig > _SIG_MAXSIG)
+		return (EINVAL);
+
+	AUDIT_ARG_SIGNUM(sig);
+	AUDIT_ARG_VALUE(ps->p_op);	/* XXX These 5 may be wrong! */
+	AUDIT_ARG_VALUE(ps->p_lidtype);
+	AUDIT_ARG_VALUE(ps->p_lid);
+	AUDIT_ARG_VALUE(ps->p_ridtype);
+	AUDIT_ARG_VALUE(ps->p_rid);
+
+	if (!supported_sigsend_idtype(ps->p_lidtype) ||
+	    !supported_sigsend_idtype(ps->p_ridtype))
+		return (EINVAL);
+
+	switch (ps->p_op) {
+	case POP_AND:
+	case POP_DIFF:
+	case POP_OR:
+	case POP_XOR:
+		break;
+	default:
+		return (EINVAL);
+		break;
+	}
+
+	ksiginfo_init(&ksi);
+	ksi.ksi_signo = sig;
+	ksi.ksi_code = SI_USER;
+	ksi.ksi_pid = td->td_proc->p_pid;
+	ksi.ksi_uid = td->td_ucred->cr_ruid;
+
+	me = td->td_proc;
+
+	ret = ESRCH;
+	sx_slock(&allproc_lock);
+	FOREACH_PROC_IN_SYSTEM(p) {
+		PROC_LOCK(p);
+		PROC_LOCK(me);
+
+		/*
+		 * Short circuit out all those processes which
+		 * we do not wish to touch in any case.
+		 *
+		 * This is simply for readability.
+		 * The compiler will certainly optimize these to
+		 * one larger OR condition block with a single body.
+		 */
+
+		if ((p->p_pid == 0) || 
+		    ((p->p_flag & P_SYSTEM) || (p->p_state == PRS_NEW))) {
+			PROC_UNLOCK(me);
+			PROC_UNLOCK(p);
+			continue;
+		}
+		else if ((ps->p_lidtype != P_PID) &&
+			 ((p == me) || (p->p_pid == 1))) {
+			PROC_UNLOCK(me);
+			PROC_UNLOCK(p);
+			continue;
+		}
+		else if ((ps->p_ridtype != P_PID) &&
+			 ((p == me) || (p->p_pid == 1))) {
+			PROC_UNLOCK(me);
+			PROC_UNLOCK(p);
+			continue;
+		}
+
+		switch (ps->p_op) {
+		case POP_OR:
+			if (!pr_matches_id (me, p,
+					    ps->p_lidtype, ps->p_lid) &&
+			    !pr_matches_id (me, p,
+					    ps->p_ridtype, ps->p_rid)) {
+				PROC_UNLOCK(me);
+				PROC_UNLOCK(p);
+				continue;
+			}
+			break;
+		case POP_AND:
+			if (!pr_matches_id (me, p,
+					    ps->p_lidtype, ps->p_lid) ||
+			    !pr_matches_id (me, p,
+					    ps->p_ridtype, ps->p_rid)) {
+				PROC_UNLOCK(me);
+				PROC_UNLOCK(p);
+				continue;
+			}
+			break;
+		case POP_DIFF:
+			if (!pr_matches_id (me, p,
+					    ps->p_lidtype, ps->p_lid) ||
+			    pr_matches_id (me, p,
+					   ps->p_ridtype, ps->p_rid)) {
+				PROC_UNLOCK(me);
+				PROC_UNLOCK(p);
+				continue;
+			}
+			break;
+		case POP_XOR:
+			lmatch = pr_matches_id (me, p,
+						ps->p_lidtype, ps->p_lid);
+			rmatch = pr_matches_id (me, p,
+						ps->p_ridtype, ps->p_rid);
+			/*
+			 *  NOTE! - The values are always either 0 or 1.
+			 *  So, we can use binary XOR here.
+			 */
+			if (! (lmatch ^ rmatch)) {
+				PROC_UNLOCK(me);
+				PROC_UNLOCK(p);
+				continue;
+			}
+			break;
+		default:
+			/*
+			 * We should never get here!
+			 */
+			PROC_UNLOCK(me);
+			PROC_UNLOCK(p);
+			ret = EINVAL;
+			goto Cleanup;
+			break;
+		}
+
+		PROC_UNLOCK(me);
+
+		error = p_cansignal(td, p, sig);
+		if (error == 0) {
+			if (sig)
+				pksignal(p, sig, &ksi);
+			ret = 0;
+		}
+		else if (ret == ESRCH)
+			ret = error;
+
+		PROC_UNLOCK(p);
+	}
+Cleanup:
+	sx_sunlock(&allproc_lock);
+	return (ret);
+}
+
+#ifndef _SYS_SYSPROTO_H_
+struct sigsendset_args {
+	procset_t   *psp;
+	int	    sig;
+};
+#endif
+int
+sys_sigsendset (td, uap)
+	struct thread *td;
+	struct sigsendset_args *uap;
+{
+	int error;
+	procset_t pset;
+
+	if ((u_int)uap->sig > _SIG_MAXSIG)
+		return (EINVAL);
+
+	if (uap->psp == NULL)
+		return (EFAULT);
+
+	error = copyin(uap->psp, &pset, sizeof (pset));
+	if (error != 0)
+		return (error);
+
+	return (kern_sigsendset (td, &pset, uap->sig));
+}
+
+int
 sys_pdkill(td, uap)
 	struct thread *td;
 	struct pdkill_args *uap;
Index: sys/compat/freebsd32/freebsd32.h
===================================================================
--- sys/compat/freebsd32/freebsd32.h	(revision 253515)
+++ sys/compat/freebsd32/freebsd32.h	(working copy)
@@ -89,6 +89,16 @@
 	struct timeval32 it_value;
 };
 
+struct procset32 {
+	int32_t	p_op;
+	int32_t p_lidtype;
+	int32_t p_lid1;
+	int32_t p_lid2;
+	int32_t p_ridtype;
+	int32_t p_rid1;
+	int32_t p_rid2;
+};
+
 #define FREEBSD4_MNAMELEN        (88 - 2 * sizeof(int32_t)) /* size of on/from name bufs */
 
 /* 4.x version */
Index: sys/compat/freebsd32/freebsd32_misc.c
===================================================================
--- sys/compat/freebsd32/freebsd32_misc.c	(revision 253515)
+++ sys/compat/freebsd32/freebsd32_misc.c	(working copy)
@@ -210,6 +210,31 @@
 	return (error);
 }
 
+int
+freebsd32_sigsendset (td, uap)
+	struct thread *td;
+	struct freebsd32_sigsendset_args *uap;
+{
+	int error;
+	procset_t pset;
+	struct procset32 pset32;
+
+	if (uap->psp == NULL)
+		return (EFAULT);
+
+	error = copyin(uap->psp, &pset32, sizeof (pset32));
+	if (error != 0)
+		return (error);
+
+	pset.p_op = pset32.p_op;
+	pset.p_lidtype = pset32.p_lidtype;
+	pset.p_lid = (id_t) PAIR32TO64 (int64_t, pset32.p_lid);
+	pset.p_ridtype = pset32.p_ridtype;
+	pset.p_rid = (id_t) PAIR32TO64 (int64_t, pset32.p_rid);
+
+	return (kern_sigsendset (td, &pset, uap->sig));
+}
+
 #ifdef COMPAT_FREEBSD4
 static void
 copy_statfs(struct statfs *in, struct statfs32 *out)
--- /dev/null	2013-07-14 20:33:01.319644342 +0300
+++ sys/sys/_idtype.h	2013-07-14 12:11:32.250746532 +0300
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2012-2013 Jukka A. Ukkonen
+ *	All rights reserved.
+ *
+ * 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 ``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 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: stable/9/sys/sys/_idtype.h 244172 2012-12-13 06:17:05Z jau $
+ */
+
+#ifndef	_SYS__IDTYPE_H_
+#define	_SYS__IDTYPE_H_
+
+#ifndef _IDTYPE_T_DECLARED
+typedef enum
+#if __BSD_VISIBLE
+	idtype		/* pollutes XPG4.2 namespace */
+#endif
+		{
+	/*
+	 * These names were mostly lifted from Solaris source code and
+	 * still use Solaris style naming to avoid breaking any
+	 * OpenSolaris code which has been ported to FreeBSD.  There
+	 * is no clear FreeBSD counterpart for all of the names, but
+	 * some have a clear correspondence to FreeBSD entities.
+	 *
+	 * The numerical values are kept synchronized with the Solaris
+	 * values.
+	 */
+	P_PID,			/* A process identifier. */
+	P_PPID,			/* A parent process identifier.	*/
+	P_PGID,			/* A process group identifier. */
+	P_SID,			/* A session identifier. */
+	P_CID,			/* A scheduling class identifier. */
+	P_UID,			/* A user identifier. */
+	P_GID,			/* A group identifier. */
+	P_ALL,			/* All processes. */
+	P_LWPID,		/* An LWP identifier. */
+	P_TASKID,		/* A task identifier. */
+	P_PROJID,		/* A project identifier. */
+	P_POOLID,		/* A pool identifier. */
+	P_JAILID,		/* A zone identifier. */
+	P_CTID,			/* A (process) contract identifier. */
+	P_CPUID,		/* CPU identifier. */
+	P_PSETID		/* Processor set identifier. */
+} idtype_t;			/* The type of id_t we are using. */
+
+#if __BSD_VISIBLE
+#define	P_ZONEID	P_JAILID
+#endif
+#define	_IDTYPE_T_DECLARED
+#endif
+
+#endif
--- /dev/null	2013-07-14 20:36:10.172402008 +0300
+++ sys/sys/procset.h	2013-07-14 20:37:56.841311890 +0300
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2012-2013 Jukka A. Ukkonen
+ *	All rights reserved.
+ *
+ * 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 ``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 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: stable/9/sys/sys/procset.h 244172 2012-12-13 06:17:05Z jau $
+ */
+
+#ifndef	_SYS_PROCSET_H_
+#define	_SYS_PROCSET_H_
+
+#include <sys/types.h>
+#include <sys/_idtype.h>
+
+typedef	enum {
+    POP_OR, POP_AND, POP_XOR, POP_DIFF, 
+} idop_t;
+
+struct __procset {
+    idop_t	p_op;
+    idtype_t	p_lidtype;
+    id_t	p_lid;
+    idtype_t	p_ridtype;
+    id_t	p_rid;
+};
+
+typedef struct __procset    procset_t;
+
+/*
+ *  Notice!
+ *  The true process ID 0 would be anyhow excluded as a target.
+ */
+
+#define	P_MYID	0
+
+#endif
--- /dev/null	2013-07-17 12:22:00.310404771 +0300
+++ lib/libc/sys/sigsendset.2	2013-07-17 12:23:35.791016650 +0300
@@ -0,0 +1,381 @@
+.\" Copyright (c) 2012-2013  Jukka A. Ukkonen
+.\"	All rights reserved.
+.\"
+.\" 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 ``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 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: stable/9/lib/libc/sys/sigsendset.2 241224 2012-10-05 14:20:53Z jau $
+.\"
+.Dd July 14, 2013
+.Dt SIGSENDSET 2
+.Os
+.Sh NAME
+.Nm sigsend ,
+.Nm sigsendset
+.Nd send a signal to a process or a group of processes
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In signal.h
+.Bd -literal
+struct __procset {
+        idop_t      p_op;
+        idtype_t    p_lidtype;
+        id_t        p_lid;
+        idtype_t    p_ridtype;
+        id_t        p_rid;
+};
+
+typedef struct __procset    procset_t;
+.Ed
+.Ft int
+.Fo sigsend
+.Fa "idtype_t idtype"
+.Fa "id_t id"
+.Fa "int sig"
+.Fc
+.Ft int
+.Fo sigsendset
+.Fa "procset_t *pset"
+.Fa "int sig"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn sigsend
+function sends a signal to the process or group of processes specified
+by
+.Fa id
+and
+.Fa idtype .
+The signal to be sent is specified by sig and is either 0 or one of
+the values listed in
+.In signal.h .
+If
+.Fa sig
+is
+.Dv 0
+(the null signal), error checking is performed but no signal is actually sent.
+This value can be used to check the validity of
+.Fa id
+and
+.Fa idtype .
+.Pp
+The real or effective user
+.Nm ID
+of the the sending process must match the real or saved user ID of
+ the receiving process, unless the sender is
+.Nm root
+or alternatively privileged through some privilege policy to send signals
+to processes owned by other UIDs.
+The signal can also be sent when 
+.Fa sig
+is
+.Dv SIGCONT
+and the sending  process has the same session ID as the receiving process.
+.Pp
+If
+.Fa idtype
+is
+.Dv P_PID ,
+.Fa sig
+is sent to the process with process
+.Nm ID
+.Fa id .
+.Pp
+If
+.Fa idtype
+is
+.Dv P_PGID ,
+.Fa sig
+is sent to all the processes with process groupd
+.Nm ID
+.Fa id .
+.Pp
+If
+.Fa idtype
+is
+.Dv P_SID ,
+.Fa sig
+is sent to all the processes with session
+.Nm ID
+.Fa id .
+.\" // No task consept in FreeBSD yet.
+.\" .Pp
+.\" If
+.\" .Fa idtype
+.\" is
+.\" .Dv P_TASKID ,
+.\" .Fa sig
+.\" is sent to all the processes with task
+.\" .Nm ID
+.\" .Fa id .
+.Pp
+If
+.Fa idtype
+is
+.Dv P_UID ,
+.Fa sig
+is sent to all processes with effective user
+.Nm ID
+.Fa id .
+.Pp
+If
+.Fa idtype
+is
+.Dv P_GID ,
+.Fa sig
+is sent to all processes with effective group
+.Nm ID
+.Fa id .
+.\" // No project consept in FreeBSD yet.
+.\" .Pp
+.\" If
+.\" .Fa idtype
+.\" is
+.\" .Dv P_PROJID ,
+.\" .Fa sig
+.\" is sent to all the processes with project
+.\" .Nm ID
+.\" .Fa id .
+.\" // The CID a.k.a. the scheduling class would be otherwise easy
+.\" // but at the moment all scheduling class info is in the thread
+.\" // structures.
+.\" // Thus the process has no unique or primary scheduling class
+.\" // of its own. :(
+.\" .Pp
+.\" If
+.\" .Fa idtype
+.\" is
+.\" .Dv P_CID ,
+.\" .Fa sig
+.\" is sent to all the processes with scheduler class
+.\" .Nm ID
+.\" .Fa id .
+.\" // No contract consept in FreeBSD yet.
+.\" .Pp
+.\" If
+.\" .Fa idtype
+.\" is
+.\" .Dv P_CTID ,
+.\" .Fa sig
+.\" is sent to all the processes with process contract
+.\" .Nm ID
+.\" .Fa id .
+.Pp
+If
+.Fa idtype
+is
+.Dv P_JAILID ,
+.Fa sig
+is sent to all processes running in jail
+.Nm ID
+.Fa id .
+.Pp
+If
+.Fa idtype
+is
+.Dv P_ALL ,
+.Fa sig
+is sent to all processes that fall within the sender's privileges
+and 
+.Fa id
+is ignored.
+.Pp
+If
+.Fa id
+is
+.Dv P_MYID ,
+the value of
+.Fa id 
+is taken from the current process.
+.Pp
+The process with a process 
+.Nm ID
+of
+.Dv 0
+always excluded.
+The process with a process
+.Nm ID
+of
+.Dv 1
+is excluded unless the
+.Fa idtype
+is equal to
+.Dv P_PID .
+.Pp
+The
+.Fn sigsendset
+function provides an alternate interface for sending signals to sets of
+processes. This function sends signals to the set of processes specified by
+.Fa pset .
+.Fa pset
+is a pointer to a structure of type
+.Nm procset_t ,
+defined in
+.In sys/procset.h ,
+which includes the members shown in the
+.Nm SYNOPSIS
+section above.
+.Pp
+The
+.Fa p_lidtype
+and
+.Fa p_lid
+members specify the
+.Nm ID
+type and
+.Nm ID
+of the "left" set of processes; the
+.Fa p_ridtype
+and
+.Fa p_rid
+members specify the
+.Nm ID
+type and
+.Nm ID
+of the "right" set of processes.
+ID types and IDs are specified just as for the
+.Fa idtype
+and
+.Fa id
+arguments to
+.Fn sigsend .
+The
+.Fa p_op
+member specifies the operation to be performed on the two sets of
+processes to get the set of processes the function is to apply to.
+The valid value for
+.Fa p_op
+and the processes they specify are:
+.Bl -tag -width Nm
+.It Nm POP_DIFF
+Set difference: processes in left set and not in right set.
+.It Nm POP_AND
+Set intersection: processes in both left and right sets.
+.It Nm POP_OR
+Set union: processes in either left or right set or in both.
+.It Nm POP_XOR
+Set exclusive-or: processes in either left or right set but in both.
+.El
+.Sh RETURN VALUES
+.Rv -std sigsend sigsendset
+.Sh ERRORS
+The
+.Fn sigsend
+and
+.Fn sigsendset
+functions will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa sig
+argument is not a valid signal number, or the
+.Fa idtype
+argument is not a supported idtype.
+.It Bq Er EINVAL
+The
+.Fa sig
+argument is
+.Dv SIGKILL ,
+.Fa idtype
+is
+.Dv P_PID
+and
+.Fa id
+is
+.Dv 1 .
+.It Bq Er EPERM
+The  effective user of the calling process does not
+match the real or saved user ID of the receiving
+process, the calling process does not have sufficient
+privileges \fI(root)\fP, and the calling process is
+not sending
+.Dv SIGCONT
+to a process that shares the same session ID.
+.sp
+The calling process does not have sufficient privileges
+\fI(root)\fP and is trying to send a signal to a process
+with a different session ID, even though the effective
+user ID of the sender matches the real or saved ID of
+the receiving process.
+.It Bq Er ESRCH
+No process can be found corresponding to that specified by
+.Fa idtype
+and
+.Fa id .
+.El
+.Pp
+The
+.Fn sigsendset
+function will also fail if:
+.Bl -tag -width Er
+.It Bq Er EFAULT
+The
+.Fa pset
+argument points to an illegal address.
+.El
+.Sh SEE ALSO
+.Xr kill 1 ,
+.Xr kill 2 ,
+.Xr getpid 2 ,
+.Xr signal 2 ,
+.Xr sigaction 2 ,
+.Xr wait 2
+.Sh STANDARDS
+The functions
+.Fn sigsend
+and
+.Fn sigsendset
+are not required by any standards.
+They are compatibility functions only.
+These functions have been previously present
+in multiple commercial
+.Ux
+versions.
+At least
+.Nm SunOS/Solaris ,
+.Nm HP-UX ,
+.Nm IRIX ,
+and
+.Nm Tru64
+are examples of vendors which have included
+these functions in their standard libraries.
+.Sh NOTE
+Though these functions provide flexibility and convenience in sending
+signals to a large number of processes in a single function call and
+though they allow specifying target processes using also other ID types
+than
+.Dv P_PID ,
+.Dv P_PGID ,
+and
+.Dv P_ALL
+which are available through the traditional
+.Fn kill ,
+using them in your code may limit portability
+to operating systems which do not provide these
+functions. \fI(e.g. Linux and AIX)\fP
+.Sh AUTHOR
+These APIs were implemented by Jukka A. Ukkonen, 2012-2013.
+.sp
+This manual page was converted to mdoc
+by Jukka A. Ukkonen, 2013,
+from its Solaris counterpart.
+A few changes were introduced in the process.
--- /dev/null	2013-07-17 19:55:01.240877948 +0300
+++ lib/libc/gen/sigsend.c	2013-07-17 19:56:30.403223006 +0300
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2012-2013 Jukka A. Ukkonen
+ *	All rights reserved.
+ *
+ * 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 ``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 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: stable/9/sys/sys/_idtype.h 244172 2012-12-13 06:17:05Z jau $
+ */
+
+#include "namespace.h"
+#include <sys/procset.h>
+#include <signal.h>
+#include "un-namespace.h"
+
+int
+__sigsend (idtype, id, sig)
+    idtype_t	idtype;
+    id_t	id;
+    int		sig;
+{
+    procset_t	pset;
+
+    pset.p_op = POP_OR;
+    pset.p_lidtype = pset.p_ridtype = idtype;
+    pset.p_lid = pset.p_rid = id;
+
+    return (_sigsendset (&pset, sig));
+}
+
+__weak_reference(__sigsend, sigsend);
+__weak_reference(__sigsend, _sigsend);


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list