mirror of https://github.com/cy384/ssheven.git
split code up into more files, create network config/read thread
This commit is contained in:
parent
4f633aba81
commit
516e60887f
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.9)
|
cmake_minimum_required(VERSION 3.9)
|
||||||
|
|
||||||
add_application(ssheven CREATOR "SSH7" ssheven.c ssheven.r)
|
add_application(ssheven CREATOR "SSH7" ssheven.c ssheven-console.c ssheven.r)
|
||||||
|
|
||||||
set_target_properties(ssheven PROPERTIES COMPILE_OPTIONS -ffunction-sections)
|
set_target_properties(ssheven PROPERTIES COMPILE_OPTIONS -ffunction-sections)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
/*
|
||||||
|
* ssheven
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 by cy384 <cy384@cy384.com>
|
||||||
|
* See LICENSE file for details
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ssheven-console.h"
|
||||||
|
|
||||||
|
|
||||||
|
void draw_char(int x, int y, Rect* r, char c)
|
||||||
|
{
|
||||||
|
TextFont(kFontIDMonaco);
|
||||||
|
TextSize(9);
|
||||||
|
TextFace(normal);
|
||||||
|
|
||||||
|
int cell_height = 12;
|
||||||
|
int cell_width = CharWidth('M');
|
||||||
|
|
||||||
|
MoveTo(r->left + x * cell_width + 2, r->top + ((y+1) * cell_height) - 2);
|
||||||
|
DrawChar(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_screen(Rect* r)
|
||||||
|
{
|
||||||
|
EraseRect(r);
|
||||||
|
for (int x = 0; x < 80; x++)
|
||||||
|
for (int y = 0; y < 24; y++)
|
||||||
|
draw_char(x, y, r, con.data[x][y]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ruler(Rect* r)
|
||||||
|
{
|
||||||
|
char itoc[] = {'0','1','2','3','4','5','6','7','8','9'};
|
||||||
|
|
||||||
|
for (int x = 0; x < 80; x++)
|
||||||
|
for (int y = 0; y < 24; y++)
|
||||||
|
draw_char(x, y, r, itoc[x%10]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bump_up_line()
|
||||||
|
{
|
||||||
|
for (int y = 0; y < 23; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < 80; x++)
|
||||||
|
{
|
||||||
|
con.data[x][y] = con.data[x][y+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = 0; x < 80; x++) con.data[x][23] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_printable(char c)
|
||||||
|
{
|
||||||
|
if (c >= 32 && c <= 126) return 1; else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_char(char c)
|
||||||
|
{
|
||||||
|
// backspace
|
||||||
|
if ('\b' == c)
|
||||||
|
{
|
||||||
|
// erase current location
|
||||||
|
con.data[con.cursor_x][con.cursor_y] = ' ';
|
||||||
|
|
||||||
|
// wrap back to the previous line if possible and necessary
|
||||||
|
if (con.cursor_x == 0 && con.cursor_y != 0)
|
||||||
|
{
|
||||||
|
con.cursor_x = 79;
|
||||||
|
con.cursor_y--;
|
||||||
|
}
|
||||||
|
// otherwise just move back a spot
|
||||||
|
else if (con.cursor_x > 0)
|
||||||
|
{
|
||||||
|
con.cursor_x--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// got a bell, give em a system beep (value of 30 recommended by docs)
|
||||||
|
if ('\a' == c) SysBeep(30);
|
||||||
|
|
||||||
|
if ('\n' == c)
|
||||||
|
{
|
||||||
|
con.cursor_y++;
|
||||||
|
con.cursor_x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_printable(c))
|
||||||
|
{
|
||||||
|
con.data[con.cursor_x][con.cursor_y] = c;
|
||||||
|
con.cursor_x++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con.cursor_x == 80)
|
||||||
|
{
|
||||||
|
con.cursor_x = 0;
|
||||||
|
con.cursor_y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con.cursor_y == 24)
|
||||||
|
{
|
||||||
|
bump_up_line();
|
||||||
|
con.cursor_y = 23;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_string_i(const char* c)
|
||||||
|
{
|
||||||
|
print_string(c);
|
||||||
|
// TODO invalidate only the correct region
|
||||||
|
InvalRect(&(con.win->portRect));
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_string(const char* c)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < strlen(c); i++)
|
||||||
|
{
|
||||||
|
print_char(c[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_window_title(WindowPtr w, const char* c_name)
|
||||||
|
{
|
||||||
|
Str255 pascal_name;
|
||||||
|
strncpy((char *) &pascal_name[1], c_name, 255);
|
||||||
|
pascal_name[0] = strlen(c_name);
|
||||||
|
|
||||||
|
SetWTitle(w, pascal_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void console_setup(void)
|
||||||
|
{
|
||||||
|
TextFont(kFontIDMonaco);
|
||||||
|
TextSize(9);
|
||||||
|
TextFace(normal);
|
||||||
|
|
||||||
|
int cell_height = 12;
|
||||||
|
int cell_width = CharWidth('M');
|
||||||
|
|
||||||
|
Rect initial_window_bounds = qd.screenBits.bounds;
|
||||||
|
InsetRect(&initial_window_bounds, 20, 20);
|
||||||
|
initial_window_bounds.top += 40;
|
||||||
|
|
||||||
|
initial_window_bounds.bottom = initial_window_bounds.top + cell_height * 24 + 2;
|
||||||
|
initial_window_bounds.right = initial_window_bounds.left + cell_width * 80 + 4;
|
||||||
|
|
||||||
|
// limits on window size changes:
|
||||||
|
// top = min vertical
|
||||||
|
// bottom = max vertical
|
||||||
|
// left = min horizontal
|
||||||
|
// right = max horizontal
|
||||||
|
//Rect window_limits = { .top = 100, .bottom = 200, .left = 100, .right = 200 };
|
||||||
|
|
||||||
|
ConstStr255Param title = "\pssheven " SSHEVEN_VERSION;
|
||||||
|
|
||||||
|
WindowPtr win = NewWindow(NULL, &initial_window_bounds, title, true, noGrowDocProc, (WindowPtr)-1, true, 0);
|
||||||
|
|
||||||
|
Rect portRect = win->portRect;
|
||||||
|
|
||||||
|
SetPort(win);
|
||||||
|
EraseRect(&portRect);
|
||||||
|
|
||||||
|
int exit_main_loop = 0;
|
||||||
|
|
||||||
|
con.win = win;
|
||||||
|
memset(con.data, ' ', sizeof(char) * 24*80);
|
||||||
|
|
||||||
|
con.cursor_x = 0;
|
||||||
|
con.cursor_y = 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* ssheven
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 by cy384 <cy384@cy384.com>
|
||||||
|
* See LICENSE file for details
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ssheven.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void draw_char(int x, int y, Rect* r, char c);
|
||||||
|
void draw_screen(Rect* r);
|
||||||
|
|
||||||
|
void ruler(Rect* r);
|
||||||
|
|
||||||
|
void bump_up_line();
|
||||||
|
|
||||||
|
int is_printable(char c);
|
||||||
|
|
||||||
|
void print_char(char c);
|
||||||
|
void print_string(const char* c);
|
||||||
|
void print_string_i(const char* c);
|
||||||
|
|
||||||
|
void set_window_title(WindowPtr w, const char* c_name);
|
||||||
|
|
||||||
|
void console_setup(void);
|
|
@ -1,3 +1,10 @@
|
||||||
|
/*
|
||||||
|
* ssheven
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 by cy384 <cy384@cy384.com>
|
||||||
|
* See LICENSE file for details
|
||||||
|
*/
|
||||||
|
|
||||||
/* handy debugging string conversions */
|
/* handy debugging string conversions */
|
||||||
|
|
||||||
/* convert libssh2 errors into strings */
|
/* convert libssh2 errors into strings */
|
408
ssheven.c
408
ssheven.c
|
@ -5,64 +5,26 @@
|
||||||
* See LICENSE file for details
|
* See LICENSE file for details
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// retro68 stdio/console library
|
#include "ssheven.h"
|
||||||
//#include <stdio.h>
|
#include "ssheven-console.h"
|
||||||
|
|
||||||
// open transport
|
|
||||||
#include <OpenTransport.h>
|
|
||||||
#include <OpenTptInternet.h>
|
|
||||||
|
|
||||||
// mac os stuff
|
|
||||||
#include <Threads.h>
|
|
||||||
#include <MacMemory.h>
|
|
||||||
#include <Quickdraw.h>
|
|
||||||
#include <Fonts.h>
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <Sound.h>
|
|
||||||
|
|
||||||
// libssh2
|
|
||||||
#include <libssh2.h>
|
|
||||||
|
|
||||||
// functions to convert error and status codes to strings
|
// functions to convert error and status codes to strings
|
||||||
#include "ssheven-debug.h"
|
#include "ssheven-debug.c"
|
||||||
|
|
||||||
// version string
|
|
||||||
#define SSHEVEN_VERSION "0.1.0"
|
|
||||||
|
|
||||||
// size for recv and send thread buffers
|
|
||||||
#define BUFFER_SIZE 4096
|
|
||||||
|
|
||||||
// terminal type to send over ssh, determines features etc.
|
|
||||||
// "vanilla" supports basically nothing, which is good for us here
|
|
||||||
#define TERMINAL_TYPE "vanilla"
|
|
||||||
|
|
||||||
// error checking convenience macros
|
// error checking convenience macros
|
||||||
#define OT_CHECK(X) err = (X); if (err != noErr) { print_string("" #X " failed\n"); return; };
|
#define OT_CHECK(X) err = (X); if (err != noErr) { print_string("" #X " failed\n"); return; };
|
||||||
#define SSH_CHECK(X) rc = (X); if (rc != LIBSSH2_ERROR_NONE) { print_string("" #X " failed: "); print_string(libssh2_error_string(rc)); print_string("\n"); return;};
|
#define SSH_CHECK(X) rc = (X); if (rc != LIBSSH2_ERROR_NONE) { print_string("" #X " failed: "); print_string(libssh2_error_string(rc)); print_string("\n"); return;};
|
||||||
|
|
||||||
// sinful globals
|
// sinful globals
|
||||||
struct ssheven_console
|
struct ssheven_console con = { NULL, {0}, 0, 0 };
|
||||||
{
|
struct ssheven_ssh_connection ssh_con = { NULL, NULL, kOTInvalidEndpointRef, NULL, NULL };
|
||||||
WindowPtr win;
|
|
||||||
|
|
||||||
char data[80][24];
|
enum { WAIT, READ, EXIT } read_thread_command = WAIT;
|
||||||
|
enum { UNITIALIZED, OPEN, CLEANUP, DONE } read_thread_state = UNITIALIZED;
|
||||||
|
|
||||||
int cursor_x;
|
char hostname[256] = {0};
|
||||||
int cursor_y;
|
char username[256] = {0};
|
||||||
} con = { NULL, {0}, 0, 0 };
|
char password[256] = {0};
|
||||||
|
|
||||||
struct ssheven_ssh_connection
|
|
||||||
{
|
|
||||||
LIBSSH2_CHANNEL* channel;
|
|
||||||
LIBSSH2_SESSION* session;
|
|
||||||
|
|
||||||
EndpointRef endpoint;
|
|
||||||
|
|
||||||
char* recv_buffer;
|
|
||||||
char* send_buffer;
|
|
||||||
} ssh_con = { NULL, NULL, kOTInvalidEndpointRef, NULL, NULL };
|
|
||||||
|
|
||||||
enum { wait, read, exit } read_thread_state = wait;
|
|
||||||
|
|
||||||
// borrowed from Retro68 sample code
|
// borrowed from Retro68 sample code
|
||||||
// draws the "default" indicator around a button
|
// draws the "default" indicator around a button
|
||||||
|
@ -92,126 +54,9 @@ static pascal void yield_notifier(void* contextPtr, OTEventCode code, OTResult r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_char(int x, int y, Rect* r, char c)
|
// read from the channel and print to console
|
||||||
{
|
|
||||||
TextFont(kFontIDMonaco);
|
|
||||||
TextSize(9);
|
|
||||||
TextFace(normal);
|
|
||||||
|
|
||||||
int cell_height = 12;
|
|
||||||
int cell_width = CharWidth('M');
|
|
||||||
|
|
||||||
MoveTo(r->left + x * cell_width + 2, r->top + ((y+1) * cell_height) - 2);
|
|
||||||
DrawChar(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_screen(Rect* r)
|
|
||||||
{
|
|
||||||
EraseRect(&(con.win->portRect));
|
|
||||||
for (int x = 0; x < 80; x++)
|
|
||||||
for (int y = 0; y < 24; y++)
|
|
||||||
draw_char(x, y, r, con.data[x][y]);
|
|
||||||
}
|
|
||||||
|
|
||||||
char itoc[] = {'0','1', '2','3','4','5','6','7','8','9'};
|
|
||||||
|
|
||||||
void ruler(Rect* r)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < 80; x++)
|
|
||||||
for (int y = 0; y < 24; y++)
|
|
||||||
draw_char(x, y, r, itoc[x%10]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bump_up_line()
|
|
||||||
{
|
|
||||||
for (int y = 0; y < 23; y++)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < 80; x++)
|
|
||||||
{
|
|
||||||
con.data[x][y] = con.data[x][y+1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int x = 0; x < 80; x++) con.data[x][23] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_printable(char c)
|
|
||||||
{
|
|
||||||
if (c >= 32 && c <= 126) return 1; else return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_char(char c)
|
|
||||||
{
|
|
||||||
// backspace
|
|
||||||
if ('\b' == c)
|
|
||||||
{
|
|
||||||
// erase current location
|
|
||||||
con.data[con.cursor_x][con.cursor_y] = ' ';
|
|
||||||
|
|
||||||
// wrap back to the previous line if possible and necessary
|
|
||||||
if (con.cursor_x == 0 && con.cursor_y != 0)
|
|
||||||
{
|
|
||||||
con.cursor_x = 79;
|
|
||||||
con.cursor_y--;
|
|
||||||
}
|
|
||||||
// otherwise just move back a spot
|
|
||||||
else if (con.cursor_x > 0)
|
|
||||||
{
|
|
||||||
con.cursor_x--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// got a bell, give em a system beep (value of 30 recommended by docs)
|
|
||||||
if ('\a' == c) SysBeep(30);
|
|
||||||
|
|
||||||
if ('\n' == c)
|
|
||||||
{
|
|
||||||
con.cursor_y++;
|
|
||||||
con.cursor_x = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_printable(c))
|
|
||||||
{
|
|
||||||
con.data[con.cursor_x][con.cursor_y] = c;
|
|
||||||
con.cursor_x++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (con.cursor_x == 80)
|
|
||||||
{
|
|
||||||
con.cursor_x = 0;
|
|
||||||
con.cursor_y++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (con.cursor_y == 24)
|
|
||||||
{
|
|
||||||
bump_up_line();
|
|
||||||
con.cursor_y = 23;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_string(const char* c)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < strlen(c); i++)
|
|
||||||
{
|
|
||||||
print_char(c[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
void set_window_title(WindowPtr w, const char* c_name)
|
|
||||||
{
|
|
||||||
Str255 pascal_name;
|
|
||||||
strncpy((char *) &pascal_name[1], c_name, 255);
|
|
||||||
pascal_name[0] = strlen(c_name);
|
|
||||||
|
|
||||||
SetWTitle(w, pascal_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssh_read(void)
|
void ssh_read(void)
|
||||||
{
|
{
|
||||||
// read from the channel
|
|
||||||
int rc = libssh2_channel_read(ssh_con.channel, ssh_con.recv_buffer, BUFFER_SIZE);
|
int rc = libssh2_channel_read(ssh_con.channel, ssh_con.recv_buffer, BUFFER_SIZE);
|
||||||
|
|
||||||
if (rc == 0) return;
|
if (rc == 0) return;
|
||||||
|
@ -219,8 +64,6 @@ void ssh_read(void)
|
||||||
if (rc > 0)
|
if (rc > 0)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < rc; ++i) print_char(ssh_con.recv_buffer[i]);
|
for(int i = 0; i < rc; ++i) print_char(ssh_con.recv_buffer[i]);
|
||||||
InvalRect(&(con.win->portRect));
|
|
||||||
//print_string("\n");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -228,11 +71,15 @@ void ssh_read(void)
|
||||||
print_string(libssh2_error_string(rc));
|
print_string(libssh2_error_string(rc));
|
||||||
print_string("\n");
|
print_string("\n");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// TODO invalidate only the correct region
|
||||||
|
InvalRect(&(con.win->portRect));
|
||||||
|
}
|
||||||
|
|
||||||
void end_connection(void)
|
void end_connection(void)
|
||||||
{
|
{
|
||||||
|
read_thread_state = CLEANUP;
|
||||||
|
|
||||||
OSStatus err = noErr;
|
OSStatus err = noErr;
|
||||||
|
|
||||||
if (ssh_con.channel)
|
if (ssh_con.channel)
|
||||||
|
@ -289,40 +136,16 @@ void end_connection(void)
|
||||||
err = OTCloseProvider(ssh_con.endpoint);
|
err = OTCloseProvider(ssh_con.endpoint);
|
||||||
if (err != noErr) print_string("OTCloseProvider failed\n");
|
if (err != noErr) print_string("OTCloseProvider failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
read_thread_state = DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void event_loop(void)
|
void check_network_events(void)
|
||||||
{
|
{
|
||||||
int exit_event_loop = 0;
|
|
||||||
OTResult look_result = 0;
|
|
||||||
OSStatus err = noErr;
|
OSStatus err = noErr;
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// system task yields to run drivers and other stuff!
|
|
||||||
//SystemTask(); // don't need to call if we use waitnextevent
|
|
||||||
//Idle();
|
|
||||||
EventRecord event;
|
|
||||||
WindowPtr eventWin;
|
|
||||||
|
|
||||||
/*
|
|
||||||
while(!GetNextEvent(everyEvent, &event))
|
|
||||||
{
|
|
||||||
SystemTask();
|
|
||||||
YieldToAnyThread();
|
|
||||||
//Idle();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// alternately we can use:
|
|
||||||
long int ct = GetCaretTime(); // should probably make this a smaller number, but eh.
|
|
||||||
|
|
||||||
// wait for some length of time to get an event
|
|
||||||
// runs the loop every time we timeout waiting for a mac event
|
|
||||||
while (!WaitNextEvent(everyEvent, &event, ct, NULL))
|
|
||||||
{
|
|
||||||
// check if we have any new network events
|
// check if we have any new network events
|
||||||
look_result = OTLook(ssh_con.endpoint);
|
OTResult look_result = OTLook(ssh_con.endpoint);
|
||||||
|
|
||||||
switch (look_result)
|
switch (look_result)
|
||||||
{
|
{
|
||||||
|
@ -358,6 +181,29 @@ void event_loop(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void event_loop(void)
|
||||||
|
{
|
||||||
|
int exit_event_loop = 0;
|
||||||
|
EventRecord event;
|
||||||
|
WindowPtr eventWin;
|
||||||
|
|
||||||
|
// maximum length of time to sleep (in ticks)
|
||||||
|
// GetCaretTime gets the number of ticks between caret on/off time
|
||||||
|
long int sleep_time = GetCaretTime();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// wait to get a GUI event
|
||||||
|
while (!WaitNextEvent(everyEvent, &event, sleep_time, NULL))
|
||||||
|
{
|
||||||
|
// timed out without any GUI events
|
||||||
|
|
||||||
|
// process any network events
|
||||||
|
//check_network_events();
|
||||||
|
|
||||||
// let any other threads run before we wait for events again
|
// let any other threads run before we wait for events again
|
||||||
YieldToAnyThread();
|
YieldToAnyThread();
|
||||||
}
|
}
|
||||||
|
@ -381,7 +227,7 @@ void event_loop(void)
|
||||||
{
|
{
|
||||||
if ('\r' == c) c = '\n';
|
if ('\r' == c) c = '\n';
|
||||||
ssh_con.send_buffer[0] = c;
|
ssh_con.send_buffer[0] = c;
|
||||||
libssh2_channel_write(ssh_con.channel, ssh_con.send_buffer, 1);
|
if (read_thread_state == OPEN) libssh2_channel_write(ssh_con.channel, ssh_con.send_buffer, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
case mouseDown:
|
case mouseDown:
|
||||||
|
@ -396,7 +242,7 @@ void event_loop(void)
|
||||||
|
|
||||||
case inGrow:
|
case inGrow:
|
||||||
{
|
{
|
||||||
//don't allow resize right now
|
//not allowing resize right now
|
||||||
break;
|
break;
|
||||||
/*long growResult = GrowWindow(eventWin, event.where, &window_limits);
|
/*long growResult = GrowWindow(eventWin, event.where, &window_limits);
|
||||||
SizeWindow(eventWin, growResult & 0xFFFF, growResult >> 16, true);
|
SizeWindow(eventWin, growResult & 0xFFFF, growResult >> 16, true);
|
||||||
|
@ -428,47 +274,6 @@ void event_loop(void)
|
||||||
} while (!exit_event_loop);
|
} while (!exit_event_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void console_setup(void)
|
|
||||||
{
|
|
||||||
TextFont(kFontIDMonaco);
|
|
||||||
TextSize(9);
|
|
||||||
TextFace(normal);
|
|
||||||
|
|
||||||
int cell_height = 12;
|
|
||||||
int cell_width = CharWidth('M');
|
|
||||||
|
|
||||||
Rect initial_window_bounds = qd.screenBits.bounds;
|
|
||||||
InsetRect(&initial_window_bounds, 20, 20);
|
|
||||||
initial_window_bounds.top += 40;
|
|
||||||
|
|
||||||
initial_window_bounds.bottom = initial_window_bounds.top + cell_height * 24 + 2;
|
|
||||||
initial_window_bounds.right = initial_window_bounds.left + cell_width * 80 + 4;
|
|
||||||
|
|
||||||
// limits on window size changes:
|
|
||||||
// top = min vertical
|
|
||||||
// bottom = max vertical
|
|
||||||
// left = min horizontal
|
|
||||||
// right = max horizontal
|
|
||||||
//Rect window_limits = { .top = 100, .bottom = 200, .left = 100, .right = 200 };
|
|
||||||
|
|
||||||
ConstStr255Param title = "\pssheven " SSHEVEN_VERSION;
|
|
||||||
|
|
||||||
WindowPtr win = NewWindow(NULL, &initial_window_bounds, title, true, noGrowDocProc, (WindowPtr)-1, true, 0);
|
|
||||||
|
|
||||||
Rect portRect = win->portRect;
|
|
||||||
|
|
||||||
SetPort(win);
|
|
||||||
EraseRect(&portRect);
|
|
||||||
|
|
||||||
int exit_main_loop = 0;
|
|
||||||
|
|
||||||
con.win = win;
|
|
||||||
memset(con.data, ' ', sizeof(char) * 24*80);
|
|
||||||
|
|
||||||
con.cursor_x = 0;
|
|
||||||
con.cursor_y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_connection(char* hostname)
|
void init_connection(char* hostname)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -479,6 +284,8 @@ void init_connection(char* hostname)
|
||||||
DNSAddress hostDNSAddress;
|
DNSAddress hostDNSAddress;
|
||||||
OSStatus result;
|
OSStatus result;
|
||||||
|
|
||||||
|
print_string_i("opening and configuring endpoint... "); YieldToAnyThread();
|
||||||
|
|
||||||
// open TCP endpoint
|
// open TCP endpoint
|
||||||
ssh_con.endpoint = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, nil, &err);
|
ssh_con.endpoint = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, nil, &err);
|
||||||
|
|
||||||
|
@ -494,28 +301,41 @@ void init_connection(char* hostname)
|
||||||
|
|
||||||
OT_CHECK(OTBind(ssh_con.endpoint, nil, nil));
|
OT_CHECK(OTBind(ssh_con.endpoint, nil, nil));
|
||||||
|
|
||||||
|
print_string_i("done.\n"); YieldToAnyThread();
|
||||||
|
|
||||||
// set up address struct, do the DNS lookup, and connect
|
// set up address struct, do the DNS lookup, and connect
|
||||||
OTMemzero(&sndCall, sizeof(TCall));
|
OTMemzero(&sndCall, sizeof(TCall));
|
||||||
|
|
||||||
sndCall.addr.buf = (UInt8 *) &hostDNSAddress;
|
sndCall.addr.buf = (UInt8 *) &hostDNSAddress;
|
||||||
sndCall.addr.len = OTInitDNSAddress(&hostDNSAddress, (char *) hostname);
|
sndCall.addr.len = OTInitDNSAddress(&hostDNSAddress, (char *) hostname);
|
||||||
|
|
||||||
|
print_string_i("connecting endpoint... "); YieldToAnyThread();
|
||||||
OT_CHECK(OTConnect(ssh_con.endpoint, &sndCall, nil));
|
OT_CHECK(OTConnect(ssh_con.endpoint, &sndCall, nil));
|
||||||
|
|
||||||
print_string("OT setup done\n");
|
print_string_i("done.\n"); YieldToAnyThread();
|
||||||
|
|
||||||
|
print_string_i("initializing SSH... "); YieldToAnyThread();
|
||||||
// init libssh2
|
// init libssh2
|
||||||
SSH_CHECK(libssh2_init(0));
|
SSH_CHECK(libssh2_init(0));
|
||||||
|
|
||||||
|
print_string_i("done.\n"); YieldToAnyThread();
|
||||||
|
|
||||||
|
print_string_i("opening SSH session... "); YieldToAnyThread();
|
||||||
ssh_con.session = libssh2_session_init();
|
ssh_con.session = libssh2_session_init();
|
||||||
if (ssh_con.session == 0)
|
if (ssh_con.session == 0)
|
||||||
{
|
{
|
||||||
print_string("failed to initialize SSH library\n");
|
print_string("failed to initialize SSH library\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
print_string_i("done.\n"); YieldToAnyThread();
|
||||||
|
|
||||||
|
print_string_i("beginning SSH session handshake... "); YieldToAnyThread();
|
||||||
SSH_CHECK(libssh2_session_handshake(ssh_con.session, ssh_con.endpoint));
|
SSH_CHECK(libssh2_session_handshake(ssh_con.session, ssh_con.endpoint));
|
||||||
|
|
||||||
|
print_string_i("done.\n"); YieldToAnyThread();
|
||||||
|
|
||||||
|
read_thread_state = OPEN;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,30 +356,6 @@ void ssh_setup_terminal(void)
|
||||||
SSH_CHECK(libssh2_channel_shell(ssh_con.channel));
|
SSH_CHECK(libssh2_channel_shell(ssh_con.channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: unused
|
|
||||||
void* read_thread(void* arg)
|
|
||||||
{
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
switch(read_thread_state)
|
|
||||||
{
|
|
||||||
case wait:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case read:
|
|
||||||
ssh_read();
|
|
||||||
InvalRect(&(con.win->portRect));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case exit:
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
YieldToAnyThread();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void intro_dialog(char* hostname, char* username, char* password)
|
void intro_dialog(char* hostname, char* username, char* password)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -610,12 +406,48 @@ void intro_dialog(char* hostname, char* username, char* password)
|
||||||
FlushEvents(everyEvent, -1);
|
FlushEvents(everyEvent, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//enum { WAIT, READ, EXIT } read_thread_command = WAIT;
|
||||||
|
//enum { UNITIALIZED, OPEN, CLEANUP, DONE } read_thread_state = UNITIALIZED;
|
||||||
|
|
||||||
|
// TODO: threads
|
||||||
|
void* read_thread(void* arg)
|
||||||
|
{
|
||||||
|
while (read_thread_command == WAIT) YieldToAnyThread();
|
||||||
|
|
||||||
|
if (read_thread_command == EXIT)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect and log in
|
||||||
|
init_connection(hostname+1);
|
||||||
|
YieldToAnyThread();
|
||||||
|
|
||||||
|
print_string_i("authenticating... "); YieldToAnyThread();
|
||||||
|
ssh_password_auth(username+1, password+1);
|
||||||
|
print_string_i("done.\n"); YieldToAnyThread();
|
||||||
|
|
||||||
|
ssh_setup_terminal();
|
||||||
|
YieldToAnyThread();
|
||||||
|
|
||||||
|
// if we failed, exit
|
||||||
|
if (read_thread_state != OPEN) return 0;
|
||||||
|
|
||||||
|
// loop as long until we've failed or are asked to EXIT
|
||||||
|
while (read_thread_command == READ && read_thread_state == OPEN)
|
||||||
|
{
|
||||||
|
check_network_events();
|
||||||
|
YieldToAnyThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we still have a connection, close it
|
||||||
|
if (read_thread_state != DONE) end_connection();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
char hostname[256] = {0};
|
|
||||||
char username[256] = {0};
|
|
||||||
char password[256] = {0};
|
|
||||||
|
|
||||||
OSStatus err = noErr;
|
OSStatus err = noErr;
|
||||||
|
|
||||||
// expands the application heap to its maximum requested size
|
// expands the application heap to its maximum requested size
|
||||||
|
@ -643,6 +475,10 @@ int main(int argc, char** argv)
|
||||||
print_string(logo);
|
print_string(logo);
|
||||||
print_string("by cy384, version " SSHEVEN_VERSION "\n");
|
print_string("by cy384, version " SSHEVEN_VERSION "\n");
|
||||||
|
|
||||||
|
BeginUpdate(con.win);
|
||||||
|
draw_screen(&(con.win->portRect));
|
||||||
|
EndUpdate(con.win);
|
||||||
|
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
|
|
||||||
if (InitOpenTransport() != noErr)
|
if (InitOpenTransport() != noErr)
|
||||||
|
@ -663,10 +499,11 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// create the network read/print thread
|
||||||
read_thread_state = wait;
|
read_thread_command = WAIT;
|
||||||
int read_thread_result = 0;
|
int read_thread_result = 0;
|
||||||
ThreadID read_thread_id = 0;
|
ThreadID read_thread_id = 0;
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
err = NewThread(kCooperativeThread, read_thread, NULL, 0, kCreateIfNeeded, NULL, &read_thread_id);
|
err = NewThread(kCooperativeThread, read_thread, NULL, 0, kCreateIfNeeded, NULL, &read_thread_id);
|
||||||
|
@ -677,28 +514,21 @@ int main(int argc, char** argv)
|
||||||
print_string("failed to create network read thread\n");
|
print_string("failed to create network read thread\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
if (ok)
|
// if we got the thread, tell it to begin operation
|
||||||
{
|
if (ok) read_thread_command = READ;
|
||||||
// those strings are pascal strings, so we skip the first char
|
|
||||||
init_connection(hostname+1);
|
|
||||||
|
|
||||||
ssh_password_auth(username+1, password+1);
|
|
||||||
ssh_setup_terminal();
|
|
||||||
|
|
||||||
read_thread_state = read;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// procede into our main event loop
|
||||||
event_loop();
|
event_loop();
|
||||||
|
|
||||||
/*
|
// tell the read thread to quit, then let it run to actually do so
|
||||||
read_thread_state = exit;
|
read_thread_command = EXIT;
|
||||||
OTCancelSynchronousCalls(ssh_con.endpoint, kOTCanceledErr);
|
YieldToAnyThread();
|
||||||
YieldToThread(read_thread_id);
|
|
||||||
// err = DisposeThread(read_thread_id, (void*)&read_thread_result, 0);
|
//OTCancelSynchronousCalls(ssh_con.endpoint, kOTCanceledErr);
|
||||||
err = DisposeThread(read_thread_id, NULL, 0);
|
//YieldToThread(read_thread_id);
|
||||||
*/
|
// err = DisposeThread(read_thread_id, (void*)&read_thread_result, 0);
|
||||||
|
//err = DisposeThread(read_thread_id, NULL, 0);
|
||||||
|
|
||||||
end_connection();
|
end_connection();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* ssheven
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 by cy384 <cy384@cy384.com>
|
||||||
|
* See LICENSE file for details
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// open transport
|
||||||
|
#include <OpenTransport.h>
|
||||||
|
#include <OpenTptInternet.h>
|
||||||
|
|
||||||
|
// mac os stuff
|
||||||
|
#include <Threads.h>
|
||||||
|
#include <MacMemory.h>
|
||||||
|
#include <Quickdraw.h>
|
||||||
|
#include <Fonts.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <Sound.h>
|
||||||
|
|
||||||
|
// libssh2
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
// version string
|
||||||
|
#define SSHEVEN_VERSION "0.1.0"
|
||||||
|
|
||||||
|
// size for recv and send thread buffers
|
||||||
|
#define BUFFER_SIZE 4096
|
||||||
|
|
||||||
|
// terminal type to send over ssh, determines features etc.
|
||||||
|
// "vanilla" supports basically nothing, which is good for us here
|
||||||
|
#define TERMINAL_TYPE "vanilla"
|
||||||
|
|
||||||
|
// sinful globals
|
||||||
|
struct ssheven_console
|
||||||
|
{
|
||||||
|
WindowPtr win;
|
||||||
|
|
||||||
|
char data[80][24];
|
||||||
|
|
||||||
|
int cursor_x;
|
||||||
|
int cursor_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct ssheven_console con;
|
||||||
|
|
||||||
|
struct ssheven_ssh_connection
|
||||||
|
{
|
||||||
|
LIBSSH2_CHANNEL* channel;
|
||||||
|
LIBSSH2_SESSION* session;
|
||||||
|
|
||||||
|
EndpointRef endpoint;
|
||||||
|
|
||||||
|
char* recv_buffer;
|
||||||
|
char* send_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct ssheven_ssh_connection ssh_con;
|
Loading…
Reference in New Issue