aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchell Riedstra <mitch@riedstra.dev>2024-01-02 17:38:12 -0500
committerMitchell Riedstra <mitch@riedstra.dev>2024-01-02 17:38:12 -0500
commit3bab6beb965b4c82aeb9a6775176ba6481f4dcfc (patch)
tree0a3eb83cd4254f9851e135e327525b69cd1fe786
parenta43600011a3ee977a10fdc863e5b79c272a7b5bd (diff)
downloadpm-3bab6beb965b4c82aeb9a6775176ba6481f4dcfc.tar.gz
pm-3bab6beb965b4c82aeb9a6775176ba6481f4dcfc.tar.xz
Add support for MacOS
-rw-r--r--.gitignore1
-rw-r--r--Makefile7
-rw-r--r--compat/reallocarray.c45
-rw-r--r--compat/strtonum.c65
-rwxr-xr-xpm85
-rw-r--r--pm-fmtdb.c4
-rw-r--r--pm-genid.c95
-rw-r--r--readme.md6
8 files changed, 252 insertions, 56 deletions
diff --git a/.gitignore b/.gitignore
index 4cea3a5..f542e5b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
ses.vim
/pm-fmtdb
+/pm-genid
diff --git a/Makefile b/Makefile
index 5aeb748..995627a 100644
--- a/Makefile
+++ b/Makefile
@@ -3,11 +3,12 @@ PREFIX ?= /usr/local
CC ?= cc
CFLAGS ?= -D_DEFAULT_SOURCE -std=c99 -pedantic -Wall -O2 -s
-all: pm-fmtdb
+all: pm-fmtdb pm-genid
-install: pm-fmtdb
+install: pm-fmtdb pm-genid
install -m 755 pm-fmtdb $(PREFIX)/bin/pm-fmtdb
+ install -m 755 pm-genid $(PREFIX)/bin/pm-genid
install -m 755 pm $(PREFIX)/bin/pm
clean:
- rm -f pm-fmtdb
+ rm -f pm-fmtdb pm-genid
diff --git a/compat/reallocarray.c b/compat/reallocarray.c
new file mode 100644
index 0000000..bb6921e
--- /dev/null
+++ b/compat/reallocarray.c
@@ -0,0 +1,45 @@
+/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
+/*
+ * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/stdlib/reallocarray.c */
+
+#ifndef HAVE_REALLOCARRAY
+
+#include <sys/types.h>
+#include <errno.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
+
+void *
+reallocarray(void *optr, size_t nmemb, size_t size)
+{
+ if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+ nmemb > 0 && SIZE_MAX / nmemb < size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ return realloc(optr, size * nmemb);
+}
+#endif /* HAVE_REALLOCARRAY */
diff --git a/compat/strtonum.c b/compat/strtonum.c
new file mode 100644
index 0000000..fdfc72a
--- /dev/null
+++ b/compat/strtonum.c
@@ -0,0 +1,65 @@
+/* $OpenBSD: strtonum.c,v 1.8 2015/09/13 08:31:48 guenther Exp $ */
+
+/*
+ * Copyright (c) 2004 Ted Unangst and Todd Miller
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#define INVALID 1
+#define TOOSMALL 2
+#define TOOLARGE 3
+
+long long
+strtonum(const char *numstr, long long minval, long long maxval,
+ const char **errstrp)
+{
+ long long ll = 0;
+ int error = 0;
+ char *ep;
+ struct errval {
+ const char *errstr;
+ int err;
+ } ev[4] = {
+ { NULL, 0 },
+ { "invalid", EINVAL },
+ { "too small", ERANGE },
+ { "too large", ERANGE },
+ };
+
+ ev[0].err = errno;
+ errno = 0;
+ if (minval > maxval) {
+ error = INVALID;
+ } else {
+ ll = strtoll(numstr, &ep, 10);
+ if (numstr == ep || *ep != '\0')
+ error = INVALID;
+ else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
+ error = TOOSMALL;
+ else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
+ error = TOOLARGE;
+ }
+ if (errstrp != NULL)
+ *errstrp = ev[error].errstr;
+ errno = ev[error].err;
+ if (error)
+ ll = 0;
+
+ return (ll);
+}
diff --git a/pm b/pm
index 5e85539..ddaa88d 100755
--- a/pm
+++ b/pm
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (c) 2023 Mitchell Riedstra
+# Copyright (c) 2024 Mitchell Riedstra
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -13,7 +13,7 @@
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
set -e
-PASTE_MANAGER_FILE=~/.pastes
+PASTE_MANAGER_FILE="${PASTE_MANAGER_FILE:-$HOME/.pastes}"
PASTE_MANAGER_LINES="${PASTE_MANAGER_LINES:-30}"
PASTE_MANAGER_X_SELECTION="${PASTE_MANAGER_X_SELECTION:-clipboard}"
@@ -21,19 +21,20 @@ PASTE_MANAGER_X_SELECTION="${PASTE_MANAGER_X_SELECTION:-clipboard}"
# the only option called elsewhere is `-p`
_menu="dmenu -l $PASTE_MANAGER_LINES -i"
+case $(uname) in
+ Darwin) _menu="choose -m -s 16 -f Monaco -n $PASTE_MANAGER_LINES -w 85" ;;
+ *) ;;
+esac
+
genid() {
+ if [ -x "$(command -v pm-genid)" ] ; then
+ pm-genid
+ return
+ fi
{ dd if=/dev/urandom 2>/dev/null | tr -C -d 'a-zA-Z0-9'; echo; } \
| fold -w 8 | sed 1q
}
-getFifo() {
- _p="$(mktemp)"
- rm -f "$_p"
- sleep 0.1
- mkfifo "$_p"
- echo "$_p"
-}
-
_clip() {
case $(uname) in
Darwin)
@@ -48,23 +49,26 @@ esac
insert() {
exec <&-
- $_menu -p "Enter name: " > "$_fifo" &
- name="$(tr -d '\n' < "$_fifo")"
+ name="$(printf "_\n" | $_menu -p "Enter name: ")"
+ name="$(echo "$name" | tr -d '\n')"
[ -z "$name" ] && exit 1
- $_menu -p "Enter content: " > "$_fifo" &
- content="$(tr -d '\n' < "$_fifo")"
+ content="$(printf "_\n" | $_menu -p "Enter content: ")"
+ content="$(echo "$content" | tr -d '\n')"
[ -z "$content" ] && exit 1
+ id="$(genid)"
+ [ -z "$id" ] && { echo "ID empty" ; exit 1; }
+
printf "%s::%s::%s::%s::%s\n" \
- "$(genid)" "$(date +%s)" "$(date +%s)" "$name" "$content" \
+ "$id" "$(date +%s)" "$(date +%s)" "$name" "$content" \
>> "$PASTE_MANAGER_FILE"
}
sel() {
pm-fmtdb -f "$PASTE_MANAGER_FILE" \
| $_menu -p "$@" \
- | sed -re 's/^ID: ([^ ]*).*$/\1/'
+ | sed -r -e 's/^ID: ([^ ]*).*$/\1/'
}
selectName() {
@@ -90,40 +94,28 @@ selectContent() {
}
copy() {
- sel "Will copy content" > "$_fifo" &
- read -r id < "$_fifo"
- selectContent "$id" \
- | _clip
+ selectContent "$(sel "Will copy content")" | _clip
}
copyName() {
- sel "Will copy entry name" > "$_fifo" &
- read -r id < "$_fifo"
- selectName "$id" \
- | _clip
+ selectName "$(sel "Will copy entry name")" | _clip
}
_type() {
- sel "Will type content" > "$_fifo" &
- read -r id < "$_fifo"
- selectContent "$id" \
+ selectContent "$(sel "Will type content")" \
| xdotool type --delay 1ms --clearmodifiers --file -
}
typeName() {
- sel "Will type entry name" > "$_fifo" &
- read -r id < "$_fifo"
- selectName "$id" \
+ selectName "$(sel "Will type entry name")" \
| xdotool type --delay 1ms --clearmodifiers --file -
}
rename() {
- sel "Item to rename" > "$_fifo" &
- read -r id < "$_fifo"
+ id="$(sel "Item to rename")"
item="$(grep "^$id" "$PASTE_MANAGER_FILE" | pm-fmtdb -f - )"
name="$(selectName "$id")"
- $_menu -p "Currently: ( $name ) New Name" > "$_fifo" &
- read -r name < "$_fifo"
+ name="$($_menu -p "Currently: ( $name ) New Name")"
cp "$PASTE_MANAGER_FILE" "$PASTE_MANAGER_FILE".bak
awk -F:: -v id="$id" -v name="$name" '
BEGIN { OFS="::"; }
@@ -138,12 +130,10 @@ rename() {
}
update() {
- sel "Item to update" > "$_fifo" &
- read -r id < "$_fifo"
+ id="$(sel "Item to update")"
item="$(grep "^$id" "$PASTE_MANAGER_FILE" | pm-fmtdb -f - )"
output="$(selectContent "$id")"
- $_menu -p "Currently: ( $output ) New Content" > "$_fifo" &
- read -r content < "$_fifo"
+ content="$(printf "_\n" | $_menu -p "Currently: ( $output ) New Content")"
cp "$PASTE_MANAGER_FILE" "$PASTE_MANAGER_FILE".bak
awk -F:: -v id="$id" -v content="$content" '
BEGIN { OFS="::"; }
@@ -158,13 +148,10 @@ update() {
}
delete() {
- sel "Item to delete" > "$_fifo" &
- read -r id < "$_fifo"
+ id="$(sel "Item to delete")"
+ [ -z "$id" ] && exit 1
item="$(grep "^$id" "$PASTE_MANAGER_FILE" | pm-fmtdb -f - )"
- echo Item: "$item"'
-yes
-no' | $_menu -p "Are you sure?" > "$_fifo" &
- read -r resp < "$_fifo"
+ resp="$(printf 'Item: "%s"\nyes\nno\n' "$item" | $_menu -p "Are you sure?")"
if [ "$resp" = "yes" ] ; then
cp "$PASTE_MANAGER_FILE" "$PASTE_MANAGER_FILE".bak
sed '/^'"$id"/d < "$PASTE_MANAGER_FILE".bak > "$PASTE_MANAGER_FILE"
@@ -181,11 +168,7 @@ rename
update'
menu() {
- echo "$actions" | $_menu -p "Command:" \
- | {
- read -r action;
- runAction "$action";
- }
+ runAction "$(echo "$actions" | $_menu -p "Command:")"
}
runAction() {
@@ -219,9 +202,5 @@ EOF
exit 1
}
-_fifo="$(getFifo)"
-
action="${1:-menu}"
runAction "$action"
-
-rm -f "$_fifo"
diff --git a/pm-fmtdb.c b/pm-fmtdb.c
index 2683112..9989e24 100644
--- a/pm-fmtdb.c
+++ b/pm-fmtdb.c
@@ -26,6 +26,10 @@
#include <fcntl.h>
#include <unistd.h>
+#if __APPLE__
+ #include "compat/reallocarray.c"
+#endif
+
#define TIME_FMT_CREATED "%H:%M:%S %m.%d.%y"
#define TIME_FMT_UPDATED "%m.%d.%y"
diff --git a/pm-genid.c b/pm-genid.c
new file mode 100644
index 0000000..5a481ce
--- /dev/null
+++ b/pm-genid.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2024 Mitchell Riedstra
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Since `tr` on MacOS cannot handle the binary stream.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#if __linux__
+ #include "compat/strtonum.c"
+#endif
+
+#define BUF_SIZE 64
+#define MAX_OUT_CHARS 65534
+
+void
+help() {
+ puts("genid [-d <rand device>] [-n <numchars]");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ const char *rdev = "/dev/urandom";
+ int chars = 8;
+ char **a = argv+1;
+ int fd, n;
+ char c;
+ int written = 0;
+
+ for (;*a;a++) {
+ if (strcmp(*a, "-d") == 0 && *(++a)) {
+ rdev = *a;
+ } else if (strcmp(*a, "-n") == 0 && *(++a)) {
+ const char *errstr;
+ chars = (int)strtonum(*a, 1, MAX_OUT_CHARS, &errstr);
+ if (errstr != NULL) {
+ printf("strtonum: %s\n", errstr);
+ help();
+ }
+ } else {
+ if (*a)
+ printf("Unknown option: '%s'\n", *a);
+
+ help();
+ }
+ }
+
+ fd = open(rdev, O_RDONLY);
+ if (fd == -1) {
+ perror("opening random device");
+ exit(1);
+ }
+
+ char buf[BUF_SIZE];
+ for (int i=0; written<chars && i<1000; i++) {
+ n = read(fd, &buf, BUF_SIZE-1);
+ if (n == -1) {
+ perror("read");
+ exit(1);
+ }
+
+ for (int j = 0; j<n && j<BUF_SIZE && written<chars; j++) {
+ c = buf[j];
+ if (
+ (c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9')
+ ) {
+ written++;
+ putc(c, stdout);
+ }
+ }
+ }
+
+ puts("");
+ close(fd);
+}
diff --git a/readme.md b/readme.md
index 1ffbda7..3733fcc 100644
--- a/readme.md
+++ b/readme.md
@@ -56,6 +56,12 @@ Edit the source code for further tweaks. The one people may have the most
interest in is the format sent to `dmenu`, that's controlled via the small c
program 'pm-fmtdb' near the top of the file.
+
+### MacOS
+
+You'll need a [menu](https://github.com/chipsenkbeil/choose), and you'll
+probably want a [hotkey daemon](https://github.com/koekeishiya/skhd).
+
## Bugs
Probably. This was written in just a few hours. Email me if you find any, I'll