rendered paste body#!/usr/bin/perl
# Copyright (c) 1996 SuSE GmbH Nuernberg, Germany. All rights reserved.
#
# Author: Marcus Schaefer <sax@suse.de>, 2000
# xc.pl configuration level 2 after sax startup level 1 (init)
#
# CVS ID:
# --------
# Status: Up-to-date
#
use lib '/usr/share/sax/modules';
use strict;
use Env;
use FileHandle;
use CreateSections;
use CheckServer;
use ParseConfig;
use Getopt::Long;
use Storable;
use XFree;
#==========================================
# Globals
#------------------------------------------
my %var; # hold all the configuration parameters
my %spec; # hold specifications for xc.pl
my $EnableAutoConf; # option variable: enable auto config
my $YaSTMode; # called from YaST2
my $StartWithSystemConfig; # option start with system config
my $EnableXF86AutoMode; # option variable: enable auto modeline
my $DialogToStartWith; # dialog to start with (xapi option)
my $Display; # option variable: set Display
my $TmpDir; # secure dir name
my %tune; # tune hash for changed mode timings
my $logHandle; # log file handle
my $FullScreen; # full screen mode
my $NoCheckPacs; # do not check package requirements
my $NoIntro; # prevent intro appearance
#==========================================
# Call main...
#------------------------------------------
main();
#==========================================
# main
#------------------------------------------
sub main {
# ...
# This function will open the configuration hash (registry)
# created by init.pl and will create configuration suggestion
# from this data. If there is no X-Server running start
# my own X-Server otherwhise try to access the running one.
# The last step is to run the GUI (xapi) on the server
# ---
#==========================================
# Initialize xc options and spec hash
#------------------------------------------
init();
#==========================================
# Open configuration hash...
#------------------------------------------
if ((prepare()) == -1) {
print "xc: level 2... abort\n";
Exit(0);
}
#==========================================
# Open LOG file handler...
#------------------------------------------
$logHandle = OpenLog();
#==========================================
# Create config suggestion
#------------------------------------------
my @part0; # header
my @part1; # Files section
my @part2; # Module section
my @part3; # ServerFlags section
my @part4; # InputDevice sections
my @part5; # Monitor sections
my @part6; # Modes sections
my @part7; # Device section
my @part8; # Screen section
my @part9; # ServerLayout section
my @part10; # DRI section
my @part11; # Extensions section
@part0 = CreateHeaderSection ();
@part1 = CreateFilesSection (\%var);
@part2 = CreateModuleSection (\%var);
@part3 = CreateServerFlagsSection (\%var);
@part4 = CreateInputDeviceSection (\%var);
if (defined $EnableXF86AutoMode) {
@part5 = CreateMonitorSection (\%var,"yes");
} else {
@part5 = CreateMonitorSection (\%var,"no");
@part6 = CreateModesSection (\%var,"no");
}
@part7 = CreateDeviceSection (\%var);
@part8 = CreateScreenSection (\%var);
@part9 = CreateServerLayoutSection (\%var);
@part10 = CreateDRISection ();
@part11 = CreateExtensionsSection (\%var);
#==========================================
# Write preliminary config file
#------------------------------------------
open (HANDLE,">$spec{AutoConf}");
print HANDLE @part0; print HANDLE "\n";
print HANDLE @part1; print HANDLE "\n";
print HANDLE @part2; print HANDLE "\n";
print HANDLE @part3; print HANDLE "\n";
print HANDLE @part4; print HANDLE "\n";
print HANDLE @part5; print HANDLE "\n";
print HANDLE @part6; print HANDLE "\n";
print HANDLE @part7; print HANDLE "\n";
print HANDLE @part8; print HANDLE "\n";
print HANDLE @part9; print HANDLE "\n";
print HANDLE @part10; print HANDLE "\n";
print HANDLE @part11; print HANDLE "\n";
close HANDLE;
#==========================================
# Write automatic config file and exit
#------------------------------------------
if (defined $EnableAutoConf) {
# /.../
# Auto configuration is enabled. This will save the auto
# detected configuration file as final config file
# ---
my $final = LinkConfiguration();
print "SaX: Automatic configuration is done\n";
print "SaX: The file $final has been written\n";
CleanTmp();
Exit(0);
}
#==========================================
# Check display server status
#------------------------------------------
my $disp = ":0.0";
my $haveServer = 0;
my @displayStatus = ();
my @xpid = GetPids();
if (@xpid > 0) {
#============================================
# check on local system according to pid's
#--------------------------------------------
@displayStatus = GetDisplay (@xpid,$spec{Corner});
$disp = $displayStatus[0];
if ($displayStatus[1] eq "grant") {
$haveServer = 1;
}
} else {
#============================================
# check for remote access, x11 forward
#--------------------------------------------
@displayStatus = X11ForwardEnabled();
if ($displayStatus[1] eq "grant") {
$disp = $displayStatus[0];
$haveServer = 1;
}
}
#==========================================
# Apply log message about display status
#------------------------------------------
Logger ("Startup...",$logHandle);
if ($haveServer) {
print "SaX: X-Server: $displayStatus[0] -> $displayStatus[1]\n";
Logger ("Startup on already running Server:
$displayStatus[0] -> $displayStatus[1]",
$logHandle
);
} else {
Logger ("Startup on new Server: <$disp>",
$logHandle
);
Logger ($spec{AutoConf},
$logHandle
);
}
#==========================================
# Start new X-Server if needed
#------------------------------------------
$spec{haveServer} = $haveServer;
if ($haveServer == 0) {
my $vt = GetVirtualTerminal();
my $XLoader = "$spec{X} $spec{Xmsg} -br -xf86config $spec{AutoConf}";
my $XFlags = "-allowMouseOpenFail -verbose 10 +accessx $vt";
my $XDisp = $disp;
if ($disp =~ /(:.*)\./) {
$XDisp = $1;
}
system("$XLoader $XFlags $XDisp >$spec{XpidFile}");
if (! open(FD,"$spec{XpidFile}")) {
die "xc: could not open file: $spec{XpidFile}";
}
while (<FD>) {
$spec{Xpid} = $_;
}
close(FD);
unlink($spec{XpidFile});
#==========================================
# save terminal settings to /var/log/xvt
#------------------------------------------
my $terminal = 7;
my $tty = Getty();
unlink($spec{XTerminal});
open (FD,">$spec{XTerminal}");
print FD "TTyX:$terminal\n";
print FD "TTyT:$tty\n";
close(FD);
#==========================================
# Check if the server starts up correctly
#------------------------------------------
if (CheckPID($spec{Xpid}) != 0) {
#==========================================
# check for missing packages
#------------------------------------------
my $install = "<none>";
my $data = qx($spec{Sysp} -q 3d);
if ($data =~ /Card3D0.*Install.*:(.*)\n.*/) {
$install = $1;
$install =~ s/ +//g;
}
if ($install ne "<none>") {
print "xc: missing base package:\n";
print " please install the following package(s):\n";
print "\n";
print " $install\n";
print "\n";
print "xc: abort...\n";
} else {
#==========================================
# Server startup failed... abort
#------------------------------------------
print "\n";
print "xc: sorry could not start configuration server\n";
print "xc: for details refer to the log file:\n";
print "\n";
print " $spec{LogFile}\n";
print "\n";
print "xc: abort...\n";
}
Logger($spec{Xmsg},$logHandle);
unlink($spec{Xmsg});
Exit(0);
}
}
#==========================================
# prepare the options passed to xapi (GUI)
#------------------------------------------
my @parent = getParentName();
my $apiopt = "--middle";
#=======================================
# Check if we are called from YaST2
#---------------------------------------
if (defined $YaSTMode) {
$apiopt = "--yast";
}
#=======================================
# Check if we are called from SaX2
#---------------------------------------
if (($haveServer) && ($parent[0] eq "sax")) {
$apiopt = "";
}
#=======================================
# In case of own server; check size
#---------------------------------------
if ($haveServer == 0) {
$apiopt .= " --sizecheck";
}
#=======================================
# Check for package check flag
#---------------------------------------
if (! defined $NoCheckPacs) {
system ("$spec{Xapi} $apiopt --checkpacs -display $disp");
}
#=======================================
# Check for fullscreen mode
#---------------------------------------
if (defined $FullScreen) {
$apiopt = $apiopt." --fullscreen";
}
#==========================================
# Apply log message about server status
#------------------------------------------
if ($haveServer == 0) {
my $glxinfo = qx (/usr/X11R6/bin/glxinfo -display $disp);
Logger ($spec{Xmsg},$logHandle);
Logger ("GLX Info:\n$glxinfo",$logHandle);
unlink ($spec{Xmsg});
}
#=======================================
# Show the intro message
#---------------------------------------
my $exit = 2;
if (defined $NoIntro) {
#=======================================
# Don't want to see a intro message
#---------------------------------------
$exit = 1;
} else {
if ($haveServer == 0) {
#=======================================
# Call intro and save exit code
#---------------------------------------
system ("$spec{Xapi} $apiopt --info -display $disp");
$exit = $? >> 8;
#=======================================
# Get information about our own server
#---------------------------------------
my @xpid = GetPids();
if (@xpid > 0) {
@displayStatus = GetDisplay (@xpid,$spec{Corner});
$disp = $displayStatus[0];
if ($displayStatus[1] ne "grant") {
$exit = 2;
}
} else {
$exit = 2;
}
} else {
#=======================================
# There is already a server to access
#---------------------------------------
$exit = 1;
}
}
#=======================================
# Handle the exit code from the intro
#---------------------------------------
my $exitCode = 0;
if ($exit == 1) {
#=======================================
# (1) Run the GUI (xapi)...
#---------------------------------------
if (open (OPT,">$spec{StartOptions}")) {
print OPT $apiopt;
close OPT;
}
if (defined $DialogToStartWith) {
$apiopt = "$apiopt -O $DialogToStartWith";
}
if ($haveServer == 0) {
if ((defined $StartWithSystemConfig) && (HeaderOK())) {
print "SaX: importing current configuration...\n";
system ("$spec{Xapi} $apiopt -display $disp");
} else {
print "SaX: using cache data...\n";
system ("$spec{Xapi} $apiopt --mode auto -display $disp");
}
} else {
if ((-f $spec{HWFlag}) || (! HeaderOK())) {
print "SaX: using cache data...\n";
system ("$spec{Xapi} $apiopt --mode auto -display $disp");
} else {
print "SaX: importing current configuration...\n";
system ("$spec{Xapi} $apiopt -display $disp");
}
}
$exitCode = $? >> 8;
} elsif ($exit == 0) {
#=======================================
# (0) Save the configuration file
#---------------------------------------
# /.../
# recreate Module Section because some modues not used
# for initial configuration are needed for final
# configuration
# ----
@part2 = CreateModuleSection(\%var);
open (HANDLE,">$spec{AutoConf}");
print HANDLE @part0; print HANDLE "\n";
print HANDLE @part1; print HANDLE "\n";
print HANDLE @part2; print HANDLE "\n";
print HANDLE @part3; print HANDLE "\n";
print HANDLE @part4; print HANDLE "\n";
print HANDLE @part5; print HANDLE "\n";
print HANDLE @part6; print HANDLE "\n";
print HANDLE @part7; print HANDLE "\n";
print HANDLE @part8; print HANDLE "\n";
print HANDLE @part9; print HANDLE "\n";
print HANDLE @part10; print HANDLE "\n";
close(HANDLE);
LinkConfiguration();
$exitCode = 1;
}
#=======================================
# In case of own server; Kill it now
#---------------------------------------
if ($haveServer == 0) {
Kill ($spec{Xpid});
}
#=======================================
# Clean temp dir and exit
#---------------------------------------
CleanTmp();
Exit ($exitCode);
}
#==========================================
# CreateSecureDir
#------------------------------------------
sub CreateSecureDir {
# ...
# this function create a secure tmp directory
# and return the name of the directory
# ---
my $saxdir = "sax2-$$";
my $result = mkdir("/tmp/$saxdir",0700);
if ($result == 0) {
print "xc: could not create tmp dir... abort\n";
Exit(0);
}
return($saxdir);
}
#==========================================
# CleanTmp
#------------------------------------------
sub CleanTmp {
# ...
# this function send a signal to the process
# itself and forces removement of the tmp dir
# ---
kill (15,$$);
}
#----[ init ]----#
sub init {
# ...
# init spec hash and test for root privileges
# ---
#==========================================
# Create secure directory
#------------------------------------------
$TmpDir = CreateSecureDir();
$SIG{HUP} = "HandleTmpSignal";
$SIG{INT} = "HandleTmpSignal";
$SIG{QUIT} = "HandleTmpSignal";
$SIG{ABRT} = "HandleTmpSignal";
$SIG{SEGV} = "HandleTmpSignal";
$SIG{PIPE} = "HandleTmpSignal";
$SIG{TERM} = "HandleTmpSignal";
$spec{Sysp} = "/usr/sbin/sysp";
$spec{DbmFile} = "/var/cache/sax/files/config";
$spec{HWFlag} = "/var/cache/sax/files/hardware.chg";
$spec{LogFile} = "/var/log/SaX.log";
$spec{XpidFile} = "/var/log/SaX.pid";
$spec{AutoConf} = "/tmp/$TmpDir/xorg.conf";
$spec{Xmsg} = "/var/log/xlog";
$spec{X} = "/usr/sbin/xw";
$spec{Xapi} = "/usr/sbin/xapi";
$spec{Intro} = "/usr/share/sax/intro.pl";
$spec{Corner} = "/usr/sbin/corner";
$spec{XTerminal} = "/var/log/xvt";
$spec{StartOptions}= "/var/cache/sax/files/xapi.opt";
#==========================================
# Get options...
#------------------------------------------
undef ($spec{Xpid});
undef ($YaSTMode);
undef ($EnableAutoConf);
undef ($Display);
undef ($FullScreen);
undef ($NoCheckPacs);
undef ($EnableXF86AutoMode);
undef ($StartWithSystemConfig);
undef ($DialogToStartWith);
undef (%tune);
my $result = GetOptions(
"auto|a" => \$EnableAutoConf,
"yast|y" => \$YaSTMode,
"xmode|x" => \$EnableXF86AutoMode,
"sysconfig|s" => \$StartWithSystemConfig,
"fullscreen|f" => \$FullScreen,
"nocheckpacs|p" => \$NoCheckPacs,
"nointro|n" => \$NoIntro,
"dialog|O=s" => \$DialogToStartWith,
"help|h" => \&usage,
"<>" => \&usage
);
if ( $result != 1 ) {
usage();
}
my $api = $spec{Xapi};
if ( ! -f $api ) {
$EnableAutoConf = "";
}
#==========================================
# Test for root privileges
#------------------------------------------
my $user = qx (whoami);
if ($user !~ /root/i) {
print "xc: only root can do this\n";
exit(0);
}
}
#==========================================
# prepare
#------------------------------------------
sub prepare {
# ...
# read saved data dictionary hash from file
# import registry information
# ---
my $hashref;
if (! -s $spec{DbmFile}) {
print "xc: could not open tree: $spec{DbmFile}\n";
return -1;
}
eval {
$hashref = retrieve($spec{DbmFile});
};
if (! defined $hashref) {
print "xc: could not open tree: $spec{DbmFile}\n";
return -1;
}
%var = %{$hashref};
return 0;
}
#==========================================
# save
#------------------------------------------
sub save {
# ...
# save hash data as file $spec{DbmFile}
# ---
unlink($spec{DbmFile});
if(!store(\%var,$spec{DbmFile})) {
print "init: could not create tree: $spec{DbmFile}\n";
return -1;
}
return 0;
}
#==========================================
# HandleTmpSignal
#------------------------------------------
sub HandleTmpSignal {
# ...
# signal function to remove tmp stuff
# ---
qx (rm -rf /tmp/$TmpDir);
qx (rm -rf /tmp/sysp-*);
}
#==========================================
# Logger
#------------------------------------------
sub Logger {
# ...
# Append log file data to LOG handler...
# ---
my $data = $_[0];
my $handle = $_[1];
my $date = qx (
LANG=POSIX /bin/date "+%d-%h %H:%M:%S"
);
$date =~ s/\n$//;
if (-f $data) {
#==========================================
# got file for logging
#------------------------------------------
print $handle "$date <X> Logging File contents: $data [\n";
my $xf = new FileHandle;
if ($xf->open("$data")) {
while (my $line=<$xf>) {
$line =~ s/^\n//;
$line =~ s/\n$//;
$line =~ s/^\t+//g;
print $handle "\t$line\n";
}
}
print $handle "]\n";
$xf->close;
} else {
#==========================================
# got string data for logging
#------------------------------------------
print $handle "$date <X> ";
my $lineWrap = 0;
$data =~ s/^\n//;
$data =~ s/\n$//;
if ($data =~ /\n+/) {
$lineWrap = 1;
}
if ($lineWrap) {
my @list = split ("\n",$data);
my $topic = shift (@list);
print $handle "[ $topic\n";
foreach (@list) {
$_ =~ s/^\t+//g;
print $handle "\t$_\n";
}
print $handle "]\n";
} else {
print $handle "$data\n";
}
}
}
#==========================================
# LinkConfiguration
#------------------------------------------
sub LinkConfiguration {
# ...
# this function is called to copy the temporary config
# file to /etc/X11/xorg.conf and create the symbolic
# X links
# ---
my $final = "/etc/X11/xorg.conf";
my $save = "/etc/X11/xorg.conf.saxsave";
my $server = "/usr/X11R6/bin/XFree86";
if (! -f $server) {
$server = "/usr/X11R6/bin/Xorg";
}
if (-f $final) {
qx (cp $final $save);
}
#==========================================
# Save configuration to /etc/X11
#------------------------------------------
qx (cp $spec{AutoConf} $final);
#==========================================
# Create startup links
#------------------------------------------
if (-f $server) {
qx (rm -f /usr/X11R6/bin/X);
qx (rm -f /var/X11R6/bin/X);
qx (ln -s /var/X11R6/bin/X /usr/X11R6/bin/X);
qx (ln -s $server /var/X11R6/bin/X);
}
unlink ( $spec{HWFlag} );
return ( $final );
}
#==========================================
# Exit
#------------------------------------------
sub Exit {
# ...
# exit function wrapper which close the
# LOG handler first...
# ---
my $code = $_[0];
CloseLog ($logHandle);
qx (rm -rf $TmpDir);
exit ($code);
}
#==========================================
# Getty
#------------------------------------------
sub Getty {
# ...
# look for the terminal ID and return it. Please
# note this function has to return a number
# ---
my $tty;
$tty = qx (tty | cut -f2 -dy);
return($tty);
}
#==========================================
# CheckPID
#------------------------------------------
sub CheckPID {
# ...
# check if the given process id still exist in
# the process table
# ---
my $pid = $_[0];
if ($pid eq "") {
return 1;
}
sleep(2); qx (ps $pid);
my $exit = $? >> 8;
return $exit;
}
#==========================================
# OpenLog
#------------------------------------------
sub OpenLog {
# ...
# remove old auto configuration file and open a
# new log file descriptor...
# ---
my $io;
unlink ($spec{AutoConf});
$io = new FileHandle;
if (! $io->open(">>$spec{LogFile}")) {
die "xc: could not create LogFile: $spec{LogFile}";
}
my $LOG = $io->fileno;
open(STDERR,">&$LOG") ||
die "could not duplicate LOG on stderr";
binmode($io, ':unix');
return ($io);
}
#==========================================
# CloseLog
#------------------------------------------
sub CloseLog {
# ...
# close current log file descriptor...
# ---
my $io = $_[0];
if (defined $io) {
$io->close;
}
}
#==========================================
# Kill
#------------------------------------------
sub Kill {
# ...
# This function will try to kill a process with
# signal 15 first and if it still exists with signal
# number 9 to be sure it gets killed
# ---
my $pid = $_[0];
my $err;
if ($pid eq "") {
return;
}
$err = system("kill -15 $pid");
$err = $? >> 8;
if ($err > 0) {
Logger ("die hard on pid: $pid",$logHandle);
system ("kill -9 $pid");
}
}
#==========================================
# getParentName
#------------------------------------------
sub getParentName {
# ...
# get the name of the parent process calling
# this script
# ---
my @return;
my $parent = getppid();
my $name = qx ( cat /proc/$parent/cmdline );
$name =~ /\/.*\/+(.*)/;
my @list = split(/\./,$1);
my $base = shift (@list);
my $cmdline = qx (
cat /proc/$parent/cmdline
);
chomp ($base);
push(@return,$base);
if ($cmdline =~ /.*-font(.*)-iso10646-1/) {
push(@return,"-fn $1-iso10646-1");
}
return (
@return
);
}
#==========================================
# HeaderOK
#------------------------------------------
sub HeaderOK {
# ...
# check if the header of the config file has been created
# from SaX2/ISaX... otherwhise this file shouldn't be
# read in
# ---
my $file = "/etc/X11/xorg.conf";
my $hunk = "SaX generated X.* config file";
my $msg1 = "SaX: header check failed !\n";
my $msg2 = "SaX: will not import $file\n";
if (! -f $file) {
print $msg1.$msg2;
return 0;
}
if (! open (FD,$file)) {
print $msg1.$msg2;
return 0;
}
while (<FD>) {
if ($_ =~ /$hunk/) {
close FD;
return 1;
}
}
close FD;
print $msg1.$msg2;
return 0;
}
#==========================================
# usage
#------------------------------------------
sub usage {
# ...
# usage message for calling xc.pl
# ---
print "Linux SaX Version 7.1 level (xc) (2005-09-26)\n";
print "(C) Copyright 2005 - SUSE LINUX Products GmbH\n";
print "\n";
print "usage: xc [ options ]\n";
print "options:\n";
print "[ -a | --auto ]\n";
print " enable automatic configuration\n";
print "\n";
print "[ -x | --xmode ]\n";
print " do not use sax calculated Modelines,\n";
print " use the server generated once instead\n";
print "\n";
print "[ -s | --sysconfig ]\n";
print " this option will only take effect if xc\n";
print " has to start its own X-Server. It will than\n";
print " read the system installed config file\n";
print " instead of the HW detection data\n" ;
print "[ -y | --yast ]\n";
print "\n";
print " start in yast mode which passed the option\n";
print " named --yast to the xapi binary\n";
print "\n";
print "[ -f | --fullscreen ]\n";
print " start the GUI in fullscreen mode\n";
print "\n";
print "[ -O | --dialog ]\n";
print " pass the option --dialog to the xapi binary\n";
print "\n";
print "[ -n | --nointro ]\n";
print " skip the greeting message\n";
print "\n";
print "[ -p | --nocheckpacs ]\n";
print " skip the check for required packages\n";
print "\n";
print "[ -h | --help ]\n";
print " show this message\n";
print "--\n";
Exit(0);
}