File:  [ELWIX - Embedded LightWeight unIX -] / embedtools / src / wdog.c
Revision 1.2: download - view: text, annotated - select for diffs - revision graph
Wed Jun 8 12:45:41 2011 UTC (13 years ago) by misho
Branches: MAIN
CVS tags: tools1_1, TOOLS1_0, HEAD
new ver

    1: /*************************************************************************
    2:  * (C) 2010 AITNET - Sofia/Bulgaria - <office@aitbg.com>
    3:  *  by Michael Pounov <misho@aitbg.com>
    4:  *
    5:  * $Author: misho $
    6:  * $Id: wdog.c,v 1.2 2011/06/08 12:45:41 misho Exp $
    7:  *
    8:  *************************************************************************/
    9: #include "global.h"
   10: 
   11: 
   12: int Verbose, Kill, Log;
   13: extern char compiled[], compiledby[], compilehost[];
   14: 
   15: 
   16: static void
   17: Usage()
   18: {
   19: 
   20: 	printf(	"WatchDog tool for risk process managment\n"
   21: 		"=== %s === %s@%s ===\n\n"
   22: 		"  Syntax: wdog [options] [exec_file]\n\n"
   23: 		"\t-v\t\tVerbose ...\n"
   24: 		"\t-c <dir>\tBefore execute chroot to dir [default=/]\n"
   25: 		"\t-u <user>\tBefore execute change user\n"
   26: 		"\t-P\t\tInfinit loop, bypass penalty timeout\n"
   27: 		"\t-S\t\tDisable send log events to syslog\n"
   28: 		"\n", compiled, compiledby, compilehost);
   29: }
   30: 
   31: static void
   32: sigHand(int sig)
   33: {
   34: 	int stat;
   35: 
   36: 	switch (sig) {
   37: 		case SIGTERM:
   38: 			Kill++;
   39: 			break;
   40: 		case SIGCHLD:
   41: 			while (waitpid(-1, &stat, WNOHANG) > 0);
   42: 			break;
   43: 	}
   44: }
   45: 
   46: static void
   47: logmsg(int prio, const char *fmt, ...)
   48: {
   49: 	va_list lst;
   50: 
   51: 	va_start(lst, fmt);
   52: 	if (!Log)
   53: 		vsyslog(prio, fmt, lst);
   54: 	else
   55: 		vprintf(fmt, lst);
   56: 	va_end(lst);
   57: }
   58: 
   59: 
   60: int
   61: main(int argc, char **argv)
   62: {
   63: 	char ch, bypass = 0, szChroot[MAXPATHLEN] = DEFAULT_CHROOT;
   64: 	int status = 0, ret = 1;
   65: 	struct sigaction sa;
   66: 	struct passwd *pass = NULL;
   67: 	u_int penalty = 1;
   68: 	uid_t uid = getuid();
   69: 
   70: 	while ((ch = getopt(argc, argv, "vhSPc:u:")) != -1)
   71: 		switch (ch) {
   72: 			case 'v':
   73: 				Verbose++;
   74: 				break;
   75: 			case 'P':
   76: 				bypass = 1;
   77: 				break;
   78: 			case 'S':
   79: 				Log = 1;
   80: 				break;
   81: 			case 'c':
   82: 				if (uid) {
   83: 					printf("Error:: can`t chroot, please run as root!\n");
   84: 					goto end;
   85: 				}
   86: 				if (access(optarg, R_OK)) {
   87: 					printf("Error:: can`t chroot to %s #%d - %s\n", optarg, 
   88: 							errno, strerror(errno));
   89: 					goto end;
   90: 				} else
   91: 					strlcpy(szChroot, optarg, MAXPATHLEN);
   92: 				status |= 1;
   93: 				break;
   94: 			case 'u':
   95: 				if (uid) {
   96: 					printf("Error:: can`t setuid, please run as root!\n");
   97: 					goto end;
   98: 				}
   99: 				pass = getpwnam(optarg);
  100: 				if (!pass) {
  101: 					printf("Error:: can`t find user %s\n", optarg);
  102: 					goto end;
  103: 				} else
  104: 					uid = pass->pw_uid;
  105: 				endpwent();
  106: 				status |= 2;
  107: 				break;
  108: 			case 'h':
  109: 			default:
  110: 				Usage();
  111: 				goto end;
  112: 		}
  113: 	argc -= optind;
  114: 	argv += optind;
  115: 	if (!argc || !argv || !*argv) {
  116: 		Usage();
  117: 		goto end;
  118: 	}
  119: 
  120: 	if (!Log)
  121: 		openlog("wdog", LOG_PID, LOG_USER);
  122: 
  123: 	VERB(2) logmsg(LOG_NOTICE, "Info:: Chroot=%s Run=%s\n", szChroot, *argv);
  124: 
  125: 	memset(&sa, 0, sizeof sa);
  126: 	sa.sa_handler = sigHand;
  127: 	sigemptyset(&sa.sa_mask);
  128: 	sigaction(SIGTERM, &sa, NULL);
  129: 	sigaction(SIGCHLD, &sa, NULL);
  130: 	sa.sa_handler = SIG_IGN;
  131: 	sigaction(SIGHUP, &sa, NULL);
  132: 	sigaction(SIGINT, &sa, NULL);
  133: 	sigaction(SIGQUIT, &sa, NULL);
  134: 	sigaction(SIGPIPE, &sa, NULL);
  135: 	sigaction(SIGTSTP, &sa, NULL);
  136: 	sigaction(SIGSTOP, &sa, NULL);
  137: 	VERB(5) logmsg(LOG_NOTICE, "Info:: Catched signals ...\n");
  138: 
  139: 	if (status & 1 && (ret = chroot(szChroot)) == -1) {
  140: 		printf("Error:: error in chroot to %s #%d - %s\n", szChroot, errno, strerror(errno));
  141: 		ret = 3;
  142: 		goto end;
  143: 	} else
  144: 		VERB(1) logmsg(LOG_NOTICE, "Info:: chrooted to %s\n", szChroot);
  145: 
  146: 	if (status & 2 && setuid(uid) == -1) {
  147: 		printf("Error:: error in setuid to %u #%d - %s\n", uid, errno, strerror(errno));
  148: 		ret = 4;
  149: 		goto end;
  150: 	} else
  151: 		VERB(1) logmsg(LOG_NOTICE, "Info:: setuid to %u\n", uid);
  152: 
  153: 	status ^= status;
  154: 	while (!Kill && penalty) {
  155: 		switch ((ret = fork())) {
  156: 			case -1:
  157: 				logmsg(LOG_ERR, "Error:: error in fork #%d - %s\n", errno, strerror(errno));
  158: 				ret = 5;
  159: 				goto end;
  160: 			case 0:
  161: 				VERB(3) logmsg(LOG_NOTICE, "Info:: I`m child of shadows ...\n");
  162: 				if (execvp(*argv, argv) == -1) {
  163: 					logmsg(LOG_ERR, "Error:: error in exec %s #%d - %s\n", 
  164: 							*argv, errno, strerror(errno));
  165: 					ret = 6;
  166: 					goto end;
  167: 				}
  168: 				/* never reached !!! */
  169: 				break;
  170: 			default:
  171: 				wait(&status);
  172: 				kill(ret, SIGTERM);
  173: 				ret = status;
  174: 		}
  175: 		/* penalty timeout retry */
  176: 		usleep(penalty);
  177: 		if (!bypass) {
  178: 			penalty <<= 1;
  179: 			VERB(2) logmsg(LOG_NOTICE, "Info:: penalty timeout %u microseconds\n", penalty);
  180: 		}
  181: 	}
  182: 	if (!penalty)
  183: 		ret = 9;
  184: end:
  185: 	if (!Log)
  186: 		closelog();
  187: 	return ret;
  188: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>