2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-13 17:26:34 +00:00

Init reorganization as the Linux fork resets serial port settings

git-svn-id: https://svn.fhem.de/fhem/trunk@814 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2011-01-29 12:07:14 +00:00
parent 83fd5300bb
commit 7d77a6212a
2 changed files with 67 additions and 35 deletions

View File

@ -13,8 +13,10 @@
- feature: attr may be a regexp (for CUL_IR) - feature: attr may be a regexp (for CUL_IR)
- feature: Homepage moved from koeniglich.de/fhem to fhem.de - feature: Homepage moved from koeniglich.de/fhem to fhem.de
- feature: eventMap attribute - feature: eventMap attribute
- feature: 64_ESA2000 added (by STefan/Gerd)
- feature: new modules 66_ECMD.pm and 67_ECMDDevice.pm for ethersex-enabled - feature: new modules 66_ECMD.pm and 67_ECMDDevice.pm for ethersex-enabled
devices and alike. devices and alike.
- bugfix: serial port setting on Linux broken if running in the background
- 2010-08-15 (5.0) - 2010-08-15 (5.0)
- **NOTE*: The default installation path is changed to satisfy lintian - **NOTE*: The default installation path is changed to satisfy lintian

View File

@ -81,6 +81,8 @@ sub fhem($);
sub fhz($); sub fhz($);
sub IsDummy($); sub IsDummy($);
sub IsIgnored($); sub IsIgnored($);
sub setGlobalAttrBeforeFork();
sub redirectStdinStdErr();
sub CommandAttr($$); sub CommandAttr($$);
sub CommandDefaultAttr($$); sub CommandDefaultAttr($$);
@ -159,13 +161,12 @@ my $logopened = 0; # logfile opened or using stdout
my %client; # Client array my %client; # Client array
my $rcvdquit; # Used for quit handling in init files my $rcvdquit; # Used for quit handling in init files
my $sig_term = 0; # if set to 1, terminate (saving the state) my $sig_term = 0; # if set to 1, terminate (saving the state)
my $modpath_set; # Check if modpath was used, and report if not.
my %intAt; # Internal at timer hash. my %intAt; # Internal at timer hash.
my $nextat; # Time when next timer will be triggered. my $nextat; # Time when next timer will be triggered.
my $intAtCnt=0; my $intAtCnt=0;
my %duplicate; # Pool of received msg for multi-fhz/cul setups my %duplicate; # Pool of received msg for multi-fhz/cul setups
my $duplidx=0; # helper for the above pool my $duplidx=0; # helper for the above pool
my $cvsid = '$Id: fhem.pl,v 1.125 2011-01-29 07:38:13 rudolfkoenig Exp $'; my $cvsid = '$Id: fhem.pl,v 1.126 2011-01-29 12:07:14 rudolfkoenig Exp $';
my $namedef = my $namedef =
"where <name> is either:\n" . "where <name> is either:\n" .
"- a single device name\n" . "- a single device name\n" .
@ -238,16 +239,6 @@ my $commonAttr = "eventMap";
Hlp=>"<devspec> <state>,trigger notify command" }, Hlp=>"<devspec> <state>,trigger notify command" },
); );
# If started as root, and there is a fhem user in the /etc/passwd, su to it
if($^O !~ m/Win/ && $< == 0) {
my @pw = getpwnam("fhem");
if(@pw) {
use POSIX qw(setuid);
setuid($pw[2]);
}
}
################################################### ###################################################
# Start the program # Start the program
if(int(@ARGV) != 1 && int(@ARGV) != 2) { if(int(@ARGV) != 1 && int(@ARGV) != 2) {
@ -258,7 +249,14 @@ if(int(@ARGV) != 1 && int(@ARGV) != 2) {
exit(1); exit(1);
} }
doGlobalDef($ARGV[0]); # If started as root, and there is a fhem user in the /etc/passwd, su to it
if($^O !~ m/Win/ && $< == 0) {
my @pw = getpwnam("fhem");
if(@pw) {
use POSIX qw(setuid);
setuid($pw[2]);
}
}
################################################### ###################################################
# Client code # Client code
@ -277,11 +275,14 @@ if(int(@ARGV) == 2) {
# End of client code # End of client code
################################################### ###################################################
################################################### ###################################################
# Server initialization # Server initialization
my $ret = CommandInclude(undef, $attr{global}{configfile}); doGlobalDef($ARGV[0]);
die($ret) if($ret);
# As newer Linux versions reset serial parameters after fork, we parse the
# config file after the fork. Since need some global attr parameters before, we
# read them here.
setGlobalAttrBeforeFork();
if($^O =~ m/Win/ && !$attr{global}{nofork}) { if($^O =~ m/Win/ && !$attr{global}{nofork}) {
Log 1, "Forcing 'attr global nofork' on WINDOWS"; Log 1, "Forcing 'attr global nofork' on WINDOWS";
@ -296,13 +297,15 @@ if($attr{global}{logfile} ne "-" && !$attr{global}{nofork}) {
exit(0) if $pid; exit(0) if $pid;
} }
die("No modpath specified in the configfile.\n") if(!$modpath_set); my $ret = CommandInclude(undef, $attr{global}{configfile});
die("$ret\n") if($ret);
die("No port specified in the configfile.\n") if(!$server); die("No port specified in the configfile.\n") if(!$server);
if($attr{global}{statefile} && -r $attr{global}{statefile}) { if($attr{global}{statefile} && -r $attr{global}{statefile}) {
$ret = CommandInclude(undef, $attr{global}{statefile}); $ret = CommandInclude(undef, $attr{global}{statefile});
die($ret) if($ret); die($ret) if($ret);
} }
SignalHandling(); SignalHandling();
my $pfn = $attr{global}{pidfilename}; my $pfn = $attr{global}{pidfilename};
@ -311,7 +314,9 @@ if($pfn) {
print PID $$ . "\n"; print PID $$ . "\n";
close(PID); close(PID);
} }
$init_done = 1; $init_done = 1;
redirectStdinStdErr();
DoTrigger("global", "INITIALIZED"); DoTrigger("global", "INITIALIZED");
Log 0, "Server started (version $attr{global}{version}, pid $$)"; Log 0, "Server started (version $attr{global}{version}, pid $$)";
@ -802,6 +807,8 @@ CommandInclude($$)
{ {
my ($cl, $arg) = @_; my ($cl, $arg) = @_;
my $fh; my $fh;
my $ret = undef;
if(!open($fh, $arg)) { if(!open($fh, $arg)) {
return "Can't open $arg: $!"; return "Can't open $arg: $!";
} }
@ -813,13 +820,14 @@ CommandInclude($$)
if($l =~ m/^(.*)\\ *$/) { # Multiline commands if($l =~ m/^(.*)\\ *$/) { # Multiline commands
$bigcmd .= "$1\\\n"; $bigcmd .= "$1\\\n";
} else { } else {
AnalyzeCommandChain($cl, $bigcmd . $l); my $tret = AnalyzeCommandChain($cl, $bigcmd . $l);
$ret = $tret if(!$ret && $tret);
$bigcmd = ""; $bigcmd = "";
} }
last if($rcvdquit); last if($rcvdquit);
} }
close($fh); close($fh);
return undef; return $ret;
} }
@ -843,7 +851,20 @@ OpenLogfile($)
$defs{global}{logfile} = $attr{global}{logfile}; $defs{global}{logfile} = $attr{global}{logfile};
open(LOG, ">>$currlogfile") || return("Can't open $currlogfile: $!"); open(LOG, ">>$currlogfile") || return("Can't open $currlogfile: $!");
redirectStdinStdErr() if($init_done);
}
LOG->autoflush(1);
$logopened = 1;
return undef;
}
sub
redirectStdinStdErr()
{
# Redirect stdin/stderr # Redirect stdin/stderr
my $currlogfile = $attr{global}{logfile};
return if($currlogfile eq "-");
open STDIN, '</dev/null' or return "Can't read /dev/null: $!"; open STDIN, '</dev/null' or return "Can't read /dev/null: $!";
@ -854,10 +875,6 @@ OpenLogfile($)
close(STDOUT); close(STDOUT);
open STDOUT, '>&STDERR' or return "Can't dup stdout: $!"; open STDOUT, '>&STDERR' or return "Can't dup stdout: $!";
STDOUT->autoflush(1); STDOUT->autoflush(1);
}
LOG->autoflush(1);
$logopened = 1;
return undef;
} }
@ -1139,7 +1156,7 @@ CommandDefine($$)
if(!$modules{$m} || !$modules{$m}{DefFn}) { if(!$modules{$m} || !$modules{$m}{DefFn}) {
my @m = grep { $modules{$_}{DefFn} || !$modules{$_}{LOADED} } my @m = grep { $modules{$_}{DefFn} || !$modules{$_}{LOADED} }
sort keys %modules; sort keys %modules;
return "Unknown argument $m, choose one of @m"; return "Unknown module $m, choose one of @m";
} }
my %hash; my %hash;
@ -1399,7 +1416,7 @@ CommandReload($$)
my %hash; my %hash;
$param =~ s,/,,g; $param =~ s,/,,g;
$param =~ s,\.pm$,,g; $param =~ s,\.pm$,,g;
my $file = "$modpath_set/$param.pm"; my $file = "$attr{global}{modpath}/FHEM/$param.pm";
return "Can't read $file: $!" if(! -r "$file"); return "Can't read $file: $!" if(! -r "$file");
my $m = $param; my $m = $param;
@ -1532,7 +1549,7 @@ GlobalAttr($$)
Listen => 10, Listen => 10,
ReuseAddr => 1); ReuseAddr => 1);
if(!$server2) { if(!$server2) {
Log 1, "Can't open server port at $port: $!\n"; Log 1, "Can't open server port at $port: $!";
return "$!" if($init_done); return "$!" if($init_done);
die "Can't open server port at $port: $!\n"; die "Can't open server port at $port: $!\n";
} }
@ -1558,7 +1575,6 @@ GlobalAttr($$)
opendir(DH, $modpath) || return "Can't read $modpath: $!"; opendir(DH, $modpath) || return "Can't read $modpath: $!";
my $counter = 0; my $counter = 0;
$modpath_set = $modpath;
foreach my $m (sort readdir(DH)) { foreach my $m (sort readdir(DH)) {
next if($m !~ m/^([0-9][0-9])_(.*)\.pm$/); next if($m !~ m/^([0-9][0-9])_(.*)\.pm$/);
$modules{$2}{ORDER} = $1; $modules{$2}{ORDER} = $1;
@ -1602,7 +1618,7 @@ CommandAttr($$)
my $list = getAllAttr($sdev); my $list = getAllAttr($sdev);
if($a[1] eq "?") { if($a[1] eq "?") {
push @rets, "Unknown argument $a[1], choose one of $list"; push @rets, "Unknown attribute $a[1], choose one of $list";
next; next;
} }
@ -1902,6 +1918,7 @@ CommandChain($$)
for(my $n = 0; $n < $retry; $n++) { for(my $n = 0; $n < $retry; $n++) {
Log 1, sprintf("Trying again $cmd (%d out of %d)", $n+1,$retry) if($n>0); Log 1, sprintf("Trying again $cmd (%d out of %d)", $n+1,$retry) if($n>0);
my $ret = AnalyzeCommand(undef, $cmd); my $ret = AnalyzeCommand(undef, $cmd);
Log 1, "> $ret";
last if(!$ret || $ret !~ m/Timeout/); last if(!$ret || $ret !~ m/Timeout/);
} }
} }
@ -2447,3 +2464,16 @@ ReplaceEventMap($$)
} }
return $str; return $str;
} }
sub
setGlobalAttrBeforeFork()
{
my $f = $attr{global}{configfile};
open(FH, $f) || die("Cant open $f: $!\n");
while(my $l = <FH>) {
chomp($l);
next if($l !~ m/^attr +global +([^ ]+) +(.*)$/);
$attr{global}{$1} = $2;
}
close(FH);
}