// $Id: rebootmgr.c 923 2004-02-17 19:55:54Z ensc $ // Copyright (C) 2003 Enrico Scholz // based on rebootmgr.cc by Jacques Gelinas // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /* The reboot manager allow a virtual server administrator to request a complete restart of his vserver. This means that all services are terminated, all remaining processes are killed and then all services are started. This is done by issuing /usr/sbin/vserver vserver restart The rebootmgr installs a unix domain socket in each vservers and listen for the reboot messages. All other message are discarded. The unix domain socket is placed in /vservers/N/dev/reboot and is turned immutable. The vreboot utility is used to send the signal from the vserver environment. */ #ifdef HAVE_CONFIG_H # include #endif #include "pathconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include static void usage() { fprintf (stderr,"rebootmgr version %s\n",VERSION); fprintf (stderr,"\n"); fprintf (stderr,"rebootmgr [--pidfile file ] vserver-name [ vserver-name ...]\n"); } static int rebootmgr_opensocket (const char *vname) { int ret = -1; char sockn[PATH_MAX]; int fd = socket (AF_UNIX,SOCK_STREAM,0); sprintf (sockn, DEFAULT_VSERVERDIR "/%s/dev/reboot",vname); unlink (sockn); if (fd == -1){ fprintf (stderr,"Can't create a unix domain socket (%s)\n" ,strerror(errno)); }else{ struct sockaddr_un un; un.sun_family = AF_UNIX; strcpy (un.sun_path,sockn); if (bind(fd,(struct sockaddr*)&un,sizeof(un))==-1){ fprintf (stderr,"Can't bind to file %s (%s)\n",sockn ,strerror(errno)); }else{ int code; chmod (sockn,0600); code = listen (fd,10); if (code == -1){ fprintf (stderr,"Can't listen to file %s (%s)\n",sockn ,strerror(errno)); }else{ ret = fd; } } } return ret; } static int rebootmgr_process (int fd, const char *vname) { int ret = -1; char buf[100]; int len = read (fd,buf,sizeof(buf)-1); // fprintf (stderr,"process %d %s len %d\n",fd,vname,len); if (len > 0){ buf[len] = '\0'; if (strcmp(buf,"reboot\n")==0){ char cmd[1000]; syslog (LOG_NOTICE,"reboot vserver %s\n",vname); snprintf (cmd,sizeof(cmd)-1, SBINDIR "/vserver %s restart >>/var/log/boot.log 2>&1", vname); system (cmd); ret = 0; }else if (strcmp(buf,"halt\n")==0){ char cmd[1000]; syslog (LOG_NOTICE,"halt vserver %s\n",vname); snprintf (cmd,sizeof(cmd)-1, SBINDIR "/vserver %s stop >>/var/log/boot.log 2>&1", vname); system (cmd); ret = 0; }else{ syslog (LOG_ERR,"Invalid request from vserver %s",vname); } } return ret; } int main (int argc, char *argv[]) { int ret = -1; if (argc < 2){ usage(); }else{ int error = 0; int start = 1; int i; int *sockets = alloca(argc * sizeof(int)); openlog ("rebootmgr",LOG_PID,LOG_DAEMON); for (i=0; i maxfd) maxfd = fd; FD_SET (fd,&fdin); } for (i=0; i maxfd) maxfd = fd; FD_SET (fd,&fdin); } ok = select (maxfd+1,&fdin,NULL,NULL,NULL); if (ok <= 0){ break; }else{ int i; int dst = 0; for (i=start; i