Annotation of embedtools/src/wdog.c, revision 1.2
1.2 ! misho 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.1.2.8 2010/10/18 15:06:10 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>