1

Compare commits

..

33 Commits

Author SHA1 Message Date
eleksir
dc58f0c6a9 i3status-anyevent moved to separate repo - i3status-ae 2021-06-19 14:15:41 +03:00
eleksir
044acbf148 i3status-anyevent: on vpn state file check mtime, not atime (it was typo) 2021-03-15 23:50:17 +03:00
eleksir
b36eaf7e40 acpid.pl: cleanup, use vars for fh instead of bare words, fix fd leak on battery status file 2021-03-13 17:48:05 +03:00
eleksir
04fdac8891 i3status-anyevent: fix incorrect vpn status file mtime check 2021-03-13 17:25:43 +03:00
Sergei Fedosov
035afae865 i3status-anyevent: Add cron plugin 2021-02-25 18:50:25 +03:00
Sergei Fedosov
58d896c597 i3status-anyevent: i3status-anyevent %SIG should be local 2021-02-25 16:56:57 +03:00
Sergei Fedosov
d1fcd2b8a4 i3status-anyevent: Add left|right click cmd for clock plugin 2021-02-24 18:06:10 +03:00
eleksir
27904b8d50 i3status-anyevent: Fix caps indicator, at last 2021-02-21 18:12:49 +03:00
eleksir
7d4e8dccb4 i3status-anyevent: Add simple net if state indicator 2021-02-21 17:56:26 +03:00
eleksir
0d2453623c i3status-anyevent: Actually check if simple-volume-pa enabled 2021-02-21 16:58:22 +03:00
eleksir
139b014f7b i3status-anyevent: Make tcp connect check only if vpn state check enabled 2021-02-21 16:54:00 +03:00
eleksir
7a270291b1 i3status-anyevent: if we cannot spawn - silently giveup 2021-02-21 16:40:14 +03:00
eleksir
b287c84eed i3status-anyevent: i3 uses xdg std for config dir path, so we too 2021-02-21 16:35:09 +03:00
eleksir
02bb1399fb i3status-anyevent: fix capslock indicator border color 2021-02-21 12:51:45 +03:00
eleksir
8fc99eeb50 i3status-anyevent: Add simplified volume indicator, make charge flash sign bigger 2021-02-21 12:49:46 +03:00
eleksir
fbb3fbdb07 i3status-anyevent: there are other files in /sys for battery on kernel 4.4.x and thinkpad 2021-02-20 22:06:06 +03:00
Sergei Fedosov
ccf477bc65 i3status-anyevent: move cpu mon file location, color and background color to config 2021-02-20 20:28:42 +03:00
Sergei Fedosov
217a86ecff i3status-anyevent: run app from button only on left-click 2021-02-20 19:50:11 +03:00
Sergei Fedosov
3a09fcf22f i3status-anyevent: upower does not provide "time to" value if battery fully chrged 2021-02-20 18:36:09 +03:00
Sergei Fedosov
1cb4103dd6 i3status-anyevent: change battery backend, fix restart i3bar issues, rename conf
* Rename config.json to i3status-anyevent.json, old name still supported
* Drop dbus and use upower directly with option use /sys poll instead
* Use setsid() to prevent windows get stoned when i3bar restarted (and
* status scrept re-launched)
* Do not use syswrite on utf8 filehandles, it's deprecated
* Move some settings to config
* Add lots of comments to config
2021-02-20 17:49:23 +03:00
Sergei Fedosov
bb41416926 i3status-anyevent: unless hiding declaration of $FH 2021-02-20 12:24:45 +03:00
Sergei Fedosov
4452e2fe0f i3status-anyevent: highlight app "buttons" with active windows, code style fixes 2021-02-19 19:32:28 +03:00
Sergei Fedosov
20789b2a2c i3status-anyevent: add ability to reload config, relaxed json parser 2021-02-18 19:08:41 +03:00
eleksir
949ce2f0c7 Refactor, modernize i3status-timers.json-io 2021-02-13 19:44:46 +03:00
Sergei Fedosov
96fc306ef7 Add i3status-anyevent 2021-02-13 19:43:10 +03:00
Sergei Fedosov
a102651d7a tpingd.go: Add laptop battery query via dbus 2020-10-14 19:41:02 +03:00
Sergei Fedosov
4fbb5170d2 tpingd.go: do not use net/http 2020-10-02 14:41:51 +03:00
Sergei Fedosov
169f4ef309 Add tpingd.go - tcp pinger 2020-09-29 09:35:09 +03:00
eleksir
b6d1722b25 i3status-timers.json-io: remap stdio to /dev/null on spawn() 2020-03-15 21:08:08 +03:00
eleksir
0324616c01 Add touchpad_toggle 2020-03-15 21:04:40 +03:00
eleksir
0cbe1eb7a0 i3status-timers.json-io: make output more gently, suppress errors on unsucessful spawn 2020-03-15 17:12:08 +03:00
eleksir
1687579c16 Add MIT License 2020-03-15 15:56:41 +03:00
eleksir
cad1f400df i3status-timers.json-io: use external config for buttons 2020-03-15 15:06:18 +03:00
5 changed files with 353 additions and 160 deletions

20
LICENSE Normal file
View File

@@ -0,0 +1,20 @@
Copyright (C) 2020 Sergei Fedosoff
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

114
acpid.pl
View File

@@ -2,15 +2,10 @@
#
# Hibernates system if battery charge drops under $MIN_CHARGE and battery discharging
use strict;
use warnings "all";
use Fcntl;
sub logger($); # logs messages if $debug != 0
# maybe one time i'll use it
sub i3wmstate; # returns 1 if i3wm running, else - 0
use warnings;
sub logger; # logs messages if $debug != 0
$0 = 'acpid.pl';
my $debug = 0;
@@ -18,8 +13,8 @@ my $MIN_CHARGE = 10;
my $base = '/sys/class/power_supply/BAT0';
unless(-f "$base/present") {
logger("Battery info at /sys/class/BAT0/present not found, quitting.\n");
unless (-f "$base/present") {
logger "Battery info at /sys/class/BAT0/present not found, quitting.";
exit 0;
}
@@ -27,90 +22,89 @@ my $battery_present = 2;
my $battery_check = 2;
my $charging = 2;
while ( sleep(180) ) {
# check that battery is in place
open(ACPI, "$base/present") or next;
my $buf = '';
while (sleep 180) {
open (my $batteryFH, '<', "$base/present") or next;
my $buf;
if (read(ACPI, $buf, 1)) {
if (read ($batteryFH, $buf, 1)) {
if ($battery_check == 0) {
logger("Ability to read from /sys/class/BAT0/present restored\n");
logger "Ability to read from $base/present restored";
$battery_check = 1;
}
if ($buf == '0') {
if ($battery_present != 0) {
logger("We have no battery, skipping charge level polling until it appears\n");
if ($battery_present) {
logger "We have no battery, skipping charge level polling until it appears";
$battery_present = 0;
}
close ACPI;
close $batteryFH;
next;
}
} else {
if ($battery_check != 0) {
logger("Unable to read from /sys/class/BAT0/present\n");
if ($battery_check) {
logger "Unable to read from /sys/class/BAT0/present";
$battery_check = 0;
}
close ACPI;
close $batteryFH;
next;
}
close ACPI;
close $batteryFH;
$battery_present = 1;
# check status, we have no need to poll battery if it charging/charged
unless (-f "$base/status") {
logger("Something broken in /sys, unable to find $base/status, quitting\n");
logger "Something broken in /sys, unable to find $base/status, quitting";
exit 1;
}
# TODO: file access save state and print on change
open(STATUS, "$base/status") or do {
logger("Unable to open $base/status\n");
open (my $statusFH, '<', "$base/status") or do {
logger "Unable to open $base/status";
next;
};
$buf = <STATUS>;
close STATUS;
chomp($buf);
$buf = <$statusFH>;
close $statusFH;
chomp $buf;
if ($buf ne 'Discharging') {
if ($charging != 1) {
logger("Battery charging.\n");
logger "Battery charging.";
$charging = 1;
}
} else {
if ($charging != 0) {
logger("Battery discharging.\n");
if ($charging) {
logger "Battery discharging.";
$charging = 0;
}
}
# read charge state
unless (-f "$base/capacity") {
logger("Something broken in /sys, unable to find $base/capacity, quitting\n");
logger "Something broken in /sys, unable to find $base/capacity, quitting";
exit 1;
}
# TODO: file access save state and print on change
open(CHARGE, "$base/capacity") or do {
open (my $chargeFH, '<', "$base/capacity") or do {
logger("Unable to open $base/capacity\n");
next;
};
read(CHARGE, $buf, 3) or do {
logger("Unable to read $base/capacity, but file is in place\n");
read ($chargeFH, $buf, 3) or do {
logger "Unable to read $base/capacity, but file is in place";
next;
};
chomp($buf); # just in case
close $chargeFH;
chomp $buf; # just in case
if ($buf < $MIN_CHARGE) {
if ($charging != 0) { # discharging
logger("Battery charge is less than 10%, hibernating\n");
logger "Battery charge is less than 10%, hibernating";
`dbus-send --system --print-reply --dest="org.freedesktop.UPower" /org/freedesktop/UPower org.freedesktop.UPower.Hibernate`;
}
} else {
@@ -122,51 +116,15 @@ while ( sleep(180) ) {
`notify-send --urgency=normal --expire-time=3000 "Battery overcharging"`;
}
logger("Charge is $buf%\n");
logger "Charge is $buf%";
}
}
sub logger ($) {
if ($debug != 0) {
sub logger {
if ($debug) {
my $msg = shift;
$msg = localtime() . ' ' . $msg;
$msg = sprintf '%s %s\n', localtime (), $msg;
syswrite STDOUT, $msg;
}
}
sub i3wmstate {
my $flag = 0;
opendir(P, '/proc') || die 'no /proc found!';
while (readdir(P)) {
my $pid = $_;
next unless(defined($pid));
next if ($pid eq '');
if (-d "/proc/$pid") {
# dir UID == APCID.pl process user owner
if ((stat("/proc/$pid"))[4] == int(getpwnam($ENV{'LOGNAME'}))) {
next unless(-r "/proc/$pid/cmdline");
open(CMDLINE, "/proc/$pid/cmdline") || die "unable to open /proc/$pid/cmdline";
my $cl = <CMDLINE>;
close(CMDLINE);
if(defined($cl)) {
if ((substr($cl, 0, 2) eq 'i3') and (length($cl) <= 4)) {
$flag = 1;
undef $cl;
undef $pid;
last;
}
}
undef $cl;
}
}
undef $pid;
}
return $flag;
}

View File

@@ -1,22 +1,26 @@
#!/usr/bin/perl
# vim: set ai noet ts=4 sw=4 sts=4 ft=perl :
use strict;
use warnings "all";
use Fcntl qw(:seek :mode :DEFAULT);
use 5.10.0;
use utf8;
use JSON::XS;
use threads;
use open qw (:std :utf8);
use strict;
use warnings;
use Carp qw (confess);
use Data::Dumper;
binmode STDOUT;
binmode STDERR;
use Fcntl qw(:seek :mode :DEFAULT);
use 5.22.2;
use JSON::XS;
use Net::DBus;
use POSIX qw (setsid);
use threads;
sub input_thread();
sub readconf();
sub gettimestr();
sub getlastr();
sub getbatterychargestr2();
sub getbatterychargestr3();
sub to_hours ($);
sub meminfo();
sub ifaces();
sub cpuspeed();
@@ -26,13 +30,26 @@ sub caps_find();
sub spawn(@);
binmode STDIN;
binmode STDERR;
binmode STDOUT;
my $read = 0;
$SIG{__DIE__} = \&Carp::confess;;
$SIG{"CONT"} = sub { $read = 1 };
$SIG{"STOP"} = sub { $read = 0 };
$SIG{"PIPE"} = sub { warn "SIGPIPE" };
$SIG{"HUP"} = sub { warn "SIGHUP" };
$SIG{"USR1"} = sub { warn "SIGUSR1" };
$SIG{"WINCH"} = sub { warn "SIGWINCH" };
my $slow_timer = 360; # 0.333 * 360 ~= 2 min
my $onesec_timer = 3; # 0.333 * 3 ~= 1 sec
# read config
my ($C, %CMD) = readconf();
my $buttonsamount = @{$C};
my @months = ('Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек');
my @wdays = ('Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб');
@@ -79,15 +96,24 @@ if ( -f "/sys/class/power_supply/ADP1/online") {
$ACFILE = "/sys/class/power_supply/AC/online";
}
# prep dee-boos connection
my $bus = Net::DBus->system;
my $upower = $bus->get_service("org.freedesktop.UPower");
my $properties = $upower->get_object("/org/freedesktop/UPower/devices/battery_BAT0", "org.freedesktop.DBus.Properties");
threads->create('input_thread')->detach();
sleep 1;
syswrite STDOUT, '{"version": 1, "stop_signal": 10, "cont_signal": 12, "click_events": true}
# capture click events and do not override sigstop and sigcont numbers
syswrite STDOUT, '{"version": 1, "click_events": true}
[ [],
';
sleep 1;
while (1) {
# json message that will be spewed to i3bar
my $je;
if ($onesec_timer >= 3) {
# $cpuspeed = cpuspeed();
@@ -119,7 +145,7 @@ while (1) {
}
if ($slow_timer >= 360) {
$tmp = getbatterychargestr2();
$tmp = getbatterychargestr3();
if ($charge ne $tmp) {
$jf = 1;
$charge = $tmp;
@@ -156,57 +182,15 @@ while (1) {
$jo->[6]->{full_text} = $caps;
$jo->[6]->{color} = '#3e78fd';
$jo->[7]->{full_text} = "mousepad";
$jo->[7]->{color} = '#ff0000';
$jo->[7]->{name} = 'mousepad';
$jo->[7]->{instance} = 'mousepad';
$jo->[7]->{align} = 'left';
@{$je} = (@{$jo}, @{$C});
@{$je} = reverse(@{$je});
$jo->[8]->{full_text} = "vsc";
$jo->[8]->{color} = '#ff0000';
$jo->[8]->{name} = 'code';
$jo->[8]->{instance} = 'code';
$jo->[8]->{align} = 'left';
my $output = eval { encode_json($je); };
$jo->[9]->{full_text} = "v";
$jo->[9]->{color} = '#ff0000';
$jo->[9]->{name} = 'vivaldi';
$jo->[9]->{instance} = 'vivaldi';
$jo->[9]->{align} = 'left';
if ($output) {
syswrite STDOUT, $output . ",\n";
}
$jo->[10]->{full_text} = "o";
$jo->[10]->{color} = '#ff0000';
$jo->[10]->{name} = 'opera';
$jo->[10]->{instance} = 'opera';
$jo->[10]->{align} = 'left';
$jo->[11]->{full_text} = "ff";
$jo->[11]->{color} = '#ff0000';
$jo->[11]->{name} = 'firefox';
$jo->[11]->{instance} = 'firefox';
$jo->[11]->{align} = 'left';
$jo->[12]->{full_text} = "sl";
$jo->[12]->{color} = '#ff0000';
$jo->[12]->{name} = 'slack';
$jo->[12]->{instance} = 'slack';
$jo->[13]->{align} = 'left';
$jo->[13]->{full_text} = "t";
$jo->[13]->{color} = '#ff0000';
$jo->[13]->{name} = 'Telegram';
$jo->[13]->{instance} = 'Telegram';
$jo->[13]->{align} = 'left';
$jo->[14]->{full_text} = "icq";
$jo->[14]->{color} = '#ff0000';
$jo->[14]->{name} = 'icq';
$jo->[14]->{instance} = 'icq';
$jo->[14]->{align} = 'left';
@{$jo} = reverse(@{$jo});
syswrite STDOUT, encode_json($jo) . ",\n";
$jf = 0;
}
# tick timers
@@ -217,6 +201,34 @@ while (1) {
select(undef, undef, undef, 0.333);
}
sub readconf() {
open (my $CONF, '<:encoding(UTF-8)', "$ENV{HOME}/.i3/config.json") or die "Unable to open $ENV{HOME}/.i3/config.json: $!\n";
my $len = (stat "$ENV{HOME}/.i3/config.json")[7];
use bytes;
read ($CONF, my $c, $len) or die "unable to read $ENV{HOME}/.i3/config.json";
no bytes;
close $CONF;
$c = eval { decode_json ($c); };
if ($@) {
die "Unable to decode $ENV{HOME}/.i3/config.json: $@\n";
}
my ($j, %cmd);
my $cnt = 0;
foreach (@{$c}) {
$j->[$cnt]->{full_text} = $_->{full_text} // 'no fucken name';
$j->[$cnt]->{name} = $_->{name} // $_->{full_text};
$j->[$cnt]->{instance} = $_->{instance} // $_->{full_text};
$j->[$cnt]->{color} = $_->{color} // '#00aa33';
$cmd{$_->{name}} = $_->{cmd} // '/usr/bin/true';
$cnt++
}
return ($j, %cmd);
}
sub input_thread() {
# on input of this script i3bar sends infinite json array
# one special thing about it: all elements of this array presented as
@@ -224,18 +236,16 @@ sub input_thread() {
# elements as independed json messages, but we have to strip leading ","
readline(*STDIN); # throw away leading "[\n"
my $char;
while (1) {
my $msg = readline(*STDIN);
$msg = substr($msg, 1, -1) if (substr($msg, 0, 1) eq ','); # drop leading ',' if present
my $msg = eval { readline(*STDIN) };
next unless ($msg);
$msg = substr($msg, 1) if (substr($msg, 0, 1) eq ','); # drop leading ',' if present
my $j = decode_json($msg);
if ($j->{name} eq 'mousepad') {
spawn('mousepad');
}
if ($j->{name} eq 'ff') {
spawn(['firefox']);
if (defined($CMD{$j->{name}})) {
spawn($CMD{$j->{name}});
}
}
}
@@ -293,6 +303,42 @@ sub getbatterychargestr2() {
return $str;
}
sub getbatterychargestr3() {
my $capacity = $properties->Get('org.freedesktop.UPower.Device', 'Percentage');
my $state = $properties->Get('org.freedesktop.UPower.Device', 'State');
my $time = "?";
if ($state == 2) {
# discharging
$time = $properties->Get('org.freedesktop.UPower.Device', 'TimeToEmpty');
# time in seconds, let's translate it to hours:minutes
$state = '▼';
} elsif ($state == 1) {
# charging
$time = $properties->Get('org.freedesktop.UPower.Device', 'TimeToFull');
$state = '▲';
} else {
# already charged
$time = 0;
$state = '•';
}
$time = to_hours ($time) unless ($time eq '?');
return sprintf("⚡ %s%% %s %s", $capacity, $state, $time);
}
sub to_hours ($) {
my $sec = shift;
my $hrs = $sec / (60 * 60);
$hrs = 0 if ( $hrs < 1 );
my $min = ($sec - ($hrs * 60 * 60)) / 60;
$min = 0 if ( $min < 1 );
return sprintf("%02d:%02d", $hrs, $min);
}
sub meminfo() {
if (defined($MEMINFOHANDLE)) {
open ($MEMINFOHANDLE, "/proc/meminfo") if (tell($MEMINFOHANDLE) == -1);
@@ -519,24 +565,36 @@ sub caps_find() {
sub spawn (@) {
my @args = @_;
# fork, detach, exec
my $pid = fork();
if ($pid) { # Parent
1;
return;
} elsif ($pid == 0) { # Child
close STDOUT;
close STDERR;
close STDIN;
my $prg = shift(@args);
POSIX::setsid ();
# we need no io streams here, right?
# it seems that at least vscode creashes if we close stdio handles
open(STDOUT, ">", "/dev/null");
open(STDERR, ">", "/dev/null");
open(STDIN, "<", "/dev/null");
$pid = fork ();
if (@args > 0) {
exec $prg @args;
} else {
exec $prg;
if ($pid) { # Parent
# in this place parent quits
exit 0;
} elsif ($pid == 0) { # Child
my $prg = shift(@args);
# weird situation, silently quit here :)
exit 0 unless(defined($prg));
if (@args > 0) {
exec $prg @args;
} else {
exec $prg;
}
} else { # Unable to fork()
syswrite STDERR, "[{\"full_text\":\"ERROR: Could not fork new process: $!\",\"color\":\"#ff0000\"}],\n";
}
} else { # Unable to fork
die "ERROR: Could not fork new process: $!\n\n";
} else { # Unable to fork()
syswrite STDERR, "[{\"full_text\":\"ERROR: Could not fork new process: $!\",\"color\":\"#ff0000\"}],\n";
}
}

8
touchpad_toggle Normal file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
if [[ $(xinput list 12|grep -c "This device is disabled") == "1" ]]; then
xinput enable 12
else
xinput disable 12
fi

149
tpingd.go Normal file
View File

@@ -0,0 +1,149 @@
package main
import (
"fmt"
"net"
"os"
"time"
"github.com/godbus/dbus/v5"
)
var pingres = false
var sleeptime time.Duration = 5
var charge = "[??% ? 00:00]"
func secondsToClock(inSeconds int64) string {
hours := (inSeconds / 60) / 60
minutes := inSeconds % 60
str := fmt.Sprintf("%02d:%02d", hours, minutes)
return str
}
func mycharge () {
for true {
conn, err := dbus.SystemBus()
if err != nil {
time.Sleep(sleeptime * time.Second)
continue
}
defer conn.Close()
obj := conn.Object("org.freedesktop.UPower", "/org/freedesktop/UPower/devices/battery_BAT0")
percentage, err := obj.GetProperty("org.freedesktop.UPower.Percentage")
if err != nil {
conn.Close()
time.Sleep(sleeptime * time.Second)
continue
}
var pcharge int = int(percentage.Value().(float64))
state, err := obj.GetProperty("org.freedesktop.UPower.State")
if err != nil {
conn.Close()
time.Sleep(sleeptime * time.Second)
continue
}
var status string = "?"
var chtime string = "00:00"
if state.Value().(uint32) == 1 {
mytime, err := obj.GetProperty("org.freedesktop.UPower.TimeToFull")
if err != nil {
chtime = "00:00"
} else {
var seconds = mytime.Value().(int64)
chtime = secondsToClock(seconds)
}
status = "▲"
} else if state.Value().(uint32) == 2 {
mytime, err := obj.GetProperty("org.freedesktop.UPower.TimeToEmpty")
if err != nil {
chtime = "00:00"
} else {
var seconds = mytime.Value().(int64)
chtime = secondsToClock(seconds)
}
status = "▼"
} else if state.Value().(uint32) == 4 {
status = "•"
}
charge = fmt.Sprintf("[%02d%% %s %s]\n", pcharge, status, chtime)
time.Sleep(sleeptime * time.Second)
}
}
func myping() {
for true {
conn, e := net.DialTimeout("tcp", "jenkins:443", 3000 * time.Millisecond)
if e != nil {
pingres = false
} else {
conn.Close()
pingres = true
}
time.Sleep(sleeptime * time.Second)
}
}
func handleConnection(conn net.Conn) {
buf := make([]byte, 1024)
bufLen, err := conn.Read(buf)
if err == nil {
tail := string(buf[bufLen - 4 : bufLen])
// ah, fuck, yea. if you check buffer with \n\r\n\r against "\n\r\n\r" you'll get always FALSE, but if check against hex values, it works
if bufLen > 4 && fmt.Sprintf("%x", tail) == "0d0a0d0a" {
if pingres {
var answer = fmt.Sprintf("HTTP/1.1 200 OK\nContent-Type: text/plain\nConnection: close\n\nReachable %s\n", charge)
conn.Write([]byte(answer))
} else {
var answer = fmt.Sprintf("HTTP/1.1 200 OK\nContent-Type: text/plain\nConnection: close\n\nUnreachable %s\n", charge)
conn.Write([]byte(answer))
}
conn.Close()
} else {
conn.Write([]byte("HTTP/1.1 400 Bad Request\nContent-Type: text/plain\nConnection: close\n\nBad Request\n"))
conn.Close()
}
}
}
func main() {
ln, e := net.Listen("tcp", "127.0.0.1:9000")
if e != nil {
fmt.Println(e)
os.Exit(1)
}
go myping()
go mycharge()
for {
// infinitely handle incomming connections
conn, e := ln.Accept()
if e != nil {
// shit happens, let's try one more time
continue
}
go handleConnection(conn)
}
}