init
This commit is contained in:
commit
90f617dcf0
165
moontalk.c
Normal file
165
moontalk.c
Normal file
@ -0,0 +1,165 @@
|
||||
/* moontalk.c - @BAKE cc -O2 -std=gnu99 -Wall -Wextra -pedantic $@ -o $* -lncurses -ltinfo $+ @STOP */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <ncurses.h>
|
||||
|
||||
#define SERV "7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion"
|
||||
#define PORT "50000"
|
||||
|
||||
#define streq(a,b) (!strcmp(a,b))
|
||||
|
||||
int g_row, g_col;
|
||||
|
||||
void free_screen(void) {
|
||||
endwin();
|
||||
}
|
||||
|
||||
void init_screen(void) {
|
||||
initscr();
|
||||
cbreak();
|
||||
noecho();
|
||||
keypad(stdscr, ERR);
|
||||
nodelay(stdscr, TRUE);
|
||||
}
|
||||
|
||||
void handle_winch(int x) {
|
||||
(void)x;
|
||||
struct winsize w;
|
||||
signal(SIGWINCH, SIG_IGN);
|
||||
|
||||
endwin();
|
||||
init_screen();
|
||||
refresh();
|
||||
clear();
|
||||
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
g_row = w.ws_row;
|
||||
g_col = w.ws_col;
|
||||
|
||||
signal(SIGWINCH, handle_winch);
|
||||
}
|
||||
|
||||
int g_sockfd = -1;
|
||||
|
||||
void free_connection(void) {
|
||||
close(g_sockfd);
|
||||
g_sockfd = -1;
|
||||
|
||||
/* the program should be at an end. If we're reconnecting, then at
|
||||
the top level (main) we'd free, even though the main's sockfd is now
|
||||
out-of-date, we can simply ignore that and take the result of socket
|
||||
init */
|
||||
}
|
||||
|
||||
/* always returns an accessible socket */
|
||||
int init_connection(char * serv, char * port) {
|
||||
int status, sockfd;
|
||||
struct addrinfo hints, * res;
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6
|
||||
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
|
||||
|
||||
if ((status = getaddrinfo(serv, port, &hints, &res)) != 0) {
|
||||
fprintf(stderr, "init_connection: %s\n", gai_strerror(status));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1)
|
||||
{ goto error; }
|
||||
if (connect(sockfd, res->ai_addr, res->ai_addrlen))
|
||||
{ goto error; }
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
g_sockfd = sockfd;
|
||||
return sockfd;
|
||||
error:
|
||||
perror("init_connection");
|
||||
exit(1);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
int main (int argc, char ** argv) {
|
||||
char * argv0 = argv[0];
|
||||
char * serv = SERV, * port = PORT, * name = "anonymous";
|
||||
|
||||
#define PREFIX_MAX 21
|
||||
char raw[(2 << 9) + (2 << 13)];
|
||||
char * sendbuf = raw + PREFIX_MAX, * recvbuf = raw + (2 << 9);
|
||||
size_t sendlen = 0, sendmax = (2 << 9) - PREFIX_MAX,
|
||||
recvlen = 0, recvmax = 2 << 13;
|
||||
|
||||
int sockfd;
|
||||
|
||||
while (++argv, --argc) {
|
||||
if (streq(*argv, "-help")) {
|
||||
printf("%s: HELP\n", argv0);
|
||||
return 1;
|
||||
}
|
||||
if (argc - 1)
|
||||
{ --argc; ++argv; }
|
||||
else {
|
||||
printf("%s: %s requires argument\n", argv0, *argv);
|
||||
return 1;
|
||||
}
|
||||
if (streq(*(argv-1), "-serv")) {
|
||||
printf("serv: %s\n", *argv);
|
||||
serv = *argv;
|
||||
}
|
||||
else if (streq(*(argv-1), "-port")) {
|
||||
printf("port: %s\n", *argv);
|
||||
}
|
||||
else if (streq(*(argv-1), "-name")) {
|
||||
printf("name: %s\n", *argv);
|
||||
}
|
||||
}
|
||||
|
||||
atexit(free_screen);
|
||||
init_screen();
|
||||
signal(SIGWINCH, handle_winch);
|
||||
printw("Connecting to %s:%s as %s\n", serv, port, name);
|
||||
refresh();
|
||||
sockfd = init_connection(serv, port);
|
||||
float interval = 1 / 30;
|
||||
int ch;
|
||||
time_t t;
|
||||
struct tm * tm;
|
||||
while (1) {
|
||||
/* send */
|
||||
ch = getch();
|
||||
if (ch != -1 && ch != '\n') {
|
||||
sendbuf[sendlen++] = ch;
|
||||
} else if (ch == '\n') {
|
||||
t = time(NULL);
|
||||
tm = gmtime(&t);
|
||||
strftime(sendbuf - PREFIX_MAX, PREFIX_MAX, "<%Y/%m/%d %H:%M:%S ", tm);
|
||||
sendbuf[sendlen++] = '\n';
|
||||
send(sockfd, sendbuf - PREFIX_MAX, sendlen + PREFIX_MAX, 0);
|
||||
sendlen = 0;
|
||||
memset(sendbuf, 0, sendlen);
|
||||
}
|
||||
/* recv */
|
||||
recvlen = recv(sockfd, recvbuf, recvmax, MSG_DONTWAIT);
|
||||
/* render */
|
||||
clear();
|
||||
mvaddnstr(0, 0, recvbuf, recvlen);
|
||||
mvaddnstr(g_row - 1, 0, sendbuf, sendlen);
|
||||
refresh();
|
||||
/* sleep */
|
||||
sleep(interval);
|
||||
}
|
||||
}
|
118
moontalk.rb
Normal file
118
moontalk.rb
Normal file
@ -0,0 +1,118 @@
|
||||
#!/usr/bin/ruby
|
||||
# written by emil
|
||||
#
|
||||
# short guide
|
||||
#
|
||||
# -serv specifies server,
|
||||
# -port specifies port,
|
||||
# -name specifies your display name,
|
||||
#
|
||||
# Type "BYE" to stop it after it connects to the moon.
|
||||
# Type Enter and nothing else to refresh the messages.
|
||||
# Type messages and send them, hopefully everyone hears you just fine.
|
||||
#
|
||||
# h = { "BYE" => 1, "QUIT" => 1, "SAY" => 2, "CLEAR" => 3, "NICK" => 4, "RECONNECT" => 5, "DELAY" => 6 }
|
||||
# 1 exits,
|
||||
# 2 says something verbatim (including a raw newline),
|
||||
# 3 clears the terminal,
|
||||
# 4 sets the nick (needs arg),
|
||||
# 5 reconnects,
|
||||
# 6 sets delays ( needs arg)
|
||||
|
||||
require 'socket'
|
||||
require 'readline'
|
||||
|
||||
@serv = '7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion'
|
||||
@port = 50000
|
||||
|
||||
@name = "anonymous"
|
||||
|
||||
def read_from(socket)
|
||||
begin # probably too large of a read size...
|
||||
puts socket.read_nonblock(2 << 16)
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
def post(socket, msg)
|
||||
update_prefix
|
||||
socket.puts(@prefix + msg)
|
||||
end
|
||||
|
||||
def update_prefix
|
||||
date = Time.now.utc.strftime("%Y/%m/%d %k:%M:%S")
|
||||
@prefix = "<#{date} #{@name}> "
|
||||
end
|
||||
|
||||
def connect
|
||||
puts "Connecting to " + @serv + ":" + @port.to_s + " as " + @name
|
||||
socket = TCPSocket.new(@serv, @port)
|
||||
if not socket
|
||||
puts "Failed to connect."
|
||||
exit 1
|
||||
end
|
||||
return socket
|
||||
end
|
||||
|
||||
def main
|
||||
begin
|
||||
ARGV.each_with_index do |element,index|
|
||||
if element == "-name"
|
||||
@name = ARGV[index + 1]
|
||||
end
|
||||
if element == "-serv"
|
||||
@serv = ARGV[index + 1]
|
||||
end
|
||||
if element == "-port"
|
||||
@port = ARGV[index + 1].to_i
|
||||
end
|
||||
end
|
||||
rescue
|
||||
end
|
||||
socket = connect
|
||||
begin
|
||||
delay = 0
|
||||
|
||||
h = { "BYE" => 1, "QUIT" => 1, "SAY" => 2, "CLEAR" => 3, "NICK" => 4, "RECONNECT" => 5, "DELAY" => 6 }
|
||||
|
||||
update_prefix
|
||||
while msg = Readline.readline(@prefix, true)
|
||||
if not msg.empty?
|
||||
msg.strip!
|
||||
word = msg.split(/^([\w]*)$|^([\w]*) (.*)$/)[1..]
|
||||
case h[word[0]]
|
||||
when h["BYE"]
|
||||
post(socket, "BYE")
|
||||
exit 0
|
||||
when h["CLEAR"]
|
||||
puts "\e[1;1H\e[2J"
|
||||
when h["NICK"]
|
||||
if not word[1].empty?
|
||||
@name = word[1]
|
||||
end
|
||||
when h["RECONNECT"]
|
||||
socket.close
|
||||
socket = connect
|
||||
when h["DELAY"]
|
||||
delay = word[1].to_i
|
||||
when h["SAY"]
|
||||
if not word.length > 1
|
||||
word.push("")
|
||||
end
|
||||
post(socket, word[1])
|
||||
else
|
||||
post(socket, msg)
|
||||
end
|
||||
end
|
||||
|
||||
read_from(socket)
|
||||
sleep delay
|
||||
update_prefix
|
||||
end
|
||||
ensure
|
||||
puts "\nSTOPPING NOW."
|
||||
socket.close
|
||||
end
|
||||
end
|
||||
|
||||
main
|
34
moontalk.tcl
Executable file
34
moontalk.tcl
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/tclsh
|
||||
package require Tk
|
||||
|
||||
set ::name anonymous
|
||||
set ::usernu x
|
||||
|
||||
set ::host 7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion
|
||||
|
||||
pack [text .msgs] -fill both -expand 1
|
||||
pack [entry .entry] -fill x
|
||||
|
||||
proc add_msg { msg } {
|
||||
.msgs insert end "$msg\n"
|
||||
.msgs yview end
|
||||
}
|
||||
|
||||
proc get_msg {} {
|
||||
set curdate [clock format [clock seconds] -format "%Y/%m/%d %T"]
|
||||
return "<$curdate $::name:$::usernu> [.entry get]"
|
||||
}
|
||||
|
||||
bind .entry <Return> {
|
||||
set msg [get_msg]
|
||||
puts $::fd $msg
|
||||
flush $::fd
|
||||
add_msg $msg
|
||||
.entry delete 0 end
|
||||
}
|
||||
|
||||
fileevent [set fd [socket $::host 50000]] readable {
|
||||
add_msg [gets $::fd]
|
||||
}
|
||||
|
||||
chan configure $::fd -translation binary
|
Loading…
Reference in New Issue
Block a user