<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/css" href="/css/atom-browser.css" ?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">	<title>Perturb.org - Scott's Geek Blog</title>
	<modified>2026-05-31T07:20:59-07:00</modified>	<link rel="alternate" type="text/html" href="http://www.perturb.org" />	<tagline>Geek blog</tagline>
	<id>tag:www.perturb.org,2026://05</id>
	<generator>Perturb ATOM v0.1</generator>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1455/" />
		<title mode="escaped">Using rsync to keep two directories in sync</title>
		<modified>2026-05-20T11:40:26-07:00</modified>
		<issued>2026-05-20T11:40:26-07:00</issued>
		<created>2026-05-20T11:40:26-07:00</created>
		<id>http://www.perturb.org/display/entry/1455/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

I have two directories with (mostly) the same content that I want to keep in sync. Specifically I want to make sure that the newest version of each file is synced to the other directory. This allows me to update a file on either side, and that version will propagate to the other. You can do this with a bi-directional `rsync` command: <br />
 <br />
```bash <br />
rsync --update -av /dir/a/ /dir/b/ <br />
rsync --update -av /dir/b/ /dir/a/ <br />
``` <br />
 <br />
Using `--update` tells `rsync` to skip files on the receiving side that are newer. If you sync `a` -> `b` and then `b` -> `a` you end up with both locations having the newest copy of each file.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1454/" />
		<title mode="escaped">Perl: ULID generation</title>
		<modified>2026-04-26T18:58:48-07:00</modified>
		<issued>2026-04-26T18:58:48-07:00</issued>
		<created>2026-04-26T18:58:48-07:00</created>
		<id>http://www.perturb.org/display/entry/1454/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

[ULID's](https://github.com/ulid/spec) are an interesting way to generate globally unique identifiers. Here is a quickie Perl implementation to generate ULIDs. This implementation does **not** include the intra-millisecond monotonic increment however. If that feature is important to you consider checking out a more full-featured implementation like [ULID::Tiny](https://github.com/scottchiefbaker/perl-ULID-Tiny). <br />
 <br />
```perl <br />
for (1 .. 5) { <br />
    say(ulid()); <br />
} <br />
``` <br />
 <br />
```perl <br />
sub ulid { <br />
    my $ts    = $_[0] || time() * 1000; <br />
    my $bytes = substr(pack("Q>", $ts), 2, 6); <br />
 <br />
    # Append 10 random bytes <br />
    for (0 .. 9) { $bytes .= chr(int(rand(256))); } <br />
 <br />
    # base32 encoding <br />
    my $bits  = unpack("B*", $bytes); <br />
    my $pad   = (5 - (length($bits) % 5)) % 5; <br />
    $bits    .= '0' x $pad; <br />
 <br />
    # Chars to use for base32 <br />
    my @CROCKFORD_CHARS = split //, '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; <br />
 <br />
    my $result  = ''; <br />
    for (my $i = 0; $i < length($bits); $i += 5) { <br />
        my $chunk = substr($bits, $i, 5); <br />
        my $index = 0; <br />
        for my $bit (split //, $chunk) { <br />
            $index = ($index << 1) | $bit; <br />
        } <br />
 <br />
        $result .= $CROCKFORD_CHARS[$index]; <br />
    } <br />
 <br />
    return $result; <br />
} <br />
``` <br />
 <br />
**See also:** [UUIDv7](https://www.perturb.org/display/1398_Perl_UUIDv7.html)
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1453/" />
		<title mode="escaped">Perl: Using Inline::C to embed C functions in your Perl scripts</title>
		<modified>2026-04-23T14:34:43-07:00</modified>
		<issued>2026-04-23T14:34:43-07:00</issued>
		<created>2026-04-23T14:34:43-07:00</created>
		<id>http://www.perturb.org/display/entry/1453/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

Perl allows "inline" code written in other languages. This is useful because you can have native C functions interact with your Perl code. By placing your C code in the `__DATA__` section of your Perl script you get clean separation between the two languages. <br />
 <br />
**Note:** `Inline::C` does not understand `uint64_t` in function definitions, so anything that interacts with Perl needs to use `UV` instead. Internally C functions can use and interact with `uint64_t` variables just fine. <br />
 <br />
```perl <br />
use strict; <br />
use warnings; <br />
use v5.16; <br />
use Inline 'C'; <br />
 <br />
############################################## <br />
 <br />
seed_splitmix64(time()); <br />
 <br />
for (1 .. 5) { <br />
    say splitmix64(); <br />
} <br />
 <br />
############################################## <br />
 <br />
__DATA__ <br />
__C__ <br />
 <br />
uint64_t x = 123456789; <br />
 <br />
void seed_splitmix64(UV seed) { <br />
    x = seed; <br />
} <br />
 <br />
UV splitmix64() { <br />
    uint64_t z = (x += 0x9e3779b97f4a7c15); <br />
    z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; <br />
    z = (z ^ (z >> 27)) * 0x94d049bb133111eb; <br />
 <br />
    return z ^ (z >> 31); <br />
} <br />
``` <br />
 <br />
This will compile the C code into a shared object in the `_Inline` directory in whichever directory you instantiated your Perl script. Code is only compiled once (and where there are changes), so your script performance will be very high.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1452/" />
		<title mode="escaped">Comparison of markup languages</title>
		<modified>2026-04-09T10:58:41-07:00</modified>
		<issued>2026-04-09T10:58:41-07:00</issued>
		<created>2026-04-09T10:58:41-07:00</created>
		<id>http://www.perturb.org/display/entry/1452/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

I've been investigating [JSON](https://www.json.org/) vs [YAML](https://yaml.org/) vs [TOML](https://toml.io/) for various applications. After testing many variations I ended up writing a [simple tool](https://www.perturb.org/code/serialize_test.php) to compare all three live.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1451/" />
		<title mode="escaped">Linux: SFTP and SCP friendly login banners</title>
		<modified>2026-03-26T14:07:00-07:00</modified>
		<issued>2026-03-26T14:07:00-07:00</issued>
		<created>2026-03-26T14:07:00-07:00</created>
		<id>http://www.perturb.org/display/entry/1451/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

To display a message when a user logs into your server, add the following to `~/.bashrc`: <br />
 <br />
```bash <br />
# If it's an interactive terminal show the banner <br />
if [[ $- == *i* ]]; then <br />
    echo "Welcome to the monitoring server" <br />
    echo "Configuration is stored in /etc/myapp" <br />
fi <br />
``` <br />
 <br />
This runs _only_ for interactive sessions. Non-interactive connections such as SFTP and SCP remain unaffected, which prevents automated processes from breaking. <br />
 <br />
**See also:** The [text_color](https://github.com/scottchiefbaker/text_color) project.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1450/" />
		<title mode="escaped">YAML is growing on me</title>
		<modified>2026-03-25T10:04:29-07:00</modified>
		<issued>2026-03-25T10:04:29-07:00</issued>
		<created>2026-03-25T10:04:29-07:00</created>
		<id>http://www.perturb.org/display/entry/1450/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

The more I learn about YAML, the more I like it. JSON is great as a machine readable format, but it sucks at being human readable. Want to add an element, better make sure you have **all** the commas and curly braces in the **exact** right place or the whole thing will be unusable. YAML on the other hand is designed to be human readable and modifiable. It's a very simple key/value system using indentation to represent layers.  <br />
 <br />
PHP has a [PECL module](https://bd808.com/pecl-file_formats-yaml/) with good YAML support. There are also pure PHP versions if you're unable to install PECL modules. [Symfony](https://github.com/symfony/yaml) provides one, and so does [Spyc](https://github.com/mustangostang/spyc). I prefer the latter because it's a single file and very easy to install. <br />
 <br />
On the Perl side there is [YAML::XS](https://metacpan.org/pod/YAML::XS), [YAML::PP](https://metacpan.org/pod/YAML::PP), and [many](https://metacpan.org/search?size=20&q=yaml) others.  <br />
 <br />
Parsing YAML is very easy in just about every language I can find. If you have a complex data structure that you need humans to interact with use YAML please. <br />
 <br />
Here is a [great breakdown](https://jsonlint.com/json-vs-yaml) of when to use YAML vs JSON: <br />
 <br />
| Use Case             | Recommended | Why                               | <br />
| -------------------- | ----------- | --------------------------------- | <br />
| API request/response | JSON        | Universal support, strict parsing | <br />
| Configuration files  | YAML        | Comments, readability             | <br />
| Browser/JavaScript   | JSON        | Native parsing                    | <br />
| Kubernetes/Docker    | YAML        | Industry standard                 | <br />
| Data interchange     | JSON        | Unambiguous, fast                 | <br />
| Human-edited files   | YAML        | Less punctuation                  | <br />
 <br />
[YAML spec](https://perlpunk.github.io/yaml-test-schema/schemas.html) differences.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1449/" />
		<title mode="escaped">C: Fill an array of unsigned integers with random data using getentropy()</title>
		<modified>2026-01-11T12:32:42-08:00</modified>
		<issued>2026-01-11T12:32:42-08:00</issued>
		<created>2026-01-11T12:32:42-08:00</created>
		<id>http://www.perturb.org/display/entry/1449/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

Often I need to generate random unsigned integers for seeding PRNGs. The best way is using the `getentropy()` system function to read OS level randomness into your array. <br />
 <br />
```c <br />
#include <sys/random.h> <br />
 <br />
// Read from system random to fill up data structure <br />
int8_t fill_urandom(void *buf, size_t bytes) { <br />
    int8_t ok = getentropy(buf, bytes); <br />
 <br />
    return (ok == 0); <br />
} <br />
``` <br />
 <br />
Declare your array of integers, and then pass it as a pointer to this function to fill with random bytes from your OS. This will get you a bunch of random integers you can use for seeding PRNGs. <br />
 <br />
```c <br />
uint64_t seed[4]; <br />
fill_urandom(seed, sizeof(seed)); <br />
```
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1448/" />
		<title mode="escaped">Books of 2026</title>
		<modified>2026-01-01T10:50:29-08:00</modified>
		<issued>2026-01-01T10:50:29-08:00</issued>
		<created>2026-01-01T10:50:29-08:00</created>
		<id>http://www.perturb.org/display/entry/1448/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

List of books I read in 2026. Also see the list of [2025](/display/1412_Books_of_2025.html). The date indicated denotes the date I started reading the book. <br />
 <br />
2026-01-01 - [White Fang](//www.google.com/search?tbo=p&q=isbn+9781453080054) by Jack London - 180 pages   <br />
2026-01-03 - [Hollow Man](//www.google.com/search?tbo=p&q=isbn+9781409146322) by John Dickson Carr - 213 pages   <br />
2026-01-06 - [The Three-body Problem](//www.google.com/search?tbo=p&q=isbn+9780765382030) by Cixin Liu - 400 pages   <br />
2026-01-12 - [Star Wars: Revelation](//www.google.com/search?tbo=p&q=isbn+9780345477576) by Karen Traviss - 410 pages   <br />
2026-01-19 - [Pale Blue Dot](//www.google.com/search?tbo=p&q=isbn+9780345376596) by Carl Sagan - 342 pages   <br />
2026-01-25 - [Dungeon Crawler Carl](//www.google.com/search?tbo=p&q=isbn+9780593820254) by Matt Dinniman - 450 pages   <br />
2026-02-01 - [Project Hail Mary](//www.google.com/search?tbo=p&q=isbn+9780593135228) by Andy Weir - 478 pages   <br />
2026-02-09 - [The Dark Forest](//www.google.com/search?tbo=p&q=isbn+9780765386694) by Cixin Liu - 512 pages   <br />
2026-02-18 - [The Hike](//www.google.com/search?tbo=p&q=isbn+9780399563874) by Drew Magary - 278 pages   <br />
2026-02-22 - [Fletch](//www.google.com/search?tbo=p&q=isbn+9781538541920) by Gregory Mcdonald - 249 pages   <br />
2026-02-26 - [Zen And The Art Of Motorcycle Maintenance](//www.google.com/search?tbo=p&q=isbn+9780060589462) by Robert M. Pirsig - 540 pages   <br />
2026-03-06 - [Aliens: The Female War](//www.google.com/search?tbo=p&q=isbn+9781783299010) by Steve Perry - 258 pages   <br />
2026-03-11 - [The Crystal Cave](//www.google.com/search?tbo=p&q=isbn+9780060548254) by Mary Stewart - 522 pages   <br />
2026-03-20 - [Nexus](//www.google.com/search?tbo=p&q=isbn+9780593734223) by Yuval Noah Harari - 420 pages   <br />
2026-03-26 - [Star Wars: Onslaught](//www.google.com/search?tbo=p&q=isbn+0345428544) by Michael A. Stackpole - 292 pages   <br />
2026-03-31 - [Death's End](//www.google.com/search?tbo=p&q=isbn+9780765386632) by Cixin Liu - 590 pages   <br />
2026-04-09 - [The Call Of The Wild](//www.google.com/search?tbo=p&q=isbn+9780141321059) by Jack London - 160 pages   <br />
2026-04-11 - [Dragons Of Autumn Twilight](//www.google.com/search?tbo=p&q=isbn+9780786915743) by Margaret Weis - 444 pages   <br />
2026-04-19 - [Wayne Of Gotham](//www.google.com/search?tbo=p&q=isbn+9780062074201) by Tracy Hickman - 296 pages   <br />
2026-04-23 - [Unwept](//www.google.com/search?tbo=p&q=isbn+9780765332035) by Tracy Hickman - 268 pages   <br />
2026-04-27 - [Star Wars: Ruin](//www.google.com/search?tbo=p&q=isbn+0345428560) by Michael A. Stackpole - 292 pages   <br />
2026-05-10 - [Invisible](//www.google.com/search?tbo=p&q=isbn+9780316405348) by James Patterson - 401 pages   <br />
2026-05-18 - [Blood Meridian](//www.google.com/search?tbo=p&q=isbn+9780679728757) by Cormac McCarthy - 349 pages   <br />
2026-05-22 - [Star Wars: Invincible](//www.google.com/search?tbo=p&q=isbn+9780345477477) by Troy Denning - 347 pages   <br />
2026-05-28 - [Atlantis Found](//www.google.com/search?tbo=p&q=isbn+0425177173) by Clive Cussler - 532 pages   <br />
 <br />
### Inheritance Cycle <br />
2026-05-02 - [Eragon](//www.google.com/search?tbo=p&q=isbn+9780375826696) by Christopher Paolini - 503 pages   <br />
2026-xx-xx - [Eldest](//www.google.com/search?tbo=p&q=isbn+9780375840401) by Christopher Paolini - 679 pages   <br />
2026-xx-xx - [Brisingr](//www.google.com/search?tbo=p&q=isbn+9780375826740) by Christopher Paolini - 763 pages   <br />
2026-xx-xx - [Inheritance](//www.google.com/search?tbo=p&q=isbn+9780375846311) by Christopher Paolini - 849 pages   <br />
 <br />
2026-xx-xx - [Dragons Of A Fallen Sun](//www.google.com/search?tbo=p&q=isbn+0786918071) by Margaret Weis - 627 pages   <br />
2026-xx-xx - [Dragons Of A Lost Star](//www.google.com/search?tbo=p&q=isbn+0786927062) by Margaret Weis - 550 pages   <br />
2026-xx-xx - [Dragons Of A Vanished Moon](//www.google.com/search?tbo=p&q=isbn+0786929502) by Margaret Weis - 629 pages   <br />
2026-xx-xx - [The Hunt For Red October](//www.google.com/search?tbo=p&q=isbn+0425133516) by Tom Clancy - 469 pages
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1447/" />
		<title mode="escaped">How far does Gandalf fall when fighting the Balrog in Khazad Dum?</title>
		<modified>2025-12-24T21:16:09-08:00</modified>
		<issued>2025-12-24T21:16:09-08:00</issued>
		<created>2025-12-24T21:16:09-08:00</created>
		<id>http://www.perturb.org/display/entry/1447/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

In the extended edition of Fellowship of the Ring Gandalf fights the Balrog and then falls for about 70 seconds. <br />
 <br />
It takes about 12 seconds to reach terminal velocity: 0.5 \* g \* t^2 = 0.5 \* 9.81 \* 12^2 ~ 706m <br />
 <br />
The remaining 58 seconds Gandalf is at terminal velocity (not speeding up) of 53m/s which is v \* t = 53 \* 58 ~ 3074m. For a total of 3780 meters, or about 2.35 miles. <br />
 <br />
Pretty impressive free-fall considering they were ALREADY under ground.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1446/" />
		<title mode="escaped">Perl: biski64 and sfc64 PRNG</title>
		<modified>2025-12-23T10:08:47-08:00</modified>
		<issued>2025-12-23T10:08:47-08:00</issued>
		<created>2025-12-23T10:08:47-08:00</created>
		<id>http://www.perturb.org/display/entry/1446/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

[Biski64](https://github.com/danielcota/biski64) is a new PRNG there is extremely fast and also very simple. This one was pretty simple so I ported it to Perl in [biski64.pl](https://www.perturb.org/code/syntax_highlight.php?file=biski64.pl). <br />
 <br />
SFC64 is also largely considered on of the better PRNGs so I ported it also in [sfc64.pl](https://www.perturb.org/code/syntax_highlight.php?file=sfc64.pl).
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1445/" />
		<title mode="escaped">PRNG: PCG64 in Perl</title>
		<modified>2025-12-12T18:33:07-08:00</modified>
		<issued>2025-12-12T18:33:07-08:00</issued>
		<created>2025-12-12T18:33:07-08:00</created>
		<id>http://www.perturb.org/display/entry/1445/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

I found a [PCG64 implementation](https://github.com/alvoskov/SmokeRand/blob/main/generators/pcg64_64.c) that I was able to borrow and convert to pure Perl: <br />
 <br />
```perl <br />
# PCG64 RXS-M-XS "simple" variant <br />
#my $seeds = [12, 34]; <br />
#my $rand  = pcg64_perl($seeds); <br />
sub pcg64_perl { <br />
    my $seeds = $_[0]; <br />
    my $ret   = (($seeds->[0] >> (($seeds->[0] >> 59) + 5)) ^ $seeds->[0]); <br />
 <br />
    use integer; <br />
    $ret *= 12605985483714917081; <br />
    $seeds->[0] = $seeds->[0] * 6364136223846793005 + $seeds->[1]; <br />
    no integer; <br />
 <br />
    $ret = ($ret >> 43) ^ $ret; <br />
 <br />
    return $ret; <br />
} <br />
``` <br />
 <br />
**Update:** Bonus points because it's [really fast](https://www.perturb.org/code/prng-bench.pl): <br />
 <br />
```text <br />
*               Rate xosh256**  biski64     sfc64     PCG32 Splitmix64     PCG64 <br />
xosh256**  1589825/s        --     -26%      -48%      -52%       -58%      -65% <br />
biski64    2145923/s       35%       --      -30%      -35%       -43%      -53% <br />
sfc64      3058104/s       92%      43%        --       -8%       -19%      -33% <br />
PCG32      3311258/s      108%      54%        8%        --       -13%      -28% <br />
Splitmix64 3787879/s      138%      77%       24%       14%         --      -17% <br />
PCG64      4587156/s      189%     114%       50%       39%        21%        -- <br />
```
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1444/" />
		<title mode="escaped">PHP: Serve large audio/video files outside of the webroot</title>
		<modified>2025-12-02T11:57:04-08:00</modified>
		<issued>2025-12-02T11:57:04-08:00</issued>
		<created>2025-12-02T11:57:04-08:00</created>
		<id>http://www.perturb.org/display/entry/1444/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

I have some large audio files that I need to serve via HTTPs. They need to be protected by my PHP login system so they cannot live *inside* of the webroot. Fortunately there is a nifty Apache module named [X-sendfile](https://github.com/nmaier/mod_xsendfile), that lets you serve files outside of the webroot. <br />
 <br />
Credential checking is done in PHP, and then you set a special HTTP header that Apache watches for. When Apaches sees the `X-Sendfile` header it serves the file directly. This gets you all the advantages of a full-blown HTTP server handling your files, but the convenience and simplicity of PHP for handling authentication. <br />
 <br />
```php <br />
if ($authorized) { <br />
    $mime_type = mime_from_filename($filepath); <br />
 <br />
    header("Content-Type: $mime_type"); <br />
    header("X-Sendfile: $filepath"); <br />
    exit; <br />
} <br />
``` <br />
 <br />
**See also:** [Get mime type for file](https://www.perturb.org/display/1443_PHP_Get_the_mime_type_for_a_file.html)
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1443/" />
		<title mode="escaped">PHP: Get the mime type for a file</title>
		<modified>2025-12-01T19:48:54-08:00</modified>
		<issued>2025-12-01T19:48:54-08:00</issued>
		<created>2025-12-01T19:48:54-08:00</created>
		<id>http://www.perturb.org/display/entry/1443/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

If you need to get the mime type for a file in PHP you can use this function which wrappers the `finfo_open()` function. <br />
 <br />
```php <br />
function mime_from_filename($filename) { <br />
    $finfo = finfo_open(FILEINFO_MIME_TYPE); <br />
    $mime  = finfo_file($finfo, $filename); <br />
    finfo_close($finfo); <br />
 <br />
    return $mine; <br />
} <br />
``` <br />
 <br />
**Note:** This function requires the file to exist on the disk.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1442/" />
		<title mode="escaped">Perl: Get terminal width</title>
		<modified>2025-11-19T14:41:22-08:00</modified>
		<issued>2025-11-19T14:41:22-08:00</issued>
		<created>2025-11-19T14:41:22-08:00</created>
		<id>http://www.perturb.org/display/entry/1442/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

If you need a fast and simple way to get the terminal width in Perl core use `Term::ReadKey`. This is almost certainly faster and better than shelling out to `tput cols`. <br />
 <br />
```perl <br />
sub get_terminal_width { <br />
    my @x      = Term::ReadKey::GetTerminalSize(); <br />
    my $width  = $x[0] || 0; <br />
 <br />
    return $width; <br />
} <br />
```
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1441/" />
		<title mode="escaped">NIST Password Recommedations for 2025</title>
		<modified>2025-11-04T14:44:15-08:00</modified>
		<issued>2025-11-04T14:44:15-08:00</issued>
		<created>2025-11-04T14:44:15-08:00</created>
		<id>http://www.perturb.org/display/entry/1441/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

Current NIST [Password Requirements](https://pages.nist.gov/800-63-4/sp800-63b.html) for 2025 (SP800-63b). <br />
 <br />
What’s gone: <br />
 <br />
❌ Required uppercase, numbers, and symbols   <br />
❌ Mandatory password resets every 90 days   <br />
❌ Arbitrary complexity policies   <br />
 <br />
What’s required now: <br />
 <br />
✅ Minimum 8-character passwords (15+ for privileged accounts)   <br />
✅ Password screening against compromised credential databases   <br />
✅ Support for passwordless authentication and passkeys <br />
 <br />
> Minimum Password Length Requirements <br />
> <br />
> Password length serves as the cornerstone of NIST's updated authentication framework. While the baseline requirement mandates a minimum of 8 characters, security research reveals that passwords under 8 characters can be cracked within hours using modern computing power. <br />
 <br />
StrongDM has a good [summary](https://www.strongdm.com/blog/nist-password-guidelines).
]]>
		</content>
	</entry>
</feed>
