aboutsummaryrefslogtreecommitdiffstats
path: root/clip
diff options
context:
space:
mode:
Diffstat (limited to 'clip')
-rwxr-xr-xclip63
1 files changed, 63 insertions, 0 deletions
diff --git a/clip b/clip
new file mode 100755
index 0000000..8e4d3dd
--- /dev/null
+++ b/clip
@@ -0,0 +1,63 @@
+#!/usr/bin/python3
+# SPDX-License-Identifier: MIT
+'''
+Simple clipboard storing anything from stdin in a file or outputing from
+the file to stdout. Direction is determined from pipe redirection.
+
+Examples:
+
+Store something to clipboard:
+ echo abc | clip
+
+Output clipboard content to console:
+ clip
+
+Use content:
+ clip > file
+ clip | command
+'''
+
+
+import contextlib
+import getpass
+import os
+import sys
+
+
+class Error(Exception): pass
+class SecurityError(Error): pass
+
+
+def fileno(filelike):
+ if getattr(filelike, 'fileno'):
+ return filelike.fileno()
+ elif getattr(filelike, 'buffer'):
+ return filelike.buffer.fileno()
+ raise Error("fileno not found inside file-like object")
+
+
+@contextlib.contextmanager
+def secure_open(path, mode='r', *l, **kw):
+ real_mode = mode
+ if 'w' in real_mode:
+ real_mode = real_mode.replace('w', 'a')
+ with open(path, real_mode, *l, **kw) as fo:
+ if os.fstat(fileno(fo)) != os.stat(path):
+ raise SecurityError("Intrusion might have been done on %s" % path)
+ if 'w' in mode:
+ os.lseek(fileno(fo), 0, os.SEEK_SET)
+ os.ftruncate(fileno(fo), 0)
+ os.fchmod(fileno(fo), 0o600)
+ yield fo
+
+
+if __name__ == '__main__':
+ clipboard_filepath = '/dev/shm/%s-clipboard' % getpass.getuser()
+ if(sys.stdin.isatty()):
+ # Should write clipboard contents out to stdout
+ with secure_open(clipboard_filepath, 'rb') as fo:
+ sys.stdout.buffer.write(fo.read())
+ elif(sys.stdout.isatty()):
+ # Should save stdin to clipboard
+ with secure_open(clipboard_filepath, 'wb') as fo:
+ fo.write(sys.stdin.buffer.read())