1

我正在为 Pidgin 开发插件。我想通过 VNC 与其他用户共享我的计算机上打开的一个窗口。当我选择要共享的窗口并按下按钮时,Pidgin 冻结并关闭。

这里运行良好:打开 vnc 连接并将端口名称发送给其他用户。(但这一个用于共享所有屏幕。)

static void
send_button_cb(GtkButton *button, PidginConversation *gtkconv)
{
  gchar *url_vnc;
  gchar *url_http;
  gchar *joinstr;

  int std_out[2];

  int autoport = purple_prefs_get_bool(PREF_AUTOPORT);
  char x11vnc_port[10] = "0";
  if (purple_prefs_get_bool(PREF_X11VNC) && ((x11vnc_pid == 0) || (kill(x11vnc_pid, 0) != 0)))
  {
    if (purple_prefs_get_bool(PREF_GENPASSWD))
    {
      readableRandomString(password, 4);
    }
    else
    {
      strcpy(password, purple_prefs_get_string(PREF_PASSWD));
    }
    sprintf(x11vnc_port, "%d", 5900 + purple_prefs_get_int(PREF_PORT));
    pipe(std_out);
    if ((x11vnc_pid = fork()) == 0)
    {
      close(1);
      close(std_out[0]);
      dup2(std_out[1], 1);
      close(std_out[1]);

      int ret = execlp("x11vnc", "x11vnc", "-shared", "-gui", "tray", "-http", "-viewonly", "-passwd", password, ((autoport) ? "-autoport" : "-rfbport"), x11vnc_port, NULL);

      perror("pidgin_vnc:x11vnc");
      exit(ret);
    }
    close(std_out[1]);
    port_num = x11vnc_port;
    if (fd = fdopen(std_out[0], "r"))
    {
      while (!feof(fd))
      {
        if (fscanf(fd, "PORT=%d", &port_num))
          break;
      }
      port_num -= 5900;
      //close (fd);
      printf("FINI\n");
    }
    else
    {
      port_num = x11vnc_port;
    }
  }
  const char *ip;
  PurpleStunNatDiscovery *stun_res = purple_stun_discover(NULL);
  if (stun_res && stun_res->status == PURPLE_STUN_STATUS_DISCOVERED)
  {
    printf("STUN mode %d %d\n", stun_res->status, stun_res->type);
    ip = purple_network_get_my_ip(-1);
  }
  else
  {
    ip = purple_upnp_get_public_ip();
    if (ip == NULL)
    {
      printf("LOCAL mode\n");
      ip = purple_network_get_my_ip(-1);
    }
    else
    {
      printf("UPNP mode\n");
    }
  }

  url_http = g_strdup_printf("http://%s:%d/", ip, 5800 + port_num);
  url_vnc = g_strdup_printf("vnc://invitation:%s@%s:%d", password, ip, port_num);
  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, url_vnc);

  joinstr = g_strdup_printf("%s.\ntry <a href=\"%s\">%s</a>\nor  <a href=\"%s\">%s</a>. Password=%s", purple_prefs_get_string(PREF_TEXT), url_vnc, url_vnc, url_http, url_http, password);

  gtk_imhtml_append_text(GTK_IMHTML(gtkconv->entry), joinstr, FALSE);
  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "imhtml display vnc\n");

  g_signal_emit_by_name(gtkconv->entry, "message_send");
  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "message sent\n");

  g_free(url_vnc);
  g_free(url_http);
  g_free(joinstr);
}

这里有问题。当我单击调用此功能的按钮时,单击该按钮时程序会崩溃。(此功能用于共享我计算机上打开的一个窗口。)

static void
send_button_cb_win(GtkButton *button, PidginConversation *gtkconv)
{
  gchar *url_vnc;
  gchar *url_http;
  gchar *joinstr;

  int std_out[2];

  int comboBoxSelectedRow = gtk_combo_box_get_active(combo_box);
  char *selectedId[1] = {0};
  selectedId[0] = ekranIds[0][comboBoxSelectedRow];

  int autoport = purple_prefs_get_bool(PREF_AUTOPORT);
  char x11vnc_port[10] = "0";

  if (purple_prefs_get_bool(PREF_X11VNC) && ((x11vnc_pid == 0) || (kill(x11vnc_pid, 0) != 0)))
  {
    if (purple_prefs_get_bool(PREF_GENPASSWD))
    {
      readableRandomString(password, 4);
    }
    else
    {
      strcpy(password, purple_prefs_get_string(PREF_PASSWD));
    }

    sprintf(x11vnc_port, "%d", 5900 + purple_prefs_get_int(PREF_PORT));
    pipe(std_out);


    if((x11vnc_pid = fork()) == 0)
    {
      close(1);
      close(std_out[0]);
      dup2(std_out[1], 1);
      close(std_out[1]);


      int ret = execlp("x11vnc", "x11vnc", "-id", selectedId[0], "-gui", "-shared", "tray", "-http", "-viewonly", "-passwd", password, ((autoport) ? "-autoport" : "-rfbport"), x11vnc_port, NULL);

      perror("pidgin_vnc:x11vnc");

      exit(ret);
    }

    close(std_out[1]);
    port_num = x11vnc_port;

    if (fd = fdopen(std_out[0], "r"))
    {
      while (!feof(fd))
      {
        if (fscanf(fd, "PORT=%d", &port_num))
          break;
      }
      port_num -= 5900;
      //close (fd);
      printf("FINI\n");
    }
    else
    {
      port_num = x11vnc_port;
    }
  }
  const char *ip;
  PurpleStunNatDiscovery *stun_res = purple_stun_discover(NULL);
  if (stun_res && stun_res->status == PURPLE_STUN_STATUS_DISCOVERED)

  {
    printf("STUN mode %d %d\n", stun_res->status, stun_res->type);
    ip = purple_network_get_my_ip(-1);
  }
  else
  {
    ip = purple_upnp_get_public_ip();
    if (ip == NULL)
    {
      printf("LOCAL mode\n");
      ip = purple_network_get_my_ip(-1);
    }
    else
    {
      printf("UPNP mode\n");
    }
  }
  url_http = g_strdup_printf("http://%s:%d/", ip, 5800 + port_num);

  url_vnc = g_strdup_printf("vnc://invitation:%s@%s:%d", password, ip, port_num);
  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, url_vnc);

  joinstr = g_strdup_printf("%s.\ntry <a href=\"%s\">%s</a>\nor  <a href=\"%s\">%s</a>. Password=%s", purple_prefs_get_string(PREF_TEXT), url_vnc, url_vnc, url_http, url_http, password);

  gtk_imhtml_append_text(GTK_IMHTML(gtkconv->entry), joinstr, FALSE);
  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "imhtml display vnc\n");

  g_signal_emit_by_name(gtkconv->entry, "message_send");
  g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "message sent\n");

  g_free(url_vnc);
  g_free(url_http);
  g_free(joinstr);
  gtk_widget_show_all(button);
}

此功能用打开的窗口名称填充组合框

static void
refresh_combo_box(GtkWidget *widget, PidginConversation *gtkconv)
{

  FILE *fp1;
  FILE *fp2;
  char path[1035];
  char path2[1035];
  char sum[1035];

  /* Open the command for reading. */
  fp1 = popen("xprop -root | grep '_NET_CLIENT_LIST_STACKING(WINDOW)'", "r");
  if (fp1 == NULL)
  {
    printf("Failed to run command\n" );
    exit(1);
  }

  /* Read the output a line at a time - output it. */
  while (fgets(path, sizeof(path) - 1, fp1) != NULL)
  {
    // printf("%s", path);
    strcat(sum, path);

  }

  char *splitter = strtok(sum, "#");
  splitter = strtok(NULL, "#");
  char *virgulSplitter = strtok(splitter, ", ");
  ekranIds[0][0] = strdup(virgulSplitter);
  int a = 1;
  while (virgulSplitter != NULL)
  {
    virgulSplitter = strtok(NULL, ",");
    if (virgulSplitter != NULL)
    {
      ekranIds[0][a] = strdup(virgulSplitter);
      a++;
    }
  }

  for (int x = 0; x < a; x++)
  {

    ekranIds[0][a - 1][strcspn(ekranIds[0][a - 1], "\n")] = 0;
    char tmp[500] = {0};
    //here is get window names by id
    sprintf(tmp, "xprop -id %s | grep '^WM_NAME'", ekranIds[0][x]);
    fp2 = popen(tmp, "r");
    if (fp1 == NULL)
    {
     printf("Failed to run command\n" );
      exit(1);
    }

    // Read the output a line at a time - output it.
    while (fgets(path2, sizeof(path2) - 1, fp2) != NULL)
    {   
      char *windowSplitter = strtok(path2, "=");
      windowSplitter = strtok(NULL, "=");    
      ekranIds[1][x] = strdup(windowSplitter);   
    }
  }
  pclose(fp2);
  pclose(fp1);
  char *combobox_source[30];
  for (int yf = 0; yf < 30; yf++)
  {
    if (ekranIds[1][yf] != NULL)
    {   
      combobox_source[yf] = strdup(ekranIds[1][yf]);
    }
  }
  gtk_list_store_clear(GTK_LIST_STORE(gtk_combo_box_get_model(combo_box)));
  for (int i = 0; i < G_N_ELEMENTS(combobox_source); i++)
  {
    gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), combobox_source[i]);
  }
  gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), 0);
  gtk_widget_show_all(combo_box);
}

第一个功能运行良好:打开 vnc 连接并将端口名称发送给其他用户。(但这一个用于共享所有屏幕。)

第二个功能有问题。当我单击调用此功能的按钮时,单击该按钮时程序会崩溃。(此功能用于共享我计算机上打开的一个窗口。)

第三个函数用打开的窗口名称填充组合框。

4

0 回答 0