526 lines
16 KiB
C++
526 lines
16 KiB
C++
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
|||
|
|
//
|
||
// Copyright (c) 2002, Haiku
|
|||
//
|
|||
// This software is part of the Haiku distribution and is covered
|
|||
|
|
// by the MIT license.
|
||
//
|
|||
|
|
// File: shutdown.cpp
|
||
|
|
// Author: Francois Revol ([email protected])
|
||
|
|
// Description: shuts down the system, either halting or rebooting.
|
||
|
|
//
|
||
|
|
// Notes:
|
||
|
|
// This program behaves identically as the BeOS R5 version, with these
|
||
|
|
// added arguments:
|
||
|
|
//
|
||
|
|
// -a alert user while counting down
|
||
|
|
// -c cancels any running shutdown
|
||
|
|
//
|
||
|
|
// There seem to be a race condition (sometimes crashes on quit with
|
||
|
|
// "the looper must be locked"), if you find it, tell me,
|
||
|
|
// tried 3 hours to find it.
|
||
|
|
// Some code from Shard's Archiver from BeBits (was BSD/MIT too :).
|
||
|
|
//
|
||
|
|
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||
|
|
|
||
// ToDo: I think we should remove the shutdown alert again - we already have one
|
|||
|
|
// in the roster, and that should really be enough.
|
||
|
|
// Also, I don't quite see a lot of sense in the delayed shutdown, either -- axeld.
|
||
|
|
|
||
|
|
#include <syscalls.h>
|
||
|
|
|
||
|
|
#include <OS.h>
|
||
#include <Application.h>
|
|||
|
|
#include <Bitmap.h>
|
||
|
|
#include <Button.h>
|
||
|
|
#include <Messenger.h>
|
||
|
|
#include <Mime.h>
|
||
#include <String.h>
|
|||
|
|
#include <StringView.h>
|
||
|
|
#include <View.h>
|
||
|
|
#include <Window.h>
|
||
|
|
|
||
#include <signal.h>
|
|||
|
|
#include <stdio.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include <unistd.h>
|
||
#include <ctype.h>
|
|||
|
|||
// timer should be handled better (with system_time())
|
|||
|
|
#define PULSE_RATE 100000
|
||
|
|
#define PULSE_MODULO 10
|
||
|
|||
//from bdb-ing /bin/shutdown:
|
|||
|
|
#define B_SYSTEM_SHUTDOWN 0x12d
|
||
|
|
#define B_SYSTEM_REBOOT 0x12e
|
||
|
|
|
||
static const char *kRosterSignature = "application/x-vnd.Be-ROST";
|
|||
|
|||
|
|
// globals
|
||
|
|
const char kIconBits[] = {
|
||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00,
|
||
|
|
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
||
|
|
0x00, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00,
|
||
|
|
0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x3f, 0x3f,
|
||
|
|
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x00,
|
||
|
|
0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x2f,
|
||
|
|
0xeb, 0x2f, 0x30, 0x2f, 0x00, 0x00, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0x2f, 0xeb, 0x2c,
|
||
|
|
0x2b, 0x2c, 0x2d, 0x30, 0x2f, 0x2f, 0x00, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x2f, 0x2b, 0x2a,
|
||
|
|
0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x00, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x2f, 0x2b, 0x2b, 0x2a,
|
||
|
|
0x2b, 0x2b, 0x2b, 0x2d, 0x2d, 0x2f, 0x30, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0x3f, 0x00, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x2f, 0x2b, 0x2b, 0x3f,
|
||
|
|
0x2b, 0x2a, 0x2c, 0x2d, 0x2d, 0xeb, 0x30, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x2f, 0x2c, 0x2b, 0x2b,
|
||
|
|
0x2a, 0x2b, 0x2c, 0x2c, 0x2e, 0x2f, 0x2f, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0x00, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x2f, 0x2d, 0x2b, 0x2c,
|
||
|
|
0x2c, 0x2b, 0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0x3f, 0x00, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x2f, 0xeb, 0x2d, 0x2d,
|
||
|
|
0x2c, 0x2c, 0x2d, 0x2d, 0xeb, 0x2f, 0x2f, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x00, 0xff,
|
||
|
|
0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x30, 0x2e, 0x2c,
|
||
|
|
0x2d, 0x2d, 0x2d, 0x2f, 0x2f, 0x2f, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0xff,
|
||
|
|
0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0x2f, 0x2f, 0xeb,
|
||
|
|
0xeb, 0xeb, 0xeb, 0xeb, 0x2f, 0x2f, 0x00, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff,
|
||
|
|
0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x3f, 0x3f, 0x00, 0x00, 0x2f,
|
||
|
|
0x2f, 0x30, 0x2f, 0x2f, 0x00, 0x00, 0x3f, 0x3f, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff,
|
||
|
|
0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x3f, 0x3f, 0x00,
|
||
|
|
0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff,
|
||
|
|
0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x3f,
|
||
|
|
0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff,
|
||
|
|
0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00,
|
||
|
|
0x00, 0x3f, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
||
|
|
0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x00,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||
};
|
|||
|
|
|
||
const char kElectronBits[] = {
|
|||
0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
|
|||
|
|
0xff, 0x00, 0x25, 0x24, 0x26, 0x00, 0xff, 0xff,
|
||
|
|
0x00, 0x25, 0x21, 0x21, 0x22, 0x26, 0x00, 0xff,
|
||
|
|
0x00, 0x21, 0x3f, 0x22, 0x22, 0x25, 0x00, 0xff,
|
||
|
|
0x00, 0x25, 0x22, 0x22, 0x24, 0x24, 0x00, 0xff,
|
||
|
|
0xff, 0x00, 0x23, 0x23, 0x25, 0x00, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
|
||
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||
};
|
|||
|
|
|
||
|
|
#define EL_POS_COUNT 17
|
||
|
|||
static const int electron1_table[][2] = {
|
|||
{3, 8}, {7, 8}, {12, 8}, {17, 10},
|
|||
|
|
{22, 12}, {26, 16}, {28, 20}, {28, 24},
|
||
|
|
{26, 26}, {22, 27}, {18, 26}, {14, 25},
|
||
|
|
{10, 24}, {5, 22}, {3, 18}, {1, 14},
|
||
|
|
{1, 10}, {-1, -1}
|
||
|
|
};
|
||
|
|||
|
|
static const int electron2_table[][2] = {
|
||
{23, 18}, {21, 22}, {18, 25}, {14, 27},
|
|||
|
|
{10, 27}, {5, 26}, {0, 25}, {1, 18},
|
||
|
|
{4, 15}, {8, 12}, {12, 10}, {16, 8},
|
||
|
|
{20, 8}, {24, 9}, {28, 11}, {27, 13},
|
||
|
|
{25, 15}, {-1, -1}
|
||
|
|
};
|
||
|
|||
|
|||
uint32 gTimeToSleep = 0;
|
|||
|
|
bool gReboot = false;
|
||
|
|||
|
|||
|
|
class SView : public BView {
|
||
public:
|
|||
SView(BRect frame);
|
|||
|
|
~SView();
|
||
|
|||
void Draw(BRect updateRect);
|
|||
|
|
void Pulse();
|
||
|
|||
|
|
BButton *fButton;
|
||
|
|
BString *fTitleStr;
|
||
|
|
BStringView *fTitle;
|
||
|
|
|
||
|
|
BBitmap *fIcon;
|
||
BBitmap *fElectron;
|
|||
int fElectronPos;
|
|||
|
|||
int fPulseDivider;
|
|||
|
|||
|
|
int32 fWidth;
|
||
|
|
int32 fHeight;
|
||
|
|
|
||
|
|
int32 fLeftMargin;
|
||
|
|
unsigned long fTimeLeft;
|
||
|
|||
|
|
static const int32 fTopMargin = 8;
|
||
};
|
|||
|
|
|
||
class ShutdownWindow : public BWindow {
|
|||
public:
|
|||
ShutdownWindow(thread_id id);
|
|||
|
|
~ShutdownWindow();
|
||
|
|
|
||
|
|
void MessageReceived(BMessage *msg);
|
||
|
|
bool QuitRequested();
|
||
|
|
|
||
private:
|
|||
SView *fView;
|
|||
|
|
thread_id fShutdownThread;
|
||
};
|
|||
|
|
|
||
class ShutdownApp : public BApplication {
|
|||
public:
|
|||
ShutdownApp(thread_id id);
|
|||
|
|
~ShutdownApp();
|
||
|
|
|
||
private:
|
|||
|
|
ShutdownWindow *fWindow;
|
||
|
|
};
|
||
|
|
|
||
|
|||
SView::SView(BRect frame)
|
|||
|
|
:BView(frame, "SView", B_FOLLOW_LEFT_RIGHT, B_PULSE_NEEDED | B_WILL_DRAW),
|
||
|
|
fButton(NULL),
|
||
|
|
fTitleStr(NULL),
|
||
|
|
fTitle(NULL),
|
||
|
|
fIcon(NULL),
|
||
fElectron(NULL),
|
|||
|
|
fElectronPos(0),
|
||
|
|
fPulseDivider(PULSE_MODULO+1),
|
||
fWidth(0),
|
|||
|
|
fHeight(0),
|
||
|
|
fLeftMargin(B_LARGE_ICON + 8),
|
||
fTimeLeft(gTimeToSleep)
|
|||
{
|
|||
|
|
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||
|
|
SetLowColor(ViewColor());
|
||
|
|
SetDrawingMode(B_OP_OVER);
|
||
|
|
fIcon = new BBitmap(BRect(0, 0, B_LARGE_ICON-1, B_LARGE_ICON-1), B_CMAP8);
|
||
|
|
fIcon->SetBits(kIconBits, B_LARGE_ICON*B_LARGE_ICON, 0, B_CMAP8);
|
||
fElectron = new BBitmap(BRect(0, 0, 7, 7), B_CMAP8);
|
|||
|
|
fElectron->SetBits(kElectronBits, 8*8, 0, B_CMAP8);
|
||
fTitleStr = new BString;
|
|||
if (gReboot)
|
|||
*fTitleStr << "Rebooting in " << (int32)fTimeLeft << " seconds !";
|
|||
|
|
else
|
||
|
|
*fTitleStr << "Shutting down in " << (int32)fTimeLeft << " seconds !";
|
||
|
|||
fTitle = new BStringView(BRect(55, 10, 260, 35), "", fTitleStr->String());
|
|||
|
|
fButton = new BButton(BRect(159, 42, 259, 66), "quit", "Cancel", new BMessage('_QRQ'));
|
||
|
|
fButton->MakeDefault(true);
|
||
|
|
AddChild(fTitle);
|
||
|
|
AddChild(fButton);
|
||
|
|
}
|
||
|
|
|
||
|
|||
SView::~SView()
|
|||
|
|
{
|
||
delete fButton;
|
|||
|
|
delete fTitle;
|
||
|
|
delete fIcon;
|
||
}
|
|||
|
|
|
||
|
|||
void
|
|||
|
|
SView::Pulse()
|
||
|
|
{
|
||
fPulseDivider--;
|
|||
|
|
if (fPulseDivider <= 0) {
|
||
|
|
fPulseDivider = PULSE_MODULO;
|
||
|
|
fTimeLeft--;
|
||
|
|
fTitleStr->SetTo("");
|
||
if (gReboot)
|
|||
*fTitleStr << "Rebooting in " << (int32)fTimeLeft << " seconds !";
|
|||
|
|
else
|
||
|
|
*fTitleStr << "Shutting down in " << (int32)fTimeLeft << " seconds !";
|
||
|
|
fTitle->SetText(fTitleStr->String());
|
||
|
|
}
|
||
|
|
fElectronPos += 1;
|
||
|
|
fElectronPos %= EL_POS_COUNT;
|
||
Invalidate();
|
|||
|
|
}
|
||
|
|
|
||
|
|||
void
|
|||
|
|
SView::Draw(BRect updateRect)
|
||
|
|
{
|
||
|
|
BRect bounds = Bounds();
|
||
|
|
|
||
|
|
// left margin background
|
||
// SetHighColor(tint_color(ViewColor(), B_HIGHLIGHT_BACKGROUND_TINT));
|
|||
|
|
SetHighColor(0xB8, 0xB8, 0xB8); // same color as the registrar shutdown dialog
|
||
FillRect(BRect(0, 0, B_LARGE_ICON, bounds.bottom));
|
|||
|
|||
|
|
if (fIcon != NULL)
|
||
DrawBitmap(fIcon, BPoint((B_LARGE_ICON / 2), fTopMargin));
|
|||
|
|||
|
|
if (fIcon != NULL) {
|
||
DrawBitmap(fElectron, BPoint((B_LARGE_ICON / 2) + electron1_table[fElectronPos][0], fTopMargin + electron1_table[fElectronPos][1]));
|
|||
|
|
DrawBitmap(fElectron, BPoint((B_LARGE_ICON / 2) + electron2_table[fElectronPos][0], fTopMargin + electron2_table[fElectronPos][1]));
|
||
}
|
|||
|
|||
if (Window())
|
|||
|
|
Window()->Flush();
|
||
}
|
|||
|
|
|
||
|
|||
ShutdownWindow::ShutdownWindow(thread_id id)
|
|||
: BWindow(BRect( 139, 81, 407, 156), "Shutdown Status", B_TITLED_WINDOW_LOOK,
|
|||
|
|
B_NORMAL_WINDOW_FEEL,
|
||
|
|
B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS),
|
||
fView(NULL)
|
|||
|
|
{
|
||
|
|
fShutdownThread = id;
|
||
SetPulseRate(PULSE_RATE);
|
|||
fView = new SView(Bounds());
|
|||
|
|
AddChild(fView);
|
||
|
|
}
|
||
|
|
|
||
|
|||
ShutdownWindow::~ShutdownWindow()
|
|||
|
|
{
|
||
|
|
fView->LockLooper();
|
||
|
|
fView->RemoveSelf();
|
||
|
|
delete fView;
|
||
|
|
}
|
||
|
|
|
||
|
|||
void
|
|||
|
|
ShutdownWindow::MessageReceived(BMessage *msg)
|
||
|
|
{
|
||
switch (msg->what) {
|
|||
default:
|
|||
|
|
BWindow::MessageReceived(msg);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|||
bool
|
|||
|
|
ShutdownWindow::QuitRequested()
|
||
|
|
{
|
||
|
|
SetPulseRate(0);
|
||
|
|
kill(fShutdownThread, SIGUSR1);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|||
ShutdownApp::ShutdownApp(thread_id id)
|
|||
: BApplication("application/x-vnd.ShutDown-app")
|
|||
{
|
|||
|
|
fWindow = new ShutdownWindow(id);
|
||
|
|
fWindow->SetWorkspaces(0xFFFFFFFF);
|
||
|
|
fWindow->Show();
|
||
|
|
}
|
||
|
|
|
||
|
|||
ShutdownApp::~ShutdownApp()
|
|||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|||
|
|
int32
|
||
|
|
app_thread(void *arg)
|
||
{
|
|||
|
|
thread_id tid = (thread_id) arg;
|
||
|
|
(new ShutdownApp(tid))->Run();
|
||
|
|
delete be_app;
|
||
|
|
return B_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|||
|
|
// #pragma mark -
|
||
|
|
|
||
|
|||
// we get here when shutdown is cancelled.
|
|||
|
|
// then sleep() returns
|
||
|
|||
|
|
void
|
||
|
|
handle_usr1(int sig)
|
||
{
|
|||
|
|
while (0);
|
||
|
|
}
|
||
|
|
|
||
|
|||
|
|
bool
|
||
|
|
parseTime(char *arg, char *argv, int32 *_i)
|
||
|
|
{
|
||
|
|
char *unit;
|
||
|
|
|
||
|
|
if (isdigit(arg[0])) {
|
||
|
|
gTimeToSleep = strtoul(arg, &unit, 10);
|
||
|
|
} else if (argv && isdigit(argv[0])) {
|
||
|
|
(*_i)++;
|
||
|
|
gTimeToSleep = strtoul(argv, &unit, 10);
|
||
|
|
} else
|
||
|
|
return false;
|
||
|
|
|
||
|
|
if (unit[0] == '\0' || !strcmp(unit, "s"))
|
||
|
|
return true;
|
||
|
|
if (!strcmp(unit, "m")) {
|
||
|
|
gTimeToSleep *= 60;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void
|
||
|
|
usage(const char *arg0)
|
||
|
|
{
|
||
|
|
const char *program = strrchr(arg0, '/');
|
||
|
|
if (program == NULL)
|
||
|
|
program = arg0;
|
||
|
|
else
|
||
|
|
program++;
|
||
|
|
|
||
|
|
fprintf(stderr, "usage: %s [-rqca] [-d time]\n"
|
||
|
|
"\t-r reboot,\n"
|
||
|
|
"\t-q quick shutdown (don't broadcast apps),\n"
|
||
|
|
"\t-c cancel a running shutdown,\n"
|
||
|
|
"\t-a alerts user while waiting,\n"
|
||
|
|
"\t-d delay shutdown by <time> seconds.\n", program);
|
||
|
|
exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
int
|
||
|
|
main(int argc, char **argv)
|
||
{
|
|||
bool quick = false;
|
|||
|
|
bool alert = false;
|
||
|
|
|
||
|
|
for (int32 i = 1; i < argc; i++) {
|
||
|
|
char *arg = argv[i];
|
||
|
|
if (arg[0] == '-') {
|
||
|
|
if (!isalpha(arg[1]))
|
||
|
|
usage(argv[0]);
|
||
|
|
|
||
|
|
while (arg && isalpha((++arg)[0])) {
|
||
|
|
switch (arg[0]) {
|
||
|
|
case 'q':
|
||
|
|
quick = true;
|
||
|
|
break;
|
||
|
|
case 'r':
|
||
|
|
gReboot = true;
|
||
|
|
break;
|
||
|
|
case 'c':
|
||
|
|
{
|
||
|
|
// find all running shutdown command and signal its shutdown thread
|
||
|
|
|
||
|
|
thread_info threadInfo;
|
||
|
|
get_thread_info(find_thread(NULL), &threadInfo);
|
||
|
|
|
||
|
|
team_id thisTeam = threadInfo.team;
|
||
|
|
|
||
|
|
int32 team_cookie = 0;
|
||
|
|
team_info teamInfo;
|
||
|
|
while (get_next_team_info(&team_cookie, &teamInfo) == B_OK) {
|
||
|
|
if (strstr(teamInfo.args, "shutdown") != NULL && teamInfo.team != thisTeam) {
|
||
|
|
int32 thread_cookie = 0;
|
||
|
|
while (get_next_thread_info(teamInfo.team, &thread_cookie, &threadInfo) == B_OK) {
|
||
|
|
if (!strcmp(threadInfo.name, "shutdown"))
|
||
|
|
kill(threadInfo.thread, SIGUSR1);
|
||
|
|
}
|
||
|
|
}
|
||
}
|
|||
exit(0);
|
|||
|
|
break;
|
||
}
|
|||
case 'a':
|
|||
|
|
alert = true;
|
||
|
|
break;
|
||
|
|
case 'd':
|
||
|
|
if (parseTime(arg + 1, argv[i + 1], &i)) {
|
||
|
|
arg = NULL;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
// supposed to fall through
|
||
|
|
|
||
|
|
default:
|
||
|
|
usage(argv[0]);
|
||
}
|
|||
|
|
}
|
||
} else
|
|||
|
|
usage(argv[0]);
|
||
}
|
|||
|
|
|
||
if (gTimeToSleep > 0) {
|
|||
|
|
thread_id appThread = -1;
|
||
|
|
int32 left;
|
||
|
|||
|
|
signal(SIGUSR1, handle_usr1);
|
||
|
|
|
||
|
|
if (alert) {
|
||
// BApplication::Run() blocks
|
|||
appThread = spawn_thread(app_thread, "ShutdownApp", B_NORMAL_PRIORITY, (void *)find_thread(NULL));
|
|||
|
|
resume_thread(appThread);
|
||
|
|
} else
|
||
|
|
printf("Delaying %s by %lu seconds...\n", gReboot ? "reboot" : "shutdown", gTimeToSleep);
|
||
|
|
|
||
|
|
left = sleep(gTimeToSleep);
|
||
|
|||
|
|
if (alert) {
|
||
|
|
be_app->PostMessage(B_QUIT_REQUESTED);
|
||
|
|||
|
|
status_t err;
|
||
|
|
wait_for_thread(appThread, &err);
|
||
snooze(100000);
|
|||
|
|
}
|
||
|
|||
if (left > 0) {
|
|||
|
|
fprintf(stderr, "Shutdown cancelled.\n");
|
||
exit(0);
|
|||
}
|
|||
|
|
}
|
||
|
|
|
||
|
|
if (quick) {
|
||
_kern_shutdown(gReboot);
|
|||
fprintf(stderr, "Shutdown failed!\n");
|
|||
|
|
return 2;
|
||
|
|
} else {
|
||
BMessenger messenger(kRosterSignature);
|
|||
|
|||
status_t err = messenger.SendMessage(gReboot ? B_SYSTEM_REBOOT : B_SYSTEM_SHUTDOWN);
|
|||
if (err != B_OK) {
|
|||
|
|
fprintf(stderr, "Failed to send message to roster server: %s\n", strerror(err));
|
||
exit(2);
|
|||
}
|
|||
|
|
}
|
||
|
|||
return 0;
|
|||
|
|
}
|
||
|
|
|