r4549 - developers/zecke/app_restarter
zecke at docs.openmoko.org
zecke at docs.openmoko.org
Tue Jul 22 21:30:17 CEST 2008
Author: zecke
Date: 2008-07-22 21:30:16 +0200 (Tue, 22 Jul 2008)
New Revision: 4549
Added:
developers/zecke/app_restarter/GNUmakefile
Modified:
developers/zecke/app_restarter/app_restarter.c
Log:
app_restarter: Use some e_alert.c code to provide a X11 interface to ask the user
Ask the user if an application should be restarted or not
Added: developers/zecke/app_restarter/GNUmakefile
===================================================================
--- developers/zecke/app_restarter/GNUmakefile (rev 0)
+++ developers/zecke/app_restarter/GNUmakefile 2008-07-22 19:30:16 UTC (rev 4549)
@@ -0,0 +1,2 @@
+app_restarter: app_restarter.o
+ $(CC) -o app_restarter app_restarter.o `pkg-config --libs x11`
Modified: developers/zecke/app_restarter/app_restarter.c
===================================================================
--- developers/zecke/app_restarter/app_restarter.c 2008-07-22 14:29:36 UTC (rev 4548)
+++ developers/zecke/app_restarter/app_restarter.c 2008-07-22 19:30:16 UTC (rev 4549)
@@ -14,15 +14,190 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
+#include <X11/Xlib.h>
+#include <X11/X.h>
+
static void usage(char* name)
{
fprintf(stderr, "%s crash_comment appname [params for app]\n", name);
}
-void fork_and_exec(char* file, int argc, char** argv)
+/*
+ * handle a crash. Open a display connection... create windows...
+ * ...
+ */
+static void handle_crash(int status, const char* question)
{
+ Display* display;
+ Font font;
+ XFontStruct *fs = NULL;
+ GC gc = 0;
+ Window win = 0, b1 = 0, b2 = 0;
+ char *title, *button1, *button2;
+ int wid, hih, mask, fw, fh, mh, button;
+ int ww = 320, hh = 240;
+ char line[1024];
+ int w, i, j, k;
+ XSetWindowAttributes att;
+ XGCValues gcv;
+ XEvent ev;
+ KeyCode key;
+
+ /* create the user interface */
+ display = XOpenDisplay(NULL);
+ if (!display) {
+ fprintf(stderr, "Opening the X display failed\n");
+ exit(-1);
+ }
+
+ font = XLoadFont(display, "fixed");
+ fs = XQueryFont(display, font);
+ if (!fs) {
+ fprintf(stderr, "XQueryFont failed\n");
+ exit(-1);
+ }
+
+ title = "Application Error";
+ button1 = "(F1) Restart";
+ button2 = "(F2) Exit";
+
+ wid = DisplayWidth(display, DefaultScreen(display));
+ hih = DisplayHeight(display, DefaultScreen(display));
+
+
+ att.background_pixel = WhitePixel(display, DefaultScreen(display));
+ att.border_pixel = BlackPixel(display, DefaultScreen(display));
+ att.override_redirect = True;
+ mask = CWBackPixel | CWBorderPixel | CWOverrideRedirect;
+
+ win = XCreateWindow(display, DefaultRootWindow(display),
+ (wid - ww) / 2, (hih - hh) / 2, ww, hh, 0,
+ CopyFromParent, InputOutput,
+ CopyFromParent, mask, &att);
+
+ b1 = XCreateWindow(display, win, -100, -100, 1, 1, 0, CopyFromParent,
+ InputOutput, CopyFromParent, mask, &att);
+ b2 = XCreateWindow(display, win, -100, -100, 1, 1, 0, CopyFromParent,
+ InputOutput, CopyFromParent, mask, &att);
+ XMapWindow(display, b1);
+ XMapWindow(display, b2);
+
+ gc = XCreateGC(display, win, 0, &gcv);
+ XSetForeground(display, gc, att.border_pixel);
+ XSelectInput(display, win, KeyPressMask | KeyReleaseMask | ExposureMask);
+
+ /* place the dialog */
+ XMapWindow(display, win);
+
+
+ /* handle the events */
+ fh = fs->ascent + fs->descent;
+ mh = ((ww - 20) / 2) - 20;
+
+ /* fixed size... */
+ w = 20;
+ XMoveResizeWindow(display, b1, w, hh - 15 - fh, mh + 10, fh + 10);
+ XSelectInput(display, b1, ButtonPressMask | ButtonReleaseMask | ExposureMask);
+ w = ww - 20 - mh;
+ XMoveResizeWindow(display, b2, w, hh - 15 - fh, mh + 10, fh + 10);
+ XSelectInput(display, b2, ButtonPressMask | ButtonReleaseMask | ExposureMask);
+
+ XMapWindow(display, win);
+ XGrabPointer(display, win, True, ButtonPressMask | ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+ XGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
+ XSetInputFocus(display, win, RevertToPointerRoot, CurrentTime);
+ XSync(display, False);
+
+ button = 0;
+ for (; button == 0;) {
+ XNextEvent(display, &ev);
+ switch (ev.type) {
+ case KeyPress:
+ key = XKeysymToKeycode(display, XStringToKeysym("F1"));
+ if (key == ev.xkey.keycode) {
+ button = 1;
+ break;
+ }
+ key = XKeysymToKeycode(display, XStringToKeysym("F2"));
+ if (key == ev.xkey.keycode) {
+ button = 2;
+ break;
+ }
+ break;
+ case ButtonPress:
+ if (ev.xbutton.window == b1)
+ button = 1;
+ else if (ev.xbutton.window == b2)
+ button = 2;
+ break;
+ case Expose:
+ while (XCheckTypedWindowEvent(display, ev.xexpose.window, Expose, &ev));
+
+ /* outline */
+ XDrawRectangle(display, win, gc, 0, 0, ww - 1, hh - 1);
+
+ XDrawRectangle(display, win, gc, 2, 2, ww - 4 - 1, fh + 4 - 1);
+
+ fw = XTextWidth(fs, title, strlen(title));
+ XDrawString(display, win, gc, 2 + 2 + ((ww - 4 - 4 - fw) / 2) , 2 + 2 + fs->ascent, title, strlen(title));
+
+ i = 0;
+ j = 0;
+ k = 2 + fh + 4 + 2;
+ while (question[i]) {
+ line[j++] = question[i++];
+ if (line[j - 1] == '\n') {
+ line[j - 1] = 0;
+ j = 0;
+ XDrawString(display, win, gc, 4, k + fs->ascent, line, strlen(line));
+ k += fh + 2;
+ }
+ }
+ fw = XTextWidth(fs, button2, strlen(button1));
+ XDrawRectangle(display, b1, gc, 0, 0, mh - 1, fh + 10 - 1);
+ XDrawString(display, b1, gc, 5 + ((mh - fw) / 2), 5 + fs->ascent, button1, strlen(button1));
+
+ fw = XTextWidth(fs, button2, strlen(button2));
+ XDrawRectangle(display, b2, gc, 0, 0, mh - 1, fh + 10 - 1);
+ XDrawString(display, b2, gc, 5 + ((mh - fw) / 2), 5 + fs->ascent, button2, strlen(button2));
+
+ XSync(display, False);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+
+ /* destruct the X connection and give up the resources */
+ XDestroyWindow(display, win);
+ XFreeGC(display, gc);
+ XFreeFont(display, fs);
+ XSync(display, False);
+ XCloseDisplay(display);
+
+ switch (button) {
+ case 2:
+ fprintf(stderr, "Was asked to quit. Bye Bye\n");
+ exit(-11);
+ case 1:
+ default:
+ break;
+ }
+}
+
+
+/*
+ * Fork and execute the command, wait for the command to finish.
+ * On any kind of exit ask the user to restart
+ */
+int fork_and_exec(char* file, int argc, char** argv)
+{
pid_t pid = vfork();
if (pid == 0) {
@@ -36,7 +211,10 @@
while (waitpid(pid, &status, 0) != pid);
fprintf(stderr, "The process exited: %d normal: %d\n", status, WIFEXITED(status));
+ return status;
}
+
+ assert(0);
}
int main(int argc, char** argv)
@@ -48,6 +226,11 @@
return EXIT_FAILURE;
}
+ if (strlen(argv[1]) >= 1024) {
+ fprintf(stderr, "The comment string has to be less than 1024 bytes\n");
+ return EXIT_FAILURE;
+ }
+
/* Create a list for execvp with a sentinel */
int commands = argc-3;
char** command_arguments = (char**) malloc(sizeof(char*)*(commands+1));
@@ -55,6 +238,8 @@
command_arguments[i] = argv[2+i];
command_arguments[commands] = NULL;
- for (;;)
- fork_and_exec(argv[2], commands, command_arguments);
+ for (;;) {
+ int status = fork_and_exec(argv[2], commands, command_arguments);
+ handle_crash(status, argv[1]);
+ }
}
More information about the commitlog
mailing list