/*
* shutdown.c: implementation of shutdown(1) as part of a Cygwin environment
*
* Copyright 1998, 2001, 2003, 2005 Corinna Vinschen,
* bug reports to cygwin@cygwin.com
*
* 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 of the License, 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.
*/
#include
#include
#include
#include
#include
#include
#define is_winnt (GetVersion() < 0x80000000L)
/* The following values must not collide with EWX_* values. */
#define HIBERNATE 32
#define SUSPEND 64
#define ABORT 128
static char *SCCSid = "@(#)shutdown V1.6, Corinna Vinschen, " __DATE__ "\n";
char *myname;
char errbuf[4096];
char *
error (DWORD err)
{
sprintf (errbuf, "Error %lu ", err);
FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, err, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) errbuf + strlen (errbuf),
sizeof (errbuf) - strlen (errbuf), NULL);
return errbuf;
}
int
usage (void)
{
printf ("Usage: %s [OPTION]... time\n", myname);
printf ("Bring the system down.\n\n");
printf (" -f, --force Forces the execution.\n");
printf (" -s, --shutdown The system will shutdown and power off (if supported)\n");
printf (" -r, --reboot The system will reboot.\n");
printf (" -h, --hibernate The system will suspend to disk (if supported)\n");
printf (" -p, --suspend The system will suspend to RAM (if supported)\n");
if (is_winnt)
printf (" -a, --abort Aborts execution of formerly started shutdown.\n");
printf (" --help Display this help and exit.\n");
printf (" --version Output version information and exit.\n");
printf ("\n`time' is either the time in seconds or `+' and the time in minutes or a\n");
printf ("timestamp in the format `hh:mm' or the word \"now\" for an immediate action.\n");
printf ("\nTo reboot is the default if started as `reboot', to hibernate if started\n");
printf ("as `hibernate', to suspend if started as `suspend', to shutdown otherwise.\n");
return 0;
}
WINBASEAPI BOOL WINAPI (*openprocesstoken) (HANDLE, DWORD, PHANDLE);
WINBASEAPI BOOL WINAPI (*adjusttokenprivileges) (HANDLE, BOOL,
PTOKEN_PRIVILEGES, DWORD,
PTOKEN_PRIVILEGES, PDWORD);
WINBASEAPI BOOL WINAPI (*lookupprivilegevalue) (LPCTSTR, LPCTSTR, PLUID);
WINBASEAPI BOOL WINAPI (*reverttoself) (VOID);
BOOL WINAPI (*initiatesystemshutdown) (LPCTSTR, LPCTSTR, DWORD, BOOL, BOOL);
BOOL WINAPI (*abortsystemshutdown) (LPCTSTR);
int
load_funcs (void)
{
HMODULE adv;
if (!is_winnt)
return 0;
if (!(adv = LoadLibrary ("advapi32.dll")))
{
fprintf (stderr, "%s: can't load advapi32.dll: %s\n",
myname, error (GetLastError ()));
return 1;
}
if (!(lookupprivilegevalue = (WINBASEAPI BOOL WINAPI (*)
(LPCTSTR, LPCTSTR, PLUID))
GetProcAddress (adv, "LookupPrivilegeValueA")))
goto err;
if (!(openprocesstoken = (WINBASEAPI BOOL WINAPI (*)
(HANDLE, DWORD, PHANDLE))
GetProcAddress (adv, "OpenProcessToken")))
goto err;
if (!(adjusttokenprivileges = (WINBASEAPI BOOL WINAPI (*)
(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD))
GetProcAddress (adv, "AdjustTokenPrivileges")))
goto err;
if (!(initiatesystemshutdown = (BOOL WINAPI (*)
(LPCTSTR, LPCTSTR, DWORD, BOOL, BOOL))
GetProcAddress (adv, "InitiateSystemShutdownA")))
goto err;
if (!(abortsystemshutdown = (BOOL WINAPI (*)
(LPCTSTR))
GetProcAddress (adv, "AbortSystemShutdownA")))
goto err;
if (!(reverttoself = (WINBASEAPI BOOL WINAPI (*)
(VOID))
GetProcAddress (adv, "RevertToSelf")))
goto err;
return 0;
err:
fprintf (stderr, "%s: can't load symbol from advapi32.dll: %s\n",
myname, error (GetLastError ()));
return 1;
}
int
setprivs (void)
{
HANDLE token;
TOKEN_PRIVILEGES privs;
/* Privileges are not supported on 9x/ME. */
if (!is_winnt)
return 0;
/* If the privilege hasn't been found, we're trying to shutdown anyway. */
if (!lookupprivilegevalue (NULL, SE_SHUTDOWN_NAME, &privs.Privileges[0].Luid))
{
fprintf (stderr, "%s: Warning: can't evaluate privilege: %s\n",
myname, error (GetLastError ()));
return 0;
}
privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
privs.PrivilegeCount = 1;
if (!openprocesstoken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES, &token))
{
fprintf (stderr, "%s: can't open process token: %s\n",
myname, error (GetLastError ()));
return 1;
}
if (!adjusttokenprivileges (token, FALSE, &privs, 0, NULL, NULL))
{
fprintf (stderr, "%s: can't set required privilege: %s\n",
myname, error (GetLastError ()));
return 1;
}
if (GetLastError () == ERROR_NOT_ALL_ASSIGNED)
{
fprintf (stderr, "%s: required privilege not held: %s\n",
myname, error (GetLastError ()));
return 1;
}
if (!reverttoself ())
{
fprintf (stderr, "%s: can't activate required privilege: %s\n",
myname, error (GetLastError ()));
return 1;
}
return 0;
}
struct option longopts[] = {
{"abort", no_argument, NULL, 'a'},
{"force", no_argument, NULL, 'f'},
{"shutdown", no_argument, NULL, 's'},
{"reboot", no_argument, NULL, 'r'},
{"hibernate", no_argument, NULL, 'h'},
{"suspend", no_argument, NULL, 'p'},
{"help", no_argument, NULL, 'H'},
{"version", no_argument, NULL, 'v'},
{0, no_argument, NULL, 0}
};
char opts[] = "afsrhp";
int
main (int argc, char **argv)
{
int c;
long secs = -1;
int action = is_winnt? EWX_POWEROFF : EWX_SHUTDOWN;
int force = 0;
char buf[4096], *arg, *endptr;
DWORD err;
if ((myname = strrchr (argv[0], '/')) || (myname = strrchr (argv[0], '\\')))
++myname;
else
myname = argv[0];
if (strrchr (myname, '.'))
*strrchr (myname, '.') = '\0';
if (!strcasecmp (myname, "reboot"))
action = EWX_REBOOT;
else if (!strcasecmp (myname, "hibernate"))
action = HIBERNATE;
else if (!strcasecmp (myname, "suspend"))
action = SUSPEND;
while ((c = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
switch (c)
{
case 'f':
/* EWX_FORCE doesn't work correctly on 9x/ME. */
if (is_winnt)
force = EWX_FORCE;
break;
case 's':
action = is_winnt ? EWX_POWEROFF : EWX_SHUTDOWN;
break;
case 'r':
action = EWX_REBOOT;
break;
case 'h':
action = HIBERNATE;
break;
case 'p':
action = SUSPEND;
break;
case 'a':
if (!is_winnt)
{
fprintf (stderr, "Try `%s --help' for more information.\n", myname);
return 1;
}
action = ABORT;
break;
case 'v':
printf ("%s\n", SCCSid + 4);
printf ("Copyright (C) 2005 Corinna Vinschen\n");
printf ("This is free software; see the source for copying conditions.\n");
printf ("There is NO warranty; not even for MERCHANTABILITY or FITNESS\n");
printf ("FOR A PARTICULAR PURPOSE.\n");
return 0;
case 'H':
return usage ();
default:
fprintf (stderr, "Try `%s --help' for more information.\n", myname);
return 1;
}
if (action != ABORT)
{
if (optind >= argc)
{
fprintf (stderr, "%s: missing arguments\n", myname);
fprintf (stderr, "Try `%s --help' for more information.\n", myname);
return 1;
}
arg = argv[optind];
if (!strcasecmp (arg, "now"))
{
secs = 0;
strcpy (buf, "NOW");
}
else if (arg[0] == '+' && isdigit (arg[1]))
{
/* Leading `+' means time in minutes. */
secs = strtol (arg, &endptr, 10) * 60;
if (*endptr)
secs = -1;
else
sprintf (buf, "in %d minute", secs / 60);
}
else if (isdigit (arg[0]) && strchr (arg + 1, ':'))
{
/* HH:MM, timestamp when to shutdown. */
long hour, minute;
time_t now, then;
struct tm *loc;
hour = strtol (arg, &endptr, 10);
if (*endptr == ':' && hour >= 0 && hour <= 23)
{
minute = strtol (endptr + 1, &endptr, 10);
if (!*endptr && minute >= 0 && minute <= 59)
{
then = now = time (NULL);
loc = localtime (&now);
if (loc->tm_hour > hour
|| (loc->tm_hour == hour && loc->tm_min >= minute))
{
then += 24 * 60 * 60; /* Next day */
loc = localtime (&then);
}
loc->tm_hour = hour;
loc->tm_min = minute;
loc->tm_sec = 0;
then = mktime (loc);
secs = then - now;
sprintf (buf, "at %02d:%02d", hour, minute);
}
}
}
else if (isdigit (arg[0]))
{
/* otherwise time in seconds. */
secs = strtol (arg, &endptr, 10);
if (*endptr)
secs = -1;
else
sprintf (buf, "in %d seconds", secs);
}
if (secs < 0)
{
fprintf (stderr, "%s: Invalid time format.\n", myname);
fprintf (stderr, "Try `%s --help' for more information.\n", myname);
return 2;
}
}
if (load_funcs ())
return 4;
if (setprivs ())
return 3;
if (action != ABORT)
printf ("WARNING!!! System is going down %s\n", buf);
if (action == EWX_POWEROFF || action == EWX_SHUTDOWN || action == EWX_REBOOT)
{
if (is_winnt)
{
if (initiatesystemshutdown (NULL,
"WARNING!!! System is going down",
secs,
force == EWX_FORCE,
action == EWX_REBOOT))
return 0;
}
else if (ExitWindow*** (action | force, 0))
return 0;
}
else if (action == ABORT)
{
if (abortsystemshutdown (NULL))
return 0;
}
else
{
while (secs)
secs = sleep (secs);
if (SetSystemPowerState (action == SUSPEND, force == EWX_FORCE))
return 0;
}
err = GetLastError ();
fprintf (stderr, "%s: Couldn't ", myname);
switch (action)
{
case EWX_POWEROFF:
case EWX_SHUTDOWN:
fprintf (stderr, "shutdown");
break;
case EWX_REBOOT:
fprintf (stderr, "reboot");
break;
case HIBERNATE:
fprintf (stderr, "hibernate");
break;
case SUSPEND:
fprintf (stderr, "suspend");
break;
case ABORT:
fprintf (stderr, "abort");
break;
}
fprintf (stderr, ": %s\n", error (err));
return 3;
}
阅读(2089) | 评论(0) | 转发(0) |