Synchronet v3.18b-Win32 (install) has been released (Sept-2020).

Synchronet v3.19a, now under development, requires libarchive-dev to build successfully.

You can donate to the Synchronet project using PayPal.

Integrate Linux Shell Apps

Linux shell applications can be added to Synchronet by using the built in js function bbs.exec(); and must pass special command line arguments that instruct sbbs to pipe the shell i/o to the client terminal.

ie: bbs.exec('links2 "google.com/search?q='+google+'"', EX_STDIO|EX_NATIVE|EX_NOLOG);

This method can also be used to launch DOS/Windows executibles as well!

Links2 Web Browser

links2 is an https compliant graphical text mode www browser typically run from in linux shell. For use with Synchronet we won't configure the graphics card and/or image support, so the output is monochrome and behaves more like a gopher client with enhanced features.

On a Debian system, make sure links2 is installed:

  $ sudo apt-get install links2

Add links2 to SBBS

Add links2 to sbbs as an external program as any other door:

[Links2 Web Browser]
 1: Name                       Links2 Web Browser
 2: Internal Code              LINKS2
 3: Start-up Directory
 4: Command Line               ?links2.js
 5: Clean-up Command Line
 6: Execution Cost             None
 7: Access Requirements
 8: Execution Requirements
 9: Multiple Concurrent Users  Yes
10: Intercept I/O              No
11: Native Executable/Script   No
12: Use Shell or New Context   No
13: Modify User Data           No
14: Execute on Event           No
15: Pause After Execution      No
16: BBS Drop File Type         None
17: Place Drop File In         Node Directory
18: Time Options...

Which (Help or Quit):           

Add to Synchronet Command Shell

edit your *.src command shell script and add:

ie: cmdkey /B
        exec_bin "links2.js"
        end_cmd

and recompile

/sbbs/exec $ ./baja myshell

add option to your menu *.ans; *.msg; *.asc, etc as appropriate.

links2 example script

load('sbbsdefs.js');
// links2.js

console.putmsg('\r\n\1n \1glinks v2.18 - text mode www browser\r\n\r\n');
console.putmsg(' \1gPressing [ESC] in Links2 for Menu or read Links2 in Text Section\r\n\r\n');
console.putmsg(' \1h\1yG\1n\1google Search  \1h\1gE\1n\1gnter URL \1h\1wor  \1rQ\1guit \1w');
var ch = console.getkeys("GEQ",K_UPPER);
if(ch === '') ch = 'G';

switch (ch) {
        case 'G':
                console.putmsg('\r\n \1gGoogle search term? \1h\1g');
                var google = console.getstr();
                if(google.length<1)
                        console.putmsg('\r\n\r\n\1g Search term omited, using default\r\n')
                else
                        console.putmsg('\r\n\r\n\1n \1gGoogling \1h\1y'+google+'\r\n');
                console.putmsg(' \1h\1yQ\1n\1guits the browser.\r\n\r\n');
                console.pause();
                google = google.replace(' ', '+');
                if(user.is_sysop)
                    bbs.exec('links2 "google.com/search?q='+google+'"', EX_STDIO|EX_NATIVE|EX_NOLOG)
                else
                    bbs.exec('links2 -anonymous "google.com/search?q='+google+'"', EX_STDIO|EX_NATIVE|EX_NOLOG);
                console.putmsg('\r\n\r\n\1g  Returning to '+system.name);
                mswait(1000);
                exit();
        break;

        case 'E':
                console.putmsg('\r\n\r\n \1gEnter URL: \1h\1g');
                var url = console.getstr();
                var v =  url.indexOf(".")
                if (v < 0) {
                        url = 'http://www.aboutlinux.info/2007/02/links2-cross-platform-console-based-web.html';
                }                
                console.putmsg('\r\n\r\n\1n \1gLoading links2 \r\n');
                console.putmsg(' \1h\1yQ\1n\1guits the browser.\r\n\r\n');
                console.pause();
                url = url.replace(' ', '+');
                
                if(user.is_sysop)
                    bbs.exec('links2 "'+url+'"', EX_STDIO|EX_NATIVE|EX_NOLOG)
                else
                    bbs.exec('links2 -anonymous "'+url+'"', EX_STDIO|EX_NATIVE|EX_NOLOG);
                console.putmsg('\r\n\r\n\1g  Returning to '+system.name);
                mswait(1000);
                exit();
        break;

        case 'Q':
                console.putmsg('\r\n\1g  Returning to '+system.name);
                mswait(1000);
                exit();
        break;
}

WeeChat IRC Client

WeeChat (Wee Enhanced Environment for Chat) makes for a decent IRC client alternative to the stock irc.js client.

First, install Weechat under Debian type:

$ sudo apt-get install weechat

add WeeChat as an external program similar to Links2 ( the script's bbs.exec('whatever', <args>); are the same to redirect i/o so no need to add it in SCFG )

add a cmdkey ... end_cmd entry in your command shell similar to links2 above, if desired.

example weechat js

Weechat looks for a configuration file in /home/<user>/.weechat/irc.conf to get the username/channel/etc information so wee need to setup a new config for each user/connection, to do this we apply some hackery:

load("sbbsdefs.js");

var enable;
var server;
var port;
var chan;
var lusr = user.alias;

var quit_msg = system.name+' - WeeChat 1.6 Linux'; // todo random quit messages

var irc = load("modopts.js", "weechat");

if(irc.enabled == undefined) enabled = true;
    else enabled = irc.enabled;
if(irc.chan === undefined) chan = '#synchronet';
    else chan = irc.chan;
if(irc.server === undefined) servers = 'irc.synchro.net';
    else server = irc.servers;

var infile = system.ctrl_dir+'irc-weechat.conf';
var outfile = system.ctrl_dir+'irc-weechat.tmp';
var weechat = '/home/sbbs/.weechat/irc.conf';
var wc_bup = '/home/sbbs/.weechat/irc-'+strftime("%Y-%m%d_%H%M", time())+'.conf';
var save_prefs = system.data_dir+'wc-prefs.'+user.number;

if(!file_exists(weechat) || !enabled) {
        if(!enabled) {
            writeln('\r\n\r\n\1rWeechat is disabled\r\n\r\n');
        } else {
            writeln('\r\n\r\n\1rirc.conf missing.\r\n');
            mswait(500);
            writeln('\1cTrying default irc client\r\n\r\n');
            load("irc.js");
            exit();
        }
}

var line;
var count;

var inf = new File(infile);
var out = new File(outfile);

writeln('\r\n\r\n \1gLoading IRC WeeChat 1.6\r\n');
writeln('\1g AlleyCat! BBS attempts connect to: \r\n');
writeln('   \1h\1yServer:  \1w'+servers);
writeln('   \1h\1yChannel: \1w'+chan);
writeln('   \1h\1yNick:    \1w'+lusr+'\r\n\r\n');

var cont = console.noyes('Would you like to Connect to IRC ');
if(cont) {
    console.putmsg('\r\n\1r Aborting...\r\n\r\n');
    exit(0);
}

console.putmsg('\r\n \1g[\1h\1yC\1g] ontinue to IRC   [\1wE\1g] dit Connection   [\1wQ\1g] uit\r\n\r\n Whadda ya wanna do? ');
var goon = console.getkey().toUpperCase();
if(goon != "Q" && goon != "E") goon = "C";
switch(goon) {
    case 'Q':
        writeln(' Returning to '+system.name+' \r\n\r\n');
        mswait(1000);
        exit();
    break;

    case 'E':
        console.putmsg('\r\n\r\n \1gChannel: \1w');
        var chan1 = console.getstr();
        if(chan1 != '')
            chan = chan1;
        console.putmsg('\1g Nick: \1w');
        var lusr1 = console.getstr();
        if(lusr1 != '')
            lusr = lusr1;
        console.putmsg('\r\n\1gUsing nick: \1h\1y'+lusr+' \1gand joining channel \1h\1y'+chan+'\r\n');
        mswait(1000);
    break;
}

inf.open("r");
out.open("w+");

count = 0;

while(!inf.eof) {
        line = inf.readln().trim();
        if(line.toUpperCase() !== "[SERVER]" && line !== null) { // dump the default settings ...
                out.writeln(line);
                count++;
        }
        else { // found [server] , this section needs to be replace with sbbs user credentials
            out.writeln('[server]');
            out.writeln('synchronet.proxy');
            out.writeln('synchronet.ipv6');
            out.writeln('synchronet.ss');
            out.writeln('synchronet.ssl_cert');
            out.writeln('synchronet.ssl_priorities');
            out.writeln('synchronet.ssl_dhkey_size');
            out.writeln('synchronet.ssl_fingerprint');
            out.writeln('synchronet.ssl_verify');
            out.writeln('synchronet.password');
            out.writeln('synchronet.capabilities');
            out.writeln('synchronet.sasl_mechanism');
            out.writeln('synchronet.sasl_username');
            out.writeln('synchronet.sasl_password');
            out.writeln('synchronet.sasl_key');
            out.writeln('synchronet.sasl_timeout');
            out.writeln('synchronet.sasl_fail');
            out.writeln('synchronet.autoconnect = on');
            out.writeln('synchronet.autoreconnect');
            out.writeln('synchronet.autoreconnect_delay');
            out.writeln('synchronet.nicks_alternate');
            out.writeln('synchronet.local_hostname');
            out.writeln('synchronet.command');
            out.writeln('synchronet.command_delay');
            out.writeln('synchronet.autojoin = "'+chan+'"');
            out.writeln('synchronet.autorejoin ');
            out.writeln('synchronet.autorejoin_delay');
            out.writeln('synchronet.connection_timeout');
            out.writeln('synchronet.anti_flood_prio_high');
            out.writeln('synchronet.anti_flood_prio_low');
            out.writeln('synchronet.away_check');
            out.writeln('synchronet.away_check_max_nicks');
            out.writeln('synchronet.msg_kick');
            out.writeln('synchronet.msg_part');
            out.writeln('synchronet.sasl_timeout');
            out.writeln('synchronet.sasl_fail');
            out.writeln('synchronet.autoconnect = on');
            out.writeln('synchronet.autoreconnect');
            out.writeln('synchronet.autoreconnect_delay');
            out.writeln('synchronet.nicks_alternate');
            out.writeln('synchronet.local_hostname');
            out.writeln('synchronet.command');
            out.writeln('synchronet.command_delay');
            out.writeln('synchronet.autojoin = "'+chan+'"');
            out.writeln('synchronet.autorejoin ');
            out.writeln('synchronet.autorejoin_delay');
            out.writeln('synchronet.connection_timeout');
            out.writeln('synchronet.anti_flood_prio_high');
            out.writeln('synchronet.anti_flood_prio_low');
            out.writeln('synchronet.away_check');
            out.writeln('synchronet.away_check_max_nicks');
            out.writeln('synchronet.msg_kick');
            out.writeln('synchronet.msg_part');
            out.writeln('synchronet.msg_quit = "' + quit_msg+'"');
            out.writeln('synchronet.notify');
            out.writeln('synchronet.nicks = "' + lusr + ',' + lusr+'_,' + '_' + lusr + '_"');
            out.writeln('synchronet.username = "' + lusr.toLowerCase() + '"');
            out.writeln('synchronet.realname = "' + lusr + ' @ ' + system.name + ' [WeeChat 1.6]"');
            out.writeln('synchronet.addresses = "' + servers + '"');
            out.writeln();
            count += 41;
            console.pause();
            out.close(); // yes, [server] is actually the last [section] in weechat irc.conf
        }
}

inf.close();
out.close();
file_rename(weechat, wc_bup);
file_copy(outfile, weechat);
bbs.exec('weechat', EX_STDIO|EX_NATIVE|EX_NOLOG); // execute bash>weechat redirecting stdout back to sbbs

console.pause();
writeln('\r\n\r\n \1gReturning to \1c'+system.name);
mswait(1000);

See Also


In Other Languages
Translations of this page: