Skip to content
15 changes: 14 additions & 1 deletion src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ foreach protocol : protocols
protocol_deps += lib
endforeach

inc = include_directories('.')

lib = static_library(
'wl-clipboard',
[
Expand Down Expand Up @@ -124,22 +126,33 @@ lib = static_library(
'types/registry.c',
'types/copy-action.h',
'types/copy-action.c',
'types/buffer.h',
'types/buffer.c',
'types/copy-source-argv.h',
'types/copy-source-argv.c',
'types/copy-source-buffer.h',
'types/copy-source-buffer.c',
'types/sensitive-section.h',
'types/sensitive-section.c',
],
dependencies: wayland,
link_with: protocol_deps
link_with: protocol_deps,
include_directories: [inc]
)

executable(
'wl-copy',
['wl-copy.c', protocol_headers],
dependencies: wayland,
link_with: lib,
include_directories: [inc],
install: true
)
executable(
'wl-paste',
['wl-paste.c', protocol_headers],
dependencies: wayland,
link_with: lib,
include_directories: [inc],
install: true
)
33 changes: 33 additions & 0 deletions src/types/buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* wl-clipboard
*
* Copyright © 2019 Sergey Bugaev <bugaevc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/


#include <string.h>

#include "buffer.h"

static void noop(struct buffer*) {
/* intentionally left blank */
}

void buffer_steal(struct buffer* dest, struct buffer* src) {
memcpy(dest, src, sizeof(*src));
src->destroy = noop;
src->ptr = NULL;
src->len = 0;
}
38 changes: 38 additions & 0 deletions src/types/buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* wl-clipboard
*
* Copyright © 2019 Sergey Bugaev <bugaevc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef TYPES_OWNED_SLICE_H
#define TYPES_OWNED_SLICE_H

#include <stddef.h>

struct buffer {
void (*destroy)(struct buffer*);

char* ptr;
size_t len;
};

/// @brief Steal buffer to dest from src, leaving the latter empty
/// @param[out] dest Uninitialised (or empty) buffer
/// @param[in] src Initialised and valid buffer
/// @note It is safe to call .destroy on src after stealing
/// @warning Does not check anything
void buffer_steal(struct buffer* dest, struct buffer* src);

#endif /* UTIL_FILES_H */
63 changes: 4 additions & 59 deletions src/types/copy-action.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,66 +68,10 @@ static void on_focus(
static void do_send(struct source *source, const char *mime_type, int fd) {
struct copy_action *self = source->data;

/* Unset O_NONBLOCK */
/* Unset O_NONBLOCK */
fcntl(fd, F_SETFL, 0);

if (self->file_to_copy != NULL) {
/* Copy the file to the given file descriptor
* by spawning an appropriate cat process.
*/
pid_t pid = fork();
if (pid < 0) {
perror("fork");
close(fd);
return;
}
if (pid == 0) {
dup2(fd, STDOUT_FILENO);
close(fd);
execlp("cat", "cat", self->file_to_copy, NULL);
perror("exec cat");
exit(1);
}
close(fd);
/* Wait for the cat process to exit. This effectively
* means waiting for the other side to read the whole
* file. In theory, a malicious client could perform a
* denial-of-serivice attack against us. Perhaps we
* should switch to an asynchronous child waiting scheme
* instead.
*/
wait(NULL);
} else {
/* We'll perform the copy ourselves */
FILE *f = fdopen(fd, "w");
if (f == NULL) {
perror("fdopen");
close(fd);
return;
}

if (self->data_to_copy.ptr != NULL) {
/* Just copy the given chunk of data */
fwrite(self->data_to_copy.ptr, 1, self->data_to_copy.len, f);
} else if (self->argv_to_copy != NULL) {
/* Copy an argv-style string array,
* inserting spaces between items.
*/
int is_first = 1;
for (argv_t word = self->argv_to_copy; *word != NULL; word++) {
if (!is_first) {
fwrite(" ", 1, 1, f);
}
is_first = 0;
fwrite(*word, 1, strlen(*word), f);
}
} else {
bail("Unreachable: nothing to copy");
}

fclose(f);
}

self->src->copy(fd, self->src);

if (self->pasted_callback != NULL) {
self->pasted_callback(self);
Expand All @@ -141,7 +85,8 @@ static void forward_cancel(struct source *source) {
}
}

void copy_action_init(struct copy_action *self) {
void copy_action_init(struct copy_action *self, struct copy_source* src) {
self->src = src;
if (self->source != NULL) {
self->source->send_callback = do_send;
self->source->cancelled_callback = forward_cancel;
Expand Down
14 changes: 4 additions & 10 deletions src/types/copy-action.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#ifndef TYPES_COPY_ACTION_H
#define TYPES_COPY_ACTION_H

#include <types/copy-source.h>
#include "util/string.h"

#include <stddef.h>
Expand All @@ -38,17 +39,10 @@ struct copy_action {
void (*pasted_callback)(struct copy_action *self);
void (*cancelled_callback)(struct copy_action *self);

/* Exactly one of these fields must be non-null if the source
* is non-null, otherwise all these fields must be null.
*/
const char *file_to_copy;
argv_t argv_to_copy;
struct {
const char *ptr;
size_t len;
} data_to_copy;
struct copy_source* src;
};

void copy_action_init(struct copy_action *self);
/// @brief Initialise copy action from specified copy source
void copy_action_init(struct copy_action *self, struct copy_source* src);

#endif /* TYPES_COPY_ACTION_H */
57 changes: 57 additions & 0 deletions src/types/copy-source-argv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* wl-clipboard
*
* Copyright © 2019 Sergey Bugaev <bugaevc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/


#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <types/copy-source-argv.h>

static void copy(int fd, struct copy_source* self) {
struct copy_source_argv* self2 = (struct copy_source_argv*)self;

FILE* file = fdopen(fd, "w");
if (!file) {
perror("copy_source_argv/copy: fdopen");
close(fd);
return;
}

argv_t word = self2->argv;
if (*word) {
fwrite(*word, 1, strlen(*word), file);
++word;
}
for (; *word; ++word) {
fputc(' ', file);
fwrite(*word, 1, strlen(*word), file);
}
fclose(file);
}


int copy_source_argv_init(struct copy_source_argv* self, argv_t argv) {
self->impl.copy = copy;
if (!argv) {
return -1;
}
self->argv = argv;
return 0;
}

41 changes: 41 additions & 0 deletions src/types/copy-source-argv.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* wl-clipboard
*
* Copyright © 2019 Sergey Bugaev <bugaevc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef TYPES_COPY_SOURCE_ARGV_H
#define TYPES_COPY_SOURCE_ARGV_H

#include <util/string.h>
#include <types/copy-source.h>

#include <stddef.h>

/// @brief Copy source, serving data from the argv-like array of strings
struct copy_source_argv {
struct copy_source impl;

argv_t argv;
};

/// @brief Initialise copy source from argv-like array of (unowned) array of strings,
/// terminated with empty string
/// @param[out] self Uninitialised copy source
/// @param[in] argv argv-like array of strings
/// @return 0 on success, negative value otherwise
int copy_source_argv_init(struct copy_source_argv* self, argv_t argv);

#endif /* TYPES_COPY_ACTION_H */
67 changes: 67 additions & 0 deletions src/types/copy-source-buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* wl-clipboard
*
* Copyright © 2019 Sergey Bugaev <bugaevc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <types/copy-source-buffer.h>

static void copy(int fd, struct copy_source* self) {
struct copy_source_buffer* self2 = (struct copy_source_buffer*)self;

const char* ptr = self2->slice.ptr;
size_t len = self2->slice.len;

for (;;) {
ssize_t bytes = write(fd, ptr, len);
if (bytes < 0) {
perror("copy_source_slice/copy: write");
close(fd);
exit(1);
}
len -= bytes;
if (!bytes || !len) {
break;
}
ptr += bytes;
}

if (close(fd)) {
perror("copy_source_slice/copy: close");
}
}

static void destroy(struct copy_source* self) {
struct copy_source_buffer* self2 = (struct copy_source_buffer*)self;
self2->slice.destroy(&self2->slice);
}


int copy_source_buffer_init(struct copy_source_buffer* self, struct buffer* slice) {
if (!slice || !slice->ptr || !slice->len) {
return -1;
}

self->impl.copy = copy;
self->impl.destroy = destroy;

buffer_steal(&self->slice, slice);
return 0;
}

Loading