Exemplo n.º 1
0
void
wlc_view_set_app_id_ptr(struct wlc_view *view, const char *app_id)
{
   if (view && !chck_cstreq(view->data.app_id.data, app_id) && chck_string_set_cstr(&view->data.app_id, app_id, true)) {
      WLC_INTERFACE_EMIT(view.properties_updated, convert_to_wlc_handle(view), WLC_BIT_PROPERTY_APP_ID);
   }
}
Exemplo n.º 2
0
WLC_API void
wlc_run(void)
{
   if (!wlc.display)
      return;

   wlc.compositor.state.ready = false;

   bool emit_ready = true;
   const char *xwayland = getenv("WLC_XWAYLAND");
   if (!xwayland || !chck_cstreq(xwayland, "0"))
      emit_ready = !wlc_xwayland_init();

   // Emit ready immediately when no Xwayland
   if (emit_ready) {
      WLC_INTERFACE_EMIT(compositor.ready);
      wlc.compositor.state.ready = true;
   }

   wlc_set_active(true);

   if (wlc_compositor_is_good(&wlc.compositor))
      wl_display_run(wlc.display);

   wlc_cleanup();
}
Exemplo n.º 3
0
static void
handle_arguments(int argc, char *argv[])
{
   for (int i = 1; i < argc; ++i) {
      if (chck_cstreq(argv[i], "--log")) {
         if (i + 1 >= argc) {
            plog(0, PLOG_ERROR, "--log takes an argument (filename)");
            abort();
         }
         log_set_file(argv[++i]);
      }
   }
}
Exemplo n.º 4
0
Arquivo: udev.c Projeto: Azarn/wlc
static bool
is_hotplug(uint32_t drm_id, struct udev_device *device)
{
   uint32_t id;
   const char *sysnum;
   if (!(sysnum = udev_device_get_sysnum(device)) || !chck_cstr_to_u32(sysnum, &id) || id != drm_id)
      return false;

   const char *val;
   if (!(val = udev_device_get_property_value(device, "HOTPLUG")))
      return false;

   return chck_cstreq(val, "1");
}
Exemplo n.º 5
0
Arquivo: test.c Projeto: Cloudef/chck
int main(void)
{
   /* TEST: stripping */
   {
      struct chck_string v = {0};
      assert(chck_string_set_cstr(&v, "   contains some whitespace     ", true));
      assert(chck_cstr_strip(v.data) == v.data + 3);
      assert(strlen(v.data + 3) == 24);
      assert(chck_cstreq(v.data + 3, "contains some whitespace"));

      assert(chck_string_set_cstr(&v, "asd", true));
      assert(chck_cstr_strip(v.data) == v.data);
      assert(strlen(v.data) == 3);
      assert(chck_cstreq(v.data, "asd"));

      assert(chck_string_set_cstr(&v, "foo baz lol", true));
      assert(chck_cstr_remove_chars(v.data, "baz") == v.data);
      assert(chck_cstreq(v.data, "foo  lol"));
      chck_string_release(&v);

      assert(chck_string_set_cstr(&v, "foo baz lol", true));
      assert(chck_cstr_remove_chars(v.data, "qwerty") == v.data);
      assert(chck_cstreq(v.data, "foo baz lol"));
      chck_string_release(&v);

      assert(chck_string_set_cstr(&v, "foo --- bar", true));
      assert(chck_cstr_replace_char(v.data, '-', '.') == v.data);
      assert(chck_cstreq(v.data, "foo ... bar"));
      chck_string_release(&v);

      assert(chck_string_set_cstr(&v, "foo --- bar", true));
      assert(chck_cstr_replace_char(v.data, '.', '-') == v.data);
      assert(chck_cstreq(v.data, "foo --- bar"));
      chck_string_release(&v);
   }

   /* TEST: tokenizing */
   {
      const char *v = "  token: this :please  ";

      {
         size_t len, i = 0;
         const char *t, *state = NULL;
         const char *except[] = { "  token", " this ", "please  " };
         while ((t = chck_cstr_tokenize(v, &len, ":", false, &state))) {
            assert(i < 3);
            assert(len == strlen(except[i]));
            assert(chck_cstrneq(except[i], t, len));
            ++i;
         }
         assert(i == 3);
      }

      {
         size_t len, i = 0;
         const char *t, *state = NULL;
         const char *except[] = { "token", "this", "please" };
         while ((t = chck_cstr_tokenize(v, &len, ":", true, &state))) {
            assert(i < 3);
            assert(len == strlen(except[i]));
            assert(chck_cstrneq(except[i], t, len));
            ++i;
         }
         assert(i == 3);
      }

      v = "some : words : \"  but this is included  \" : \"yay : yoy\" : \"foo\"";

      {
         size_t len, i = 0;
         const char *t, *state = NULL;
         const char *except[] = { "some", "words", "  but this is included  ", "yay : yoy", "foo" };
         while ((t = chck_cstr_tokenize_quoted(v, &len, ":", "\"", &state))) {
            assert(i < 5);
            assert(len == strlen(except[i]));
            assert(chck_cstrneq(except[i], t, len));
            ++i;
         }
         assert(i == 5);
      }

      v = "some words  \"  but this is included  \" \"yay  yoy\"  \"foo\"";

      {
         size_t len, i = 0;
         const char *t, *state = NULL;
         const char *except[] = { "some", "words", "  but this is included  ", "yay  yoy", "foo" };
         while ((t = chck_cstr_tokenize_quoted(v, &len, " ", "\"", &state))) {
            assert(i < 5);
            assert(len == strlen(except[i]));
            assert(chck_cstrneq(except[i], t, len));
            ++i;
         }
         assert(i == 5);
      }
   }

   /* TEST: bool conversion tests */
   {
      bool v;
      assert(chck_cstr_to_bool("true", &v) && v == true);
      assert(chck_cstr_to_bool("false", &v) && v == false);
      assert(chck_cstr_to_bool("1", &v) && v == true);
      assert(chck_cstr_to_bool("0", &v) && v == false);
      assert(!chck_cstr_to_bool("falsef", NULL));
      assert(!chck_cstr_to_bool("fals", NULL));
      assert(!chck_cstr_to_bool("truee", NULL));
      assert(!chck_cstr_to_bool("tru", NULL));
      assert(!chck_cstr_to_bool("not-a-bool", NULL));
      assert(!chck_cstr_to_bool("5", NULL));
   }

   /* TEST: float conversion tests */
   {
      float v;
      assert(chck_cstr_to_f("0.123", &v) && chck_equalf(v, 0.123, 1.0f));
      assert(chck_cstr_to_f("0.1e2", &v) && chck_equalf(v, 0.1e2, 1.0f));
      assert(!chck_cstr_to_f("0.1e1000", NULL));
      assert(!chck_cstr_to_f("not-float", NULL));
   }

   /* TEST: double conversion tests */
   {
      double v;
      assert(chck_cstr_to_d("0.123", &v) && chck_equal(v, 0.123, 1.0));
      assert(chck_cstr_to_d("0.1e100", &v) && chck_equal(v, 0.1e100, 1.0));
      assert(!chck_cstr_to_d("0.1e1000", NULL));
      assert(!chck_cstr_to_d("not-double", NULL));
   }

   /* TEST: long double conversion tests */
   {
      long double v; // valgrind does not handle long double so we don't do 1e1000 here
      assert(chck_cstr_to_ld("0.123", &v) && chck_equalld(v, 0.123l, 1.0l));
      assert(chck_cstr_to_ld("0.1e100", &v) && chck_equalld(v, 0.1e100l, 1.0));
      assert(!chck_cstr_to_ld("0.1e100000", NULL));
      assert(!chck_cstr_to_ld("not-long-double", NULL));
   }

   /* TEST: i64 conversion tests */
   {
      int64_t v;
      assert(chck_cstr_to_i64("1", &v) && v == 1);
      assert(chck_cstr_to_i64("-1", &v) && v == -1);
      assert(chck_cstr_to_i64("9223372036854775807", &v) && v == INT64_MAX);
      assert(chck_cstr_to_i64("-9223372036854775808", &v) && v == INT64_MIN);
      assert(!chck_cstr_to_i64("9223372036854775808", &v));
      assert(!chck_cstr_to_i64("-9223372036854775809", &v));
      assert(!chck_cstr_to_i64("1.0", &v));

      uint64_t uv;
      assert(chck_cstr_to_u64("1", &uv) && uv == 1);
      assert(!chck_cstr_to_u64("-1", &uv));
      assert(chck_cstr_to_u64("18446744073709551615", &uv) && uv == UINT64_MAX);
      assert(!chck_cstr_to_u64("18446744073709551616", &uv));
      assert(!chck_cstr_to_u64("1.0", &uv));
   }

   /* TEST: i32 conversion tests */
   {
      int32_t v;
      assert(chck_cstr_to_i32("1", &v) && v == 1);
      assert(chck_cstr_to_i32("-1", &v) && v == -1);
      assert(chck_cstr_to_i32("2147483647", &v) && v == INT32_MAX);
      assert(chck_cstr_to_i32("-2147483648", &v) && v == INT32_MIN);
      assert(!chck_cstr_to_i32("2147483648", &v));
      assert(!chck_cstr_to_i32("-2147483649", &v));
      assert(!chck_cstr_to_i32("1.0", &v));

      uint32_t uv;
      assert(chck_cstr_to_u32("1", &uv) && uv == 1);
      assert(!chck_cstr_to_u32("-1", &uv));
      assert(chck_cstr_to_u32("4294967295", &uv) && uv == UINT32_MAX);
      assert(!chck_cstr_to_u32("4294967296", &uv));
      assert(!chck_cstr_to_u32("1.0", &uv));
   }

   /* TEST: i16 conversion tests */
   {
      int16_t v;
      assert(chck_cstr_to_i16("1", &v) && v == 1);
      assert(chck_cstr_to_i16("-1", &v) && v == -1);
      assert(chck_cstr_to_i16("32767", &v) && v == INT16_MAX);
      assert(chck_cstr_to_i16("-32768", &v) && v == INT16_MIN);
      assert(!chck_cstr_to_i16("32768", &v));
      assert(!chck_cstr_to_i16("-32769", &v));
      assert(!chck_cstr_to_i16("1.0", &v));

      uint16_t uv;
      assert(chck_cstr_to_u16("1", &uv) && uv == 1);
      assert(!chck_cstr_to_u16("-1", &uv));
      assert(chck_cstr_to_u16("65535", &uv) && uv == UINT16_MAX);
      assert(!chck_cstr_to_u16("65536", &uv));
      assert(!chck_cstr_to_u16("1.0", &uv));
   }

   /* TEST: i8 conversion tests */
   {
      int8_t v;
      assert(chck_cstr_to_i8("1", &v) && v == 1);
      assert(chck_cstr_to_i8("-1", &v) && v == -1);
      assert(chck_cstr_to_i8("127", &v) && v == INT8_MAX);
      assert(chck_cstr_to_i8("-128", &v) && v == INT8_MIN);
      assert(!chck_cstr_to_i8("128", &v));
      assert(!chck_cstr_to_i8("-129", &v));
      assert(!chck_cstr_to_i8("1.0", &v));

      uint8_t uv;
      assert(chck_cstr_to_u8("1", &uv) && uv == 1);
      assert(!chck_cstr_to_u8("-1", &uv));
      assert(chck_cstr_to_u8("255", &uv) && uv == UINT8_MAX);
      assert(!chck_cstr_to_u8("257", &uv));
      assert(!chck_cstr_to_u8("1.0", &uv));
   }

   /* TEST: string tests */
   {
      struct chck_string str = {0};
      assert(chck_string_set_cstr(&str, "foobar", false));
      assert(str.data && str.size == strlen("foobar") && chck_string_eq_cstr(&str, "foobar"));
      assert(chck_string_ends_with_cstr(&str, "") && chck_string_ends_with_cstr(&str, NULL) && chck_string_ends_with_cstr(&str, "foobar") && chck_string_ends_with_cstr(&str, "bar") && !chck_string_ends_with_cstr(&str, "bur"));
      assert(chck_string_starts_with_cstr(&str, "") && chck_string_starts_with_cstr(&str, NULL) && chck_string_starts_with_cstr(&str, "foobar") && chck_string_starts_with_cstr(&str, "foo") && !chck_string_starts_with_cstr(&str, "fuo"));
      assert(!chck_string_is_empty(&str));
      assert(chck_string_set_cstr(&str, "", false));
      assert(!str.data && str.size == strlen("") && chck_string_eq_cstr(&str, ""));
      assert(!str.data && str.size == 0 && chck_string_eq_cstr(&str, NULL)); // string_eq_cstr treats empty string as NULL
      assert(chck_string_ends_with_cstr(&str, "") && chck_string_ends_with_cstr(&str, NULL) && !chck_string_ends_with_cstr(&str, "foobar"));
      assert(chck_string_starts_with_cstr(&str, "") && chck_string_starts_with_cstr(&str, NULL) && !chck_string_starts_with_cstr(&str, "foobar"));
      assert(chck_string_is_empty(&str));
      assert(chck_string_set_cstr(&str, NULL, false));
      assert(!str.data && str.size == 0 && !chck_string_eq_cstr(&str, "foobar"));
      assert(chck_string_ends_with_cstr(&str, "") && chck_string_ends_with_cstr(&str, NULL) && !chck_string_ends_with_cstr(&str, "foobar"));
      assert(chck_string_starts_with_cstr(&str, "") && chck_string_starts_with_cstr(&str, NULL) && !chck_string_starts_with_cstr(&str, "foobar"));
      assert(chck_string_is_empty(&str));

      // is_heap is false, so nothing is copied.
      // since chck_strings do not copy when is_heap is false, printf for .data would print whole "foobar" in this case.
      // if is_heap is set to true, the string is copied and terminated correctly.
      assert(chck_string_set_cstr_with_length(&str, "foobar", 3, false));
      assert(str.data && str.size == strlen("foo") && chck_string_eq_cstr(&str, "foo") && !chck_string_eq_cstr(&str, "foobar"));

      struct chck_string str2 = {0};
      assert(chck_string_set(&str2, &str, false));
      assert(str.data == str2.data && str2.size == strlen("foo") && chck_string_eq(&str, &str2));
      assert(chck_string_ends_with(&str, &str2));
      assert(chck_string_starts_with(&str, &str2));
      assert(chck_string_set(&str2, &str, true));
      assert(str.data != str2.data && str2.size == strlen("foo") && chck_string_eq(&str, &str2));
      assert(chck_string_ends_with(&str, &str2));
      assert(chck_string_starts_with(&str, &str2));
      assert(chck_string_set_cstr(&str2, "foobar2", false));
      assert(str.data != str2.data && str2.size == strlen("foobar2") && !chck_string_eq(&str, &str2));
      assert(!chck_string_ends_with(&str, &str2));
      assert(!chck_string_starts_with(&str, &str2));

      assert(chck_string_set_format(&str, "%s-%s", "test", str2.data));
      assert(str.data && str.size == strlen("test-foobar2") && str.is_heap && chck_string_eq_cstr(&str, "test-foobar2"));

      chck_string_release(&str);
      chck_string_release(&str2);
      assert(!str.data && !str2.data && str.size + str2.size == 0);
      assert(chck_string_eq(&str, &str2));

      assert(chck_cstreq("foobar", "foobar"));
      assert(!chck_cstreq("foobar", "foo"));
      assert(!chck_cstreq("foobar", NULL));
      assert(chck_cstreq(NULL, NULL));

      assert(chck_cstrneq("foobar", "foo", 3));
      assert(chck_cstrneq("fo", "fo", 3));
      assert(!chck_cstrneq("foobar", "foa", 3));
      assert(chck_cstrneq(NULL, NULL, 3));
      assert(chck_cstrneq(NULL, NULL, 0));

      assert(!chck_cstr_is_empty("foobar"));
      assert(chck_cstr_ends_with("foobar", "foobar") && chck_cstr_ends_with("foobar", "bar") && !chck_cstr_ends_with("foobar", "bur"));
      assert(chck_cstr_starts_with("foobar", "foobar") && chck_cstr_starts_with("foobar", "foo") && !chck_cstr_starts_with("foobar", "fur"));
      assert(chck_cstr_is_empty("") && chck_cstr_is_empty(NULL));
      assert(chck_cstr_ends_with("", "") && chck_cstr_ends_with(NULL, NULL));
      assert(chck_cstr_starts_with("", "") && chck_cstr_starts_with(NULL, NULL));
   }
   return EXIT_SUCCESS;
}
Exemplo n.º 6
0
Arquivo: wlc.c Projeto: UIKit0/wlc
WLC_API bool
wlc_init(const struct wlc_interface *interface, int argc, char *argv[])
{
   assert(interface);

   if (!interface)
      die("no wlc_interface was given");

   if (wlc.display)
      return true;

   memset(&wlc, 0, sizeof(wlc));

   wl_log_set_handler_server(wl_cb_log);

   for (int i = 1; i < argc; ++i) {
      if (chck_cstreq(argv[i], "--log")) {
         if (i + 1 >= argc)
            die("--log takes an argument (filename)");
         wlc_set_log_file(fopen(argv[++i], "a"));
      }
   }

   unsetenv("TERM");
   const char *x11display = getenv("DISPLAY");
   bool privilidged = false;
   const bool has_logind  = wlc_logind_available();

   if (getuid() != geteuid() || getgid() != getegid()) {
      wlc_log(WLC_LOG_INFO, "Doing work on SUID/SGID side and dropping permissions");
      privilidged = true;
   } else if (getuid() == 0) {
      die("Do not run wlc compositor as root");
   } else if (!x11display && !has_logind && access("/dev/input/event0", R_OK | W_OK) != 0) {
      die("Not running from X11 and no access to /dev/input/event0 or logind available");
   }

#ifndef NDEBUG
   {
      struct sigaction action = {
         .sa_handler = backtrace
      };
      sigaction(SIGABRT, &action, NULL);
      sigaction(SIGSEGV, &action, NULL);

      // XXX: Some weird sigfpes seems to come when running
      // wlc compositor inside wlc compositor (X11 backend).
      // Seems to be caused by resolution changes and mouse clicks.
      // Gather more information about this later and see what's going on.
      if (!getenv("WAYLAND_DISPLAY"))
         fpesetup(&action);
   }
#endif

   int vt = 0;

#ifdef HAS_LOGIND
   // Init logind if we are not running as SUID.
   // We need event loop for logind to work, and thus we won't allow it on SUID process.
   if (!privilidged && !x11display && has_logind) {
      if (!(wlc.display = wl_display_create()))
         die("Failed to create wayland display");
      if (!(vt = wlc_logind_init("seat0")))
         die("Failed to init logind");
   }
#else
   (void)privilidged;
#endif

   if (!x11display)
      wlc_tty_init(vt);

   // -- we open tty before dropping permissions
   //    so the fd process can also handle cleanup in case of crash
   //    if logind initialized correctly, fd process does nothing but handle crash.

   {
      struct wl_display *display = wlc.display;
      wlc.display = NULL;
      wlc_fd_init(argc, argv, (vt != 0));
      wlc.display = display;
   }


   // -- permissions are now dropped

   wl_signal_init(&wlc.signals.terminate);
   wl_signal_init(&wlc.signals.activate);
   wl_signal_init(&wlc.signals.compositor);
   wl_signal_init(&wlc.signals.focus);
   wl_signal_init(&wlc.signals.surface);
   wl_signal_init(&wlc.signals.input);
   wl_signal_init(&wlc.signals.output);
   wl_signal_init(&wlc.signals.render);
   wl_signal_init(&wlc.signals.xwayland);
   wl_signal_add(&wlc.signals.compositor, &compositor_listener);

   if (!wlc_resources_init())
      die("Failed to init resource manager");

   if (!wlc.display && !(wlc.display = wl_display_create()))
      die("Failed to create wayland display");

   const char *socket_name;
   if (!(socket_name = wl_display_add_socket_auto(wlc.display)))
      die("Failed to add socket to wayland display");

   if (socket_name) // shut up static analyze
      setenv("WAYLAND_DISPLAY", socket_name, true);

   if (wl_display_init_shm(wlc.display) != 0)
      die("Failed to init shm");

   if (!wlc_udev_init())
      die("Failed to init udev");

   const char *libinput = getenv("WLC_LIBINPUT");
   if (!x11display || (libinput && !chck_cstreq(libinput, "0"))) {
      if (!wlc_input_init())
         die("Failed to init input");
   }

   memcpy(&wlc.interface, interface, sizeof(wlc.interface));

   if (!wlc_compositor(&wlc.compositor))
      die("Failed to init compositor");

   const char *xwayland = getenv("WLC_XWAYLAND");
   if (!xwayland || !chck_cstreq(xwayland, "0")) {
      if (!(wlc_xwayland_init()))
         die("Failed to init xwayland");
   } else {
      wlc.set_ready_on_run = true;
   }

   wlc_set_active(true);
   return wlc_compositor_is_good(&wlc.compositor);
}
Exemplo n.º 7
0
WLC_API bool
wlc_init(const struct wlc_interface *interface, int argc, char *argv[])
{
   assert(interface);

   if (!interface)
      die("no wlc_interface was given");

   if (wlc.display)
      return true;

   // reset wlc state, but keep log function
   void *log_fun = wlc.log_fun;
   memset(&wlc, 0, sizeof(wlc));
   wlc.log_fun = log_fun;

   wl_log_set_handler_server(wl_cb_log);

   unsetenv("TERM");
   const char *x11display = getenv("DISPLAY");
   bool privileged = false;
   const bool has_logind = wlc_logind_available();

   if (getuid() != geteuid() || getgid() != getegid()) {
      wlc_log(WLC_LOG_INFO, "Doing work on SUID/SGID side and dropping permissions");
      privileged = true;
   } else if (getuid() == 0) {
      die("Do not run wlc compositor as root");
   } else if (!x11display && !has_logind && access("/dev/input/event0", R_OK | W_OK) != 0) {
      die("Not running from X11 and no access to /dev/input/event0 or logind available");
   }

   int vt = 0;

#ifdef HAS_LOGIND
   // Init logind if we are not running as SUID.
   // We need event loop for logind to work, and thus we won't allow it on SUID process.
   if (!privileged && !x11display && has_logind) {
      if (!(wlc.display = wl_display_create()))
         die("Failed to create wayland display");
      if (!(vt = wlc_logind_init("seat0")))
         die("Failed to init logind");
   }
#else
   (void)privileged;
#endif

   if (!x11display)
      wlc_tty_init(vt);

   // -- we open tty before dropping permissions
   //    so the fd process can also handle cleanup in case of crash
   //    if logind initialized correctly, fd process does nothing but handle crash.

   {
      struct wl_display *display = wlc.display;
      wlc.display = NULL;
      wlc_fd_init(argc, argv, (vt != 0));
      wlc.display = display;
   }

   // -- permissions are now dropped

   wl_signal_init(&wlc.signals.terminate);
   wl_signal_init(&wlc.signals.activate);
   wl_signal_init(&wlc.signals.compositor);
   wl_signal_init(&wlc.signals.focus);
   wl_signal_init(&wlc.signals.surface);
   wl_signal_init(&wlc.signals.input);
   wl_signal_init(&wlc.signals.output);
   wl_signal_init(&wlc.signals.render);
   wl_signal_init(&wlc.signals.xwayland);
   wl_signal_add(&wlc.signals.compositor, &compositor_listener);

   if (!wlc_resources_init())
      die("Failed to init resource manager");

   if (!wlc.display && !(wlc.display = wl_display_create()))
      die("Failed to create wayland display");

   const char *socket_name;
   if (!(socket_name = wl_display_add_socket_auto(wlc.display)))
      die("Failed to add socket to wayland display");

   if (socket_name) // shut up static analyze
      setenv("WAYLAND_DISPLAY", socket_name, true);

   if (wl_display_init_shm(wlc.display) != 0)
      die("Failed to init shm");

   if (!wlc_udev_init())
      die("Failed to init udev");

   const char *libinput = getenv("WLC_LIBINPUT");
   if (!x11display || (libinput && !chck_cstreq(libinput, "0"))) {
      if (!wlc_input_init())
         die("Failed to init input");
   }

   if (!wlc_compositor(&wlc.compositor))
      die("Failed to init compositor");

   memcpy(&wlc.interface, interface, sizeof(wlc.interface));
   return true;
}