Christos Margiolis: plan9 Christos Margiolis http://margiolis.net/tags/plan9/ Git on 9front http://margiolis.net/w/git9/ Sun, 13 Mar 2022 00:00:00 +1200 <p>This article is also mirrored on the <a href="http://wiki.9front.org/git9">9front Wiki</a>.</p> <h2 id="resources">Resources</h2> <ul> <li><a href="http://man.9front.org/1/git">9front git man page</a></li> <li><a href="https://orib.dev/git9.html">Ori&rsquo;s article on Git9</a></li> </ul> <h2 id="user-configuration">User configuration</h2> <pre tabindex="0"><code>; mkdir $home/lib/git ; cat &gt; $home/lib/git/config [user] name=Your Name email=me@example.org ^D </code></pre><h2 id="examples">Examples</h2> <p>Create, commit and push a repo:</p> <pre tabindex="0"><code>; cd repo ; git/init # add a remote in .git/config... ; git/add . ; git/commit -m &#39;commitmsg&#39; foo.c heads/front: 817a3f121083091291c45f1ddfcd1b042343efab ; git/push </code></pre><p>Clone and push changes to a repo:</p> <pre tabindex="0"><code>; git/clone git://git.example.org/repo ; cd repo # make changes... ; git/commit foo.c ; git/push </code></pre><p>Make a patch:</p> <pre tabindex="0"><code># make changes... ; git/commit -m &#39;commitmsg&#39; foo.c heads/front: 817a3f121083091291c45f1ddfcd1b042343efab ; git/export &gt; patch.diff </code></pre><p>Apply a patch:</p> <pre tabindex="0"><code>; git/import &lt; patch.diff applying commitmsg </code></pre><p>See which files have changed:</p> <pre tabindex="0"><code>; git/diff -s M foo.c M bar.c </code></pre><h2 id="shithub-usage">Shithub usage</h2> <p>First ask Ori (ori AT eigenstate DOT org) for a user.</p> <p>Create and push a repository:</p> <pre tabindex="0"><code>; rcpu -u $user -h shithub.us -c \ newrepo -d &#39;description&#39; -c &#39;me@example.org&#39; reponame ; git/push -u hjgit://shithub.us/$user/reponame </code></pre><p>Repositories live under <code>/usr/git/$user</code>. Each repo contains editable files in <code>/usr/git/$user/repo/.git</code>:</p> <dl> <dt><code>webpublish</code></dt> <dd>If this file exists, then the repository is published in the public web list of repositories.</dd> <dt><code>desc, description</code></dt> <dd>The short description of the repository. It shows up in the repo list.</dd> <dt><code>contact</code></dt> <dd>Contact information for submitting patches. Shows up on the repository info page.</dd> </dl> 9front CPU server setup http://margiolis.net/w/9front_cpu/ Mon, 07 Mar 2022 00:00:00 +1200 <p>The contents of <code>/net/ndb</code> will be useful throughout the whole process; have them visible in another window:</p> <pre tabindex="0"><code>; ip/ipconfig ; cat /net/ndb ip=192.168.1.152 ipmask=255.255.255.0 ipgw=192.168.1.3 sys=cirno dns=192.168.1.1 dns=192.168.1.1 </code></pre><h2 id="boot-settings">Boot settings</h2> <p>The <code>9fat</code> partition contains the kernel, bootloader and boot settings. Add the following lines to <code>plan9.ini</code>. Make sure the values match your own configuration:</p> <pre tabindex="0"><code>; 9fs 9fat ; cd /n/9fat ; cat &gt;&gt; plan9.ini user=glenda cpu=192.168.1.152 auth=192.168.1.152 authdom=someauth service=cpu ^D </code></pre><p><code>user</code> is kinda like the root user on UNIX systems, <code>cpu</code> and <code>auth</code> define the IP addresses for the CPU and auth server respectively, <code>authdom</code> is the domain name of our the server, and <code>service=cpu</code> starts the CPU listener at boot time.</p> <p>9front needs to boot hands-free, so the <code>bootargs</code> prompt has to be skipped. To do that, change the <code>bootargs</code> variable (its values might be different) in <code>plan9.ini</code>:</p> <pre tabindex="0"><code>bootargs=local!/dev/sdE0/fs # change to... noobootprompt=local!/dev/sdE0/fs -m 291 -A -a tcp!*!564 </code></pre><h2 id="auth-server">Auth server</h2> <p>Set up the auth server hostowner&rsquo;s name and password; <code>authid</code> and <code>authdom</code> have to match the values in <code>plan9.ini</code>:</p> <pre tabindex="0"><code>; auth/wrkey bad nvram des key bad authentication id bad authentication domain authid: glenda authdom: someauth secstore key: password: &lt;your_pass&gt; </code></pre><p>Add <code>glenda</code>&rsquo;s password. This <em>has</em> to be the same as the one you typed in <code>wrkey(8)</code>. Always run <code>keyfs(4)</code> before modifying keys:</p> <pre tabindex="0"><code>; auth/keyfs ; auth/changeuser glenda Password: &lt;your_pass&gt; Confirm password: &lt;your_pass&gt; assign new Inferno/POP secret? [y/n]: y make it the same as Plan 9 password? [y/n]: y Expiration date (YYYYMMDD or never)[never]: Post id: User&#39;s full name: Department #: User&#39;s email address: user glenda installed for Plan 9 ; auth/enable glenda </code></pre><h2 id="network-database">Network database</h2> <p>Add the following lines to <code>/lib/ndb/local</code> (pay close attention to detail, especially <code>ip=</code>):</p> <pre tabindex="0"><code>; cat &gt;&gt; /lib/ndb/local authdom=someauth auth=192.168.1.152 ipnet=iphome ip=192.168.1.0 ipmask=255.255.255.0 ipgw=192.168.1.3 auth=192.168.1.152 authdom=someauth fs=192.168.1.152 cpu=192.168.1.152 dns=192.168.1.1 ^D </code></pre><p><code>ipnet</code> can be anything.</p> <p>Sync the changes and reboot the system:</p> <pre tabindex="0"><code>; echo sync &gt;&gt; /srv/hjfs.cmd ; fshalt -r </code></pre><h2 id="on-reboot">On reboot</h2> <p>Enable networking:</p> <pre tabindex="0"><code>; bind -a &#39;#l0&#39; /net ; ip/ipconfig ; ip/ipconfig ether /net/ether0 </code></pre><p>Drawterm as <code>glenda</code>:</p> <pre tabindex="0"><code>$ drawterm -u glenda cpu[cpu]: 192.168.1.152 auth[192.168.1.152]: glenda@someauth dp9ik password: &lt;your_pass&gt; </code></pre><p>Start a <code>rio(1)</code> instance:</p> <pre tabindex="0"><code>cpu% rio -s -i riostart </code></pre><p><code>/cfg/$sysname/cpustart</code> contains commands that run on boot. You can put whatever you want in it &mdash; I&rsquo;m going to just add the same commands I ran after we rebooted to make my life easier.</p> <pre tabindex="0"><code>; mkdir /cfg/$sysname ; cat &gt; /cfg/$sysname/cpustart bind -a &#39;#l0&#39; /net ip/ipconfig ip/ipconfig ether /net/ether0 cat /net/ndb ^D </code></pre><h2 id="new-user">New user</h2> <p>Add the new user to the file server, add it to some standard groups and assign it a password:</p> <pre tabindex="0"><code>; echo newuser christos &gt;&gt; /srv/hjfs.cmd ; echo newuser sys +christos &gt;&gt; /srv/hjfs.cmd ; echo newuser adm +christos &gt;&gt; /srv/hjfs.cmd ; echo newuser upas +christos &gt;&gt; /srv/hjfs.cmd ; echo newuser cron +christos &gt;&gt; /srv/hjfs.cmd ; auth/keyfs ; auth/changeuser christos ... ; auth/enable christos </code></pre><p>Let the new user &ldquo;speak for&rdquo; for other users by adding the following lines to <code>/lib/ndb/auth</code>:</p> <pre tabindex="0"><code>; cat &gt;&gt; /lib/ndb/auth hostid=christos uid=!sys uid=!adm uid=* ^D </code></pre><p>Reboot for the changes to take effect:</p> <pre tabindex="0"><code>; fshalt -r </code></pre><p>Drawterm as <code>christos</code> and run <code>newuser(8)</code> to set up his home directory:</p> <pre tabindex="0"><code>$ drawterm -u christos ... ; /sys/lib/newuser </code></pre> Acme editor notes http://margiolis.net/w/acme_notes/ Sun, 06 Mar 2022 00:00:00 +1200 <p><img src="http://margiolis.net/files/acme.jpg" alt=""></p> <h2 id="resources">Resources</h2> <ul> <li><a href="https://acme.cat-v.org/">The Acme User Interface for Programmers</a></li> <li><a href="https://www.youtube.com/watch?v=dP1xVpMPn8M">A Tour of the Acme Editor</a> - Watch this if you&rsquo;re completely new.</li> <li><a href="https://www.youtube.com/watch?v=dopu3ZtdCsg">Plan9 Acme Intro - Part 1</a></li> <li><a href="https://benghancock.github.io/blog/2022/tao-of-acme.html">The Tao of Acme</a></li> <li><a href="https://mostlymaths.net/2013/03/extensibility-programming-acme-text-editor.html/">Extensibility in the Acme text editor</a></li> </ul> <h2 id="mouse">Mouse</h2> <p>Acme needs a 3-button mouse to work properly. All buttons can be used to select text, but their function is different upon release. The left button is used for just selecting text. The middle button is used for executing text. The right button is for searching text and loading files or directories. Text doesn&rsquo;t have to first be selected when using button 2 and 3 (middle and right) if the selection is only one word.</p> <p>Acme also makes use of mouse chording (e.g pressing more than one button).</p> <table border="solid"> <tr> <td>Button 1-2</td> <td>Cut.</td> </tr> <tr> <td>Button 1-3</td> <td>Paste.</td> </tr> <tr> <td>Select text + Button 2-1</td> <td>Execute with selection as argument.</td> </tr> </table> <h2 id="move-around">Move around</h2> <table border="solid"> <tr> <td><code>:2</code></td> <td>Go to 2nd line.</td> </tr> <tr> <td><code>:0</code></td> <td>Go to beginning of file.</td> </tr> <tr> <td><code>:$</code></td> <td>Go to end of file.</td> </tr> <tr> <td><code>CTRL-A</code></td> <td>Go to beginning of line.</td> </tr> <tr> <td><code>CTRL-E</code></td> <td>Go to end of line.</td> </tr> <tr> <td><code>CTRL-F</code></td> <td>Filepath autocompletion.</td> </tr> <tr> <td><code>Edit =</code></td> <td>Find current line number.</td> </tr> </table> <h2 id="search-and-select">Search and select</h2> <table border="solid"> <tr> <td><code>:,</code> <br> <code>Edit ,</code></td> <td>Select all lines.</td> </tr> <tr> <td><code>:1,5</code> <br> <code>Edit 1,5</code></td> <td>Select lines 1 to 5.</td> </tr> <tr> <td><code>:/regexp/</code></td> <td>Select lines matching regexp.</td> </tr> <tr> <td><code>:/regexp1/,/regexp2/</code></td> <td>Select lines between regexp1 and regexp2.</td> </tr> <tr> <td> <code>Edit +/foo</code><br> <code>:/foo</code><br> <code>:foo</code><br> Right click on word. </td> <td>Forward search.</td> </tr> <tr> <td> <code>Edit -/foo</code><br> <code>:-/foo</code><br> <code>:-foo</code><br> </td> <td>Backward search.</td> </tr> </table> <h2 id="edit-text">Edit text</h2> <table border="solid"> <tr> <td><code>CTRL-U</code></td> <td>Delete from cursor to beginning of line.</td> </tr> <tr> <td><code>CTRL-W</code></td> <td>Delete before cursor.</td> </tr> <tr> <td><code>CTRL-H</code></td> <td>Delete character before cursor.</td> </tr> <tr> <td><code>Edit , d</code></td> <td>Clear window.</td> </tr> <tr> <td> <code>Edit , s/foo/bar/g</code><br> <code>Edit , | sed 's/foo/bar/g' </td> <td>Global replace.</td> </tr> <tr> <td><code>Edit s/foo/bar/g</code></td> <td>Replace in selection.</td> </tr> <tr> <td><code>Edit 2 d</code></td> <td>Delete 2nd line.</td> </tr> <tr> <td><code>Edit 2 c/foo</code></td> <td>Change 2nd line.</td> </tr> <tr> <td><code>Edit 2 a/foo</code></td> <td>Append after 2nd line.</td> </tr> <tr> <td><code>Edit 2 i/foo</code></td> <td>Insert before 2nd line.</td> </tr> </table> <h2 id="work-with-external-commands">Work with external commands</h2> <table border="solid"> <tr> <td><code>cmd</code></td> <td>Run cmd with the file as argument.</td> </tr> <tr> <td><code>|cmd</code></td> <td>Pipe selection through cmd and also apply changes.</td> </tr> <tr> <td><code>&gt;cmd</code></td> <td>Send selection to cmd and see result in a temporary window.</td> </tr> <tr> <td><code>&lt;cmd</code></td> <td>Paste output of cmd in current window (no selection required).</td> </tr> </table> <p>Any command can be used, these are just a few examples.</p> <table border="solid"> <tr> <td><code>Edit , &lt; echo foo</code></td> <td>Replace window body with some text (works with any command).</td> </tr> <tr> <td><code>echo foo | 9p write acme/$winid/body</code></td> <td>Append to end of current window body.</td> </tr> <tr> <td><code>Edit , &gt; wc -l</code></td> <td>Count lines.</td> </tr> <tr> <td><code>Edit , | sort</code></td> <td>Sort lines.</td> </tr> <tr> <td><code>Edit ,x/regexp/ &lt; date</code></td> <td>Replace regexp with the output of date(1).</td> </tr> <tr> <td>Select text + <code>| sed '' &gt; foo.txt</code></td> <td>Cut to foo.txt.</td> </tr> <tr> <td>Select text + <code>&gt; sed '' &gt; foo.txt</code></td> <td>Copy to foo.txt.</td> </tr> </table> <h2 id="files">Files</h2> <p>As mentioned earlier, files are opened using the right mouse click.</p> <table border="solid"> <tr> <td><code>foo.c</code></td> <td>Open file.</td> </tr> <tr> <td><code>foo.c:3</code></td> <td>Open file to line 3.</td> </tr> <tr> <td><code>foo.c:3:9</code></td> <td>Open file to line 3 column 9.</td> </tr> <tr> <td><code>foo.c:/^func</code></td> <td>Open file to the line starting with "func".</td> </tr> <tr> <td><code>foo.c:/bar/,/baz/</code></td> <td>Open file with a selection from "bar" to "baz".</td> </tr> </table> <h2 id="useful-acme-commands">Useful Acme commands</h2> <table border="solid"> <tr> <td><code>win</code></td> <td>Spawn shell as a window.</td> </tr> <tr> <td><code>web URL</code></td> <td>Open URL in browser.</td> </tr> <tr> <td><code>Dump</code></td> <td>Save current state.</td> </tr> <tr> <td><code>Load</code></td> <td>Load dump.</td> </tr> <tr> <td><code>Tab 8</code></td> <td>Set tab width to 8.</td> </tr> </table> <h2 id="variables">Variables</h2> <table border="solid"> <tr> <td><code>$%</code><br><code>$samfile</code></td> <td>Current file name.</td> </tr> <tr> <td><code>$winid</code></td> <td>Current window.</td> </tr> </table> 9front using bhyve(8) on FreeBSD http://margiolis.net/w/9front_bhyve/ Tue, 23 Nov 2021 00:00:00 +1200 <p>This article is also mirrored on the <a href="https://wiki.freebsd.org/bhyve/9front">FreeBSD Wiki</a>. and <a href="http://wiki.9front.org/freebsd-bhyve">9front Wiki</a>.</p> <p>Required ports:</p> <pre tabindex="0"><code>sysutils/bhyve-firmware sysutils/uefi-edk2-bhyve sysutils/uefi-edk2-bhyve-csm net/tigervnc-viewer </code></pre><p>Add the following lines to <code>/etc/rc.conf</code>. Replace <code>re0</code> with your own network interface. It&rsquo;s good practice to assign each VM a unique <code>tap</code> interface in case you need to run multiple VMs at the same time. For simplicity&rsquo;s sake, this setup uses only one <code>tap</code>:</p> <pre tabindex="0"><code>if_bridge_load=&#34;YES&#34; if_tap_load=&#34;YES&#34; cloned_interfaces=&#34;bridge0 tap0&#34; ifconfig_bridge0=&#34;DHCP addm re0 addm tap0&#34; ifconfig_bridge0_alias0=&#34;inet 10.0.0.1/24&#34; </code></pre><p>Reboot your machine and then grab a <a href="http://9front.org/releases/">9front ISO</a>.</p> <p>Make a directory where you&rsquo;ll store everything 9front-related. I usually keep all my <a href="https://www.freebsd.org/cgi/man.cgi?query=bhyve&amp;sektion=8">bhyve(8)</a> VMs under a <a href="https://docs.freebsd.org/en/books/handbook/zfs/">ZFS dataset</a>:</p> <pre tabindex="0"><code>$ cd /path/to/vms/ $ mkdir 9front $ mv /path/to/9front_iso 9front.iso </code></pre><p>Create an empty file to be used as the VM&rsquo;s hard drive. 10G will be more than enough:</p> <pre tabindex="0"><code>$ truncate -s 10G disk.img </code></pre><p>Make a startup script. Feel free to tweak the variable values to match your own setup. Obviously, when you&rsquo;re done installing 9front from the ISO, you&rsquo;ll be running the script without the <code>-s 3,...</code> line:</p> <pre tabindex="0"><code>$ cat 9front_start #!/bin/sh name=&#34;9front&#34; cpu=&#34;2&#34; mem=&#34;2G&#34; iso=&#34;9front.iso&#34; disk=&#34;disk.img&#34; tap=&#34;tap0&#34; ifconfig ${tap} up bhyve -c ${cpu} -m ${mem} -wH \ -s 0,hostbridge \ -s 3,ahci-cd,${iso} \ -s 4,ahci-hd,${disk} \ -s 5,virtio-net,${tap} \ -s 29,fbuf,tcp=0.0.0.0:5900,w=800,h=600,wait \ -s 30,xhci,tablet \ -s 31,lpc \ -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \ ${name} </code></pre><p>Make a shutdown script in order for bhyve(8) to shutdown properly:</p> <pre tabindex="0"><code>$ cat 9front_stop #!/bin/sh name=&#34;9front&#34; tap=&#34;tap0&#34; ifconfig ${tap} down bhyvectl --force-poweroff --vm=${name} bhyvectl --destroy --vm=${name} </code></pre><p>Make the scripts executable and start the VM:</p> <pre tabindex="0"><code>$ chmod +x 9front_start 9front_stop # ./9front_start; ./9front_stop </code></pre><p>Run vncviewer(1) to connect to the VNC display:</p> <pre tabindex="0"><code>$ vncviewer 0.0.0.0 </code></pre><p>When prompted for the monitor type during boot, choose <code>xga</code>.</p>