Esempio n. 1
0
File: dm.c Progetto: bbidulock/wdm
void WaitForChild(void)
{
	int pid;
	struct display *d;
	waitType status;
	sigset_t mask, omask;

	sigemptyset(&mask);
	sigaddset(&mask, SIGCHLD);
	sigaddset(&mask, SIGHUP);
	sigprocmask(SIG_BLOCK, &mask, &omask);
	WDMDebug("signals blocked\n");
	if (!ChildReady && !Rescan)
		sigsuspend(&omask);
	ChildReady = 0;
	sigprocmask(SIG_SETMASK, &omask, (sigset_t *) NULL);
	while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
	{
		WDMDebug("Manager wait returns pid: %d sig %d core %d code %d\n", pid, waitSig(status), waitCore(status), waitCode(status));
		if (autoRescan.i)
			RescanIfMod();
		/* SUPPRESS 560 */
		if ((d = FindDisplayByPid(pid))) {
			d->pid = -1;
			switch (waitVal(status)) {
			case UNMANAGE_DISPLAY:
				WDMDebug("Display exited with UNMANAGE_DISPLAY\n");
				StopDisplay(d);
				break;
			case OBEYSESS_DISPLAY:
				d->startTries = 0;
				WDMDebug("Display exited with OBEYSESS_DISPLAY\n");
				if (d->displayType.lifetime != Permanent || d->status == zombie)
					StopDisplay(d);
				else
					RestartDisplay(d, FALSE);
				break;
			default:
				WDMDebug("Display exited with unknown status %d\n", waitVal(status));
				WDMError("Unknown session exit code %d from process %d\n", waitVal(status), pid);
				StopDisplay(d);
				break;
			case OPENFAILED_DISPLAY:
				WDMDebug("Display exited with OPENFAILED_DISPLAY, try %d of %d\n", d->startTries, d->startAttempts);
				WDMError("Display %s cannot be opened\n", d->name);
				/*
				 * no display connection was ever made, tell the
				 * terminal that the open attempt failed
				 */
#ifdef XDMCP
				if (d->displayType.origin == FromXDMCP)
					SendFailed(d, "Cannot open display");
#endif
				if (d->displayType.origin == FromXDMCP || d->status == zombie || ++d->startTries >= d->startAttempts) {
					WDMError("Display %s is being disabled\n", d->name);
					StopDisplay(d);
				} else {
					RestartDisplay(d, TRUE);
				}
				break;
			case RESERVER_DISPLAY:
				d->startTries = 0;
				WDMDebug("Display exited with RESERVER_DISPLAY\n");
				if (d->displayType.origin == FromXDMCP || d->status == zombie)
					StopDisplay(d);
				else
					RestartDisplay(d, TRUE);
				{
					Time_t Time;
					time(&Time);
					WDMDebug("time %i %i\n", (int)Time, (int)d->lastCrash);
					if (d->lastCrash && ((Time - d->lastCrash) < XDM_BROKEN_INTERVAL)) {
						WDMDebug("Server crash frequency too high:" " removing display %s\n", d->name);
						WDMError("Server crash rate too high:" " removing display %s\n", d->name);
						RemoveDisplay(d);
					} else
						d->lastCrash = Time;
				}
				break;
			case waitCompose(SIGTERM, 0, 0):
				WDMDebug("Display exited on SIGTERM, try %d of %d\n", d->startTries, d->startAttempts);
				if (d->displayType.origin == FromXDMCP || d->status == zombie || ++d->startTries >= d->startAttempts) {
					WDMError("Display %s is being disabled\n", d->name);
					StopDisplay(d);
				} else
					RestartDisplay(d, TRUE);
				break;
			case REMANAGE_DISPLAY:
				d->startTries = 0;
				WDMDebug("Display exited with REMANAGE_DISPLAY\n");
				/*
				 * XDMCP will restart the session if the display
				 * requests it
				 */
				if (d->displayType.origin == FromXDMCP || d->status == zombie)
					StopDisplay(d);
				else
					RestartDisplay(d, FALSE);
				break;
			}
		}
		/* SUPPRESS 560 */
		else if ((d = FindDisplayByServerPid(pid))) {
			d->serverPid = -1;
			switch (d->status) {
			case zombie:
				WDMDebug("Zombie server reaped, removing display %s\n", d->name);
				RemoveDisplay(d);
				break;
			case phoenix:
				WDMDebug("Phoenix server arises, restarting display %s\n", d->name);
				d->status = notRunning;
				break;
			case running:
				WDMDebug("Server for display %s terminated unexpectedly, status %d %d\n", d->name, waitVal(status), status);
				WDMError("Server for display %s terminated unexpectedly: %d\n", d->name, waitVal(status));
				d->status = notRunning;
				if (d->pid != -1) {
					WDMDebug("Terminating session pid %d\n", d->pid);
					TerminateProcess(d->pid, SIGTERM);
				}
				break;
			case notRunning:
				WDMDebug("Server exited for notRunning session on display %s\n", d->name);
				break;
			}
		} else {
			WDMDebug("Unknown child termination, status %d\n", waitVal(status));
		}
	}
	StartDisplays();
}
Esempio n. 2
0
int CommandLine::run(int argc, char *argv[])
{
    int32_t ret = 0;
    int32_t err = 0;
    sigset_t oldMask;
    bool needWait = false;
    char pidFile[PATH_MAX + 1] = {0};
    char confName[PATH_MAX + 1] = {0};
    pid_t curPid = 0;
    Args args(argc, argv);
    char *pconf = get_realpath(args.getConfPath(), confName);
    if (_server) {
        fprintf(stderr, "%s is running.\n", _name);
        return -1;
    }
    if (args.isForHelp()) {
        help();
        return 0;
    }
    else if (args.isForLongVersion()) {
        showLongVersion();
        return 0;
    }
    else if (args.isForShortVersion()) {
        showShortVersion();
        return 0;
    }
    sigemptyset(&_mask);
    sigaddset(&_mask, SIGINT);
    sigaddset(&_mask, SIGTERM);
    sigaddset(&_mask, SIGUSR1);
    sigaddset(&_mask, SIGUSR2);
    sigaddset(&_mask, SIGPIPE);
    if ((err=pthread_sigmask(SIG_BLOCK, &_mask, &oldMask))!=0) {
        fprintf(stderr, "Set sigmask error.\n", _name);
        return -1;
    }
    //    register_sig();
    for (char *pTmp=pconf; *pTmp; pTmp++) {
        if (*pTmp == '/') {
            *pTmp='_';
        }
    }
    snprintf(pidFile, strlen(_name)+strlen(pidFileTMPL)+strlen(pconf)+1,
             pidFileTMPL, _name, pconf);
    curPid = getPidFromFile(pidFile);
    if (args.getCommandType() == cmd_unknown
            || strlen(args.getConfPath()) == 0)
    {
        help(-1);
        return -1;
    }
    else if (args.getCommandType() == cmd_stop) {
        if (curPid > 0) {
            if (kill(curPid, SIGTERM)!=0) {
                fprintf(stderr, "kill process error, pid = %ld\n", curPid);
            }
        }
        else {
            fprintf(stderr, "process not running.\n");
        }
        return -1;
    }
    else if (args.getCommandType() == cmd_restart) {
        if (curPid > 0) {
            if (kill(curPid, SIGTERM)!=0) {
                fprintf(stderr, "kill process error, pid = %ld\n", curPid);
                return -1;
            }
            needWait = true;
        }
        else {
            fprintf(stderr, "process not running.\n");
        }
    }
    else if (args.getCommandType() == cmd_start) {
        if (curPid > 0) {
            fprintf(stderr, "process already running."
                    "stop it first. pid=%ld, pidfile=%s\n", curPid, pidFile);
            return -1;
        }
    }
    _server = makeServer();
    if (unlikely(!_server)) {
        alog::Logger::shutdown();
        fprintf(stderr, "create server failed.\n");
    }
    if (args.asDaemon()) {
        if (daemon(1, 1) == -1) {
            fprintf(stderr, "set self process as daemon failed.\n");
        }
    }
    if ((args.getCommandType()==cmd_restart)&&(needWait)) {
        int errnum = 0;
        while (getPidFromFile(pidFile) >= 0) {
            if (errnum > 3000) {
                fprintf(stderr, "shutdown previous server failed: too slow\n");
                if (_server) {
                    delete _server;
                }
                alog::Logger::shutdown();
                return -1;
            }
            usleep(20);
            errnum++;
        }
    }
    if (updatePidFile(pidFile) < 0) {
        fprintf(stderr, "write pid to file %s error\n", pidFile);
        delete _server;
        _server = NULL;
        alog::Logger::shutdown();
        return -1;
    }
    if (strlen(args.getLogConfPath()) > 0) {
        try {
            alog::Configurator::configureLogger(args.getLogConfPath());
        } catch(std::exception &e) {
            fprintf(stderr, "config from '%s' failed, using default root.\n",
                    args.getLogConfPath());
            alog::Configurator::configureRootLogger();
        }
    } else {
        alog::Configurator::configureRootLogger();
    }
    ret = _server->start(args.getConfPath());
    if (ret != KS_SUCCESS) {
        fprintf(stderr, "startting server by `%s' failed(%d).\n",
                args.getConfPath(), ret);
        delete _server;
        _server = NULL;
        alog::Logger::shutdown();
        unlink(pidFile);
        return -2;
    }
    MUTEX_LOCK(G_CMD_LOCK);
    _next = G_CMD_LIST;
    G_CMD_LIST = this;
    MUTEX_UNLOCK(G_CMD_LOCK);
    waitSig();
    _server->wait();
    delete _server;
    _server = NULL;
    alog::Logger::shutdown();
    unlink(pidFile);
    MUTEX_LOCK(G_CMD_LOCK);
    if (G_CMD_LIST == this) {
        G_CMD_LIST = _next;
    }
    else {
        for (CommandLine *prev = G_CMD_LIST; prev; prev = prev->_next) {
            if (prev->_next == this) {
                prev->_next = _next;
                break;
            }
        }
    }
    MUTEX_UNLOCK(G_CMD_LOCK);
    return 0;
}
Esempio n. 3
0
void
WaitForChild (void)
{
    pid_t		pid;
    struct display	*d;
    waitType	status;
    sigset_t mask, omask;

    sigemptyset(&mask);
    sigaddset(&mask, SIGCHLD);
    sigaddset(&mask, SIGHUP);
    sigprocmask(SIG_BLOCK, &mask, &omask);
    Debug ("signals blocked\n");
    if (!ChildReady && !Rescan)
	sigsuspend(&omask);
    ChildReady = 0;
    sigprocmask(SIG_SETMASK, &omask, (sigset_t *)NULL);
    while ((pid = waitpid (-1, &status, WNOHANG)) > 0)
    {
	Debug ("Manager wait returns pid: %d sig %d core %d code %d\n",
	       pid, waitSig(status), waitCore(status), waitCode(status));
	if (autoRescan)
	    RescanIfMod ();
	/* SUPPRESS 560 */
	if ((d = FindDisplayByPid (pid))) {
	    d->pid = -1;
	    switch (waitVal (status)) {
	    case UNMANAGE_DISPLAY:
		Debug ("Display exited with UNMANAGE_DISPLAY\n");
		StopDisplay (d);
		break;
	    case OBEYSESS_DISPLAY:
		d->startTries = 0;
		d->reservTries = 0;
		Debug ("Display exited with OBEYSESS_DISPLAY\n");
		if (d->status == zombie)
		    StopDisplay (d);
		else
		    RestartDisplay (d, FALSE);
		break;
	    case OPENFAILED_DISPLAY:
		Debug ("Display exited with OPENFAILED_DISPLAY, try %d of %d\n",
		       d->startTries, d->startAttempts);
		LogError ("Display %s cannot be opened\n", d->name);
		/*
		 * no display connection was ever made, tell the
		 * terminal that the open attempt failed
		 */
		if (d->status == zombie ||
		    ++d->startTries >= d->startAttempts)
		{
		    LogError ("Display %s is being disabled\n", d->name);
		    StopDisplay (d);
		}
		else
		{
		    RestartDisplay (d, TRUE);
		}
		break;
	    case RESERVER_DISPLAY:
		d->startTries = 0;
		Debug ("Display exited with RESERVER_DISPLAY\n");
		if (d->status == zombie)
		    StopDisplay(d);
		else {
		  Time_t now;
		  int crash;

		  time(&now);
		  crash = d->lastReserv &&
		    ((now - d->lastReserv) < XDM_BROKEN_INTERVAL);
		  Debug("time %lli %lli try %i of %i%s\n", 
			(long long)now, (long long)d->lastReserv,
			d->reservTries, d->reservAttempts,
			crash ? " crash" : "");

		  if (!crash)
		    d->reservTries = 0;

		  if (crash && ++d->reservTries >= d->reservAttempts) {
		    const char *msg =
			"Server crash frequency too high: stopping display";
		    Debug("%s %s\n", msg, d->name);
		    LogError("%s %s\n", msg, d->name);
		    /* For a local X server either:
		     * 1. The server exit was returned by waitpid().  So
		     *    serverPid==-1 => StopDisplay() calls RemoveDisplay()
		     *
		     * 2. The server is in zombie state or still running.  So
		     *    serverPid>1 => StopDisplay()
		     *                   a. sets status=zombie,
		     *                   b. kills the server.
		     *    The next waitpid() returns this zombie server pid
		     *    and the 'case zombie:' below then calls
		     *    RemoveDisplay().
		     */
		    StopDisplay(d);
		  } else {
		    RestartDisplay(d, TRUE);
		  }
		  d->lastReserv = now;
		}
		break;
	    case waitCompose (SIGTERM,0,0):
		Debug ("Display exited on SIGTERM, try %d of %d\n",
			d->startTries, d->startAttempts);
		if (d->status == zombie ||
		    ++d->startTries >= d->startAttempts)
		{
		    /*
		     * During normal xdm shutdown, killed local X servers
		     * can be zombies; this is not an error.
		     */
		    if (d->status == zombie &&
			(d->startTries < d->startAttempts))
			LogInfo ("display %s is being disabled\n", d->name);
		    else
			LogError ("display %s is being disabled\n", d->name);
		    StopDisplay(d);
		} else
		    RestartDisplay (d, TRUE);
		break;
	    case REMANAGE_DISPLAY:
		d->startTries = 0;
		Debug ("Display exited with REMANAGE_DISPLAY\n");
		/*
		 * XDMCP will restart the session if the display
		 * requests it
		 */
		if (d->status == zombie)
		    StopDisplay(d);
		else
		    RestartDisplay (d, FALSE);
		break;
	    default:
		Debug ("Display exited with unknown status %d\n", waitVal(status));
		LogError ("Unknown session exit code %d from process %d\n",
			  waitVal (status), pid);
		StopDisplay (d);
		break;
	    }
	}
	/* SUPPRESS 560 */
	else if ((d = FindDisplayByServerPid (pid)))
	{
	    d->serverPid = -1;
	    switch (d->status)
	    {
	    case zombie:
		Debug ("Zombie server reaped, removing display %s\n", d->name);
		RemoveDisplay (d);
		break;
	    case phoenix:
		Debug ("Phoenix server arises, restarting display %s\n", d->name);
		d->status = notRunning;
		break;
	    case running:
		Debug ("Server for display %s terminated unexpectedly, status %d %d\n", d->name, waitVal (status), status);
		LogError ("Server for display %s terminated unexpectedly: %d\n", d->name, waitVal (status));
		if (d->pid != -1)
		{
		    Debug ("Terminating session pid %d\n", d->pid);
		    kill (d->pid, SIGTERM);
		}
		break;
	    case notRunning:
		Debug ("Server exited for notRunning session on display %s\n", d->name);
		break;
	    }
	}
	else
	{
	    Debug ("Unknown child termination, status %d\n", waitVal (status));
	}
    }
    StartDisplays ();
}
Esempio n. 4
0
/***************************************************************************
 *
 *  Account
 *
 *  update utmp/wtmp files.  
 ***************************************************************************/
void 
Account( struct display *d, char *user, char *line, pid_t pid,
#if NeedWidePrototypes
        int type,
#else
        short type,
#endif /* NeedWidePrototypes */
        waitType exitcode )
{
#if !defined(CSRG_BASED) /* we cannot do this on BSD ... */
    struct utmp utmp;		/* local struct for new entry	   	   */
    struct utmp *u;		/* pointer to entry in utmp file	   */
    int	fd;
    char	buf[32];
    char* user_str = user ? user : "******";
    char* line_str = line ? line : "NULL";
            
#ifdef __PASSWD_ETC
    struct rtmp rtmp;
    struct rtmp *r;
    int tty_slot;
    int rtmp_fd;
#endif

    if (d->utmpId == NULL) return;
    
    switch (type) {
    
    case INIT_PROCESS:	strcpy(buf, "INIT_PROCESS");	break;
    case LOGIN_PROCESS:	strcpy(buf, "LOGIN_PROCESS");	break;
    case USER_PROCESS:	strcpy(buf, "USER_PROCESS");	break;
    case DEAD_PROCESS:	strcpy(buf, "DEAD_PROCESS");	break;
    default:		strcpy(buf, "UNKNOWN");		break;
    }

    Debug("Account: id=%s, user=%s, line=%s, pid=%d, type=%s\n",
	   d->utmpId, user_str, line_str, pid, buf);

#ifdef PAM
    PamAccounting("dtlogin", d->name, d->utmpId, user, 
		        line, pid, type, exitcode);
#else
#   ifdef SUNAUTH
       solaris_accounting("dtlogin", d->name, d->utmpId, user, 
		           line, pid, type, exitcode);
#   endif
#endif

#ifdef sun
    return;
#else
    bzero(&utmp, sizeof(struct utmp));

    strncpy(utmp.ut_id, d->utmpId, sizeof(u->ut_id));
    utmp.ut_type = LOGIN_PROCESS;
    
    setutent();
    if ( (u = getutid(&utmp)) == NULL ) u = &utmp;

    /*
     *  make sure process ID's match if this is DEAD_PROCESS...
     *  don't update an already DEAD_PROCESS...
     */

    if ((type == DEAD_PROCESS && pid != 0 && u->ut_pid != pid) ||
        (type == DEAD_PROCESS && u->ut_type == DEAD_PROCESS)	) {

	endutent();
	return;
    }


    /*
     *  fill in required fields of utmp structure...
     *
     *  Note: for USER_PRCESS the "e_exit" field is overloaded to contain
     *        the method for counting this user. This is used later to
     *        determine if restricted user licenses have been exceeded.
     *	      Currently, an unlimited number of foreign displays can log in.
     */
     
    if (user) strncpy(u->ut_user, user, sizeof(u->ut_user));
    if (line) {
#ifdef _AIX
/*
      For AIX the Init process writes the exact mapped device name for console
      to the utmp file (like hft/0), if a getty on /dev/console record exists
      in the Inittab file.Hitherto, we need to have a similar logic to make
      sure for having the correct entry in the utmp file in order for the correct
      operation of the GettyRunning function. It should be noted that by having
      the correct value in the d->gettyLine field, the utmp file eventuallly
      updated by the Account function in dm.c will have the right value. And
      thus the GettyRunning function returns the appropriate value. So, it
      is important that the following logic be included here for AIX platform
      only.
      Raghu Krovvidi         07.06.93
 */

        if (!strcmp(line,"console")) {
             char *ttynm;
             int fd=0;

             fd = open("/dev/console",O_RDONLY);
             ttynm = ttyname(fd);
             ttynm += 5;
             strcpy(u->ut_line,ttynm);
             close(fd);
        }
	else
             strncpy(u->ut_line, line, sizeof(u->ut_line));
	     
#else
             strncpy(u->ut_line, line, sizeof(u->ut_line));
#endif
    }
    if (pid ) u->ut_pid = pid;
    if (type) {
	u->ut_type = type;
	if (type == DEAD_PROCESS) {
	    u->ut_exit.e_termination = waitSig(exitcode);
	    u->ut_exit.e_exit = waitCode(exitcode);
#ifndef SVR4
	    (void) memset((char *) u->ut_host, '\0', sizeof(u->ut_host));
#endif
	}

 	if (type == LOGIN_PROCESS && d->displayType.location != Local ) {
#ifndef SVR4
 	    strncpy(u->ut_host, d->name, sizeof(u->ut_host));
#endif
#ifdef __hpux
 	    u->ut_addr = 0;
#endif
 	}
 		    
	if (type == USER_PROCESS)
	    u->ut_exit.e_exit = (d->displayType.location == Local ? 1 : 0 );
    }	

    (void) time(&u->ut_time);

    /* 
     * write to utmp...  
     *
     * (Do not close utmp yet. If "u" points to the static structure, it is
     *  cleared upon close. This does not bode well for the following write
     *  to wtmp!)
     */

    pututline(u);


    /*
     *  write the same entry to wtmp...
     */

    if ((fd = open(WTMP_FILE, O_WRONLY | O_APPEND)) >= 0) {
	write(fd, u, sizeof(utmp));
	close(fd);
    }


    /*
     *  close utmp...
     */
     
    endutent();

#ifdef __PASSWD_ETC
    /* Now fill in the "rgy utmp" struct */
    if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line));
    bzero(rtmp.rt_host, sizeof(rtmp.rt_host));
    rtmp.rt_time = u->ut_time;
    r = &rtmp;

    /* Write entry to rtmp */
    tty_slot = ttyslot();

    if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) {
         lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0);
         write(rtmp_fd, (char *) r, sizeof(struct rtmp));
         close(rtmp_fd);
    }
#endif
#if defined(AIXV3) && !defined(_POWER)
	/* Log the lastlogin data ..    RK  09.13.93  */
	/** in AIX 4.1 this is taken care of during authentication **/
    if(type == USER_PROCESS) {
	int loginType;
	char tempTtyName[128];
	char *hostname;

	GetLoginInfo(d, &loginType, tempTtyName, &hostname);
	time(&last_login.stime);

	if(line) {
		Debug("tty_last_login is (line=%s)\n",line);
		last_login.stty = (char *)malloc(strlen(line) + 1);
		strcpy(last_login.stty,line);
	} else {
	    last_login.stty = (char *)malloc(strlen(tempTtyName) + 1);
	    strcpy(last_login.stty,tempTtyName);
	}

        last_login.shost = (char *) malloc (MAXHOSTNAMELEN);
	if (hostname == NULL) {
            gethostname (last_login.shost , MAXHOSTNAMELEN);
	} else {
	    strncpy(last_login.shost, hostname, MAXHOSTNAMELEN);
	    last_login.shost[MAXHOSTNAMELEN -1] = '\0';
	}

	Debug("logging lastlogin entry (user=%s)\n",user);
	dt_lastlogin(user,&last_login); 
	free(last_login.stty);
	free(last_login.shost);
    }
#endif

#endif /* !sun */
#endif /* !CSRG_BASED */
}