Skip to content

Commit 369e351

Browse files
committed
Add new argument to pass a file directly.
Instead of always using stdin and creating a tempfile, this argument will use a file passed by the user instead. This can be useful for integrating into other programs, that don't want to start a subshell to use pipes.
1 parent 091d602 commit 369e351

File tree

1 file changed

+59
-36
lines changed

1 file changed

+59
-36
lines changed

src/wl-copy.c

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ static struct {
4545
int primary;
4646
int sensitive;
4747
const char *seat_name;
48+
char *input_file;
4849
} options;
4950

5051
static void did_set_selection_callback(struct copy_action *copy_action) {
@@ -118,6 +119,7 @@ static void print_usage(FILE *f, const char *argv0) {
118119
"\t-o, --paste-once\tOnly serve one paste request and then exit.\n"
119120
"\t-f, --foreground\tStay in the foreground instead of forking.\n"
120121
"\t-c, --clear\t\tInstead of copying, clear the clipboard.\n"
122+
"\t-i, --input-file\tInstead of copying from stdin copy file-content of this file.\n"
121123
"\t-p, --primary\t\tUse the \"primary\" clipboard.\n"
122124
"\t-n, --trim-newline\tDo not copy the trailing newline character.\n"
123125
"\t-t, --type mime/type\t"
@@ -155,7 +157,7 @@ static void parse_options(int argc, argv_t argv) {
155157
};
156158
while (1) {
157159
int option_index;
158-
const char *opts = "vhpnofct:s:";
160+
const char *opts = "vhpnofcti:s:";
159161
int c = getopt_long(argc, argv, opts, long_options, &option_index);
160162
if (c == -1) {
161163
break;
@@ -194,6 +196,9 @@ static void parse_options(int argc, argv_t argv) {
194196
case 's':
195197
options.seat_name = strdup(optarg);
196198
break;
199+
case 'i':
200+
options.input_file = strdup(optarg);
201+
break;
197202
default:
198203
/* getopt has already printed an error message */
199204
print_usage(stderr, argv[0]);
@@ -259,42 +264,60 @@ int main(int argc, argv_t argv) {
259264
/* Copy our command-line arguments */
260265
copy_action->argv_to_copy = &argv[optind];
261266
} else {
262-
/* Copy data from our stdin.
263-
* It's important that we only do this
264-
* after going through the initial stages
265-
* that are likely to result in errors,
266-
* so that we don't forget to clean up
267-
* the temp file.
268-
*/
269-
char *temp_file = dump_stdin_into_a_temp_file();
270-
if (options.trim_newline) {
271-
trim_trailing_newline(temp_file);
272-
}
273-
if (options.mime_type == NULL) {
274-
options.mime_type = infer_mime_type_from_contents(temp_file);
275-
}
276-
copy_action->fd_to_copy_from = open(
277-
temp_file,
278-
O_RDONLY | O_CLOEXEC
279-
);
280-
if (copy_action->fd_to_copy_from < 0) {
281-
perror("Failed to open temp file");
282-
return 1;
283-
}
284-
/* Now, remove the temp file and its
285-
* containing directory. We still keep
286-
* access to the file through our open
287-
* file descriptor.
288-
*/
289-
int rc = unlink(temp_file);
290-
if (rc < 0) {
291-
perror("Failed to unlink temp file");
292-
}
293-
rc = rmdir(dirname(temp_file));
294-
if (rc < 0) {
295-
perror("Failed to remove temp file directory");
267+
if (options.input_file != NULL) {
268+
/* The user already passed a file to copy, so use that instead of
269+
creating a tempfile.*/
270+
if (options.trim_newline) {
271+
trim_trailing_newline(options.input_file);
272+
}
273+
if (options.mime_type == NULL) {
274+
options.mime_type = infer_mime_type_from_contents(options.input_file);
275+
}
276+
copy_action->fd_to_copy_from = open(options.input_file, O_RDONLY | O_CLOEXEC);
277+
if (copy_action->fd_to_copy_from < 0) {
278+
fprintf(stderr, "Could not open file: %s\n", options.input_file);
279+
return 1;
280+
}
281+
free(options.input_file);
282+
options.input_file = NULL;
283+
} else {
284+
/* Copy data from our stdin.
285+
* It's important that we only do this
286+
* after going through the initial stages
287+
* that are likely to result in errors,
288+
* so that we don't forget to clean up
289+
* the temp file.
290+
*/
291+
char *temp_file = dump_stdin_into_a_temp_file();
292+
if (options.trim_newline) {
293+
trim_trailing_newline(temp_file);
294+
}
295+
if (options.mime_type == NULL) {
296+
options.mime_type = infer_mime_type_from_contents(temp_file);
297+
}
298+
copy_action->fd_to_copy_from = open(
299+
temp_file,
300+
O_RDONLY | O_CLOEXEC
301+
);
302+
if (copy_action->fd_to_copy_from < 0) {
303+
perror("Failed to open temp file");
304+
return 1;
305+
}
306+
/* Now, remove the temp file and its
307+
* containing directory. We still keep
308+
* access to the file through our open
309+
* file descriptor.
310+
*/
311+
int rc = unlink(temp_file);
312+
if (rc < 0) {
313+
perror("Failed to unlink temp file");
314+
}
315+
rc = rmdir(dirname(temp_file));
316+
if (rc < 0) {
317+
perror("Failed to remove temp file directory");
318+
}
319+
free(temp_file);
296320
}
297-
free(temp_file);
298321
}
299322

300323
/* Create the source */

0 commit comments

Comments
 (0)