174 unsigned int *length) {
175 FILE *fd = fopen(path,
"r");
178 size_t buffer_length = 0;
180 while (getline(&buffer, &buffer_length, fd) > 0) {
182 char *start = g_strstrip(&(buffer[0]));
184 if (*start ==
'#' || *start ==
'@') {
193 char *end = strstr(start,
" ");
200 start = strsep(&sep,
", ");
203 if (start[0] ==
'[') {
205 char *strend = strchr(start,
']');
210 start = strsep(&sep,
", ");
213 if (strend[1] ==
':')
217 gchar *endptr = NULL;
218 gint64 number = g_ascii_strtoll(&(strend[2]), &endptr, 10);
220 g_warning(
"Failed to parse port number: %s.", &(strend[2]));
221 }
else if (endptr == &(strend[2])) {
222 g_warning(
"Failed to parse port number: %s, invalid number.",
224 }
else if (number < 0 || number > 65535) {
225 g_warning(
"Failed to parse port number: %s, out of range.",
235 for (
unsigned int j = 0; j < (*length); j++) {
236 if (!g_ascii_strcasecmp(start, retv[j].hostname)) {
244 retv = g_realloc(retv, ((*length) + 2) *
sizeof(
SshEntry));
245 retv[(*length)].
hostname = g_strdup(start);
246 retv[(*length)].
aliases = NULL;
247 retv[(*length)].
port = port;
248 retv[(*length) + 1].
hostname = NULL;
249 retv[(*length) + 1].
aliases = NULL;
250 retv[(*length) + 1].
port = 0;
253 start = strsep(&sep,
", ");
256 if (buffer != NULL) {
259 if (fclose(fd) != 0) {
260 g_warning(
"Failed to close hosts file: '%s'", g_strerror(errno));
263 g_debug(
"Failed to open KnownHostFile: '%s'", path);
279 FILE *fd = fopen(
"/etc/hosts",
"r");
282 size_t buffer_length = 0;
284 while (getline(&buffer, &buffer_length, fd) > 0) {
286 unsigned int index = 0, ti = 0;
287 char *token = buffer;
291 char c = buffer[index];
293 if (c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\0' || c ==
'#') {
294 buffer[index] =
'\0';
296 if (token[0] !=
'\0') {
303 for (
unsigned int j = 0; j < (*length); j++) {
304 if (!g_ascii_strcasecmp(token, retv[j].hostname)) {
312 retv = g_realloc(retv, ((*length) + 2) *
sizeof(
SshEntry));
313 retv[(*length)].
hostname = g_strdup(token);
314 retv[(*length)].
aliases = NULL;
315 retv[(*length)].
port = 0;
316 retv[(*length) + 1].
hostname = NULL;
317 retv[(*length) + 1].
aliases = NULL;
323 token = &buffer[index + 1];
331 }
while (buffer[index] !=
'\0' && buffer[index] !=
'#');
333 if (buffer != NULL) {
336 if (fclose(fd) != 0) {
337 g_warning(
"Failed to close hosts file: '%s'", g_strerror(errno));
356 SshEntry **retv,
unsigned int *length,
357 unsigned int num_favorites) {
358 FILE *fd = fopen(filename,
"r");
360 g_debug(
"Parsing ssh config file: %s", filename);
363 size_t buffer_length = 0;
364 char *strtok_pointer = NULL;
365 while (getline(&buffer, &buffer_length, fd) > 0) {
374 if (!token || *token ==
'#') {
377 char *low_token = g_ascii_strdown(token, -1);
378 if (g_strcmp0(low_token,
"include") == 0) {
380 g_debug(
"Found Include: %s", token);
382 gchar *full_path = NULL;
383 if (!g_path_is_absolute(path)) {
384 char *dirname = g_path_get_dirname(filename);
385 full_path = g_build_filename(dirname, path, NULL);
388 full_path = g_strdup(path);
390 glob_t globbuf = {.gl_pathc = 0, .gl_pathv = NULL, .gl_offs = 0};
392 if (glob(full_path, 0, NULL, &globbuf) == 0) {
393 for (
size_t iter = 0; iter < globbuf.gl_pathc; iter++) {
402 }
else if (g_strcmp0(low_token,
"userknownhostsfile") == 0) {
404 g_debug(
"Found extra UserKnownHostsFile: %s", token);
407 }
else if (g_strcmp0(low_token,
"host") == 0) {
416 const char *
const sep =
"*?";
417 if (*token ==
'!' || strpbrk(token, sep)) {
430 for (
unsigned int j = 0; j < num_favorites; j++) {
431 if (!g_ascii_strcasecmp(token, (*retv)[j].hostname)) {
435 if ((*retv)[j].aliases != NULL) {
436 for (
int x = 0; (*retv)[j].aliases[x] != NULL; x++) {
437 if (!g_ascii_strcasecmp(token, (*retv)[j].aliases[x])) {
451 (*retv) = g_realloc((*retv), ((*length) + 2) *
sizeof(
SshEntry));
452 (*retv)[(*length)].hostname = g_strdup(token);
453 (*retv)[(*length)].aliases = NULL;
454 (*retv)[(*length)].port = 0;
455 (*retv)[(*length) + 1].hostname = NULL;
456 (*retv)[(*length) + 1].aliases = NULL;
460 int index = (*length) - 1;
462 if ((*retv)[index].aliases != NULL) {
463 l = g_strv_length((*retv)[index].aliases);
465 (*retv)[index].aliases =
466 g_realloc((*retv)[index].aliases, (l + 2) *
sizeof(
char *));
467 (*retv)[index].aliases[l] = g_strdup(token);
468 (*retv)[index].aliases[l + 1] = NULL;
474 if (buffer != NULL) {
478 if (fclose(fd) != 0) {
479 g_warning(
"Failed to close ssh configuration file: '%s'",
495 unsigned int num_favorites = 0;
498 if (g_get_home_dir() == NULL) {
505 retv = g_malloc0((*length) *
sizeof(
SshEntry));
506 for (
unsigned int i = 0; i < (*length); i++) {
508 char **ssplit = g_strsplit(h[i],
"\x1F", -1);
509 guint ssplit_len = g_strv_length(ssplit);
510 if (ssplit_len > 1) {
512 gchar *endptr = NULL;
513 gint64 number = g_ascii_strtoll(ssplit[1], &endptr, 10);
515 g_warning(
"Failed to parse port number: %s.", (ssplit[1]));
516 }
else if (endptr == (ssplit[1])) {
517 g_warning(
"Failed to parse port number: %s, invalid number.",
519 }
else if (number < 0 || number > 65535) {
520 g_warning(
"Failed to parse port number: %s, out of range.",
526 retv[i].
hostname = g_strdup(ssplit[0]);
529 gint naliases = ssplit_len - 2;
531 retv[i].
aliases = g_malloc0(
sizeof(
char *) * (naliases + 1));
532 for (gint j = 0; j < naliases; j++) {
533 retv[i].
aliases[j] = g_strdup(ssplit[2 + j]);
541 num_favorites = (*length);
543 const char *hd = g_get_home_dir();
544 path = g_build_filename(hd,
".ssh",
"config", NULL);
548 char *known_hosts_path =
549 g_build_filename(g_get_home_dir(),
".ssh",
"known_hosts", NULL);
551 g_free(known_hosts_path);
553 iter = g_list_next(iter)) {
557 g_free(user_known_hosts_path);
gboolean helper_execute(const char *wd, char **args, const char *error_precmd, const char *error_cmd, RofiHelperExecuteContext *context)
void history_set(const char *filename, const char *entry)
void history_remove(const char *filename, const char *entry)
char ** history_get_list(const char *filename, unsigned int *length)
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)
static void parse_ssh_config_file(SSHModePrivateData *pd, const char *filename, SshEntry **retv, unsigned int *length, unsigned int num_favorites)