sopen

Suckless mimeopen alternative
git clone git://pollux.codes/git/sopen.git
Log | Files | Refs | README | LICENSE

commit 154c3d32af887121dc5779607c3ddf784ee05893
parent f5f2ddb9fd5f8d8c93805614d9b56f0eddf04457
Author: Pollux <pollux@pollux.codes>
Date:   Tue, 11 Feb 2025 23:30:44 -0600

feat: Add command line arguments

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

Diffstat:
Msopen.1 | 13+++++++++++--
Msopen.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 83 insertions(+), 6 deletions(-)

diff --git a/sopen.1 b/sopen.1 @@ -2,11 +2,20 @@ .SH "NAME" sopen \- A suckless resources opener .SH "SYNOPSIS" -.B sopen <url/file> +.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 Joseph "Pollux" Hand. -.SH "SEE ALSO" 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; } }