Diff for /embedtools/src/wdog.c between versions 1.1 and 1.2

version 1.1, 2010/10/16 03:30:51 version 1.2, 2011/06/08 12:45:41
Line 0 Line 1
   /*************************************************************************
    * (C) 2010 AITNET - Sofia/Bulgaria - <office@aitbg.com>
    *  by Michael Pounov <misho@aitbg.com>
    *
    * $Author$
    * $Id$
    *
    *************************************************************************/
   #include "global.h"
   
   
   int Verbose, Kill, Log;
   extern char compiled[], compiledby[], compilehost[];
   
   
   static void
   Usage()
   {
   
           printf( "WatchDog tool for risk process managment\n"
                   "=== %s === %s@%s ===\n\n"
                   "  Syntax: wdog [options] [exec_file]\n\n"
                   "\t-v\t\tVerbose ...\n"
                   "\t-c <dir>\tBefore execute chroot to dir [default=/]\n"
                   "\t-u <user>\tBefore execute change user\n"
                   "\t-P\t\tInfinit loop, bypass penalty timeout\n"
                   "\t-S\t\tDisable send log events to syslog\n"
                   "\n", compiled, compiledby, compilehost);
   }
   
   static void
   sigHand(int sig)
   {
           int stat;
   
           switch (sig) {
                   case SIGTERM:
                           Kill++;
                           break;
                   case SIGCHLD:
                           while (waitpid(-1, &stat, WNOHANG) > 0);
                           break;
           }
   }
   
   static void
   logmsg(int prio, const char *fmt, ...)
   {
           va_list lst;
   
           va_start(lst, fmt);
           if (!Log)
                   vsyslog(prio, fmt, lst);
           else
                   vprintf(fmt, lst);
           va_end(lst);
   }
   
   
   int
   main(int argc, char **argv)
   {
           char ch, bypass = 0, szChroot[MAXPATHLEN] = DEFAULT_CHROOT;
           int status = 0, ret = 1;
           struct sigaction sa;
           struct passwd *pass = NULL;
           u_int penalty = 1;
           uid_t uid = getuid();
   
           while ((ch = getopt(argc, argv, "vhSPc:u:")) != -1)
                   switch (ch) {
                           case 'v':
                                   Verbose++;
                                   break;
                           case 'P':
                                   bypass = 1;
                                   break;
                           case 'S':
                                   Log = 1;
                                   break;
                           case 'c':
                                   if (uid) {
                                           printf("Error:: can`t chroot, please run as root!\n");
                                           goto end;
                                   }
                                   if (access(optarg, R_OK)) {
                                           printf("Error:: can`t chroot to %s #%d - %s\n", optarg, 
                                                           errno, strerror(errno));
                                           goto end;
                                   } else
                                           strlcpy(szChroot, optarg, MAXPATHLEN);
                                   status |= 1;
                                   break;
                           case 'u':
                                   if (uid) {
                                           printf("Error:: can`t setuid, please run as root!\n");
                                           goto end;
                                   }
                                   pass = getpwnam(optarg);
                                   if (!pass) {
                                           printf("Error:: can`t find user %s\n", optarg);
                                           goto end;
                                   } else
                                           uid = pass->pw_uid;
                                   endpwent();
                                   status |= 2;
                                   break;
                           case 'h':
                           default:
                                   Usage();
                                   goto end;
                   }
           argc -= optind;
           argv += optind;
           if (!argc || !argv || !*argv) {
                   Usage();
                   goto end;
           }
   
           if (!Log)
                   openlog("wdog", LOG_PID, LOG_USER);
   
           VERB(2) logmsg(LOG_NOTICE, "Info:: Chroot=%s Run=%s\n", szChroot, *argv);
   
           memset(&sa, 0, sizeof sa);
           sa.sa_handler = sigHand;
           sigemptyset(&sa.sa_mask);
           sigaction(SIGTERM, &sa, NULL);
           sigaction(SIGCHLD, &sa, NULL);
           sa.sa_handler = SIG_IGN;
           sigaction(SIGHUP, &sa, NULL);
           sigaction(SIGINT, &sa, NULL);
           sigaction(SIGQUIT, &sa, NULL);
           sigaction(SIGPIPE, &sa, NULL);
           sigaction(SIGTSTP, &sa, NULL);
           sigaction(SIGSTOP, &sa, NULL);
           VERB(5) logmsg(LOG_NOTICE, "Info:: Catched signals ...\n");
   
           if (status & 1 && (ret = chroot(szChroot)) == -1) {
                   printf("Error:: error in chroot to %s #%d - %s\n", szChroot, errno, strerror(errno));
                   ret = 3;
                   goto end;
           } else
                   VERB(1) logmsg(LOG_NOTICE, "Info:: chrooted to %s\n", szChroot);
   
           if (status & 2 && setuid(uid) == -1) {
                   printf("Error:: error in setuid to %u #%d - %s\n", uid, errno, strerror(errno));
                   ret = 4;
                   goto end;
           } else
                   VERB(1) logmsg(LOG_NOTICE, "Info:: setuid to %u\n", uid);
   
           status ^= status;
           while (!Kill && penalty) {
                   switch ((ret = fork())) {
                           case -1:
                                   logmsg(LOG_ERR, "Error:: error in fork #%d - %s\n", errno, strerror(errno));
                                   ret = 5;
                                   goto end;
                           case 0:
                                   VERB(3) logmsg(LOG_NOTICE, "Info:: I`m child of shadows ...\n");
                                   if (execvp(*argv, argv) == -1) {
                                           logmsg(LOG_ERR, "Error:: error in exec %s #%d - %s\n", 
                                                           *argv, errno, strerror(errno));
                                           ret = 6;
                                           goto end;
                                   }
                                   /* never reached !!! */
                                   break;
                           default:
                                   wait(&status);
                                   kill(ret, SIGTERM);
                                   ret = status;
                   }
                   /* penalty timeout retry */
                   usleep(penalty);
                   if (!bypass) {
                           penalty <<= 1;
                           VERB(2) logmsg(LOG_NOTICE, "Info:: penalty timeout %u microseconds\n", penalty);
                   }
           }
           if (!penalty)
                   ret = 9;
   end:
           if (!Log)
                   closelog();
           return ret;
   }

Removed from v.1.1  
changed lines
  Added in v.1.2


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