#!/usr/bin/env perl # lincityng.wrapper - Launcher for "lincityng" main program # License: Creative Commons Attribution-NonCommercial-ShareAlike 2.5 # Revision: 091215 # Note: The license indicated above applies to this file. It doesn't # apply to the official version of the target program, or to any file # derived from the official package. #--------------------------------------------------------------------- # license information #--------------------------------------------------------------------- # This section may not be modified except as approved by the author or # licensor, or to make non-content changes such as adjustments to par- # agraph formatting or white space. # This version of this software is distributed under the following # license: # # Creative Commons Attribution-NonCommercial-ShareAlike 2.5 # You may use, modify, and redistribute this software without fees or # royalties, but only under the terms and conditions set forth by the # license. In particular, copies and derived works cannot be used for # commercial purposes. Additionally, the license propagates to copies # and derived works. Furthermore, you must provide attribution "in the # manner specified by the author or licensor". The latter point is # discussed below. # The author [and licensor] hereby specifies that attribution must be # handled in the following manner: a. If the software is interactive, # any About or Credits dialog boxes, windows, or output text provided # by the original version must be preserved and readily accessible to # the end user at runtime. b. If the software is non-interactive, or # if it does not provide About or Credits dialog boxes, windows, or # output text, the operating system and/or desktop environment used # must provide attribution that is visible and/or readily accessible # to the end user at runtime. # The following techniques do not meet the attribution requirements: # Attribution through text files, attribution through printed docu- # mentation, verbal attribution, or postings on external web sites # [i.e., web sites that are not an intrinsic local component of the # operating system or desktop environment used]. These examples are # provided for illustrative purposes only. # It should be noted that trademarks are an additional issue. If this # software uses any trademarks, trademark-related restrictions may # apply. # This is not a complete explanation of the terms and conditions in- # volved. For more information, see the Creative Commons Attribution- # NonCommercial-ShareAlike 2.5 license. #--------------------------------------------------------------------- # explanation #--------------------------------------------------------------------- # 1. Overview. # "lincityng.wrapper" is a wrapper for the main Lincity-NG program # file [which must be named "lincityng.bin"]. This wrapper performs # the following operations: # # a. It optionally verifies that multiple instances of the program # aren't running. If the test is done, and multiple instances # are running, a fatal-error message is displayed. # # b. It optionally verifies that the program isn't running through # VNC. If the test is done, and the program is running through # VNC, a fatal-error message is displayed. # # c. It optionally verifies that direct rendering is available. # If the test is done, and direct rendering isn't available, a # fatal-error message is displayed. # # d. It optionally tries to prevent crashes related to system-mem- # ory issues. Specifically, if memory appears to be low, the # wrapper warns the user and asks for confirmation before run- # ning the main executable. # # e. It optionally sets the SDL environment variable SDL_MOUSE_ # RELATIVE to a specified integer [and exports the variable]. # This fixes mouse-related problems. # # f. It optionally adjusts the standard environment variable LD_ # LIBRARY_PATH [and exports the variable]. This fixes library- # related errors. # # g. It optionally clips the system's Master Volume setting to # predefined minimum and maximum values. # # h. It optionally switches to a specified "run" directory. # # i. If no errors have occurred so far, the wrapper runs the main # executable. # # j. If a crash occurs, the wrapper tries to switch the display # back to a usable state. # # Note: Memory-related crashes may shut down the network [by # terminating name servers, etc.]. The wrapper doesn't try to # fix network problems. # # k. The original Master Volume setting is restored on exit, if # possible. # # l. "xclockmove" is executed, if necessary. # To enable, disable, or configure the tests listed here, edit the # source code and modify the appropriate settings in the "program # parameters" section. #--------------------------------------------------------------------- # 2. Requirements. # Partial list of requirements [not including the main executable]: # # a. Gtk2 # b. Perl # c. Perl-Gtk2 # d. SDL - Used by "setx11dim" # e. glxinfo - Used to check the status of direct rendering # f. getx11dim - Distro-specific utility # g. setx11dim - Ditto # h. resetpcmvol - Ditto # i. LACSUB - Distro-specific Perl-based framework # Note: You should be able to obtain source code for the distro-speci- # fic components from the same site as this file. #--------------------------------------------------------------------- # standard module setup #--------------------------------------------------------------------- require 5.8.1; use strict; use Carp; use warnings; # Trap warnings $SIG {__WARN__} = sub { die @_; }; #--------------------------------------------------------------------- # add CPAN module[s] #--------------------------------------------------------------------- use Gtk2 '-init'; use Gtk2::SimpleList; #--------------------------------------------------------------------- # add LACSUB module[s] #--------------------------------------------------------------------- use LACSUB::GUI ( @LACSUB::GUI::EXPORT_OK ); #--------------------------------------------------------------------- # basic constants #--------------------------------------------------------------------- use constant ZERO => 0; # Zero use constant ONE => 1; # One use constant FALSE => 0; # Boolean FALSE use constant TRUE => 1; # Boolean TRUE #--------------------------------------------------------------------- # program parameters #--------------------------------------------------------------------- my $DIR_BASE = '__META_PREFIX__'; my $IE = 'Internal error'; my $PROGNAME = 'lincityng'; my $REVISION = '080924'; # Revision [or release] string my $ALERT_ICON_PATH = "$DIR_BASE/misc/alert.png"; my $TARGET_EXE = "$DIR_BASE/bin/$PROGNAME.bin"; #--------------------------------------------------------------------- # If you'd like to prohibit multiple instances, set $FLAG_PROHIBIT_ # MULTI_INSTANCE to TRUE. Otherwise, set this flag to FALSE. my $FLAG_PROHIBIT_MULTI_INSTANCE = TRUE; #--------------------------------------------------------------------- # If this program shouldn't try to run under VNC, set $FLAG_PROHIBIT_ # VNC equal to TRUE. Otherwise, set this flag equal to FALSE. my $FLAG_PROHIBIT_VNC = TRUE; #--------------------------------------------------------------------- # If you'd like to enforce a direct-rendering requirement, set $FLAG_ # REQUIRE_DIRECT_RENDERING to TRUE. Otherwise, set this flag to FALSE. my $FLAG_REQUIRE_DIRECT_RENDERING = TRUE; #--------------------------------------------------------------------- # If this program should run "xclockmove" before terminating, set # $FLAG_XCLOCK_MOVE equal to TRUE. Otherwise, set this flag equal to # FALSE. my $FLAG_XCLOCK_MOVE = TRUE; #--------------------------------------------------------------------- # If you'd like to enforce a minimum-memory requirement, set $MIN_ # FREE_KB to a memory-size value (in KB). Otherwise, set this parame- # ter to zero. # If $MIN_FREE_KB specifies a positive integer, this program tries to # estimate the amount of system memory that's available (or that could # be made available). If the estimated amount is less than the speci- # fied amount, it'll warn the user and prompt for confirmation before # proceeding. my $MIN_FREE_KB = 80000; #--------------------------------------------------------------------- # If $SDL_MOUSE_RELATIVE is defined, and it specifies zero or a posi- # tive integer, the wrapper sets the environment variable SDL_MOUSE_ # RELATIVE equal to the specified number [and exports the vari- # able]. Otherwise, the wrapper doesn't look at or change SDL_MOUSE_ # RELATIVE. # This parameter is used to prevent mouse-related problems: # # a. If the main executable uses SDL, and the mouse is slow or # "laggy", try setting $SDL_MOUSE_RELATIVE to ZERO. # # b. If you're experiencing other mouse-related problems, try set- # ting this parameter to ONE. # # c. If these settings cause problems, as opposed to fixing them, # set $SDL_MOUSE_RELATIVE to -1 or undefine it. my $SDL_MOUSE_RELATIVE = -1; #--------------------------------------------------------------------- # If the main executable requires any special LD_LIBRARY_PATH entries, # you can specify them here. Set $EXTRA_LIBPATHS to a colon-delimited # list of absolute directory paths. If there's only one entry, no co- # lons are required. # If no special LD_LIBRARY_PATH entries are required, set $EXTRA_ # LIBPATHS to an empty string. my $EXTRA_LIBPATHS = ""; #--------------------------------------------------------------------- # If you'd like to specify a minimum initial Master Volume level, set # $MINVOL to a positive integer from one to 100. Otherwise, set this # parameter to zero. # If you'd like to specify a maximum initial Master Volume level, set # $MAXVOL to a positive integer from one to 100. Otherwise, set this # parameter to zero. my $MINVOL = ZERO; my $MAXVOL = ZERO; #--------------------------------------------------------------------- # If you'd like to run the main executable from a specific directory, # set $PATH_RUNDIR equal to an absolute path for the directory. Other- # wise, set this parameter equal to an empty string. my $PATH_RUNDIR = ""; #--------------------------------------------------------------------- # main routine #--------------------------------------------------------------------- sub Main { my $data; # Data buffer my $str; # Scratch #--------------------------------------------------------------------- # Initial setup. select STDERR; $| = ONE; # Set flush-on-write mode select STDOUT; $| = ONE; # Ditto [note: this line must be last] #--------------------------------------------------------------------- # Handle multiple-instances test (if enabled). &VerifyNotRunning ( -icon_path => $ALERT_ICON_PATH , -name => $PROGNAME , -pattern_this => ':\d\d\s(perl |)(\S+/|)' . $PROGNAME . '(|\.wrapper)\s' , -pattern_next => ':\d\d\s(perl |)(\S+/|)' . $PROGNAME . '\.bin\s' ) if $FLAG_PROHIBIT_MULTI_INSTANCE; #--------------------------------------------------------------------- # Handle VNC test (if enabled). &AbortIfVNC ( -icon_path => $ALERT_ICON_PATH , -name => $PROGNAME ) if $FLAG_PROHIBIT_VNC; #--------------------------------------------------------------------- # Handle direct-rendering test (if enabled). &AbortUnlessDRI ( -icon_path => $ALERT_ICON_PATH , -name => $PROGNAME ) if $FLAG_REQUIRE_DIRECT_RENDERING; #--------------------------------------------------------------------- # Handle available-memory test (if enabled). &CheckAvailableMemory ( -icon_path => $ALERT_ICON_PATH , -min_free => $MIN_FREE_KB , -name => $PROGNAME ) if defined ($MIN_FREE_KB) && ($MIN_FREE_KB =~ m@^[1-9]\d*\z@); #--------------------------------------------------------------------- # Set SDL_MOUSE_RELATIVE, if necessary. if (defined ($SDL_MOUSE_RELATIVE) && ($SDL_MOUSE_RELATIVE =~ m@^\d+\z@)) { $ENV {SDL_MOUSE_RELATIVE} = $SDL_MOUSE_RELATIVE; } #--------------------------------------------------------------------- # Adjust LD_LIBRARY_PATH, if necessary. if (defined ($EXTRA_LIBPATHS) && length ($EXTRA_LIBPATHS)) { $str = $ENV {LD_LIBRARY_PATH}; $str = "" unless defined $str; $str = "$EXTRA_LIBPATHS:$str"; $str =~ s@^:+@@; $str =~ s@:+\z@@; $str =~ y/:/:/s; $ENV {LD_LIBRARY_PATH} = $str; } #--------------------------------------------------------------------- # Adjust initial volume (if necessary). # Note: This code runs "resetpcmvol" whether or not minimum and/or # maximum volume levels are specified. Reasons: a. "resetpcmvol" may # correct certain problems either way. b. This simplifies the cleanup # code at the end of the wrapper. my $resetshow = '__META_LACUTIL__/resetpcmvol --show'; $str = $resetshow; $str .= " --min=$MINVOL" if defined ($MINVOL) && ($MINVOL =~ m@^\d+\z@) && ($MINVOL > ZERO) && ($MINVOL <= 100); $str .= " --max=$MAXVOL" if defined ($MAXVOL) && ($MAXVOL =~ m@^\d+\z@) && ($MAXVOL > ZERO) && ($MAXVOL <= 100); $str = `$str 2>&1`; $str = "" unless defined ($str) && ($str =~ m@^\d+\s*\z@); $str =~ s@\s+\z@@s; my $OrigVolume = $str; sleep ONE; system $resetshow; sleep ONE; #--------------------------------------------------------------------- # Get initial display dimensions (if possible). my $X11DIM; $str = `__META_LACUTIL__/getx11dim 2>&1`; $str = "" unless defined $str; $str =~ s@\s+\z@@s; $X11DIM = $str if $str =~ m@^\d+x\d+\z@; #--------------------------------------------------------------------- # Go to appropriate directory. # Use a specified directory? if (!defined ($PATH_RUNDIR) || !length ($PATH_RUNDIR) || (!-d $PATH_RUNDIR) || !chdir ($PATH_RUNDIR)) { # No - Use home directory instead my $HOME = $ENV {HOME}; $HOME = '/' unless defined $HOME; chdir $HOME; } #--------------------------------------------------------------------- # Run the target program. system $TARGET_EXE; #--------------------------------------------------------------------- # Fix resulting display problems (if necessary). if (defined ($X11DIM)) { $str = `__META_LACUTIL__/getx11dim 2>&1`; $str = "" unless defined $str; $str =~ s@\s+\z@@s; system "__META_LACUTIL__/setx11dim --fast $X11DIM" unless $str eq $X11DIM; } #--------------------------------------------------------------------- # Restore original volume (if possible). # Do we know the original volume? if ($OrigVolume =~ m@^\d+\z@) { # Yes - Restore it system "__META_LACUTIL__/resetpcmvol --set=$OrigVolume"; } #--------------------------------------------------------------------- # Run "xclockmove" (if necessary). if ($FLAG_XCLOCK_MOVE) { system "__META_LACUTIL__/xclockmove"; } undef; } #--------------------------------------------------------------------- # main program #--------------------------------------------------------------------- &Main(); # Call the main routine exit ZERO; # Normal exit