# /etc/rawhide.conf: rh system-wide configuration.
# See rh(1) and rawhide.conf(5) for more information.


/*
This file constitutes the rawhide standard library.

On some systems, this file could be somewhere other than /etc
(e.g., /usr/local/etc, /opt/local/etc, /usr/pkg/etc).

You can modify this file, and/or place additional files
in the /etc/rawhide.conf.d directory.
They'll be read after this file, in lexicographic order.
Any files whose names start with dot are skipped.

You can also create your own user-specific rawhide
functions in ~/.rhrc and ~/.rhrc.d/*. They'll be read
by rh in the same manner after these system-wide files.
*/



// File types (canonical, aliases)

type { mode & IFMT }

reg  { type == IFREG }
dir  { type == IFDIR }
blk  { type == IFBLK }
chr  { type == IFCHR }
lnk  { type == IFLNK }
sock { type == IFSOCK }
fifo { type == IFIFO }
door { type == IFDOOR } # Solaris

file      { reg }
directory { dir }
block     { blk }
char      { chr }
device    { blk || chr }
symlink   { lnk }
link      { lnk }
socket    { sock }
namedpipe { fifo }
pipe      { fifo }

f { reg }
d { dir }
b { blk }
c { chr }
l { lnk }
s { sock }
p { fifo }
D { door } # Solaris


// File permissions (canonical, aliases, helpers)

perm { mode & ~IFMT }

ur { perm & IRUSR }
uw { perm & IWUSR }
ux { perm & IXUSR }
gr { perm & IRGRP }
gw { perm & IWGRP }
gx { perm & IXGRP }
or { perm & IROTH }
ow { perm & IWOTH }
ox { perm & IXOTH }
wr { perm & IROTH }
ww { perm & IWOTH }
wx { perm & IXOTH }

user_readable    { ur }
user_writable    { uw }
user_executable  { ux }
group_readable   { gr }
group_writable   { gw }
group_executable { gx }
other_readable   { or }
other_writable   { ow }
other_executable { ox }
world_readable   { wr }
world_writable   { ww }
world_executable { wx }


suid { perm & ISUID }
sgid { perm & ISGID }
svtx { perm & ISVTX }

setuid { suid }
setgid { sgid }
sticky { svtx }


all(bitmask)  { (perm & bitmask) == bitmask }
any(bitmask)  { perm & bitmask }
none(bitmask) { !any(bitmask) }

allr  { all(IRUSR | IRGRP | IROTH) }
allw  { all(IWUSR | IWGRP | IWOTH) }
allx  { all(IXUSR | IXGRP | IXOTH) }
anyr  { any(IRUSR | IRGRP | IROTH) }
anyw  { any(IWUSR | IWGRP | IWOTH) }
anyx  { any(IXUSR | IXGRP | IXOTH) }
noner { !anyr }
nonew { !anyw }
nonex { !anyx }

all_readable    { allr }
all_writable    { allw }
all_executable  { allx }
any_readable    { anyr }
any_writable    { anyw }
any_executable  { anyx }
none_readable   { noner }
none_writable   { nonew }
none_executable { nonex }


// Aliases for built-ins

inode    { ino }
nlinks   { nlink }
user     { uid }
group    { gid }
space    { blocks * 512 }
accessed { atime }
modified { mtime } # Refers to the contents
changed  { ctime } # Refers to the inode
len      { strlen }
sz       { size }

seconds  { second }
minutes  { minute }
hours    { hour }
days     { day }
weeks    { week }
months   { month }
years    { year }
quit     { exit }

imayread  { readable }   # Uses access(2) not perm
imaywrite { writable }   # Uses access(2) not perm
imayexec  { executable } # Uses access(2) not perm

ir { readable }
iw { writable }
ix { executable }


// File types for symlink targets (canonical, aliases)

ttype { tmode & IFMT }

treg  { ttype == IFREG }
tdir  { ttype == IFDIR }
tblk  { ttype == IFBLK }
tchr  { ttype == IFCHR }
tsock { ttype == IFSOCK }
tfifo { ttype == IFIFO }
tdoor { ttype == IFDOOR } # Solaris

tfile      { treg }
tdirectory { tdir }
tblock     { tblk }
tchar      { tchr }
tdevice    { tblk || tchr }
tsocket    { tsock }
tnamedpipe { tfifo }
tpipe      { tfifo }

tf { treg }
td { tdir }
tb { tblk }
tc { tchr }
ts { tsock }
tp { tfifo }
tD { tdoor } # Solaris

target_type { ttype }

target_reg  { treg }
target_dir  { tdir }
target_blk  { tblk }
target_chr  { tchr }
target_sock { tsock }
target_fifo { tfifo }
target_door { tdoor } # Solaris

target_file      { treg }
target_directory { tdir }
target_block     { tblk }
target_char      { tchr }
target_device    { tblk || tchr }
target_socket    { tsock }
target_namedpipe { tfifo }
target_pipe      { tfifo }

target_f { treg }
target_d { tdir }
target_b { tblk }
target_c { tchr }
target_s { tsock }
target_p { tfifo }
target_D { tdoor }


// File permissions for symlink targets (canonical, aliases, helpers)

tperm { tmode & ~IFMT }

tur { tperm & IRUSR }
tuw { tperm & IWUSR }
tux { tperm & IXUSR }
tgr { tperm & IRGRP }
tgw { tperm & IWGRP }
tgx { tperm & IXGRP }
tor { tperm & IROTH }
tow { tperm & IWOTH }
tox { tperm & IXOTH }
twr { tperm & IROTH }
tww { tperm & IWOTH }
twx { tperm & IXOTH }

target_perm { tperm }

target_ur { tur }
target_uw { tuw }
target_ux { tux }
target_gr { tgr }
target_gw { tgw }
target_gx { tgx }
target_or { tor }
target_ow { tow }
target_ox { tox }
target_wr { twr }
target_ww { tww }
target_wx { twx }

target_user_readable    { tur }
target_user_writable    { tuw }
target_user_executable  { tux }
target_group_readable   { tgr }
target_group_writable   { tgw }
target_group_executable { tgx }
target_other_readable   { tor }
target_other_writable   { tow }
target_other_executable { tox }
target_world_readable   { twr }
target_world_writable   { tww }
target_world_executable { twx }


tsuid { tperm & ISUID }
tsgid { tperm & ISGID }
tsvtx { tperm & ISVTX }

tsetuid { tsuid }
tsetgid { tsgid }
tsticky { tsvtx }

target_suid { tsuid }
target_sgid { tsgid }
target_svtx { tsvtx }

target_setuid { tsuid }
target_setgid { tsgid }
target_sticky { tsvtx }


tall(bitmask)  { (tperm & bitmask) == bitmask }
tany(bitmask)  { tperm & bitmask }
tnone(bitmask) { !tany(bitmask) }

tallr  { tall(IRUSR | IRGRP | IROTH) }
tallw  { tall(IWUSR | IWGRP | IWOTH) }
tallx  { tall(IXUSR | IXGRP | IXOTH) }
tanyr  { tany(IRUSR | IRGRP | IROTH) }
tanyw  { tany(IWUSR | IWGRP | IWOTH) }
tanyx  { tany(IXUSR | IXGRP | IXOTH) }
tnoner { !tanyr }
tnonew { !tanyw }
tnonex { !tanyx }

target_all(bitmask)  { tall(bitmask) }
target_any(bitmask)  { tany(bitmask) }
target_none(bitmask) { tnone(bitmask) }

target_allr  { tallr }
target_allw  { tallw }
target_allx  { tallx }
target_anyr  { tanyr }
target_anyw  { tanyw }
target_anyx  { tanyx }
target_noner { tnoner }
target_nonew { tnonew }
target_nonex { tnonex }

target_all_readable    { tallr }
target_all_writable    { tallw }
target_all_executable  { tallx }
target_any_readable    { tanyr }
target_any_writable    { tanyw }
target_any_executable  { tanyx }
target_none_readable   { tnoner }
target_none_writable   { tnonew }
target_none_executable { tnonex }


// Aliases for symlink target built-ins

target_exists  { texists }
target_dev     { tdev }
target_ino     { tino }
target_mode    { tmode }
target_nlink   { tnlink }
target_uid     { tuid }
target_gid     { tgid }
target_rdev    { trdev }
target_size    { tsize }
target_blksize { tblksize }
target_blocks  { tblocks }
target_atime   { tatime }
target_mtime   { tmtime }
target_ctime   { tctime }
target_strlen  { tstrlen }

tinode    { tino }
tnlinks   { tnlink }
tuser     { tuid }
tgroup    { tgid }
tspace    { tblocks * 512 }
taccessed { tatime }
tmodified { tmtime } # Refers to the target's contents
tchanged  { tctime } # Refers to the target's inode
tlen      { tstrlen }
tsz       { tsize }

target_inode    { tinode }
target_nlinks   { tnlinks }
target_user     { tuser }
target_group    { tgroup }
target_space    { tspace }
target_accessed { taccessed }
target_modified { tmodified }
target_changed  { tchanged }
target_len      { tlen }
target_sz       { tsz }


// Aliases for size units

KiB { 1K }
MiB { 1M }
GiB { 1G }
TiB { 1T }
PiB { 1P }
EiB { 1E }

KB { 1k }
MB { 1m }
GB { 1g }
TB { 1t }
PB { 1p }
EB { 1e }


// Miscellaneous helper functions

empty { size == 0 } # Only for files and readable directories
roots { uid == 0 }
mine { uid == $$ }
ours { gid == @@ }
broken { symlink && !texists }
dangling { broken }
gmtoday { now - now % day }

ago(sec)  { now - sec }
old(sec)  { mtime <= ago(sec) }
past(sec) { mtime >= ago(sec) }

min(x, y) { (x < y) ? x : y }
max(x, y) { (x > y) ? x : y }
abs(x)    { (x < 0) ? -x : x }


// Examples

// Complex tests can be very readable (and/or very concise)
// rootshell { setuid && roots && (group_writable | other_writable) }
// rootshell { suid && roots && (gw | ow) }
// csrc { "*.[ch]" || "[Mm]akefile" }
// oldaout { "a.out" && f && old(week) }
// oldcore { "^core(\.\d+)?$".re && f && old(week) }
// bad { oldaout || oldcore || "*.BAK" || "*.CKP" || (gw | ow) }
// Note: Read "<" and ">" as before/after, not as less/more than
// recent { modified >= ago(hour) }

// Silly recursive functions are possible (but not mutual recursion)
// sqrt1(n, odd) { (n <= 0) ? 0 : sqrt1(n - odd, odd + 2) + 1 }
// sqrt(n) { sqrt1(n, 1) }
// prime1(n, i) { (i * i > n) ? 1 : !(n % i) ? 0 : prime1(n, i + 2) }
// prime(n) { (n < 2) ? 0 : !(n % 2) ? n == 2 : prime1(n, 3) }
// factorial(x) { (x > 0) ? x * factorial(x - 1) : 1 }
// ack(x, y) { !x ? y+1 : !y ? ack(x-1, 1) : ack(x-1, ack(x, y-1)) }


