home | blog | art | now | git gpg | email | rss

sopen

Suckless mimeopen alternative
git clone git://pollux.codes/git/sopen.git
Log | Files | Refs | README | LICENSE
commit 351848b8f321dc49706b2133e899cf46df5be5a6
parent 66bf65deca9ca42f31cd986412fbc96e83753030
Author: Pollux <pollux@pollux.codes>
Date:   Tue, 11 Feb 2025 22:54:04 -0600

docs: Add man page

Signed-off-by: Pollux <pollux@pollux.codes>

Diffstat:
MMakefile | 5++++-
Asopen.1 | 21+++++++++++++++++++++
Msopen.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 97 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile @@ -2,6 +2,7 @@ PREFIX ?= /usr/local BINDIR ?= $(PREFIX)/bin +MANDIR ?= $(PREFIX)/share/man BINSUFFIX ?= PROGNAME = sopen @@ -32,6 +33,8 @@ clean: rm "$(PROGNAME)$(BINSUFFIX)" install: - install -d $(DESTDIR)$(BINDIR)/ + install -d $(DESTDIR)$(BINDIR)/ $(DESTDIR)$(MANDIR)/man1/ install -s -m 755 "$(PROGNAME)$(BINSUFFIX)" \ $(DESTDIR)$(BINDIR)/$(PROGNAME)$(BINSUFFIX) + install -m 644 -D "$(PROGNAME).1" \ + "$(DESTDIR)$(MANDIR)/man1/" diff --git a/sopen.1 b/sopen.1 @@ -0,0 +1,21 @@ +.TH "sopen" 1 +.SH "NAME" +sopen \- A suckless resources opener +.SH "SYNOPSIS" +.B sopen [-h] [-V] [-d] <url/file> +.SH "DESCRIPTION" +sopen is a minimal resource opener, like mime-open, that matches compile-time +configured regular expressions against the url or file path provided and runs +the desired program with the same url or path. +.SH "OPTIONS" +.TP +.B \-d +dry run (print command that would have been executed, but don't execute). +.TP +.B \-h +print usage information to stdout, then exit. +.TP +.B \-V +print version information to stdout, then exit. +.SH "AUTHORS" +sopen was written by Pollux. diff --git a/sopen.c b/sopen.c @@ -1,5 +1,6 @@ /* See LICENSE file for copyright and license details. */ +#include <getopt.h> #include <magic.h> #include <regex.h> #include <spawn.h> @@ -13,6 +14,11 @@ #define REGEX_PROTOCOL "^[a-z]*://" #define REGEX_URL "^(([a-z]*)://(.*)/)?(.*)$" +#define USAGE "usage: sopen [-h] [-v] [-d] <url/file>" + +#define STR_LITERAL(x) #x +#define STRINGIFY(x) STR_LITERAL(x) + typedef struct { const char *protocol_regex; const char *url_regex; @@ -21,6 +27,10 @@ typedef struct { const char *program; } Rule; +void print_help(); +void print_version(); +void parse_args(const int argc, char *const *argv, int *dry_run, + int *url_ind); int parse_url(const char *url, char *protocol, char *file); int match_rule(const Rule rule, const char *url, const char *protocol, const char *file, @@ -28,6 +38,50 @@ int match_rule(const Rule rule, const char *url, #include "config.h" +void +print_help() { + printf(USAGE "\n"); +} + +void +print_version() { + printf(STRINGIFY(PROGNAME) " " STRINGIFY(VERSION) "\n"); + printf("CFLAGS: " STRINGIFY(CFLAGS) "\n"); + printf("LDFLAGS: " STRINGIFY(LDFLAGS) "\n"); +} + +void +parse_args(const int argc, char *const *argv, int *dry_run, int *url_ind) { + + char *cvalue = NULL; + int index; + int c; + + opterr = 0; + + while((c = getopt(argc, argv, "dhV")) != -1) { + switch (c) { + case 'd': + *dry_run = 1; + break; + case 'h': + print_help(); + exit(0); + case 'V': + print_version(); + exit(0); + case '?': + fprintf(stderr, + "Unknown option `\\x%x'. Run `sopen -h' for usage.\n", + optopt); + exit(1); + default: + exit(255); + } + } + *url_ind = optind; +} + int parse_url(const char *url, char *protocol, char *file) { @@ -61,6 +115,8 @@ match_rule(const Rule rule, const char *url, const char *protocol, regex_t regex; int res; + int dry_run = 0; + res = regcomp(&regex, rule.url_regex, REG_EXTENDED); if(res > 0) { printf("Failed to compile url regex: %s\n", rule.url_regex); @@ -102,16 +158,19 @@ match_rule(const Rule rule, const char *url, const char *protocol, } int -main(int argc, const char **argv) { +main(int argc, char *const *argv) { int res; + int dry_run; + int url_ind; magic_t cookie; regex_t has_protocol; - const char *url; const char *mime_type; + + const char *url; char protocol[16]; char file[1024]; @@ -124,7 +183,11 @@ main(int argc, const char **argv) { } magic_load(cookie, NULL); - url = argv[1]; + parse_args(argc, argv, &dry_run, &url_ind); + url = argv[url_ind]; + + printf("%s\n", url); + printf("%d\n", dry_run); res = regcomp(&has_protocol, REGEX_PROTOCOL, REG_EXTENDED); if(res > 0) @@ -145,10 +208,15 @@ main(int argc, const char **argv) { res = match_rule(rules[n], url, protocol, file, mime_type); if(res == 0) { + child_args[0] = (char *)rules[n].program; child_args[1] = (char *)url; child_args[2] = NULL; - execvp(rules[n].program, child_args); + if(dry_run) { + printf("%s %s\n", child_args[0], child_args[1]); + } else { + execvp(rules[n].program, child_args); + } return 0; } }