@ -98,7 +98,7 @@ static const unsigned char ssb_cap[] = {
static void usage ( ) {
fputs ( " usage: sbotc [-j] [-T] \n "
" [ [ -n] | [-c <cap>] [-k <key>] [-K <keypair_seed>] ]\n "
" [ -n | [-c <cap>] [-k <key>] [-K <keypair_seed>] ]\n "
" [ [-s <host>] [-p <port>] | [-u <socket_path>] ] \n "
" [-t <type>] <method> [<argument>...] \n " , stderr ) ;
exit ( EXIT_FAILURE ) ;
@ -132,6 +132,31 @@ static int tcp_connect(const char *host, const char *port) {
return fd ;
}
static int unix_connect ( const char * path ) {
struct sockaddr_un name ;
const size_t path_len = strlen ( path ) ;
int s , rc ;
if ( path_len > = sizeof ( name . sun_path ) - 1 ) errx ( 1 , " socket path too long " ) ;
s = socket ( AF_UNIX , SOCK_STREAM , 0 ) ;
if ( s < 0 ) return - 1 ;
memset ( & name , 0 , sizeof ( struct sockaddr_un ) ) ;
name . sun_family = AF_UNIX ;
strncpy ( name . sun_path , path , sizeof ( name . sun_path ) - 1 ) ;
rc = connect ( s , ( const struct sockaddr * ) & name , sizeof name ) ;
if ( rc < 0 ) return - 1 ;
return s ;
}
static int get_socket_path ( char * buf , size_t len , const char * app_dir ) {
struct stat st ;
int sz = snprintf ( buf , len - 1 , " %s/%s " , app_dir , " socket " ) ;
if ( sz < 0 | | sz > = ( int ) len - 1 ) err ( 1 , " failed to get socket path " ) ;
int rc = stat ( buf , & st ) ;
if ( rc < 0 ) return - 1 ;
if ( ! ( st . st_mode & S_IFSOCK ) ) { errno = EINVAL ; return - 1 ; }
return 0 ;
}
static int read_all ( int fd , void * buf , size_t count ) {
ssize_t nbytes ;
while ( count > 0 ) {
@ -836,6 +861,7 @@ int main(int argc, char *argv[]) {
bool noauth = false ;
bool host_arg = false ;
bool port_arg = false ;
bool key_arg = false ;
bool shs_cap_key_str_arg = false ;
get_app_dir ( app_dir , sizeof ( app_dir ) ) ;
@ -861,7 +887,7 @@ int main(int argc, char *argv[]) {
case ' j ' : ptype = pkt_type_json ; break ;
case ' T ' : test = true ; break ;
case ' s ' : host = argv [ + + i ] ; host_arg = true ; break ;
case ' k ' : key = argv [ + + i ] ; break ;
case ' k ' : key = argv [ + + i ] ; key_arg = true ; break ;
case ' K ' : keypair_seed_str = argv [ + + i ] ; break ;
case ' p ' : port = argv [ + + i ] ; port_arg = true ; break ;
case ' u ' : socket_path = argv [ + + i ] ; break ;
@ -931,27 +957,33 @@ int main(int argc, char *argv[]) {
memcpy ( remote_key , public_key , 32 ) ;
}
bool implied_tcp = host_arg | | port_arg ;
bool implied_auth = key_arg | | keypair_seed_str | | shs_cap_key_str_arg | | test ;
if ( test ) {
infd = STDIN_FILENO ;
outfd = STDOUT_FILENO ;
s = - 1 ;
} else if ( socket_path ) {
if ( port_arg ) errx ( 1 , " -p port conflicts with -u socket_path " ) ;
if ( host_arg ) errx ( 1 , " -s host conflicts with -u socket_path " ) ;
struct sockaddr_un name ;
size_t path_len = strlen ( socket_path ) ;
if ( path_len > = sizeof ( name . sun_path ) - 1 ) errx ( 1 , " socket path too long " ) ;
s = socket ( AF_UNIX , SOCK_STREAM , 0 ) ;
if ( s < 0 ) err ( 1 , " socket " ) ;
memset ( & name , 0 , sizeof ( struct sockaddr_un ) ) ;
name . sun_family = AF_UNIX ;
strncpy ( name . sun_path , socket_path , sizeof ( name . sun_path ) - 1 ) ;
rc = connect ( s , ( const struct sockaddr * ) & name , sizeof name ) ;
if ( rc < 0 ) err ( 1 , " connect " ) ;
if ( implied_tcp ) errx ( 1 , " -u option conflicts with -s and -p options " ) ;
s = unix_connect ( socket_path ) ;
if ( s < 0 ) err ( 1 , " unix_connect " ) ;
infd = outfd = s ;
} else if ( ! implied_tcp & & ! implied_auth ) {
char socket_path_buf [ _POSIX_PATH_MAX ] ;
rc = get_socket_path ( socket_path_buf , sizeof ( socket_path_buf ) , app_dir ) ;
if ( rc < 0 & & noauth ) err ( 1 , " get_socket_path " ) ;
if ( rc < 0 ) goto do_tcp_connect ;
s = unix_connect ( socket_path_buf ) ;
if ( s < 0 & & noauth ) err ( 1 , " unix_connect " ) ;
if ( s < 0 ) goto do_tcp_connect ;
noauth = true ;
infd = outfd = s ;
} else {
do_tcp_connect :
s = tcp_connect ( host , port ) ;
if ( s < 0 ) err ( 1 , " tcp_connect " ) ;
infd = outfd = s ;
@ -961,10 +993,7 @@ int main(int argc, char *argv[]) {
if ( noauth ) {
bs . s = s ;
bs . noauth = true ;
if ( key ) errx ( 1 , " -k keypair_seed conflicts with -n (noauth) " ) ;
if ( keypair_seed_str ) errx ( 1 , " -K keypair_seed conflicts with -n (noauth) " ) ;
if ( shs_cap_key_str_arg ) errx ( 1 , " -c cap_key conflicts with -n (noauth) " ) ;
if ( test ) errx ( 1 , " -n (noauth) conflicts with -T (test shs) " ) ;
if ( implied_auth ) errx ( 1 , " -n option conflicts with -k, -K, -c and -T options. " ) ;
} else {
shs_connect ( s , infd , outfd , public_key , private_key , shs_cap_key , remote_key , & bs ) ;
}