36 #define G_LOG_DOMAIN "Dialogs.Ssh" 45 #include <sys/types.h> 62 #define SSH_CACHE_FILE "rofi-2.sshcache" 68 #define SSH_TOKEN_DELIM "= \t\r\n" 84 gsize l = strlen (
"Connecting to '' via rofi" ) + strlen ( host ) + 1;
85 gchar *desc = g_newa ( gchar, l );
87 g_snprintf ( desc, l,
"Connecting to '%s' via rofi", host );
104 if ( !host || !host[0] ) {
126 if ( !host || !host[0] ) {
144 char *path = g_build_filename ( g_get_home_dir (),
".ssh",
"known_hosts", NULL );
145 FILE *fd = fopen ( path,
"r" );
148 size_t buffer_length = 0;
150 while ( getline ( &buffer, &buffer_length, fd ) > 0 ) {
152 char *
start = g_strstrip(&(buffer[0]));
156 printf(
"Comment.\n");
159 if ( *
start ==
'|' ) {
163 if ( *
start ==
'[' ) {
168 char *end = strstr (
start,
" " );
175 start = strsep(&sep,
", " );
181 for (
unsigned int j = 0; j < ( *length ); j++ ) {
182 if ( !g_ascii_strcasecmp (
start, retv[j] ) ) {
190 retv = g_realloc ( retv, ( ( *length ) + 2 ) *
sizeof (
char* ) );
191 retv[( *length )] = g_strdup (
start );
192 retv[( *length ) + 1] = NULL;
195 start = strsep(&sep,
", " );
198 if ( buffer != NULL ) {
201 if ( fclose ( fd ) != 0 ) {
202 g_warning (
"Failed to close hosts file: '%s'", g_strerror ( errno ) );
221 FILE *fd = fopen (
"/etc/hosts",
"r" );
224 size_t buffer_length = 0;
226 while ( getline ( &buffer, &buffer_length, fd ) > 0 ) {
228 unsigned int index = 0, ti = 0;
229 char *token = buffer;
233 char c = buffer[index];
235 if ( c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\0' || c ==
'#' ) {
236 buffer[index] =
'\0';
238 if ( token[0] !=
'\0' ) {
245 for (
unsigned int j = 0; j < ( *length ); j++ ) {
246 if ( !g_ascii_strcasecmp ( token, retv[j] ) ) {
254 retv = g_realloc ( retv,
255 ( ( *length ) + 2 ) *
sizeof (
char* ) );
256 retv[( *length )] = g_strdup ( token );
257 retv[( *length ) + 1] = NULL;
263 token = &buffer[index + 1];
271 }
while ( buffer[index] !=
'\0' && buffer[index] !=
'#' );
273 if ( buffer != NULL ) {
276 if ( fclose ( fd ) != 0 ) {
277 g_warning (
"Failed to close hosts file: '%s'", g_strerror ( errno ) );
284 static void parse_ssh_config_file (
const char *filename,
char ***retv,
unsigned int *length,
unsigned int num_favorites )
286 FILE *fd = fopen ( filename,
"r" );
288 g_debug (
"Parsing ssh config file: %s", filename );
291 size_t buffer_length = 0;
292 char *strtok_pointer = NULL;
293 while ( getline ( &buffer, &buffer_length, fd ) > 0 ) {
303 if ( !token || *token ==
'#' ) {
307 if ( g_strcmp0 ( token,
"Include" ) == 0 ) {
309 g_debug (
"Found Include: %s", token );
311 gchar *full_path = NULL;
312 if ( !g_path_is_absolute ( path ) ) {
313 char *dirname = g_path_get_dirname ( filename );
314 full_path = g_build_filename ( dirname, path, NULL );
318 full_path = g_strdup ( path );
320 glob_t globbuf = { .gl_pathc = 0, .gl_pathv = NULL, .gl_offs = 0 };
322 if ( glob ( full_path, 0, NULL, &globbuf ) == 0 ) {
323 for (
size_t iter = 0; iter < globbuf.gl_pathc; iter++ ) {
327 globfree ( &globbuf );
329 g_free ( full_path );
332 else if ( g_strcmp0 ( token,
"Host" ) == 0 ) {
338 while ( ( token = strtok_r ( NULL,
SSH_TOKEN_DELIM, &strtok_pointer ) ) ) {
340 const char *
const sep =
"*?";
341 if ( *token ==
'!' || strpbrk ( token, sep ) ) {
346 if ( *token ==
'#' ) {
354 for (
unsigned int j = 0; j < num_favorites; j++ ) {
355 if ( !g_ascii_strcasecmp ( token, ( *retv )[j] ) ) {
366 ( *retv ) = g_realloc ( ( *retv ), ( ( *length ) + 2 ) *
sizeof (
char* ) );
367 ( *retv )[( *length )] = g_strdup ( token );
368 ( *retv )[( *length ) + 1] = NULL;
373 if ( buffer != NULL ) {
377 if ( fclose ( fd ) != 0 ) {
378 g_warning (
"Failed to close ssh configuration file: '%s'", g_strerror ( errno ) );
390 static char **
get_ssh (
unsigned int *length )
393 unsigned int num_favorites = 0;
396 if ( g_get_home_dir () == NULL ) {
403 num_favorites = ( *length );
412 const char *hd = g_get_home_dir ();
413 path = g_build_filename ( hd,
".ssh",
"config", NULL );
443 pd->hosts_list =
get_ssh ( &( pd->hosts_list_length ) );
468 if ( rmpd != NULL ) {
501 else if ( ( mretv &
MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] !=
'\0' ) {
526 static char *
_get_display_value (
const Mode *sw,
unsigned int selected_line, G_GNUC_UNUSED
int *state, G_GNUC_UNUSED GList **attr_list,
int get_entry )
529 return get_entry ? g_strdup ( rmpd->
hosts_list[selected_line] ) : NULL;
550 .cfg_name_key =
"display-ssh",
557 ._get_completion = NULL,
558 ._preprocess_input = NULL,
559 .private_data = NULL,
unsigned int hosts_list_length
unsigned int parse_known_hosts
static char * _get_display_value(const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **attr_list, int get_entry)
void history_set(const char *filename, const char *entry)
char ** history_get_list(const char *filename, unsigned int *length)
static void exec_ssh(const char *host)
static char ** get_ssh(unsigned int *length)
static unsigned int ssh_mode_get_num_entries(const Mode *sw)
static char ** read_known_hosts_file(char **retv, unsigned int *length)
gboolean helper_execute(const char *wd, char **args, const char *error_precmd, const char *error_cmd, RofiHelperExecuteContext *context)
static void parse_ssh_config_file(const char *filename, char ***retv, unsigned int *length, unsigned int num_favorites)
void * mode_get_private_data(const Mode *mode)
void history_remove(const char *filename, const char *entry)
int helper_token_match(rofi_int_matcher *const *tokens, const char *input)
static void ssh_mode_destroy(Mode *sw)
static int ssh_token_match(const Mode *sw, rofi_int_matcher **tokens, unsigned int index)
static char ** read_hosts_file(char **retv, unsigned int *length)
static ModeMode ssh_mode_result(Mode *sw, int mretv, char **input, unsigned int selected_line)
char * rofi_expand_path(const char *input)
static void delete_ssh(const char *host)
int helper_parse_setup(char *string, char ***output, int *length,...)
void mode_set_private_data(Mode *mode, void *pd)
static int ssh_mode_init(Mode *sw)
static int execshssh(const char *host)