(root)/
util-linux-2.39/
tests/
helpers/
test_sigreceive.c
       1  /*
       2   * SPDX-License-Identifier: GPL-2.0-or-later
       3   *
       4   * test_sigreceive - wait for signal and exit with value of it
       5   *
       6   * Written by Sami Kerola <kerolasa@iki.fi>
       7   */
       8  
       9  #include <err.h>
      10  #include <getopt.h>
      11  #include <pwd.h>
      12  #include <signal.h>
      13  #include <stdio.h>
      14  #include <stdlib.h>
      15  #include <sys/select.h>
      16  #include <sys/types.h>
      17  #include <unistd.h>
      18  
      19  #include "strutils.h"
      20  
      21  #define TEST_SIGRECEIVE_FAILURE 0
      22  
      23  static void __attribute__((__noreturn__)) usage(FILE *out)
      24  {
      25  	fputs("Usage: test_sigreceive [-s|--setuid <login|uid>]\n", out);
      26  	exit(TEST_SIGRECEIVE_FAILURE);
      27  }
      28  
      29  static __attribute__((__noreturn__))
      30  void exiter(int signo __attribute__((__unused__)),
      31  	    siginfo_t *info,
      32  	    void *context __attribute__((__unused__)))
      33  {
      34  	int ret = info->si_signo;
      35  
      36  	if (info->si_code == SI_QUEUE && info->si_value.sival_int != 0)
      37  		ret = info->si_value.sival_int;
      38  	_exit(ret);
      39  }
      40  
      41  int main(int argc, char **argv)
      42  {
      43  	struct sigaction sigact;
      44  	fd_set rfds;
      45  	struct timeval timeout;
      46  	char *user = NULL;
      47  	int c;
      48  
      49  	static const struct option longopts[] = {
      50  		{"setuid", required_argument, NULL, 's'},
      51  		{NULL, 0, NULL, 0}
      52  	};
      53  
      54  	while ((c = getopt_long(argc, argv, "s:h", longopts, NULL)) != -1)
      55  		switch (c) {
      56  		case 's':
      57  			user = optarg;
      58  			break;
      59  		case 'h':
      60  			usage(stdout);
      61  		default:
      62  			usage(stderr);
      63  		}
      64  
      65  	if (user) {
      66  		struct passwd *pw;
      67  		uid_t uid;
      68  
      69  		pw = getpwnam(user);
      70  		if (pw)
      71  			uid = pw->pw_uid;
      72  		else
      73  			uid = strtou32_or_err(user, "failed to parse uid");
      74  		if (setuid(uid) < 0)
      75  			err(TEST_SIGRECEIVE_FAILURE, "setuid failed");
      76  	}
      77  
      78  	sigemptyset(&sigact.sa_mask);
      79  	sigact.sa_flags = SA_SIGINFO;
      80  	sigact.sa_sigaction = exiter;
      81  	timeout.tv_sec = 5;
      82  	timeout.tv_usec = 0;
      83  
      84  	sigaction(SIGINT, &sigact, NULL);
      85  	sigaction(SIGQUIT, &sigact, NULL);
      86  	sigaction(SIGILL, &sigact, NULL);
      87  #ifdef SIGTRAP
      88  	sigaction(SIGTRAP, &sigact, NULL);
      89  #endif
      90  	sigaction(SIGABRT, &sigact, NULL);
      91  #ifdef SIGIOT
      92  	sigaction(SIGIOT, &sigact, NULL);
      93  #endif
      94  #ifdef SIGEMT
      95  	sigaction(SIGEMT, &sigact, NULL);
      96  #endif
      97  #ifdef SIGBUS
      98  	sigaction(SIGBUS, &sigact, NULL);
      99  #endif
     100  	sigaction(SIGFPE, &sigact, NULL);
     101  	sigaction(SIGUSR1, &sigact, NULL);
     102  	sigaction(SIGSEGV, &sigact, NULL);
     103  	sigaction(SIGUSR2, &sigact, NULL);
     104  	sigaction(SIGPIPE, &sigact, NULL);
     105  	sigaction(SIGALRM, &sigact, NULL);
     106  	sigaction(SIGTERM, &sigact, NULL);
     107  #ifdef SIGSTKFLT
     108  	sigaction(SIGSTKFLT, &sigact, NULL);
     109  #endif
     110  	sigaction(SIGCHLD, &sigact, NULL);
     111  #ifdef SIGCLD
     112  	sigaction(SIGCLD, &sigact, NULL);
     113  #endif
     114  	sigaction(SIGCONT, &sigact, NULL);
     115  	sigaction(SIGTSTP, &sigact, NULL);
     116  	sigaction(SIGTTIN, &sigact, NULL);
     117  	sigaction(SIGTTOU, &sigact, NULL);
     118  #ifdef SIGURG
     119  	sigaction(SIGURG, &sigact, NULL);
     120  #endif
     121  #ifdef SIGXCPU
     122  	sigaction(SIGXCPU, &sigact, NULL);
     123  #endif
     124  #ifdef SIGXFSZ
     125  	sigaction(SIGXFSZ, &sigact, NULL);
     126  #endif
     127  #ifdef SIGVTALRM
     128  	sigaction(SIGVTALRM, &sigact, NULL);
     129  #endif
     130  #ifdef SIGPROF
     131  	sigaction(SIGPROF, &sigact, NULL);
     132  #endif
     133  #ifdef SIGWINCH
     134  	sigaction(SIGWINCH, &sigact, NULL);
     135  #endif
     136  #ifdef SIGIO
     137  	sigaction(SIGIO, &sigact, NULL);
     138  #endif
     139  #ifdef SIGPOLL
     140  	sigaction(SIGPOLL, &sigact, NULL);
     141  #endif
     142  #ifdef SIGINFO
     143  	sigaction(SIGINFO, &sigact, NULL);
     144  #endif
     145  #ifdef SIGLOST
     146  	sigaction(SIGLOST, &sigact, NULL);
     147  #endif
     148  #ifdef SIGPWR
     149  	sigaction(SIGPWR, &sigact, NULL);
     150  #endif
     151  #ifdef SIGUNUSED
     152  	sigaction(SIGUNUSED, &sigact, NULL);
     153  #endif
     154  #ifdef SIGSYS
     155  	sigaction(SIGSYS, &sigact, NULL);
     156  #endif
     157  #ifdef SIGRTMIN
     158  	sigaction(SIGRTMIN, &sigact, NULL);
     159  	sigaction(SIGRTMAX, &sigact, NULL);
     160  #endif
     161  	/* Keep SIGHUP last, the bit it flips tells to check script the
     162  	 * helper is ready to be killed.  */
     163  	sigaction(SIGHUP, &sigact, NULL);
     164  
     165  	FD_ZERO(&rfds);
     166  	FD_SET(STDIN_FILENO, &rfds);
     167  	select(0, &rfds, NULL, NULL, &timeout);
     168  
     169  	exit(TEST_SIGRECEIVE_FAILURE);
     170  }