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 ) {
151 char *sep = strstr ( buffer,
"," );
158 for (
unsigned int j = 0; j < ( *length ); j++ ) {
159 if ( !g_ascii_strcasecmp ( buffer, retv[j] ) ) {
167 retv = g_realloc ( retv, ( ( *length ) + 2 ) *
sizeof (
char* ) );
168 retv[( *length )] = g_strdup ( buffer );
169 retv[( *length ) + 1] = NULL;
174 if ( buffer != NULL ) {
177 if ( fclose ( fd ) != 0 ) {
178 g_warning (
"Failed to close hosts file: '%s'", g_strerror ( errno ) );
197 FILE *fd = fopen (
"/etc/hosts",
"r" );
200 size_t buffer_length = 0;
202 while ( getline ( &buffer, &buffer_length, fd ) > 0 ) {
204 unsigned int index = 0, ti = 0;
205 char *token = buffer;
209 char c = buffer[index];
211 if ( c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\0' || c ==
'#' ) {
212 buffer[index] =
'\0';
214 if ( token[0] !=
'\0' ) {
221 for (
unsigned int j = 0; j < ( *length ); j++ ) {
222 if ( !g_ascii_strcasecmp ( token, retv[j] ) ) {
230 retv = g_realloc ( retv,
231 ( ( *length ) + 2 ) *
sizeof (
char* ) );
232 retv[( *length )] = g_strdup ( token );
233 retv[( *length ) + 1] = NULL;
239 token = &buffer[index + 1];
247 }
while ( buffer[index] !=
'\0' && buffer[index] !=
'#' );
249 if ( buffer != NULL ) {
252 if ( fclose ( fd ) != 0 ) {
253 g_warning (
"Failed to close hosts file: '%s'", g_strerror ( errno ) );
260 static void parse_ssh_config_file (
const char *filename,
char ***retv,
unsigned int *length,
unsigned int num_favorites )
262 FILE *fd = fopen ( filename,
"r" );
264 g_debug (
"Parsing ssh config file: %s", filename );
267 size_t buffer_length = 0;
268 char *strtok_pointer = NULL;
269 while ( getline ( &buffer, &buffer_length, fd ) > 0 ) {
279 if ( !token || *token ==
'#' ) {
283 if ( g_strcmp0 ( token,
"Include" ) == 0 ) {
285 g_debug (
"Found Include: %s", token );
287 gchar *full_path = NULL;
288 if ( !g_path_is_absolute ( path ) ) {
289 char *dirname = g_path_get_dirname ( filename );
290 full_path = g_build_filename ( dirname, path, NULL );
294 full_path = g_strdup ( path );
296 glob_t globbuf = { .gl_pathc = 0, .gl_pathv = NULL, .gl_offs = 0 };
298 if ( glob ( full_path, 0, NULL, &globbuf ) == 0 ) {
299 for (
size_t iter = 0; iter < globbuf.gl_pathc; iter++ ) {
303 globfree ( &globbuf );
305 g_free ( full_path );
308 else if ( g_strcmp0 ( token,
"Host" ) == 0 ) {
314 while ( ( token = strtok_r ( NULL,
SSH_TOKEN_DELIM, &strtok_pointer ) ) ) {
316 const char *
const sep =
"*?";
317 if ( *token ==
'!' || strpbrk ( token, sep ) ) {
322 if ( *token ==
'#' ) {
330 for (
unsigned int j = 0; j < num_favorites; j++ ) {
331 if ( !g_ascii_strcasecmp ( token, ( *retv )[j] ) ) {
342 ( *retv ) = g_realloc ( ( *retv ), ( ( *length ) + 2 ) *
sizeof (
char* ) );
343 ( *retv )[( *length )] = g_strdup ( token );
344 ( *retv )[( *length ) + 1] = NULL;
349 if ( buffer != NULL ) {
353 if ( fclose ( fd ) != 0 ) {
354 g_warning (
"Failed to close ssh configuration file: '%s'", g_strerror ( errno ) );
366 static char **
get_ssh (
unsigned int *length )
369 unsigned int num_favorites = 0;
372 if ( g_get_home_dir () == NULL ) {
379 num_favorites = ( *length );
388 const char *hd = g_get_home_dir ();
389 path = g_build_filename ( hd,
".ssh",
"config", NULL );
419 pd->hosts_list =
get_ssh ( &( pd->hosts_list_length ) );
444 if ( rmpd != NULL ) {
477 else if ( ( mretv &
MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] !=
'\0' ) {
503 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 )
506 return get_entry ? g_strdup ( rmpd->
hosts_list[selected_line] ) : NULL;
527 .cfg_name_key =
"display-ssh",
534 ._get_completion = NULL,
535 ._preprocess_input = NULL,
536 .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)