<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.panglossian.net/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Stuart</id>
	<title>The Dreaming - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.panglossian.net/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Stuart"/>
	<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/w/Special:Contributions/Stuart"/>
	<updated>2026-07-07T20:41:48Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=456</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=456"/>
		<updated>2025-10-30T17:01:25Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added holiday 2026 link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== Marvel Puzzle Quest ==&lt;br /&gt;
* Strange Sights: Doom -&amp;gt; Maggia -&amp;gt; Hand&lt;br /&gt;
** Because there are more movers to the left of the above, and they get harder day after day. &lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
This space intentionally left blank.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[Holiday/2026]]&lt;br /&gt;
* [[User:Stuart/Honeymoon]]&lt;br /&gt;
* [[User:Stuart/Dad]]&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* [[Game Board/Print And Play]]&lt;br /&gt;
* [[User:Stuart/Meal Planning|&#039;&#039;Meal Planning&#039;&#039;]]&lt;br /&gt;
** [[User:Stuart/Meal Planning/2022-11-14|14/11/2022]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Liz&amp;diff=455</id>
		<title>User:Liz</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Liz&amp;diff=455"/>
		<updated>2025-09-28T16:30:46Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added Holiday Link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[Holiday/2026]]&lt;br /&gt;
&lt;br /&gt;
Bit of a cheat sheet:&lt;br /&gt;
&lt;br /&gt;
= Heading One =&lt;br /&gt;
&lt;br /&gt;
== Heading Two ==&lt;br /&gt;
&lt;br /&gt;
=== Heading Three ===&lt;br /&gt;
(etc)&lt;br /&gt;
&lt;br /&gt;
See? &#039;&#039;Now&#039;&#039; - &#039;&#039;&#039;it&#039;&#039;&#039; exists.&lt;br /&gt;
* And&lt;br /&gt;
* this&lt;br /&gt;
* is bullets&lt;br /&gt;
&lt;br /&gt;
# And&lt;br /&gt;
# this&lt;br /&gt;
# is a numbered list&lt;br /&gt;
&lt;br /&gt;
 And this is&lt;br /&gt;
 preformatted code (ie.&lt;br /&gt;
 start with a space&lt;br /&gt;
 &lt;br /&gt;
 To break a para in pre code,&lt;br /&gt;
 Write a space and then press enter&lt;br /&gt;
&lt;br /&gt;
[[Image:Destruction Of The Endless.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
!Column One&lt;br /&gt;
!Column Two&lt;br /&gt;
!Column Three&lt;br /&gt;
|-&lt;br /&gt;
|Row 2 Cell 1&lt;br /&gt;
|Row 2 Cell 2&lt;br /&gt;
|Row 2 Cell 3&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|Row 3 Cell 1-2&lt;br /&gt;
|Row 3 Cell 3&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Holiday/2026&amp;diff=453</id>
		<title>Holiday/2026</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Holiday/2026&amp;diff=453"/>
		<updated>2025-09-14T17:57:53Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Interrail Global Pass Adult&lt;br /&gt;
7 Travel Days within 1 month&lt;br /&gt;
1st class&lt;br /&gt;
968 euro each&lt;br /&gt;
&lt;br /&gt;
September best time to go.&lt;br /&gt;
&lt;br /&gt;
=== Day 1 ===&lt;br /&gt;
Travel Day 1:&amp;lt;br&amp;gt;&lt;br /&gt;
* Lancaster -&amp;gt; London. Around 3 hrs.&lt;br /&gt;
* London to Brussels: Eurostar train from London St Pancras to Brussels-Midi. Around 2 hrs.&lt;br /&gt;
* Brussels to Cologne. Around 2 hours.&lt;br /&gt;
&lt;br /&gt;
=== Day 1 - 2 (1 night) ===&lt;br /&gt;
Travel Day 2:&lt;br /&gt;
* Cologne to Hamburg, a journey of around 4 hours. &lt;br /&gt;
&lt;br /&gt;
=== Days 2 - 5 (3 nights) ===&lt;br /&gt;
Travel Day 3:&lt;br /&gt;
* Hamburg to Copenhagen: From Hamburg, take the train to Copenhagen, the capital of Denmark. Around 5 hrs.&lt;br /&gt;
&lt;br /&gt;
=== Days 5 - 8 (3 nights) ===&lt;br /&gt;
Travel Day 4:&lt;br /&gt;
* Copenhagen to Gothenburg: From Copenhagen, proceed by train to Gothenburg, Sweden. Around 3 hrs and 30 minutes.&lt;br /&gt;
&lt;br /&gt;
=== Days 8 - 11 (3 nights) ===&lt;br /&gt;
Travel Day 5:&lt;br /&gt;
* Gothenburg to Oslo: Finally, catch a train from Gothenburg to Oslo, which takes approximately 3 hours and 40 minutes. &lt;br /&gt;
&lt;br /&gt;
=== Days 11 - 14 (3 nights) ===&lt;br /&gt;
Travel Day 6:&lt;br /&gt;
* Oslo to Myrdal &lt;br /&gt;
* Flam Railway - 30% of with interrail (https://www.norwaysbest.com/en/things-to-do/the-flam-railway)&lt;br /&gt;
* Mydral to Bergen&lt;br /&gt;
&lt;br /&gt;
=== Days 14 - 17 (3 nights) ===&lt;br /&gt;
Travel Day 7:&lt;br /&gt;
* Bergen to Oslo &lt;br /&gt;
&lt;br /&gt;
=== Day 17+ ===&lt;br /&gt;
Fly Home&lt;br /&gt;
&lt;br /&gt;
Notes.....&lt;br /&gt;
&lt;br /&gt;
Bergen Card includes travel and discounts on the fjord cruise....plus the finicular&lt;br /&gt;
&lt;br /&gt;
Could do an organised thing if we wanted - Round trip to Oslo&lt;br /&gt;
&lt;br /&gt;
https://www.fjordtours.com/en/norway/tours/packages/unesco-geirangerfjord-and-norway-in-a-nutshell&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Holiday/2026&amp;diff=450</id>
		<title>Holiday/2026</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Holiday/2026&amp;diff=450"/>
		<updated>2025-09-14T13:46:14Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Frist&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This space intentionally left blank&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=449</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=449"/>
		<updated>2025-06-26T18:27:52Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Puzzle Quest section added&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== Marvel Puzzle Quest ==&lt;br /&gt;
* Strange Sights: Doom -&amp;gt; Maggia -&amp;gt; Hand&lt;br /&gt;
** Because there are more movers to the left of the above, and they get harder day after day. &lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
This space intentionally left blank.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Honeymoon]]&lt;br /&gt;
* [[User:Stuart/Dad]]&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* [[Game Board/Print And Play]]&lt;br /&gt;
* [[User:Stuart/Meal Planning|&#039;&#039;Meal Planning&#039;&#039;]]&lt;br /&gt;
** [[User:Stuart/Meal Planning/2022-11-14|14/11/2022]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=To-do&amp;diff=444</id>
		<title>To-do</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=To-do&amp;diff=444"/>
		<updated>2022-11-15T10:46:02Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Moved to DONE&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A page detailing the things that I need to do... I&#039;ll put something more formal together later.&lt;br /&gt;
&lt;br /&gt;
Things I might have to do something with:&lt;br /&gt;
&lt;br /&gt;
= CURRENT =&lt;br /&gt;
&lt;br /&gt;
== Home Insurance ==&lt;br /&gt;
* https://account.policyexpert.co.uk/summary&lt;br /&gt;
* Add ring... value?&lt;br /&gt;
* Policy number: 35666001262083&lt;br /&gt;
* End date: 20/01/2023&lt;br /&gt;
* Cover level: Silver Home Insurance&lt;br /&gt;
* 0330 0600 601&lt;br /&gt;
&lt;br /&gt;
= DONE =&lt;br /&gt;
== Atlas Alarms ==&lt;br /&gt;
* https://sites.google.com/atlasalarms.co.uk/atlasalarms-co-uk/home&lt;br /&gt;
* 01254 873232&lt;br /&gt;
* service@atlasalarms.co.uk&lt;br /&gt;
----&lt;br /&gt;
&#039;&#039;&#039;14/11/2022 11:00&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Dave, the surveyor, to call me back on my mobile to organise something.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;15/11/2022 10:30&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Dave called back, he&#039;s coming round at 13:00 on Friday (18/11/2022).&lt;br /&gt;
&lt;br /&gt;
== Booking meal in Grasmere ==&lt;br /&gt;
* Wed 23/11/2022&lt;br /&gt;
----&lt;br /&gt;
&#039;&#039;&#039;14/11/2022 12:45&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Called, left a message&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;14/11/2022 13:00&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
They called back prompt-ish; booked for 23/11/2022 18:30&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Meal_Planning/2022-11-14&amp;diff=443</id>
		<title>User:Stuart/Meal Planning/2022-11-14</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Meal_Planning/2022-11-14&amp;diff=443"/>
		<updated>2022-11-14T13:38:04Z</updated>

		<summary type="html">&lt;p&gt;Stuart: WIP&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Rules ==&lt;br /&gt;
Allowed one each of:&lt;br /&gt;
* pasta&lt;br /&gt;
* rice&lt;br /&gt;
* potatoes&lt;br /&gt;
* bread&lt;br /&gt;
&lt;br /&gt;
Exceptions allowed when eating out. S&#039;a treat, innit?&lt;br /&gt;
&lt;br /&gt;
= Diary =&lt;br /&gt;
&lt;br /&gt;
== Monday ==&lt;br /&gt;
* Lunch: &#039;&#039;missed&#039;&#039;&lt;br /&gt;
* Dinner: Ragu with **pasta**&lt;br /&gt;
** Leftovers&lt;br /&gt;
&lt;br /&gt;
== Tuesday ==&lt;br /&gt;
* Lunch: Chicken, Vegetable &amp;amp; Pearl Barley soup&lt;br /&gt;
** Source: &#039;&#039;A Soup For Every Day&#039;&#039;; Page: 334&lt;br /&gt;
* Dinner: &lt;br /&gt;
&lt;br /&gt;
== Wednesday ==&lt;br /&gt;
* Lunch:&lt;br /&gt;
* Dinner:&lt;br /&gt;
&lt;br /&gt;
== Thursday ==&lt;br /&gt;
* Lunch: Chicken &amp;amp; Chorizo Gumbo&lt;br /&gt;
** Source: &#039;&#039;A Soup For Every Day&#039;&#039;; Page: 340&lt;br /&gt;
* Dinner: Out with Chris &amp;amp; Claire&lt;br /&gt;
&lt;br /&gt;
== Friday ==&lt;br /&gt;
* Lunch:&lt;br /&gt;
* Dinner: Sausages braised in red wine, served with champ mash (**potatoes**)&lt;br /&gt;
** Source: &#039;&#039;Complete Cookery Course&#039;&#039;; Page: 178&lt;br /&gt;
&lt;br /&gt;
== Saturday ==&lt;br /&gt;
* Lunch: &lt;br /&gt;
* Dinner:&lt;br /&gt;
&lt;br /&gt;
== Sunday ==&lt;br /&gt;
* Lunch: Apple, Cider salad with melted Camembert dressing&lt;br /&gt;
** Source: &#039;&#039;Winter Collection&#039;&#039;; Page: 40&lt;br /&gt;
* Dinner:&lt;br /&gt;
&lt;br /&gt;
= Ingredients =&lt;br /&gt;
&lt;br /&gt;
= Addenda =&lt;br /&gt;
== For later consideration ==&lt;br /&gt;
* Camembert croquettes with fresh date and apple chutney&lt;br /&gt;
** Source: &#039;&#039;Winter Collection&#039;&#039;; Page: 38/39&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=442</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=442"/>
		<updated>2022-11-14T13:16:30Z</updated>

		<summary type="html">&lt;p&gt;Stuart: /* Global Bookmarks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
This space intentionally left blank.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Honeymoon]]&lt;br /&gt;
* [[User:Stuart/Dad]]&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* [[Game Board/Print And Play]]&lt;br /&gt;
* [[User:Stuart/Meal Planning|&#039;&#039;Meal Planning&#039;&#039;]]&lt;br /&gt;
** [[User:Stuart/Meal Planning/2022-11-14|14/11/2022]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=To-do&amp;diff=441</id>
		<title>To-do</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=To-do&amp;diff=441"/>
		<updated>2022-11-14T12:52:01Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added Grasmere meal&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A page detailing the things that I need to do... I&#039;ll put something more formal together later.&lt;br /&gt;
&lt;br /&gt;
Things I might have to do something with:&lt;br /&gt;
&lt;br /&gt;
= CURRENT =&lt;br /&gt;
== Atlas Alarms ==&lt;br /&gt;
* https://sites.google.com/atlasalarms.co.uk/atlasalarms-co-uk/home&lt;br /&gt;
* 01254 873232&lt;br /&gt;
* service@atlasalarms.co.uk&lt;br /&gt;
----&lt;br /&gt;
&#039;&#039;&#039;11:00&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Dave, the surveyor, to call me back on my mobile to organise something.&lt;br /&gt;
&lt;br /&gt;
== Home Insurance ==&lt;br /&gt;
* https://account.policyexpert.co.uk/summary&lt;br /&gt;
* Add ring... value?&lt;br /&gt;
* Policy number: 35666001262083&lt;br /&gt;
* End date: 20/01/2023&lt;br /&gt;
* Cover level: Silver Home Insurance&lt;br /&gt;
* 0330 0600 601&lt;br /&gt;
&lt;br /&gt;
== Booking meal in Grasmere ==&lt;br /&gt;
* Wed 23/11/2022&lt;br /&gt;
----&lt;br /&gt;
&#039;&#039;&#039;12:45&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Called, left a message&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=To-do&amp;diff=440</id>
		<title>To-do</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=To-do&amp;diff=440"/>
		<updated>2022-11-14T11:02:21Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A page detailing the things that I need to do... I&#039;ll put something more formal together later.&lt;br /&gt;
&lt;br /&gt;
Things I might have to do something with:&lt;br /&gt;
&lt;br /&gt;
= CURRENT =&lt;br /&gt;
== Atlas Alarms ==&lt;br /&gt;
* https://sites.google.com/atlasalarms.co.uk/atlasalarms-co-uk/home&lt;br /&gt;
* 01254 873232&lt;br /&gt;
* service@atlasalarms.co.uk&lt;br /&gt;
----&lt;br /&gt;
&#039;&#039;&#039;11:00&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Dave, the surveyor, to call me back on my mobile to organise something.&lt;br /&gt;
&lt;br /&gt;
== Home Insurance ==&lt;br /&gt;
* https://account.policyexpert.co.uk/summary&lt;br /&gt;
* Add ring... value?&lt;br /&gt;
* Policy number: 35666001262083&lt;br /&gt;
* End date: 20/01/2023&lt;br /&gt;
* Cover level: Silver Home Insurance&lt;br /&gt;
* 0330 0600 601&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=To-do&amp;diff=439</id>
		<title>To-do</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=To-do&amp;diff=439"/>
		<updated>2022-11-14T11:01:20Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Cleared the old stuff - new stuff added.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A page detailing the things that I need to do... I&#039;ll put something more formal together later.&lt;br /&gt;
&lt;br /&gt;
Things I might have to do something with:&lt;br /&gt;
&lt;br /&gt;
= CURRENT =&lt;br /&gt;
== Atlas Alarms ==&lt;br /&gt;
* https://sites.google.com/atlasalarms.co.uk/atlasalarms-co-uk/home&lt;br /&gt;
* 01254 873232&lt;br /&gt;
* service@atlasalarms.co.uk&lt;br /&gt;
----&lt;br /&gt;
*11:00*&amp;lt;br&amp;gt;&lt;br /&gt;
Dave, the surveyor, to call me back on my mobile to organise something.&lt;br /&gt;
&lt;br /&gt;
== Home Insurance ==&lt;br /&gt;
* https://account.policyexpert.co.uk/summary&lt;br /&gt;
* Add ring... value?&lt;br /&gt;
* Policy number: 35666001262083&lt;br /&gt;
* End date: 20/01/2023&lt;br /&gt;
* Cover level: Silver Home Insurance&lt;br /&gt;
* 0330 0600 601&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=425</id>
		<title>User:Stuart/Dad</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=425"/>
		<updated>2022-09-20T06:12:33Z</updated>

		<summary type="html">&lt;p&gt;Stuart: &amp;quot;journal entry&amp;quot; -&amp;gt; &amp;quot;something&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== My Dad ===&lt;br /&gt;
&lt;br /&gt;
My Dad was a teacher.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to accept people as they are and not as I think they should be.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to make plans but always be prepared for them to be thrown away at the first instance.&amp;lt;br&amp;gt;&lt;br /&gt;
He tried, a few times, to teach me ship stability, but that never took.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me the contentment you could achieve by sitting on the top of a mountain and enjoying being there.&amp;lt;br&amp;gt;&lt;br /&gt;
And the satisfaction you could achieve with a nice pint after the walk.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a student.&amp;lt;br&amp;gt;&lt;br /&gt;
He wanted to learn about everyone he met.&amp;lt;br&amp;gt;&lt;br /&gt;
He&#039;d greet a waiter in a cafe with the same enthusiasm that he&#039;d greet an old friend, and be genuinely interested to learn about them and their life in the same way.&amp;lt;br&amp;gt;&lt;br /&gt;
He was learning to speak Spanish, to play the accordion, forever learning new skills on the computer.&amp;lt;br&amp;gt;&lt;br /&gt;
He was always trying to improve, never just accepting that he was done and there was no point in changing any more.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a counsellor.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would listen, without judgement or impatience, to anyone who needed to talk.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would be the rock you could rely on when you were unsure of the ground you were standing on.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was all of these things and more and I miss him.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to finish with something he wrote after he completed his Camino:&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;font-style: italic&amp;quot;&amp;gt;&lt;br /&gt;
I am very very happy.&lt;br /&gt;
&lt;br /&gt;
Words to describe the feeling in all its depth and richness are so difficult to find.&amp;lt;br&amp;gt;&lt;br /&gt;
Life it seems cannot stop giving me gift after gift. I am reminded of Meister Eckhart&amp;lt;br&amp;gt;&lt;br /&gt;
and his description of an overflowingness of Life that cannot stop giving. Also of that&amp;lt;br&amp;gt;&lt;br /&gt;
poetic piece from Davina of Findhorn.&lt;br /&gt;
&lt;br /&gt;
My feelings are of gratitude and surprise, reassurance and encouragement, thankfulness&amp;lt;br&amp;gt;&lt;br /&gt;
for the rich blessings that I am given, the Friendships I am given, surprise at what&amp;lt;br&amp;gt;&lt;br /&gt;
comes &#039;out of the blue&#039;, trust in life, awareness of the transience of life and the&amp;lt;br&amp;gt;&lt;br /&gt;
willingness to embrace the joys I am given knowing that all my life experiences are&amp;lt;br&amp;gt;&lt;br /&gt;
transient except where we are all headed.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=424</id>
		<title>User:Stuart/Dad</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=424"/>
		<updated>2022-09-19T21:41:34Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Removed the other quotes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== My Dad ===&lt;br /&gt;
&lt;br /&gt;
My Dad was a teacher.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to accept people as they are and not as I think they should be.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to make plans but always be prepared for them to be thrown away at the first instance.&amp;lt;br&amp;gt;&lt;br /&gt;
He tried, a few times, to teach me ship stability, but that never took.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me the contentment you could achieve by sitting on the top of a mountain and enjoying being there.&amp;lt;br&amp;gt;&lt;br /&gt;
And the satisfaction you could achieve with a nice pint after the walk.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a student.&amp;lt;br&amp;gt;&lt;br /&gt;
He wanted to learn about everyone he met.&amp;lt;br&amp;gt;&lt;br /&gt;
He&#039;d greet a waiter in a cafe with the same enthusiasm that he&#039;d greet an old friend, and be genuinely interested to learn about them and their life in the same way.&amp;lt;br&amp;gt;&lt;br /&gt;
He was learning to speak Spanish, to play the accordion, forever learning new skills on the computer.&amp;lt;br&amp;gt;&lt;br /&gt;
He was always trying to improve, never just accepting that he was done and there was no point in changing any more.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a counsellor.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would listen, without judgement or impatience, to anyone who needed to talk.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would be the rock you could rely on when you were unsure of the ground you were standing on.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was all of these things and more and I miss him.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to finish with a journal entry he wrote after he completed his Camino:&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;font-style: italic&amp;quot;&amp;gt;&lt;br /&gt;
I am very very happy.&lt;br /&gt;
&lt;br /&gt;
Words to describe the feeling in all its depth and richness are so difficult to find.&amp;lt;br&amp;gt;&lt;br /&gt;
Life it seems cannot stop giving me gift after gift. I am reminded of Meister Eckhart&amp;lt;br&amp;gt;&lt;br /&gt;
and his description of an overflowingness of Life that cannot stop giving. Also of that&amp;lt;br&amp;gt;&lt;br /&gt;
poetic piece from Davina of Findhorn.&lt;br /&gt;
&lt;br /&gt;
My feelings are of gratitude and surprise, reassurance and encouragement, thankfulness&amp;lt;br&amp;gt;&lt;br /&gt;
for the rich blessings that I am given, the Friendships I am given, surprise at what&amp;lt;br&amp;gt;&lt;br /&gt;
comes &#039;out of the blue&#039;, trust in life, awareness of the transience of life and the&amp;lt;br&amp;gt;&lt;br /&gt;
willingness to embrace the joys I am given knowing that all my life experiences are&amp;lt;br&amp;gt;&lt;br /&gt;
transient except where we are all headed.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=423</id>
		<title>User:Stuart/Dad</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=423"/>
		<updated>2022-09-19T21:01:20Z</updated>

		<summary type="html">&lt;p&gt;Stuart: And another finish&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== My Dad ===&lt;br /&gt;
&lt;br /&gt;
My Dad was a teacher.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to accept people as they are and not as I think they should be.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to make plans but always be prepared for them to be thrown away at the first instance.&amp;lt;br&amp;gt;&lt;br /&gt;
He tried, a few times, to teach me ship stability, but that never took.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me the contentment you could achieve by sitting on the top of a mountain and enjoying being there.&amp;lt;br&amp;gt;&lt;br /&gt;
And the satisfaction you could achieve with a nice pint after the walk.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a student.&amp;lt;br&amp;gt;&lt;br /&gt;
He wanted to learn about everyone he met.&amp;lt;br&amp;gt;&lt;br /&gt;
He&#039;d greet a waiter in a cafe with the same enthusiasm that he&#039;d greet an old friend, and be genuinely interested to learn about them and their life in the same way.&amp;lt;br&amp;gt;&lt;br /&gt;
He was learning to speak Spanish, to play the accordion, forever learning new skills on the computer.&amp;lt;br&amp;gt;&lt;br /&gt;
He was always trying to improve, never just accepting that he was done and there was no point in changing any more.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a counsellor.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would listen, without judgement or impatience, to anyone who needed to talk.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would be the rock you could rely on when you were unsure of the ground you were standing on.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was all of these things and more and I miss him.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to finish with a short excerpt from his favourite book - &#039;The Prophet&#039; by Kahlil Gibran:&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;font-style: italic&amp;quot;&amp;gt;&lt;br /&gt;
 Say not &amp;quot;I have found the truth&amp;quot;, but rather &amp;quot;I have found a truth&amp;quot;.&amp;lt;br/&amp;gt;&lt;br /&gt;
 Say not &amp;quot;I have found the path of the soul.&amp;quot;&amp;lt;br/&amp;gt;&lt;br /&gt;
 Say, rather, &amp;quot;I have met the soul walking on my path.&amp;quot;&amp;lt;br/&amp;gt;&lt;br /&gt;
 For the soul walks on all paths.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to finish with a short excerpt from his favourite book - &#039;The Prophet&#039; by Kahlil Gibran:&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;font-style: italic&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;You give but little when you give of your possessions.&lt;br /&gt;
It is when you give of yourself that you truly give.&amp;quot;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to finish with a journal entry he wrote after he completed his Camino:&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;font-style: italic&amp;quot;&amp;gt;&lt;br /&gt;
I am very very happy.&lt;br /&gt;
&lt;br /&gt;
Words to describe the feeling in all its depth and richness are so difficult to find.&amp;lt;br&amp;gt;&lt;br /&gt;
Life it seems cannot stop giving me gift after gift. I am reminded of Meister Eckhart&amp;lt;br&amp;gt;&lt;br /&gt;
and his description of an overflowingness of Life that cannot stop giving. Also of that&amp;lt;br&amp;gt;&lt;br /&gt;
poetic piece from Davina of Findhorn.&lt;br /&gt;
&lt;br /&gt;
My feelings are of gratitude and surprise, reassurance and encouragement, thankfulness&amp;lt;br&amp;gt;&lt;br /&gt;
for the rich blessings that I am given, the Friendships I am given, surprise at what&amp;lt;br&amp;gt;&lt;br /&gt;
comes &#039;out of the blue&#039;, trust in life, awareness of the transience of life and the&amp;lt;br&amp;gt;&lt;br /&gt;
willingness to embrace the joys I am given knowing that all my life experiences are&amp;lt;br&amp;gt;&lt;br /&gt;
transient except where we are all headed.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=422</id>
		<title>User:Stuart/Dad</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=422"/>
		<updated>2022-09-19T20:52:23Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Formattings&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== My Dad ===&lt;br /&gt;
&lt;br /&gt;
My Dad was a teacher.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to accept people as they are and not as I think they should be.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to make plans but always be prepared for them to be thrown away at the first instance.&amp;lt;br&amp;gt;&lt;br /&gt;
He tried, a few times, to teach me ship stability, but that never took.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me the contentment you could achieve by sitting on the top of a mountain and enjoying being there.&amp;lt;br&amp;gt;&lt;br /&gt;
And the satisfaction you could achieve with a nice pint after the walk.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a student.&amp;lt;br&amp;gt;&lt;br /&gt;
He wanted to learn about everyone he met.&amp;lt;br&amp;gt;&lt;br /&gt;
He&#039;d greet a waiter in a cafe with the same enthusiasm that he&#039;d greet an old friend, and be genuinely interested to learn about them and their life in the same way.&amp;lt;br&amp;gt;&lt;br /&gt;
He was learning to speak Spanish, to play the accordion, forever learning new skills on the computer.&amp;lt;br&amp;gt;&lt;br /&gt;
He was always trying to improve, never just accepting that he was done and there was no point in changing any more.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a counsellor.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would listen, without judgement or impatience, to anyone who needed to talk.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would be the rock you could rely on when you were unsure of the ground you were standing on.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was all of these things and more and I miss him.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to finish with a short excerpt from his favourite book - &#039;The Prophet&#039; by Kahlil Gibran:&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;font-style: italic&amp;quot;&amp;gt;&lt;br /&gt;
 Say not &amp;quot;I have found the truth&amp;quot;, but rather &amp;quot;I have found a truth&amp;quot;.&amp;lt;br/&amp;gt;&lt;br /&gt;
 Say not &amp;quot;I have found the path of the soul.&amp;quot;&amp;lt;br/&amp;gt;&lt;br /&gt;
 Say, rather, &amp;quot;I have met the soul walking on my path.&amp;quot;&amp;lt;br/&amp;gt;&lt;br /&gt;
 For the soul walks on all paths.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to finish with a journal entry he wrote after he completed his Camino:&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;font-style: italic&amp;quot;&amp;gt;&lt;br /&gt;
I am very very happy.&lt;br /&gt;
&lt;br /&gt;
Words to describe the feeling in all its depth and richness are so difficult to find.&amp;lt;br&amp;gt;&lt;br /&gt;
Life it seems cannot stop giving me gift after gift. I am reminded of Meister Eckhart&amp;lt;br&amp;gt;&lt;br /&gt;
and his description of an overflowingness of Life that cannot stop giving. Also of that&amp;lt;br&amp;gt;&lt;br /&gt;
poetic piece from Davina of Findhorn.&lt;br /&gt;
&lt;br /&gt;
My feelings are of gratitude and surprise, reassurance and encouragement, thankfulness&amp;lt;br&amp;gt;&lt;br /&gt;
for the rich blessings that I am given, the Friendships I am given, surprise at what&amp;lt;br&amp;gt;&lt;br /&gt;
comes &#039;out of the blue&#039;, trust in life, awareness of the transience of life and the&amp;lt;br&amp;gt;&lt;br /&gt;
willingness to embrace the joys I am given knowing that all my life experiences are&amp;lt;br&amp;gt;&lt;br /&gt;
transient except where we are all headed.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=421</id>
		<title>User:Stuart/Dad</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=421"/>
		<updated>2022-09-19T20:51:54Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added journal entry - not sure which way to go yet.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== My Dad ===&lt;br /&gt;
&lt;br /&gt;
My Dad was a teacher.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to accept people as they are and not as I think they should be.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to make plans but always be prepared for them to be thrown away at the first instance.&amp;lt;br&amp;gt;&lt;br /&gt;
He tried, a few times, to teach me ship stability, but that never took.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me the contentment you could achieve by sitting on the top of a mountain and enjoying being there.&amp;lt;br&amp;gt;&lt;br /&gt;
And the satisfaction you could achieve with a nice pint after the walk.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a student.&amp;lt;br&amp;gt;&lt;br /&gt;
He wanted to learn about everyone he met.&amp;lt;br&amp;gt;&lt;br /&gt;
He&#039;d greet a waiter in a cafe with the same enthusiasm that he&#039;d greet an old friend, and be genuinely interested to learn about them and their life in the same way.&amp;lt;br&amp;gt;&lt;br /&gt;
He was learning to speak Spanish, to play the accordion, forever learning new skills on the computer.&amp;lt;br&amp;gt;&lt;br /&gt;
He was always trying to improve, never just accepting that he was done and there was no point in changing any more.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a counsellor.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would listen, without judgement or impatience, to anyone who needed to talk.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would be the rock you could rely on when you were unsure of the ground you were standing on.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was all of these things and more and I miss him.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to finish with a short excerpt from his favourite book - &#039;The Prophet&#039; by Kahlil Gibran:&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;font-style: italic&amp;quot;&amp;gt;&lt;br /&gt;
 Say not &amp;quot;I have found the truth&amp;quot;, but rather &amp;quot;I have found a truth&amp;quot;.&amp;lt;br/&amp;gt;&lt;br /&gt;
 Say not &amp;quot;I have found the path of the soul.&amp;quot;&amp;lt;br/&amp;gt;&lt;br /&gt;
 Say, rather, &amp;quot;I have met the soul walking on my path.&amp;quot;&amp;lt;br/&amp;gt;&lt;br /&gt;
 For the soul walks on all paths.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to finish with a journal entry he wrote after he completed his Camino:&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;font-style: italic&amp;quot;&amp;gt;&lt;br /&gt;
I am very very happy.&lt;br /&gt;
&lt;br /&gt;
Words to describe the feeling in all its depth and richness are so difficult to find.&lt;br /&gt;
Life it seems cannot stop giving me gift after gift. I am reminded of Meister Eckhart&lt;br /&gt;
and his description of an overflowingness of Life that cannot stop giving. Also of that&lt;br /&gt;
poetic piece from Davina of Findhorn.&lt;br /&gt;
&lt;br /&gt;
My feelings are of gratitude and surprise, reassurance and encouragement, thankfulness&lt;br /&gt;
for the rich blessings that I am given, the Friendships I am given, surprise at what&lt;br /&gt;
comes &#039;out of the blue&#039;, trust in life, awareness of the transience of life and the&lt;br /&gt;
willingness to embrace the joys I am given knowing that all my life experiences are&lt;br /&gt;
transient except where we are all headed.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=420</id>
		<title>User:Stuart/Dad</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=420"/>
		<updated>2022-09-19T20:45:57Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Tidy up&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== My Dad ===&lt;br /&gt;
&lt;br /&gt;
My Dad was a teacher.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to accept people as they are and not as I think they should be.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to make plans but always be prepared for them to be thrown away at the first instance.&amp;lt;br&amp;gt;&lt;br /&gt;
He tried, a few times, to teach me ship stability, but that never took.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me the contentment you could achieve by sitting on the top of a mountain and enjoying being there.&amp;lt;br&amp;gt;&lt;br /&gt;
And the satisfaction you could achieve with a nice pint after the walk.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a student.&amp;lt;br&amp;gt;&lt;br /&gt;
He wanted to learn about everyone he met.&amp;lt;br&amp;gt;&lt;br /&gt;
He&#039;d greet a waiter in a cafe with the same enthusiasm that he&#039;d greet an old friend, and be genuinely interested to learn about them and their life in the same way.&amp;lt;br&amp;gt;&lt;br /&gt;
He was learning to speak Spanish, to play the accordion, forever learning new skills on the computer.&amp;lt;br&amp;gt;&lt;br /&gt;
He was always trying to improve, never just accepting that he was done and there was no point in changing any more.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a counsellor.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would listen, without judgement or impatience, to anyone who needed to talk.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would be the rock you could rely on when you were unsure of the ground you were standing on.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was all of these things and more and I miss him.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to finish with a short excerpt from his favourite book - &#039;The Prophet&#039; by Kahlil Gibran.&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;font-style: italic&amp;quot;&amp;gt;&lt;br /&gt;
 Say not &amp;quot;I have found the truth&amp;quot;, but rather &amp;quot;I have found a truth&amp;quot;.&amp;lt;br/&amp;gt;&lt;br /&gt;
 Say not &amp;quot;I have found the path of the soul.&amp;quot;&amp;lt;br/&amp;gt;&lt;br /&gt;
 Say, rather, &amp;quot;I have met the soul walking on my path.&amp;quot;&amp;lt;br/&amp;gt;&lt;br /&gt;
 For the soul walks on all paths.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=419</id>
		<title>User:Stuart/Dad</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Dad&amp;diff=419"/>
		<updated>2022-09-19T20:43:25Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Created page with &amp;quot;My Dad was a teacher.&amp;lt;br&amp;gt; He taught me to accept people as they are and not as I think they should be.&amp;lt;br&amp;gt; He taught me to make plans but always be prepared for them to be thr...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;My Dad was a teacher.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to accept people as they are and not as I think they should be.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me to make plans but always be prepared for them to be thrown away at the first instance.&amp;lt;br&amp;gt;&lt;br /&gt;
He tried, a few times, to teach me ship stability, but that never took.&amp;lt;br&amp;gt;&lt;br /&gt;
He taught me the contentment you could achieve by sitting on the top of a mountain and enjoying being there.&amp;lt;br&amp;gt;&lt;br /&gt;
And the satisfaction you could achieve with a nice pint after the walk.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a student.&amp;lt;br&amp;gt;&lt;br /&gt;
He wanted to learn about everyone he met.&amp;lt;br&amp;gt;&lt;br /&gt;
He&#039;d greet a waiter in a cafe with the same enthusiasm that he&#039;d greet an old friend, and be genuinely interested to learn about them and their life in the same way.&amp;lt;br&amp;gt;&lt;br /&gt;
He was learning to speak Spanish, to play the accordion, forever learning new skills on the computer.&amp;lt;br&amp;gt;&lt;br /&gt;
He was always trying to improve, never just accepting that he was done and there was no point in changing any more.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was a counsellor.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would listen, without judgement or impatience, to anyone who needed to talk.&amp;lt;br/&amp;gt;&lt;br /&gt;
He would be the rock you could rely on when you were unsure of the ground you were standing on.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
My Dad was all of these things and more.&lt;br /&gt;
I&#039;m going to finish with a short excerpt from his favourite book - &#039;The Prophet&#039; by Kahlil Gibran.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Say not &amp;quot;I have found the truth&amp;quot;, but rather &amp;quot;I have found a truth&amp;quot;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Say not &amp;quot;I have found the path of the soul.&amp;quot;&amp;lt;br/&amp;gt;&lt;br /&gt;
Say, rather, &amp;quot;I have met the soul walking on my path.&amp;quot;&amp;lt;br/&amp;gt;&lt;br /&gt;
For the soul walks on all paths.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=418</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=418"/>
		<updated>2022-09-19T19:32:22Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added a Dad link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
This space intentionally left blank.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Honeymoon]]&lt;br /&gt;
* [[User:Stuart/Dad]]&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* [[Game Board/Print And Play]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Honeymoon&amp;diff=417</id>
		<title>User:Stuart/Honeymoon</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Honeymoon&amp;diff=417"/>
		<updated>2022-06-07T17:58:49Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added The Ardross&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Options for holiday cottage for honeymoon fun:&lt;br /&gt;
&lt;br /&gt;
== Cornwall ==&lt;br /&gt;
* [https://www.holidaycottages.co.uk/cottage/45739-kennack-heights--kennack-sands?n=7&amp;amp;sd=05092022 Kennack Heights]&lt;br /&gt;
&lt;br /&gt;
== Highlands ==&lt;br /&gt;
* [https://www.cottages-and-castles.co.uk/cottages/the-lovat-mackenzie?sd=10092022 Lovat, near Inverness]&lt;br /&gt;
* [https://www.cottages-and-castles.co.uk/cottages/the-ardross-residence?sd=10092022 The Ardross Residence, &#039;&#039;actually&#039;&#039; Inverness]&lt;br /&gt;
&lt;br /&gt;
== Something to consider for lads walking holiday ==&lt;br /&gt;
* [https://www.cottages-and-castles.co.uk/cottages/dhivach-lodge--drumnadrochit?sd=09092022 Dhivach Lodge - Drumnadrochit]&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Honeymoon&amp;diff=416</id>
		<title>User:Stuart/Honeymoon</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Honeymoon&amp;diff=416"/>
		<updated>2022-06-07T17:53:05Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added potential lads lodge in Scotland&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Options for holiday cottage for honeymoon fun:&lt;br /&gt;
&lt;br /&gt;
== Cornwall ==&lt;br /&gt;
* [https://www.holidaycottages.co.uk/cottage/45739-kennack-heights--kennack-sands?n=7&amp;amp;sd=05092022 Kennack Heights]&lt;br /&gt;
&lt;br /&gt;
== Highlands ==&lt;br /&gt;
* [https://www.cottages-and-castles.co.uk/cottages/the-lovat-mackenzie?sd=10092022 Lovat, near Inverness]&lt;br /&gt;
&lt;br /&gt;
== Something to consider for lads walking holiday ==&lt;br /&gt;
* [https://www.cottages-and-castles.co.uk/cottages/dhivach-lodge--drumnadrochit?sd=09092022 Dhivach Lodge - Drumnadrochit]&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Honeymoon&amp;diff=415</id>
		<title>User:Stuart/Honeymoon</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Honeymoon&amp;diff=415"/>
		<updated>2022-06-07T17:46:48Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added highlands section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Options for holiday cottage for honeymoon fun:&lt;br /&gt;
&lt;br /&gt;
== Cornwall ==&lt;br /&gt;
* [https://www.holidaycottages.co.uk/cottage/45739-kennack-heights--kennack-sands?n=7&amp;amp;sd=05092022 Kennack Heights]&lt;br /&gt;
&lt;br /&gt;
== Highlands ==&lt;br /&gt;
* [https://www.cottages-and-castles.co.uk/cottages/the-lovat-mackenzie?sd=10092022 Lovat, near Inverness]&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Honeymoon&amp;diff=414</id>
		<title>User:Stuart/Honeymoon</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart/Honeymoon&amp;diff=414"/>
		<updated>2022-06-07T16:45:42Z</updated>

		<summary type="html">&lt;p&gt;Stuart: First cut - Kennack Heights&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Options for holiday cottage for honeymoon fun:&lt;br /&gt;
&lt;br /&gt;
== Cornwall ==&lt;br /&gt;
* [https://www.holidaycottages.co.uk/cottage/45739-kennack-heights--kennack-sands?n=7&amp;amp;sd=05092022 Kennack Heights]&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=413</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=413"/>
		<updated>2022-06-07T16:44:35Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added Honeymoon page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
This space intentionally left blank.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Honeymoon]]&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* [[Game Board/Print And Play]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Game_Board/Print_And_Play&amp;diff=412</id>
		<title>Game Board/Print And Play</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Game_Board/Print_And_Play&amp;diff=412"/>
		<updated>2022-05-23T11:24:17Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Full howto plus ingredients added&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Card Printing ==&lt;br /&gt;
For reasonable feel cards:&lt;br /&gt;
=== Martin Gonzalvez ===&lt;br /&gt;
* [https://www.youtube.com/watch?v=00h0KFbkViA How to make print and play cards]&lt;br /&gt;
* [https://www.youtube.com/watch?v=jSnM6j9Nqh8 Print and play cards that riffle shuffle]&lt;br /&gt;
&lt;br /&gt;
=== Rachel Bruner ===&lt;br /&gt;
* [https://www.youtube.com/watch?v=geJGoGsSUxE Print and play cards made like playing cards]&lt;br /&gt;
* [https://www.youtube.com/watch?v=DgNJmAkO1_M How To Make Game Cards that Shuffle - Print and Play Tutorial]&lt;br /&gt;
&lt;br /&gt;
=== Howto ===&lt;br /&gt;
Ingredients:&lt;br /&gt;
* 90-100 gsm linen paper (e.g. [https://www.amazon.co.uk/Southworth-Linen-Business-Pounds-P564CK/dp/B0087D7ZAU Southworth 25% 90gsm Cotton Paper]&lt;br /&gt;
* 3mm laminating pouches&lt;br /&gt;
* Acrylic sealer (e.g. [https://www.amazon.com/Mod-Podge-Acrylic-12-Ounce-1469/dp/B003VY9DNM/?th=1 Mod Podge Clear Acrylic Matte Sealer]&lt;br /&gt;
* Spray glue&lt;br /&gt;
&lt;br /&gt;
Briefly:&lt;br /&gt;
# Print, single-sided; front down the left, back down the right&lt;br /&gt;
# Fold the paper such that the front and back match up, unfold again ready for the core laminate sheet&lt;br /&gt;
# Spray the glue over the back of the paper&lt;br /&gt;
# Insert one sheet of the laminating pouch (tear the sheets apart for this) into the fold and press the glued paper onto it - it must line up&lt;br /&gt;
# Use the other side of the laminate sheet for another 4 cards done the same way as above&lt;br /&gt;
# Trim off all excess laminate - you want just paper showing, no clear laminate parts&lt;br /&gt;
# Put it through the laminator&lt;br /&gt;
# Cut and corner each card&lt;br /&gt;
&lt;br /&gt;
This will work great for the Arkham Horror like stuff, especially once sleeved.&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=411</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=411"/>
		<updated>2022-05-23T11:08:02Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added Print And Play; Removed obsolete TODOs.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
This space intentionally left blank.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* [[Game Board/Print And Play]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=File:New-tube-map.jpg&amp;diff=410</id>
		<title>File:New-tube-map.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=File:New-tube-map.jpg&amp;diff=410"/>
		<updated>2022-05-20T14:57:03Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Stuart uploaded a new version of File:New-tube-map.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Tube map, including Elizabeth line&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Tube&amp;diff=409</id>
		<title>Tube</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Tube&amp;diff=409"/>
		<updated>2022-05-20T14:56:31Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Just link to the image. Far nicer&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Media:New-tube-map.jpg|Tube Map]]&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Tube&amp;diff=408</id>
		<title>Tube</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Tube&amp;diff=408"/>
		<updated>2022-05-20T14:49:01Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added tube map&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:New-tube-map.jpg]]&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=File:New-tube-map.jpg&amp;diff=407</id>
		<title>File:New-tube-map.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=File:New-tube-map.jpg&amp;diff=407"/>
		<updated>2022-05-20T14:48:07Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Tube map, including Elizabeth line&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Tube map, including Elizabeth line&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=406</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=406"/>
		<updated>2022-03-20T09:32:14Z</updated>

		<summary type="html">&lt;p&gt;Stuart: /* 18/03/2022 */ Library done&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
=== 18/03/2022 ===&lt;br /&gt;
* Dukes:&lt;br /&gt;
** Cancel standing order (joint account? yes, and not due til 14/11, so no great rush)&lt;br /&gt;
** Phone/call/go round and organise new friends payments&lt;br /&gt;
* &amp;lt;s&amp;gt;Homeserve:&amp;lt;/s&amp;gt;&lt;br /&gt;
** &amp;lt;s&amp;gt;Call them up and see why a 50% rise in price; maybe cancel. Probably cancel.&amp;lt;/s&amp;gt;&lt;br /&gt;
* &amp;lt;s&amp;gt;Library books&amp;lt;/s&amp;gt;&lt;br /&gt;
** &amp;lt;s&amp;gt;not due til 24/03, but all read now.&amp;lt;/s&amp;gt;&lt;br /&gt;
* Co-op Bank&lt;br /&gt;
** &amp;lt;s&amp;gt;Look into / setup new security requirements&amp;lt;/s&amp;gt;&lt;br /&gt;
*** &#039;&#039;Had a look - this can wait; they ain&#039;t ready, and 1* reviews from last year, getting no better. Co-op really are crap.&#039;&#039;&lt;br /&gt;
** &amp;lt;s&amp;gt;2 invoices to Riverside to pay; see Accounts below.&amp;lt;/s&amp;gt;&lt;br /&gt;
* Accounts&lt;br /&gt;
** &amp;lt;s&amp;gt;2 invoices to put into Sage&amp;lt;/s&amp;gt;&lt;br /&gt;
** &amp;lt;s&amp;gt;Both invoices need paying; See Co-op Bank above&amp;lt;/s&amp;gt;&lt;br /&gt;
** Company accounts for last year to sign and return&lt;br /&gt;
** Bring bank transactions up to date&lt;br /&gt;
*** Maybe write a little program to convert co-op CSV to sage CSV&lt;br /&gt;
* Edinburgh&lt;br /&gt;
** Look for somewhere to eat on Sunday evening&lt;br /&gt;
** Maybe Sunday afternoon too&lt;br /&gt;
** Pick up tickets from station&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=405</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=405"/>
		<updated>2022-03-18T13:32:58Z</updated>

		<summary type="html">&lt;p&gt;Stuart: /* 18/03/2022 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
=== 18/03/2022 ===&lt;br /&gt;
* Dukes:&lt;br /&gt;
** Cancel standing order (joint account? yes, and not due til 14/11, so no great rush)&lt;br /&gt;
** Phone/call/go round and organise new friends payments&lt;br /&gt;
* &amp;lt;s&amp;gt;Homeserve:&amp;lt;/s&amp;gt;&lt;br /&gt;
** &amp;lt;s&amp;gt;Call them up and see why a 50% rise in price; maybe cancel. Probably cancel.&amp;lt;/s&amp;gt;&lt;br /&gt;
* Library books&lt;br /&gt;
** not due til 24/03, but all read now.&lt;br /&gt;
* Co-op Bank&lt;br /&gt;
** &amp;lt;s&amp;gt;Look into / setup new security requirements&amp;lt;/s&amp;gt;&lt;br /&gt;
*** &#039;&#039;Had a look - this can wait; they ain&#039;t ready, and 1* reviews from last year, getting no better. Co-op really are crap.&#039;&#039;&lt;br /&gt;
** &amp;lt;s&amp;gt;2 invoices to Riverside to pay; see Accounts below.&amp;lt;/s&amp;gt;&lt;br /&gt;
* Accounts&lt;br /&gt;
** &amp;lt;s&amp;gt;2 invoices to put into Sage&amp;lt;/s&amp;gt;&lt;br /&gt;
** &amp;lt;s&amp;gt;Both invoices need paying; See Co-op Bank above&amp;lt;/s&amp;gt;&lt;br /&gt;
** Company accounts for last year to sign and return&lt;br /&gt;
** Bring bank transactions up to date&lt;br /&gt;
*** Maybe write a little program to convert co-op CSV to sage CSV&lt;br /&gt;
* Edinburgh&lt;br /&gt;
** Look for somewhere to eat on Sunday evening&lt;br /&gt;
** Maybe Sunday afternoon too&lt;br /&gt;
** Pick up tickets from station&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=404</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=404"/>
		<updated>2022-03-18T13:14:46Z</updated>

		<summary type="html">&lt;p&gt;Stuart: /* 18/03/2022 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
=== 18/03/2022 ===&lt;br /&gt;
* Dukes:&lt;br /&gt;
** Cancel standing order (joint account? yes, and not due til 14/11, so no great rush)&lt;br /&gt;
** Phone/call/go round and organise new friends payments&lt;br /&gt;
* &amp;lt;s&amp;gt;Homeserve:&amp;lt;/s&amp;gt;&lt;br /&gt;
** &amp;lt;s&amp;gt;Call them up and see why a 50% rise in price; maybe cancel. Probably cancel.&amp;lt;/s&amp;gt;&lt;br /&gt;
* Library books&lt;br /&gt;
** not due til 24/03, but all read now.&lt;br /&gt;
* Co-op Bank&lt;br /&gt;
** Look into / setup new security requirements&lt;br /&gt;
** &amp;lt;s&amp;gt;2 invoices to Riverside to pay; see Accounts below.&amp;lt;/s&amp;gt;&lt;br /&gt;
* Accounts&lt;br /&gt;
** &amp;lt;s&amp;gt;2 invoices to put into Sage&amp;lt;/s&amp;gt;&lt;br /&gt;
** &amp;lt;s&amp;gt;Both invoices need paying; See Co-op Bank above&amp;lt;/s&amp;gt;&lt;br /&gt;
** Company accounts for last year to sign and return&lt;br /&gt;
** Bring bank transactions up to date&lt;br /&gt;
*** Maybe write a little program to convert co-op CSV to sage CSV&lt;br /&gt;
* Edinburgh&lt;br /&gt;
** Look for somewhere to eat on Sunday evening&lt;br /&gt;
** Maybe Sunday afternoon too&lt;br /&gt;
** Pick up tickets from station&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=403</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=403"/>
		<updated>2022-03-18T13:04:24Z</updated>

		<summary type="html">&lt;p&gt;Stuart: /* 18/03/2022 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
=== 18/03/2022 ===&lt;br /&gt;
* Dukes:&lt;br /&gt;
** Cancel standing order (joint account? yes, and not due til 14/11, so no great rush)&lt;br /&gt;
** Phone/call/go round and organise new friends payments&lt;br /&gt;
* &amp;lt;s&amp;gt;Homeserve:&amp;lt;/s&amp;gt;&lt;br /&gt;
** &amp;lt;s&amp;gt;Call them up and see why a 50% rise in price; maybe cancel. Probably cancel.&amp;lt;/s&amp;gt;&lt;br /&gt;
* Library books&lt;br /&gt;
** not due til 24/03, but all read now.&lt;br /&gt;
* Co-op Bank&lt;br /&gt;
** Look into / setup new security requirements&lt;br /&gt;
** 2 invoices to Riverside to pay; see Accounts below.&lt;br /&gt;
* Accounts&lt;br /&gt;
** &amp;lt;s&amp;gt;2 invoices to put into Sage&amp;lt;/s&amp;gt;&lt;br /&gt;
** &amp;lt;s&amp;gt;Both invoices need paying; See Co-op Bank above&amp;lt;/s&amp;gt;&lt;br /&gt;
** Company accounts for last year to sign and return&lt;br /&gt;
** Bring bank transactions up to date&lt;br /&gt;
*** Maybe write a little program to convert co-op CSV to sage CSV&lt;br /&gt;
* Edinburgh&lt;br /&gt;
** Look for somewhere to eat on Sunday evening&lt;br /&gt;
** Maybe Sunday afternoon too&lt;br /&gt;
** Pick up tickets from station&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=402</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=402"/>
		<updated>2022-03-18T13:03:34Z</updated>

		<summary type="html">&lt;p&gt;Stuart: /* 18/03/2022 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
=== 18/03/2022 ===&lt;br /&gt;
* Dukes:&lt;br /&gt;
** Cancel standing order (joint account? yes, and not due til 14/11, so no great rush)&lt;br /&gt;
** Phone/call/go round and organise new friends payments&lt;br /&gt;
* &amp;lt;s&amp;gt;Homeserve:&amp;lt;/s&amp;gt;&lt;br /&gt;
** &amp;lt;s&amp;gt;Call them up and see why a 50% rise in price; maybe cancel. Probably cancel.&amp;lt;/s&amp;gt;&lt;br /&gt;
* Library books&lt;br /&gt;
** not due til 24/03, but all read now.&lt;br /&gt;
* Co-op Bank&lt;br /&gt;
** Look into / setup new security requirements&lt;br /&gt;
** 2 invoices to Riverside to pay; see Accounts below.&lt;br /&gt;
* Accounts&lt;br /&gt;
** &amp;lt;s&amp;gt;2 invoices to put into Sage&amp;lt;/s&amp;gt;&lt;br /&gt;
** Both invoices need paying; See Co-op Bank above&lt;br /&gt;
** Company accounts for last year to sign and return&lt;br /&gt;
* Edinburgh&lt;br /&gt;
** Look for somewhere to eat on Sunday evening&lt;br /&gt;
** Maybe Sunday afternoon too&lt;br /&gt;
** Pick up tickets from station&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=401</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=401"/>
		<updated>2022-03-18T12:09:02Z</updated>

		<summary type="html">&lt;p&gt;Stuart: /* 18/03/2022 */ Homeserve done&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
=== 18/03/2022 ===&lt;br /&gt;
* Dukes:&lt;br /&gt;
** Cancel standing order (joint account? yes, and not due til 14/11, so no great rush)&lt;br /&gt;
** Phone/call/go round and organise new friends payments&lt;br /&gt;
* &amp;lt;s&amp;gt;Homeserve:&amp;lt;/s&amp;gt;&lt;br /&gt;
** &amp;lt;s&amp;gt;Call them up and see why a 50% rise in price; maybe cancel. Probably cancel.&amp;lt;/s&amp;gt;&lt;br /&gt;
* Library books&lt;br /&gt;
** not due til 24/03, but all read now.&lt;br /&gt;
* Co-op Bank&lt;br /&gt;
** Look into / setup new security requirements&lt;br /&gt;
** 2 invoices to Riverside to pay; see Accounts below.&lt;br /&gt;
* Accounts&lt;br /&gt;
** 2 invoices to put into Sage&lt;br /&gt;
** Both invoices need paying; See Co-op Bank above&lt;br /&gt;
** Company accounts for last year to sign and return&lt;br /&gt;
* Edinburgh&lt;br /&gt;
** Look for somewhere to eat on Sunday evening&lt;br /&gt;
** Maybe Sunday afternoon too&lt;br /&gt;
** Pick up tickets from station&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=400</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=400"/>
		<updated>2022-03-18T11:57:20Z</updated>

		<summary type="html">&lt;p&gt;Stuart: /* 18/03/2022 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
=== 18/03/2022 ===&lt;br /&gt;
* Dukes:&lt;br /&gt;
** Cancel standing order (joint account? yes, and not due til 14/11, so no great rush)&lt;br /&gt;
** Phone/call/go round and organise new friends payments&lt;br /&gt;
* Homeserve:&lt;br /&gt;
** Call them up and see why a 50% rise in price; maybe cancel. Probably cancel.&lt;br /&gt;
* Library books&lt;br /&gt;
** not due til 24/03, but all read now.&lt;br /&gt;
* Co-op Bank&lt;br /&gt;
** Look into / setup new security requirements&lt;br /&gt;
** 2 invoices to Riverside to pay; see Accounts below.&lt;br /&gt;
* Accounts&lt;br /&gt;
** 2 invoices to put into Sage&lt;br /&gt;
** Both invoices need paying; See Co-op Bank above&lt;br /&gt;
** Company accounts for last year to sign and return&lt;br /&gt;
* Edinburgh&lt;br /&gt;
** Look for somewhere to eat on Sunday evening&lt;br /&gt;
** Maybe Sunday afternoon too&lt;br /&gt;
** Pick up tickets from station&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=399</id>
		<title>User:Stuart</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=User:Stuart&amp;diff=399"/>
		<updated>2022-03-18T11:56:03Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added TODO to do&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{nav/stuart}}&lt;br /&gt;
My user page. Not much of anything on it at the moment... except...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
=== 18/03/2022 ===&lt;br /&gt;
* Dukes:&lt;br /&gt;
** Cancel standing order (joint account?)&lt;br /&gt;
** Phone/call/go round and organise new friends payments&lt;br /&gt;
* Homeserve:&lt;br /&gt;
** Call them up and see why a 50% rise in price; maybe cancel. Probably cancel.&lt;br /&gt;
* Library books&lt;br /&gt;
** not due til 24/03, but all read now.&lt;br /&gt;
* Co-op Bank&lt;br /&gt;
** Look into / setup new security requirements&lt;br /&gt;
** 2 invoices to Riverside to pay; see Accounts below.&lt;br /&gt;
* Accounts&lt;br /&gt;
** 2 invoices to put into Sage&lt;br /&gt;
** Both invoices need paying; See Co-op Bank above&lt;br /&gt;
** Company accounts for last year to sign and return&lt;br /&gt;
* Edinburgh&lt;br /&gt;
** Look for somewhere to eat on Sunday evening&lt;br /&gt;
** Maybe Sunday afternoon too&lt;br /&gt;
** Pick up tickets from station&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad|My Scratchpad]] ==&lt;br /&gt;
Which is primarily a work-in-progress pad on which I sketch out work in various states of not done.&lt;br /&gt;
&lt;br /&gt;
== [[User:Stuart/Scratchpad II|My Second Scratchpad]] ==&lt;br /&gt;
For when the first scratchpad is in use / gets too full (like, er, now).&lt;br /&gt;
&lt;br /&gt;
== [[:Category:Best Ofs|Best Ofs]] ==&lt;br /&gt;
A record of the tapes I made when I were a nipper, so I might recreate them and wallow in nostalgia and cringe at my appalling music taste.&lt;br /&gt;
&lt;br /&gt;
== Global Bookmarks ==&lt;br /&gt;
* [[User:Stuart/Git Aliases]]&lt;br /&gt;
* [[User:Stuart/Public Keys]]&lt;br /&gt;
* [[User:Stuart/Leave Sheet]]&lt;br /&gt;
* [https://blog.habets.se/2011/07/OpenSSH-certificates.html OpenSSH Certificates]&lt;br /&gt;
* [[Waterdeep: Dragon Heist]]&lt;br /&gt;
* [[Jobs/FLAC Conversion]]&lt;br /&gt;
* [[Tech/Network]]&lt;br /&gt;
* &#039;&#039;DWP Stuff&#039;&#039;&lt;br /&gt;
** [[Noctam/DWP/ACS Test Harness|ACS Test Harness]]&lt;br /&gt;
&lt;br /&gt;
== Additional command line options for EAC ==&lt;br /&gt;
LAME:&lt;br /&gt;
 -V0 --add-id3v2 --pad-id3v2 --ta &amp;quot;%artist%&amp;quot; --tt &amp;quot;%title%&amp;quot; --tg &amp;quot;%genre%&amp;quot; --tl &amp;quot;%albumtitle%&amp;quot; --ty &amp;quot;%year%&amp;quot; --tn &amp;quot;%tracknr%/%numtracks%&amp;quot; %source% %dest%&lt;br /&gt;
(not keen on the track number output, though; I may tweak that)&lt;br /&gt;
&lt;br /&gt;
Looking into the LAME options, you kinda have to hand-craft most of the tags (partially limited LAME implementation; partially limited ID3 implementation).&lt;br /&gt;
[https://hydrogenaud.io/index.php?topic=95917.0 This topic on HydrogenAudio] explains how to about it.&lt;br /&gt;
&lt;br /&gt;
I also installed [https://sourceforge.net/projects/taginspector/ Tag Inspector] to have a look at the tags on &#039;&#039;dream&#039;&#039; - specifically Ayreon tags for multi-disc albums.&lt;br /&gt;
There were quite a few {{c|TXXX: DISCNUMBER}} type things mentioned on, er, &amp;quot;a web page&amp;quot;. Which unfortunately, I can&#039;t find, but it shouldn&#039;t be too hard to piece together.&lt;br /&gt;
----&lt;br /&gt;
FLAC:&lt;br /&gt;
 -6 -V -T &amp;quot;ARTIST=%artist%&amp;quot; -T &amp;quot;TITLE=%title%&amp;quot; -T &amp;quot;ALBUM=%albumtitle%&amp;quot; -T &amp;quot;DATE=%year%&amp;quot; -T &amp;quot;TRACKNUMBER=%tracknr%&amp;quot; -T &amp;quot;GENRE=%genre%&amp;quot; -T &amp;quot;COMMENT=%comment%&amp;quot; -T &amp;quot;BAND=%albuminterpret%&amp;quot; -T &amp;quot;ALBUMARTIST=%artist%&amp;quot; -T &amp;quot;COMPOSER=%composer%&amp;quot; %haslyrics%--tag-from-file=LYRICS=&amp;quot;%lyricsfile%&amp;quot;%haslyrics% -T &amp;quot;DISCNUMBER=%cdnumber%&amp;quot; -T &amp;quot;TOTALDISCS=%totalcds%&amp;quot; -T &amp;quot;TOTALTRACKS=%numtracks%&amp;quot; %hascover%--picture=&amp;quot;%coverfile%&amp;quot;%hascover% %source% -o %dest%&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools/Confluence_Version&amp;diff=397</id>
		<title>Noctam/DWP/ACS Test Harness/Existing System/CISSIM/Command Line Tools/Confluence Version</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools/Confluence_Version&amp;diff=397"/>
		<updated>2021-10-19T15:43:21Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Created page with &amp;quot;&amp;lt;noinclude&amp;gt;{{nav/ACS Test Harness}}&amp;lt;/noinclude&amp;gt; There are many command line tools to do various things within the CISSIM / proxy / data management / testing stub / kitchen  si...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{nav/ACS Test Harness}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
There are many command line tools to do various things within the CISSIM / proxy / data management / testing stub / kitchen  sink application.&lt;br /&gt;
&lt;br /&gt;
This page tries to exhaustively go through all of them. It fails. But it continues to try.&lt;br /&gt;
= File formats =&lt;br /&gt;
There are a few file formats used here.&lt;br /&gt;
&lt;br /&gt;
== base64-ebcdic ==&lt;br /&gt;
EBCDIC data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
This is the form for most PD calls - the content is a record whose definition is held elsewhere (in COBOL copybook-ish form)&lt;br /&gt;
&lt;br /&gt;
Used as input and output to/from [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdutils pdutils] and [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdedit pdedit].&lt;br /&gt;
&lt;br /&gt;
== base64-ascii ==&lt;br /&gt;
ASCII data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
Just like [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#base64-ebcdic base64-ebcdic] except the text fields are encoded into ASCII rather than EBCDIC.&lt;br /&gt;
&lt;br /&gt;
This can be used as input to [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdutils pdutils] when using the {{c|CONVERT2E}} option to convert it to [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#base64-ebcdic base64-ebcdic], and output from [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdutils pdutils] using the {{c|CONVERT2A}} option.&lt;br /&gt;
&lt;br /&gt;
= Filename format =&lt;br /&gt;
Some of the following utilities expect the filename to be in one of a number of specific formats. They use this&lt;br /&gt;
format to embed information about the transaction that the file represents, later extracted by the programs to look up&lt;br /&gt;
related data and/or structures.&lt;br /&gt;
&lt;br /&gt;
== pdconvert formats ==&lt;br /&gt;
The [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdconvert pdconvert], [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdconvertone pdconvertone] and [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdconvertall pdconvertall] programs expect&lt;br /&gt;
the files to be named in one of two dot-separated formats; one with 4 &#039;parts&#039;, one with any other number of &#039;parts&#039;&lt;br /&gt;
as long they number at least 3. The 4 part format is represented by the regex:&lt;br /&gt;
&lt;br /&gt;
 ^(?P&amp;lt;dialognum&amp;gt;[^.]{0,6})\.[^.]*\.[^.]*\.(?P&amp;lt;direction&amp;gt;in|out)$&lt;br /&gt;
 &lt;br /&gt;
 eg. &amp;quot;DCI908.NINO.STUB.out&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The 4 dot-separated parts indicate that this is an &#039;R&#039; (read) mode transaction. A suffix of &#039;in&#039; indicates a &#039;RQST&#039; direction,&lt;br /&gt;
&#039;out&#039; indicates a &#039;RPLY&#039; direction. The dialog is extracted as the first 6 chars of the first part, the mode and the direction&lt;br /&gt;
separated by underscores, so the above example would yield:&lt;br /&gt;
 DCI908_R_RQST&lt;br /&gt;
&lt;br /&gt;
The &#039;any number above 2, except 4&#039; format (?) extracts more information from the filename:&lt;br /&gt;
 ^(?P&amp;lt;dialognum&amp;gt;[^.]*)\.[^.]{3}(?P&amp;lt;messageid&amp;gt;[^.]{4})(?P&amp;lt;txnmode&amp;gt;[^.]).*\.(?P&amp;lt;direction&amp;gt;in|out)$&lt;br /&gt;
 &lt;br /&gt;
 eg. &amp;quot;PD375.CIS6084RCURRINT.153250.634934c5c8d6.in&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This builds the dialog and transaction mode from the filename. The direction is mapped to &#039;RQST&#039; or &#039;RPLY&#039; where the filename&lt;br /&gt;
has &#039;in&#039; or &#039;out&#039;, and the dialog is built up as: {{c|&amp;lt;dialognum&amp;gt;_&amp;lt;messageid&amp;gt;_&amp;lt;txnmode&amp;gt;_&amp;lt;direction&amp;gt;}}. The above example&lt;br /&gt;
would end up with the dialog:&lt;br /&gt;
 PD375_6084_R_RQST&lt;br /&gt;
&lt;br /&gt;
= Programs =&lt;br /&gt;
&lt;br /&gt;
== pdutils ==&lt;br /&gt;
Primarily a library file, used throughout various calls from the daemon programs as well as other utilities.&lt;br /&gt;
It can, however, also be called directly from the command line.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdutils &amp;lt;DUMP/OUT/SAVE/CONVERT2E/CONVERT2A&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;requestfile/replyfile&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   Note that SAVE requires redirected input from an ASCII text string, such as &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
        and that CONVERT requires redirected input from B64 encoded ASCII data &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
=== DUMP ===&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This puts &#039;&#039;everything&#039;&#039; out - ie. all the fields, the fillers and the groups. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
It prefixes the field with the data structure (&#039;&#039;eg&#039;&#039; B4 for binary 4 bytes; X16 for char 16 bytes; N2 for numeric char 2 bytes).&lt;br /&gt;
&lt;br /&gt;
It suffixes the value with the hex value found for the field, separated into space-separated octets, wrapped in parantheses.&lt;br /&gt;
&lt;br /&gt;
=== OUT ===&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This only puts out the fields and fillers. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
=== SAVE ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
I have tweaked the code to work in Windows and... I don&#039;t really know what this does, i.e. I don&#039;t know what format the input file is expected to be in. It&#039;s not the same as the &#039;requestfile/replyfile&#039; used for DUMP and OUT, because that fails with the exception message: &#039;&#039;invalid literal for int() with base 10: &#039;AAAAMMPJ4&#039; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== CONVERT2E ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded ASCII record format to the output file, in base64-encoded EBCDIC record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
=== CONVERT2A ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded EBCDIC record format to the output file, in base64-encoded ASCII record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
== pdedit ==&lt;br /&gt;
Edits the PD and DCI call data via a curses interface, using the COBOL data layouts for the calls.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdedit &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;sourcefile&#039; in this case is the same as the &#039;requestfile/replyfile&#039; provided in pdutils, that is, a file containing base64-encoded EBCDIC data. The &#039;destfile&#039; is in the same format with the changes applied (assuming that you save inside pdedit).&lt;br /&gt;
&lt;br /&gt;
Intriguingly, it appears to ignore the &#039;RQST/RPLY&#039; in the dialog and effectively overwrites it with the RQST/RPLY argument given to the program.&lt;br /&gt;
Not really sure why... that dialog is a bit of a hack, really, I suspect just to avoid multiple keys or too much structure in the config.&lt;br /&gt;
&lt;br /&gt;
 PD350/1151/RQST/R&lt;br /&gt;
might have worked better, with a structured system, be it XML or JSON or YAML or whatever. Since I don&#039;t really understand which things would be better grouped together, I&#039;ll leave this as an idle thought for now.&lt;br /&gt;
&lt;br /&gt;
== pddb ==&lt;br /&gt;
Creates a database entry which effectively maps a response file onto a request.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddb &amp;lt;dialog&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt; &amp;lt;EBCDIC/ASCII&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The output is in the form:&lt;br /&gt;
 &amp;lt;dialog&amp;gt;:&amp;lt;response-file&amp;gt;:&amp;lt;input-field-name=value[;...]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for a PD350 1151 request, you might see something like:&lt;br /&gt;
 $ python cissim/pddb.py PD350_1151_R_RQST requests/pd350-request-e messages/PD350.CIS1151RSTRTDIA.AASTUB.out EBCDIC&lt;br /&gt;
 PD350_1151_R_RQST:PD350.CIS1151RSTRTDIA.AASTUB.out:H1151-NINO=ST000001;H1151-NINO-SFX-TX=A;H1151-RQST-DSS-DAYS=20190213;H1151-RQST-DIA-ID=PD350 ;H1151-RQST-USR-NS-LVL=0000;H1151-RQST-USR-LS-LVL=0000;H1151-RQST-USR-BUS-SYS-NO=43;H1151-DEPT-ID-TP=1;H1151-OFF-LOC-NO=04710;H1151-RQST-SPCFC-BUS-TP=85;&lt;br /&gt;
&lt;br /&gt;
These entries can be appended into a single file, with each entry on a separate line and work together to a form a readonly database of sorts, which the server can use to lookup the response to use based on the values of the inputs provided in the request.&lt;br /&gt;
&lt;br /&gt;
== pdserve ==&lt;br /&gt;
This is what uses the given &#039;database&#039; files from pddb to serve the data based on the requests.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserve &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
It takes a config file which is effectively made up of paths to the &#039;databases&#039; built up using pddb along with an (optional) SSL flag. Each pddb line in the config is something like:&lt;br /&gt;
 &amp;lt;path-to-db-file&amp;gt;:&amp;lt;folder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for example:&lt;br /&gt;
&lt;br /&gt;
configfile.ja030&lt;br /&gt;
 SSL=N&lt;br /&gt;
 pdbase/JA030_01.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_02.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_99.CIS.txt:pdbase&lt;br /&gt;
&lt;br /&gt;
pdserve will expect to find the response files with the names defined in the &#039;database&#039; within the folder specified in the config, so you could have multiple entries here pointing to different databases.&lt;br /&gt;
&lt;br /&gt;
The &#039;port&#039; here is the port it will listen on. This is analogous to a &#039;swimlane&#039; (&#039;&#039;&amp;lt;sigh&amp;gt;&#039;&#039;) and, indeed, the terms are used interchangeably in some places. The default port value used is &#039;&#039;9127&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The recommended way of running this is using {{c|nohup}} so that you can exit the shell and it will continue to run... something like:&lt;br /&gt;
 nohup python pdserve.py configfile.ja030 9130 &amp;gt;ja030.log &amp;amp;&lt;br /&gt;
&lt;br /&gt;
... and of course, the only way to kill it after doing that is by identifying the process that&#039;s running and using the {{c|kill}} command.&lt;br /&gt;
&lt;br /&gt;
Final thing. Quite important.&amp;lt;br/&amp;gt;&lt;br /&gt;
The version I have doesn&#039;t work.&lt;br /&gt;
&lt;br /&gt;
In Python 2:&lt;br /&gt;
  $ python2 ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 68&lt;br /&gt;
      print(s.server_version, end=&#039; &#039;)&lt;br /&gt;
                                 ^&lt;br /&gt;
  SyntaxError: invalid syntax&lt;br /&gt;
&lt;br /&gt;
In Python 3:&lt;br /&gt;
  $ python ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
  Traceback (most recent call last):&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 316, in &amp;lt;module&amp;gt;&lt;br /&gt;
      status = main()&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 260, in main&lt;br /&gt;
      if &#039;#&#039; in line:&lt;br /&gt;
  TypeError: a bytes-like object is required, not &#039;str&#039;&lt;br /&gt;
&lt;br /&gt;
It looks like it&#039;s been half-heartedly converted from 2 to 3, but untested. I&#039;m assuming that either nobody uses it, or it&#039;s been fixed in place wherever it is used and the changes haven&#039;t been reflected back to the source.&lt;br /&gt;
&lt;br /&gt;
== pdcall ==&lt;br /&gt;
(Incidentally, this was a bit messy to get working due to using pycurl, I had to {{c|apt install libcurl4-openssl-dev libssl-dev}} and {{c|pip install pycurl}} in order to get this to work on my Ubuntu machine - no idea what this will require on Mac, but be prepared for pain, given how little access we have.)&lt;br /&gt;
&lt;br /&gt;
This can be used to call the server and test that it&#039;s working correctly.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdcall &amp;lt;swimlane&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&amp;lt;swimlane&amp;gt;&#039; here is the port that the server is listening on.&lt;br /&gt;
&lt;br /&gt;
This opens the request file and displays it using [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdedit pdedit]. After editing and saving, it posts the updated request to the server, captures the response and then opens &#039;&#039;that&#039;&#039; in pdedit too so that you can see (and, indeed, edit) the response, before saving to the output file.&lt;br /&gt;
&lt;br /&gt;
At least, I think that&#039;s what it does - because I couldn&#039;t get [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserve pdserve] running, I had very little to test, so this is conjecture and glancery.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
I&#039;ve just dumped all the &#039;pd&#039; python files here for further processing.&lt;br /&gt;
&lt;br /&gt;
== pdacs ==&lt;br /&gt;
Calls a running ACS instance with an edited request, storing the response into the required output file.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdacs &amp;lt;service&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This pops up a {{c|pdedit}} window to edit the request (actually saving the resultant file to the given location), then creates the&lt;br /&gt;
request by prepending the ACS input header, with the uppercased {{c|service}} embedded in it, to the input file contents.&lt;br /&gt;
&lt;br /&gt;
The ACS input header is fixed (service aside) and has the following content:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 0ed1249b558f||True|101307|            |DCP26PD350  |null|&amp;lt;service&amp;gt;|11606730|null|DWDDE662|2|1548331293|0|500|0|false|P|60|468|&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full input is saved to a file in the current directory called {{c|&amp;lt;requestfile&amp;gt;.acs}}. The response from ACS is saved into the&lt;br /&gt;
provided {{c|replyfile}}.&lt;br /&gt;
&lt;br /&gt;
== pdconvertall ==&lt;br /&gt;
Converts *.in files and corresponding *.out files from a source folder into a destination folder. &lt;br /&gt;
&lt;br /&gt;
 Usage: pdconvertall.py &amp;lt;sourcefolder&amp;gt; &amp;lt;targetfolder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the filename format is significant for this program and, natch, undocumented.&lt;br /&gt;
See [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdconvert formats pdconvert formats] for more details.&lt;br /&gt;
&lt;br /&gt;
This scans the {{c|sourcefolder}} for all files matching {{c|*.in}} which &#039;&#039;do not&#039;&#039; start with the characters {{c|NPS}} and&lt;br /&gt;
have corresponding {{c|*.out}} files and &#039;converts&#039; them to a text-based format for use with [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserved pdserved].&lt;br /&gt;
&lt;br /&gt;
The conversion of the input file is almost identical to the processing done by calling [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdutils pdutils] with the&lt;br /&gt;
dialog and direction specified explicitly, though this program picks up that information from the embedded data in the filename.&lt;br /&gt;
&lt;br /&gt;
The directory structure it creates is:&lt;br /&gt;
 &amp;lt;outputfolder&amp;gt;&lt;br /&gt;
  |- &amp;lt;dialog&amp;gt;&lt;br /&gt;
      |- &amp;lt;rundate-yyyyMMdd&amp;gt;&lt;br /&gt;
          |- &amp;lt;nino&amp;gt;.DATA&lt;br /&gt;
&lt;br /&gt;
The format is text-based in the style of the [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdutils pdutils] format. The [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserved pdserved] server then reads&lt;br /&gt;
from the directory when it is processing the requests and determining the responses to return. The files can be modified in&lt;br /&gt;
place, or new files can be placed there. The server will pick up any external changes made to these files.&lt;br /&gt;
 &lt;br /&gt;
== pdconvertone ==&lt;br /&gt;
This is a thin wrapper around [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdconvertall pdconvertall] which works for a single input and output file. That is, it&lt;br /&gt;
still expects a {{c|*.in}} and corresponding {{c|*.out}} file to convert, and it emits the output into the directory&lt;br /&gt;
structure described in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdconvertall pdconvertall].&lt;br /&gt;
 Usage: pdconvertone.py &amp;lt;sourcespec&amp;gt; &amp;lt;targetfolder&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
This calls {{c|pdconvertall}} with the single file identified by {{c|sourcespec}}. Note that if the file begins with the&lt;br /&gt;
characters {{c|NPS}} or there is no corresponding {{c|*.out}} file, it will be skipped&lt;br /&gt;
&lt;br /&gt;
== pdconvert ==&lt;br /&gt;
Converts a single file into its text-based format, emitting the output to stdout.&lt;br /&gt;
 &lt;br /&gt;
 Usage: pdconvert.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This does not have the same restrictions as [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdconvertall pdconvertall] and [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdconvertone pdconvertone] - i.e.&lt;br /&gt;
it does not require corresponding {{c|*.in}} and {{c|*.out}} files, though the given file&#039;s filename must be one of those.&lt;br /&gt;
It will still not work for NPS files (though, unlike the above programs, it will try and probably crash and burn in the&lt;br /&gt;
attempt).&lt;br /&gt;
&lt;br /&gt;
== pddata ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This has a load of functions in it, only some of which I understand.&lt;br /&gt;
The main one appears to be {{c|getninodata}} which, typical cissim style, takes 10 arguments (interrobang?!) and has...&lt;br /&gt;
well, &#039;&#039;some&#039;&#039; documentation which concentrates on one or two arguments and expects a fairly solid understanding of&lt;br /&gt;
what it&#039;s doing before you start reading.&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to have to come back to this to try and grasp it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This technically can be executed, but it looks like the stuff in the main call is just development stuff - testing&lt;br /&gt;
other functions and such like.&lt;br /&gt;
&lt;br /&gt;
== pddump ==&lt;br /&gt;
This dumps the data from the given (base64-encoded EBCDIC) file to the console in text form with square brackets to enclose&lt;br /&gt;
the data values. Note: This uses the [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdconvert formats pdconvert formats] for the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddump.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a call to [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#DUMP DUMP] which takes the dialog / direction arguments from the filename&lt;br /&gt;
format rather than requiring them to be stated explicitly.&lt;br /&gt;
&lt;br /&gt;
== pdout ==&lt;br /&gt;
This dumps the data from the given (base64-encoded EBCDIC) file to the console in text form with square brackets to enclose&lt;br /&gt;
the data values. Note: This uses the [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdconvert formats pdconvert formats] for the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdout.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a call to [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#OUT OUT] which takes the dialog / direction arguments from the filename&lt;br /&gt;
&lt;br /&gt;
== pdparams ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contains a single function: {{c|processparams}}. This function also exists in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdutils pdutils], and it looks like that&lt;br /&gt;
one is used but this one is not. I presume it&#039;s obsolete, though there&#039;s no indication of that in the code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== pdproxy ==&lt;br /&gt;
A very straightforward proxy which writes the request and response of any CIS calls made to it to files in the current&lt;br /&gt;
directory.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdproxy &amp;lt;swimlane&amp;gt; &amp;lt;configfile&amp;gt; &amp;lt;folder&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
The swimlane determines whether the &#039;real&#039; CIS is called or whether the &#039;SIM&#039; is called. Basically, if the {{c|swimlane}}&lt;br /&gt;
argument is in the ranges: 14-15 or 17-28 (both inclusive), onward calls from the proxy will go to CIS proper. Any other&lt;br /&gt;
value is treated as the port that the simulator is listening on and it will be connected to using that port number.&lt;br /&gt;
&lt;br /&gt;
== pdreadall ==&lt;br /&gt;
Reads all registered dialogs and calls them for the specified NINo and optional surname.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadall &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;folder&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
 &lt;br /&gt;
== pdreadoneedit ==&lt;br /&gt;
Calls a specified dialog in CIS (or a CIS simulator) for a given NINo and optional surname. This allows the editing of&lt;br /&gt;
the record to be sent in the request before the call is made. The input and output files are created (I &#039;&#039;think&#039;&#039;) in&lt;br /&gt;
the current directory with the appropriate filename format.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadoneedit &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== pdreadone ==&lt;br /&gt;
Calls a specified dialog in CIS (or a CIS simulator) for a given NINo and optional surname. This does not allow the&lt;br /&gt;
editing of the record to be sent in the request before the call is made. The input and output files are created (I&lt;br /&gt;
&#039;&#039;think&#039;&#039;) in the current directory with the appropriate filename format.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadone &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
 &lt;br /&gt;
== pdscreen ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This file contains a single class &#039;{{c|Textbox}}&#039; which provides the editing widget used in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdedit pdedit] to&lt;br /&gt;
edit a value in a record file.&lt;br /&gt;
&lt;br /&gt;
== pdserved ==&lt;br /&gt;
An upgraded version of [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserve pdserve] with NPS support and separate message directories.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserved.py &amp;lt;port&amp;gt; -P &amp;lt;pddfolder&amp;gt; -D &amp;lt;dcifolder&amp;gt; [-N &amp;lt;npsfolder&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Aside from working in Python3 and adding the NPS handling which was added in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdservep pdservep], this primarily&lt;br /&gt;
implements the separation of the data directories into &#039;PD&#039;, &#039;DCI&#039; and &#039;NPS&#039; folders. These could all be the same&lt;br /&gt;
folder (I think), but the option is there now to have different ones for each type. Presumably, you might want&lt;br /&gt;
different PD responses for different services, but you want to use the same DCI/NPS responses each time, so this&lt;br /&gt;
saves on a load of copying and pasting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== pdservedt ==&lt;br /&gt;
[https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserved pdserved] with a {{c|process_wait()}} function, which loads the timing data from the hardcoded location&lt;br /&gt;
at {{c|../serve/transtimes.py}}. Not ideal - it requires running the program from a specific directory, and, of course,&lt;br /&gt;
this is undocumented (as far as I can see anyway).&lt;br /&gt;
&lt;br /&gt;
The timing data is a map of timings against dialog; the example in the code is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# timings are a list, first tuple is times to cycle through, rest are exceptional count/time pairs&lt;br /&gt;
# &#039;CP650_1151_R_RPLY&#039;:  [(0.15, 0.25, 0.21, 0.17, 0.20, 0.16), (20, 2.3), (100, 28)],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Basically, it will cycle through the first tuple of timings, except when the count for a given dialog reaches the&lt;br /&gt;
first value in any of the following tuples. If it does (in this case, the 20th and 100th time a dialog is processed&lt;br /&gt;
within the server), it will use the timing associated with that number. Reasonably straightforward.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This seems the most sensible one to draw a &#039;proper&#039; version from. If we want to re-do the timing, then&lt;br /&gt;
we could branch from [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserved pdserved] instead... it certainly needs changing a bit (the config is dire - a&lt;br /&gt;
hardcoded filename in a directory reached using a relative path... ugh), and it&#039;s quite simplistic, but it does&lt;br /&gt;
work.&lt;br /&gt;
&lt;br /&gt;
== pdservep ==&lt;br /&gt;
This is [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserve pdserve] with more NPS handling (and fixed for Python3).&lt;br /&gt;
&lt;br /&gt;
The NPS changes in here appear to be included in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserved pdserved] too, so this and [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserve pdserve], at&lt;br /&gt;
first glance, would seem to be obsolete.&lt;br /&gt;
&lt;br /&gt;
== pdshow ==&lt;br /&gt;
Shows and edits a base64-encoded file, extracting the dialog and direction from the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdshow.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a wrapper around a call to [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdedit pdedit] which extracts the dialog and direction from the filename,&lt;br /&gt;
rather than needing it specified explicitly.&lt;br /&gt;
&lt;br /&gt;
== pdstub ==&lt;br /&gt;
Stub server which provides more flexible lookup and response-modification than pdserve.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdstub &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
This program provides a basic server which serves PD, DCI and NPS. Rather than a straight NINo/Rundate lookup, it&lt;br /&gt;
uses search parameters to determine which response file to return for a request, and it allows replacement of data&lt;br /&gt;
in that response file with static parameters, or inputs derived from the request.&lt;br /&gt;
&lt;br /&gt;
It uses a single messages folder, rather than the separated responses folder of pdserve and each request/response&lt;br /&gt;
mapping is defined in a single line within the config file.&lt;br /&gt;
&lt;br /&gt;
== pdstubt ==&lt;br /&gt;
This is [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdstub pdstub] with a {{c|process_wait()}} function, which works exactly like the same function in&lt;br /&gt;
[https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdservedt pdservedt].&lt;br /&gt;
&lt;br /&gt;
== pdstubtt ==&lt;br /&gt;
This is [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdstubt pdstubt] with a multi-threaded HTTP server. It&#039;s a fairly trivial change to the code; I haven&#039;t&lt;br /&gt;
looked through it to see if there are any thread localisation issues in there - I&#039;m assuming not, because this is&lt;br /&gt;
being used as is at the moment, and that would probably have been noticed by now.&lt;br /&gt;
&lt;br /&gt;
This seems to me to be the most mature of the pdstub implementations - multithreading the server is a no-brainer,&lt;br /&gt;
in my humble, and the timings can be ignored. It still has the problem of a hardcoded timing config, but that&lt;br /&gt;
shouldn&#039;t be too hard to fix in a less fragile manner.&lt;br /&gt;
&lt;br /&gt;
== pdtux ==&lt;br /&gt;
A Tuxedo server which advertises a few tux operations, namely:&lt;br /&gt;
* ping&lt;br /&gt;
* DCI913&lt;br /&gt;
* DCI923&lt;br /&gt;
* VMERCIS&lt;br /&gt;
* RESETCOUNTER&lt;br /&gt;
&lt;br /&gt;
This extracts the data out of the request packet and gets the data using [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pddata pddata],&lt;br /&gt;
returning the resultant data (the whole thing for DCI calls, separated CIS header and W90 header for PDD calls).&lt;br /&gt;
&lt;br /&gt;
There are no arguments to this program, but it does require the installation of the &#039;tuxedo&#039; python module.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
And the non-&#039;pd&#039; python files:&lt;br /&gt;
&lt;br /&gt;
== certs ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Holds the paths to the various certificates used within cissim. 2 groups of cert and cacert files for connecting to&lt;br /&gt;
DCI and PD; 2 groups of cert and private key files for serving.&lt;br /&gt;
&lt;br /&gt;
Used in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdcall pdcall], [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserve pdserve] and [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdstub pdstub] programs, and in some test functions&lt;br /&gt;
in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#sslutils sslutils].&lt;br /&gt;
&lt;br /&gt;
== checkport ==&lt;br /&gt;
&#039;&#039;Redundant&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Checks if it&#039;s possible to connect to {{c|localhost:9127}}. That&#039;s it really. &lt;br /&gt;
&lt;br /&gt;
Basically, a python version of:&lt;br /&gt;
 netstat -nap | grep &#039;:9127.*LISTEN&#039;&lt;br /&gt;
&lt;br /&gt;
== dci9n3rec ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Technically, this can be called from the command line, but it seems a bit pointless. It appears to read in a file&lt;br /&gt;
called &#039;in&#039; in the current directory and, uh, loads it into a DCI9n3 record structure and prints it. I guess it&#039;s&lt;br /&gt;
for testing purposes.&lt;br /&gt;
&lt;br /&gt;
Anyway, this contains the definition of a DCI913 or DCI923 record, packed to byte alignment for the fields, with&lt;br /&gt;
the 12 fields and their sizes defined as fixed length byte arrays.&lt;br /&gt;
&lt;br /&gt;
It&#039;s only used in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdtux pdtux] for extracting the data from an incoming DCI struct. The equivalent for a PD&lt;br /&gt;
record is [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#w80construct w80construct]&lt;br /&gt;
&lt;br /&gt;
== extractodis ==&lt;br /&gt;
&#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Usage: extractodis.py &amp;lt;log_filename&amp;gt; [&amp;lt;PID&amp;gt;] [&amp;lt;starttime&amp;gt;] [&amp;lt;endtime&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
This is completely out there. So. It takes the filename and creates 3 shell scripts with names based on it, which&lt;br /&gt;
perform some function on the payload (base64-encoded ASCII). These scripts are:&lt;br /&gt;
* {{c|&amp;lt;filename&amp;gt;.write.sh}}: to write the transaction for ACS emulation (just writing the record out)&lt;br /&gt;
* {{c|&amp;lt;filename&amp;gt;.conv.sh}}: to write the transaction for CIS emulation (calling [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#CONVERT2E CONVERT2E])&lt;br /&gt;
* {{c|&amp;lt;filename&amp;gt;.db.sh}}: to write the transaction to the &#039;database&#039; for serving (calling [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pddb pddb])&lt;br /&gt;
&lt;br /&gt;
Aside from some very ropey python issues (mix of tabs and spaces in leading whitespace - very verboten in python),&lt;br /&gt;
it&#039;s just a very odd way of doing things.&lt;br /&gt;
&lt;br /&gt;
This is the oldschool format; it&#039;s dealing with the records as is, rather than moving them to the date/nino-based&lt;br /&gt;
database used by [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserved pdserved] and beyond; the pddb output is used in the original&lt;br /&gt;
[https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserve pdserve] program too. It&#039;s still valid for the &#039;write.sh&#039;, I guess, but I suspect that&#039;s all.&lt;br /&gt;
&lt;br /&gt;
== fpcapprec ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
This was used in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdtux pdtux], but is no longer used. The using has been deleted, so I can&#039;t see the context.&lt;br /&gt;
&lt;br /&gt;
== getfieldoffset ==&lt;br /&gt;
&#039;&#039;Test file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
I&#039;m pretty sure this is just testing that the [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdlayouts.pd pdlayouts.pd] method is working&lt;br /&gt;
correctly.&lt;br /&gt;
&lt;br /&gt;
== key ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This provides a few constants for keycodes, used in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdedit pdedit] and [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdscreen pdscreen].&lt;br /&gt;
&lt;br /&gt;
To be honest, it really needn&#039;t be here. The function key and some other constants are already defined in the curses&lt;br /&gt;
module; most of the rest are defined in the curses.ascii module. {{c|UP_LIST}} is home-made, but really doesn&#039;t&lt;br /&gt;
deserve its own file; any home-grown key values could go in the [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdscreen pdscreen] file.&lt;br /&gt;
&lt;br /&gt;
== loadninos ==&lt;br /&gt;
&#039;&#039;Library File&#039;&#039; and &#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Usage: loadninos.py &amp;lt;office-file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Used in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdstub pdstub] and its variants.&lt;br /&gt;
&lt;br /&gt;
Loads NINOs from a CSV file (actually looks like a &#039;Whitespace-separated variables&#039; style file, though it has a&lt;br /&gt;
name of {{c|csvfile}} within the code). This looks for input in the form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 SVC     Office&lt;br /&gt;
 JSOV    109809&lt;br /&gt;
 JSRZ    107476&lt;br /&gt;
 JSFP    107038&lt;br /&gt;
 JSLH    103401&lt;br /&gt;
 JSKR    103838&lt;br /&gt;
 JSLF    102636&lt;br /&gt;
 JSGR    102805&lt;br /&gt;
 JSRT    100598&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above example is half-inched from the code. The code is ferociously simplistic, but I guess it does the job.&lt;br /&gt;
&lt;br /&gt;
Anyway, it takes the &#039;Office&#039; from the lines in the &#039;CSV&#039; file, strips the leading digit from it, then looks for&lt;br /&gt;
another &#039;csv&#039; file with that office number as a filename, in the same directory as the provided CSV file, so the&lt;br /&gt;
above will look for &#039;09809.csv&#039;, &#039;07476.csv&#039; etc. It will load that file, taking the first 8 chars of each line&lt;br /&gt;
as a NINo and then maps the office to that NINo, such that each NINo has the office number of the file that it&lt;br /&gt;
was loaded from mapped against it.&lt;br /&gt;
&lt;br /&gt;
This is used in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdstub pdstub] to get the office for a particular NINo, which is then used as part of the&lt;br /&gt;
response in a DCI913 call. The stub loads the NINos using this function passing the {{c|OFFICECSVFILE}} config&lt;br /&gt;
parameter value to load them from. It doesn&#039;t handle errors well, but I guess once it&#039;s running, you don&#039;t&lt;br /&gt;
change it that much.&lt;br /&gt;
&lt;br /&gt;
== logextract ==&lt;br /&gt;
&#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Usage: logextract.py &amp;lt;logfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Extracts a {{c|DCI913CopyRecord}} from a logfile. It&#039;s a bit hacky - in the middle of it, it does some strange&lt;br /&gt;
stuff with the string &#039;127.0.0.1&#039;; I presume the logfile isn&#039;t really designed for extracting records from and&lt;br /&gt;
so this has to hardcode some messing around into it. It&#039;s very fragile - logfiles aren&#039;t typically structured&lt;br /&gt;
output (or, at least, not structured in this way).&lt;br /&gt;
&lt;br /&gt;
== npsload ==&lt;br /&gt;
&#039;&#039;Executable&#039;&#039; - this is an executable only; no part of it is called by other programs / libraries.&lt;br /&gt;
&lt;br /&gt;
 Usage: npsload &amp;lt;folder&amp;gt; &amp;lt;csvfile&amp;gt; &amp;lt;listfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loads the {{c|csvfile}} from {{c|folder}} (i.e. the file is just the filename, not the {{c|/path/to/file}}),&lt;br /&gt;
and writes all output, including the {{c|listfile}} in the same folder.&lt;br /&gt;
&lt;br /&gt;
The CSV file is defined as:&lt;br /&gt;
 Entry/ies  Description&lt;br /&gt;
 1          NINo&lt;br /&gt;
 2          Surname&lt;br /&gt;
 3          Office&lt;br /&gt;
 4          LOP 25x Past&lt;br /&gt;
 5-20       NUBS2 record x 4&lt;br /&gt;
 21-36      LOP record x 4&lt;br /&gt;
 37         Data not found flag&lt;br /&gt;
 38         BFM Return Code&lt;br /&gt;
 39         RDS Code&lt;br /&gt;
&lt;br /&gt;
Each NUBS2 record and LOP record is made up of 4 comma-separated entries, with the fields:&lt;br /&gt;
 Entry Description&lt;br /&gt;
 1     Year&lt;br /&gt;
 2     x25&lt;br /&gt;
 3     x50&lt;br /&gt;
 4     Priority&lt;br /&gt;
&lt;br /&gt;
This program loops through all the NINo entries, and writes an XML file for each one, calling it {{c|NPSrply.&amp;lt;nino&amp;gt;.xml}},&lt;br /&gt;
adding an entry into the {{c|listfile}} for each file it created. It adds a final &#039;NINO not found&#039; entry to the listfile&lt;br /&gt;
and exits.&lt;br /&gt;
&lt;br /&gt;
== paths ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contains the paths used for calls to PD, DCI and NPS, as well as a few functions which operate on and around those paths.&lt;br /&gt;
&lt;br /&gt;
This is used liberally throughout the rest of the CISSim suite.&lt;br /&gt;
&lt;br /&gt;
== ports ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This just holds all the ports for the CIS swimlanes and returns the appropriate ports for a given swimlane when asked, in the form {{c|(pdd-port, dci-port, host)}}.&lt;br /&gt;
&lt;br /&gt;
== selectserver ==&lt;br /&gt;
&#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
I have no idea what this is trying to do. It&#039;s messing around with servers and message queues, but I&#039;m a bit lost.&lt;br /&gt;
&lt;br /&gt;
== sslutils ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contains functions to call servers using SSL certificates. Used in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdacs pdacs], [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdcall pdcall], [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdproxy pdproxy]&lt;br /&gt;
and [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#teststub teststub]&lt;br /&gt;
&lt;br /&gt;
== temp ==&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
Seems to be a copy of [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdserved pdserved] with some testing code in there.&lt;br /&gt;
&lt;br /&gt;
== teststub ==&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
Tests connecting to the CIS Sim using curl and a socket. Prints things. Not particularly useful.&lt;br /&gt;
&lt;br /&gt;
== utils ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
A variety of utility functions; apparently not used anywhere.&lt;br /&gt;
&lt;br /&gt;
== vmeutils ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039; and &#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Usage: vmeutils &amp;lt;D/B&amp;gt; &amp;lt;date&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some VME date functions and a small utility executable to convert a date into a VME date ({{c|&#039;B&#039;}}, obviously) or&lt;br /&gt;
a VME date into a date ({{c|&#039;D&#039;}}). A &#039;VME date&#039; in this context is the number of days since 29/02/1852.&lt;br /&gt;
&lt;br /&gt;
== w80construct ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Like [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#dci9n3rec dci9n3rec], this can be called from the command line, but it also seems a bit pointless.&lt;br /&gt;
I guess it&#039;s for testing purposes.&lt;br /&gt;
&lt;br /&gt;
Anyway, this contains the definition of a W80 record, packed to byte alignment for the fields, with the various fields&lt;br /&gt;
and their sizes defined mostly as fixed length byte arrays, though there are a few integer and long integer fields&lt;br /&gt;
defined too - these will be compiler-dependent, so I guess that&#039;s how the tux that it&#039;s interfacing with/mocking&lt;br /&gt;
works too?&lt;br /&gt;
&lt;br /&gt;
It&#039;s only used in [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#pdtux pdtux] for extracting the data from an incoming DCI struct. The equivalent for a DCI&lt;br /&gt;
record is [https://dwpdigital.atlassian.net/wiki/spaces/BO/pages/132486857398/CIS+Simulator+Python+System#dci9n3rec dci9n3rec]&lt;br /&gt;
&lt;br /&gt;
= Files in pdlayouts =&lt;br /&gt;
&lt;br /&gt;
== pdlayouts/PDM ==&lt;br /&gt;
The &#039;PD Map&#039; contains the fields used in the CIS header and the W80 PD header, including their name, data type and length and&lt;br /&gt;
an optional &#039;style&#039; type argument which provides metadata for the field, &#039;&#039;eg.&#039;&#039; {{c|nino8}} indicates the first 8 chars of&lt;br /&gt;
a NINo, {{c|runtime8}} indicates that it contains a time in the format {{c|%H%M%S%f}}, {{c|vmedate}} indicates that the field&lt;br /&gt;
contains a &#039;VME date&#039;, ie. the number of days since 29/02/1852.&lt;br /&gt;
&lt;br /&gt;
These &#039;style&#039; arguments are used in {{c|pdutils.makerequestfile}} to autopopulate various fields for input based on the static&lt;br /&gt;
&#039;RUNDATE&#039; parameter value.&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=396</id>
		<title>Noctam/DWP/ACS Test Harness/Existing System/CISSIM/Command Line Tools</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=396"/>
		<updated>2021-10-19T08:28:16Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Removed extraneous .py&amp;#039;s&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{nav/ACS Test Harness}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
There are many command line tools to do various things within the CISSIM / proxy / data management / testing stub / kitchen  sink application.&lt;br /&gt;
&lt;br /&gt;
This page tries to exhaustively go through all of them. It fails. But it continues to try.&lt;br /&gt;
= File formats =&lt;br /&gt;
There are a few file formats used here.&lt;br /&gt;
&lt;br /&gt;
== base64-ebcdic ==&lt;br /&gt;
EBCDIC data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
This is the form for most PD calls - the content is a record whose definition is held elsewhere (in COBOL copybook-ish form)&lt;br /&gt;
&lt;br /&gt;
Used as input and output to/from [[#pdutils|pdutils]] and [[#pdedit|pdedit]].&lt;br /&gt;
&lt;br /&gt;
== base64-ascii ==&lt;br /&gt;
ASCII data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
Just like [[#base64-ebcdic|base64-ebcdic]] except the text fields are encoded into ASCII rather than EBCDIC.&lt;br /&gt;
&lt;br /&gt;
This can be used as input to [[#pdutils|pdutils]] when using the {{c|CONVERT2E}} option to convert it to [[#base64-ebcdic|base64-ebcdic]], and output from [[#pdutils|pdutils]] using the {{c|CONVERT2A}} option.&lt;br /&gt;
&lt;br /&gt;
= Filename format =&lt;br /&gt;
Some of the following utilities expect the filename to be in one of a number of specific formats. They use this&lt;br /&gt;
format to embed information about the transaction that the file represents, later extracted by the programs to look up&lt;br /&gt;
related data and/or structures.&lt;br /&gt;
&lt;br /&gt;
== pdconvert formats ==&lt;br /&gt;
The [[#pdconvert|pdconvert]], [[#pdconvertone|pdconvertone]] and [[#pdconvertall|pdconvertall]] programs expect&lt;br /&gt;
the files to be named in one of two dot-separated formats; one with 4 &#039;parts&#039;, one with any other number of &#039;parts&#039;&lt;br /&gt;
as long they number at least 3. The 4 part format is represented by the regex:&lt;br /&gt;
&lt;br /&gt;
 ^(?P&amp;lt;dialognum&amp;gt;[^.]{0,6})\.[^.]*\.[^.]*\.(?P&amp;lt;direction&amp;gt;in|out)$&lt;br /&gt;
 &lt;br /&gt;
 eg. &amp;quot;DCI908.NINO.STUB.out&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The 4 dot-separated parts indicate that this is an &#039;R&#039; (read) mode transaction. A suffix of &#039;in&#039; indicates a &#039;RQST&#039; direction,&lt;br /&gt;
&#039;out&#039; indicates a &#039;RPLY&#039; direction. The dialog is extracted as the first 6 chars of the first part, the mode and the direction&lt;br /&gt;
separated by underscores, so the above example would yield:&lt;br /&gt;
 DCI908_R_RQST&lt;br /&gt;
&lt;br /&gt;
The &#039;any number above 2, except 4&#039; format (?) extracts more information from the filename:&lt;br /&gt;
 ^(?P&amp;lt;dialognum&amp;gt;[^.]*)\.[^.]{3}(?P&amp;lt;messageid&amp;gt;[^.]{4})(?P&amp;lt;txnmode&amp;gt;[^.]).*\.(?P&amp;lt;direction&amp;gt;in|out)$&lt;br /&gt;
 &lt;br /&gt;
 eg. &amp;quot;PD375.CIS6084RCURRINT.153250.634934c5c8d6.in&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This builds the dialog and transaction mode from the filename. The direction is mapped to &#039;RQST&#039; or &#039;RPLY&#039; where the filename&lt;br /&gt;
has &#039;in&#039; or &#039;out&#039;, and the dialog is built up as: {{c|&amp;lt;dialognum&amp;gt;_&amp;lt;messageid&amp;gt;_&amp;lt;txnmode&amp;gt;_&amp;lt;direction&amp;gt;}}. The above example&lt;br /&gt;
would end up with the dialog:&lt;br /&gt;
 PD375_6084_R_RQST&lt;br /&gt;
&lt;br /&gt;
= Programs =&lt;br /&gt;
&lt;br /&gt;
== pdutils ==&lt;br /&gt;
Primarily a library file, used throughout various calls from the daemon programs as well as other utilities.&lt;br /&gt;
It can, however, also be called directly from the command line.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdutils &amp;lt;DUMP/OUT/SAVE/CONVERT2E/CONVERT2A&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;requestfile/replyfile&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   Note that SAVE requires redirected input from an ASCII text string, such as &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
        and that CONVERT requires redirected input from B64 encoded ASCII data &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
=== DUMP ===&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This puts &#039;&#039;everything&#039;&#039; out - ie. all the fields, the fillers and the groups. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
It prefixes the field with the data structure (&#039;&#039;eg&#039;&#039; B4 for binary 4 bytes; X16 for char 16 bytes; N2 for numeric char 2 bytes).&lt;br /&gt;
&lt;br /&gt;
It suffixes the value with the hex value found for the field, separated into space-separated octets, wrapped in parantheses.&lt;br /&gt;
&lt;br /&gt;
=== OUT ===&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This only puts out the fields and fillers. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
=== SAVE ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
I have tweaked the code to work in Windows and... I don&#039;t really know what this does, i.e. I don&#039;t know what format the input file is expected to be in. It&#039;s not the same as the &#039;requestfile/replyfile&#039; used for DUMP and OUT, because that fails with the exception message: &#039;&#039;invalid literal for int() with base 10: &#039;AAAAMMPJ4&#039; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== CONVERT2E ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded ASCII record format to the output file, in base64-encoded EBCDIC record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
=== CONVERT2A ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded EBCDIC record format to the output file, in base64-encoded ASCII record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
== pdedit ==&lt;br /&gt;
Edits the PD and DCI call data via a curses interface, using the COBOL data layouts for the calls.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdedit &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;sourcefile&#039; in this case is the same as the &#039;requestfile/replyfile&#039; provided in pdutils, that is, a file containing base64-encoded EBCDIC data. The &#039;destfile&#039; is in the same format with the changes applied (assuming that you save inside pdedit).&lt;br /&gt;
&lt;br /&gt;
Intriguingly, it appears to ignore the &#039;RQST/RPLY&#039; in the dialog and effectively overwrites it with the RQST/RPLY argument given to the program.&lt;br /&gt;
Not really sure why... that dialog is a bit of a hack, really, I suspect just to avoid multiple keys or too much structure in the config.&lt;br /&gt;
&lt;br /&gt;
 PD350/1151/RQST/R&lt;br /&gt;
might have worked better, with a structured system, be it XML or JSON or YAML or whatever. Since I don&#039;t really understand which things would be better grouped together, I&#039;ll leave this as an idle thought for now.&lt;br /&gt;
&lt;br /&gt;
== pddb ==&lt;br /&gt;
Creates a database entry which effectively maps a response file onto a request.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddb &amp;lt;dialog&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt; &amp;lt;EBCDIC/ASCII&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The output is in the form:&lt;br /&gt;
 &amp;lt;dialog&amp;gt;:&amp;lt;response-file&amp;gt;:&amp;lt;input-field-name=value[;...]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for a PD350 1151 request, you might see something like:&lt;br /&gt;
 $ python cissim/pddb.py PD350_1151_R_RQST requests/pd350-request-e messages/PD350.CIS1151RSTRTDIA.AASTUB.out EBCDIC&lt;br /&gt;
 PD350_1151_R_RQST:PD350.CIS1151RSTRTDIA.AASTUB.out:H1151-NINO=ST000001;H1151-NINO-SFX-TX=A;H1151-RQST-DSS-DAYS=20190213;H1151-RQST-DIA-ID=PD350 ;H1151-RQST-USR-NS-LVL=0000;H1151-RQST-USR-LS-LVL=0000;H1151-RQST-USR-BUS-SYS-NO=43;H1151-DEPT-ID-TP=1;H1151-OFF-LOC-NO=04710;H1151-RQST-SPCFC-BUS-TP=85;&lt;br /&gt;
&lt;br /&gt;
These entries can be appended into a single file, with each entry on a separate line and work together to a form a readonly database of sorts, which the server can use to lookup the response to use based on the values of the inputs provided in the request.&lt;br /&gt;
&lt;br /&gt;
== pdserve ==&lt;br /&gt;
This is what uses the given &#039;database&#039; files from pddb to serve the data based on the requests.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserve &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
It takes a config file which is effectively made up of paths to the &#039;databases&#039; built up using pddb along with an (optional) SSL flag. Each pddb line in the config is something like:&lt;br /&gt;
 &amp;lt;path-to-db-file&amp;gt;:&amp;lt;folder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for example:&lt;br /&gt;
&lt;br /&gt;
configfile.ja030&lt;br /&gt;
 SSL=N&lt;br /&gt;
 pdbase/JA030_01.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_02.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_99.CIS.txt:pdbase&lt;br /&gt;
&lt;br /&gt;
pdserve will expect to find the response files with the names defined in the &#039;database&#039; within the folder specified in the config, so you could have multiple entries here pointing to different databases.&lt;br /&gt;
&lt;br /&gt;
The &#039;port&#039; here is the port it will listen on. This is analogous to a &#039;swimlane&#039; (&#039;&#039;&amp;lt;sigh&amp;gt;&#039;&#039;) and, indeed, the terms are used interchangeably in some places. The default port value used is &#039;&#039;9127&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The recommended way of running this is using {{c|nohup}} so that you can exit the shell and it will continue to run... something like:&lt;br /&gt;
 nohup python pdserve.py configfile.ja030 9130 &amp;gt;ja030.log &amp;amp;&lt;br /&gt;
&lt;br /&gt;
... and of course, the only way to kill it after doing that is by identifying the process that&#039;s running and using the {{c|kill}} command.&lt;br /&gt;
&lt;br /&gt;
Final thing. Quite important.&amp;lt;br/&amp;gt;&lt;br /&gt;
The version I have doesn&#039;t work.&lt;br /&gt;
&lt;br /&gt;
In Python 2:&lt;br /&gt;
  $ python2 ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 68&lt;br /&gt;
      print(s.server_version, end=&#039; &#039;)&lt;br /&gt;
                                 ^&lt;br /&gt;
  SyntaxError: invalid syntax&lt;br /&gt;
&lt;br /&gt;
In Python 3:&lt;br /&gt;
  $ python ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
  Traceback (most recent call last):&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 316, in &amp;lt;module&amp;gt;&lt;br /&gt;
      status = main()&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 260, in main&lt;br /&gt;
      if &#039;#&#039; in line:&lt;br /&gt;
  TypeError: a bytes-like object is required, not &#039;str&#039;&lt;br /&gt;
&lt;br /&gt;
It looks like it&#039;s been half-heartedly converted from 2 to 3, but untested. I&#039;m assuming that either nobody uses it, or it&#039;s been fixed in place wherever it is used and the changes haven&#039;t been reflected back to the source.&lt;br /&gt;
&lt;br /&gt;
== pdcall ==&lt;br /&gt;
(Incidentally, this was a bit messy to get working due to using pycurl, I had to {{c|apt install libcurl4-openssl-dev libssl-dev}} and {{c|pip install pycurl}} in order to get this to work on my Ubuntu machine - no idea what this will require on Mac, but be prepared for pain, given how little access we have.)&lt;br /&gt;
&lt;br /&gt;
This can be used to call the server and test that it&#039;s working correctly.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdcall &amp;lt;swimlane&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&amp;lt;swimlane&amp;gt;&#039; here is the port that the server is listening on.&lt;br /&gt;
&lt;br /&gt;
This opens the request file and displays it using [[#pdedit|pdedit]]. After editing and saving, it posts the updated request to the server, captures the response and then opens &#039;&#039;that&#039;&#039; in pdedit too so that you can see (and, indeed, edit) the response, before saving to the output file.&lt;br /&gt;
&lt;br /&gt;
At least, I think that&#039;s what it does - because I couldn&#039;t get [[#pdserve|pdserve]] running, I had very little to test, so this is conjecture and glancery.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
I&#039;ve just dumped all the &#039;pd&#039; python files here for further processing.&lt;br /&gt;
&lt;br /&gt;
== pdacs ==&lt;br /&gt;
Calls a running ACS instance with an edited request, storing the response into the required output file.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdacs &amp;lt;service&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This pops up a {{c|pdedit}} window to edit the request (actually saving the resultant file to the given location), then creates the&lt;br /&gt;
request by prepending the ACS input header, with the uppercased {{c|service}} embedded in it, to the input file contents.&lt;br /&gt;
&lt;br /&gt;
The ACS input header is fixed (service aside) and has the following content:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 0ed1249b558f||True|101307|            |DCP26PD350  |null|&amp;lt;service&amp;gt;|11606730|null|DWDDE662|2|1548331293|0|500|0|false|P|60|468|&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full input is saved to a file in the current directory called {{c|&amp;lt;requestfile&amp;gt;.acs}}. The response from ACS is saved into the&lt;br /&gt;
provided {{c|replyfile}}.&lt;br /&gt;
&lt;br /&gt;
== pdconvertall ==&lt;br /&gt;
Converts *.in files and corresponding *.out files from a source folder into a destination folder. &lt;br /&gt;
&lt;br /&gt;
 Usage: pdconvertall.py &amp;lt;sourcefolder&amp;gt; &amp;lt;targetfolder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the filename format is significant for this program and, natch, undocumented.&lt;br /&gt;
See [[#pdconvert formats|pdconvert formats]] for more details.&lt;br /&gt;
&lt;br /&gt;
This scans the {{c|sourcefolder}} for all files matching {{c|*.in}} which &#039;&#039;do not&#039;&#039; start with the characters {{c|NPS}} and&lt;br /&gt;
have corresponding {{c|*.out}} files and &#039;converts&#039; them to a text-based format for use with [[#pdserved|pdserved]].&lt;br /&gt;
&lt;br /&gt;
The conversion of the input file is almost identical to the processing done by calling [[#pdutils|pdutils OUT]] with the&lt;br /&gt;
dialog and direction specified explicitly, though this program picks up that information from the embedded data in the filename.&lt;br /&gt;
&lt;br /&gt;
The directory structure it creates is:&lt;br /&gt;
 &amp;lt;outputfolder&amp;gt;&lt;br /&gt;
  |- &amp;lt;dialog&amp;gt;&lt;br /&gt;
      |- &amp;lt;rundate-yyyyMMdd&amp;gt;&lt;br /&gt;
          |- &amp;lt;nino&amp;gt;.DATA&lt;br /&gt;
&lt;br /&gt;
The format is text-based in the style of the [[#pdutils|pdutils OUT]] format. The [[#pdserved|pdserved]] server then reads&lt;br /&gt;
from the directory when it is processing the requests and determining the responses to return. The files can be modified in&lt;br /&gt;
place, or new files can be placed there. The server will pick up any external changes made to these files.&lt;br /&gt;
 &lt;br /&gt;
== pdconvertone ==&lt;br /&gt;
This is a thin wrapper around [[#pdconvertall|pdconvertall]] which works for a single input and output file. That is, it&lt;br /&gt;
still expects a {{c|*.in}} and corresponding {{c|*.out}} file to convert, and it emits the output into the directory&lt;br /&gt;
structure described in [[#pdconvertall|pdconvertall]].&lt;br /&gt;
 Usage: pdconvertone.py &amp;lt;sourcespec&amp;gt; &amp;lt;targetfolder&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
This calls {{c|pdconvertall}} with the single file identified by {{c|sourcespec}}. Note that if the file begins with the&lt;br /&gt;
characters {{c|NPS}} or there is no corresponding {{c|*.out}} file, it will be skipped&lt;br /&gt;
&lt;br /&gt;
== pdconvert ==&lt;br /&gt;
Converts a single file into its text-based format, emitting the output to stdout.&lt;br /&gt;
 &lt;br /&gt;
 Usage: pdconvert.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This does not have the same restrictions as [[#pdconvertall|pdconvertall]] and [[#pdconvertone|pdconvertone]] - i.e.&lt;br /&gt;
it does not require corresponding {{c|*.in}} and {{c|*.out}} files, though the given file&#039;s filename must be one of those.&lt;br /&gt;
It will still not work for NPS files (though, unlike the above programs, it will try and probably crash and burn in the&lt;br /&gt;
attempt).&lt;br /&gt;
&lt;br /&gt;
== pddata ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This has a load of functions in it, only some of which I understand.&lt;br /&gt;
The main one appears to be {{c|getninodata}} which, typical cissim style, takes 10 arguments (interrobang?!) and has...&lt;br /&gt;
well, &#039;&#039;some&#039;&#039; documentation which concentrates on one or two arguments and expects a fairly solid understanding of&lt;br /&gt;
what it&#039;s doing before you start reading.&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to have to come back to this to try and grasp it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This technically can be executed, but it looks like the stuff in the main call is just development stuff - testing&lt;br /&gt;
other functions and such like.&lt;br /&gt;
&lt;br /&gt;
== pddump ==&lt;br /&gt;
This dumps the data from the given (base64-encoded EBCDIC) file to the console in text form with square brackets to enclose&lt;br /&gt;
the data values. Note: This uses the [[#pdconvert formats|pdconvert format]] for the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddump.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a call to [[#DUMP|pdutils DUMP]] which takes the dialog / direction arguments from the filename&lt;br /&gt;
format rather than requiring them to be stated explicitly.&lt;br /&gt;
&lt;br /&gt;
== pdout ==&lt;br /&gt;
This dumps the data from the given (base64-encoded EBCDIC) file to the console in text form with square brackets to enclose&lt;br /&gt;
the data values. Note: This uses the [[#pdconvert formats|pdconvert format]] for the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdout.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a call to [[#OUT|pdutils OUT]] which takes the dialog / direction arguments from the filename&lt;br /&gt;
&lt;br /&gt;
== pdparams ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contains a single function: {{c|processparams}}. This function also exists in [[#pdutils|pdutils]], and it looks like that&lt;br /&gt;
one is used but this one is not. I presume it&#039;s obsolete, though there&#039;s no indication of that in the code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== pdproxy ==&lt;br /&gt;
A very straightforward proxy which writes the request and response of any CIS calls made to it to files in the current&lt;br /&gt;
directory.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdproxy &amp;lt;swimlane&amp;gt; &amp;lt;configfile&amp;gt; &amp;lt;folder&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
The swimlane determines whether the &#039;real&#039; CIS is called or whether the &#039;SIM&#039; is called. Basically, if the {{c|swimlane}}&lt;br /&gt;
argument is in the ranges: 14-15 or 17-28 (both inclusive), onward calls from the proxy will go to CIS proper. Any other&lt;br /&gt;
value is treated as the port that the simulator is listening on and it will be connected to using that port number.&lt;br /&gt;
&lt;br /&gt;
== pdreadall ==&lt;br /&gt;
Reads all registered dialogs and calls them for the specified NINo and optional surname.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadall &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;folder&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
 &lt;br /&gt;
== pdreadoneedit ==&lt;br /&gt;
Calls a specified dialog in CIS (or a CIS simulator) for a given NINo and optional surname. This allows the editing of&lt;br /&gt;
the record to be sent in the request before the call is made. The input and output files are created (I &#039;&#039;think&#039;&#039;) in&lt;br /&gt;
the current directory with the appropriate filename format.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadoneedit &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== pdreadone ==&lt;br /&gt;
Calls a specified dialog in CIS (or a CIS simulator) for a given NINo and optional surname. This does not allow the&lt;br /&gt;
editing of the record to be sent in the request before the call is made. The input and output files are created (I&lt;br /&gt;
&#039;&#039;think&#039;&#039;) in the current directory with the appropriate filename format.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadone &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
 &lt;br /&gt;
== pdscreen ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This file contains a single class &#039;{{c|Textbox}}&#039; which provides the editing widget used in [[#pdedit|pdedit]] to&lt;br /&gt;
edit a value in a record file.&lt;br /&gt;
&lt;br /&gt;
== pdserved ==&lt;br /&gt;
An upgraded version of [[#pdserve|pdserve]] with NPS support and separate message directories.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserved.py &amp;lt;port&amp;gt; -P &amp;lt;pddfolder&amp;gt; -D &amp;lt;dcifolder&amp;gt; [-N &amp;lt;npsfolder&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Aside from working in Python3 and adding the NPS handling which was added in [[#pdservep|pdservep]], this primarily&lt;br /&gt;
implements the separation of the data directories into &#039;PD&#039;, &#039;DCI&#039; and &#039;NPS&#039; folders. These could all be the same&lt;br /&gt;
folder (I think), but the option is there now to have different ones for each type. Presumably, you might want&lt;br /&gt;
different PD responses for different services, but you want to use the same DCI/NPS responses each time, so this&lt;br /&gt;
saves on a load of copying and pasting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== pdservedt ==&lt;br /&gt;
[[#pdserved|pdserved]] with a {{c|process_wait()}} function, which loads the timing data from the hardcoded location&lt;br /&gt;
at {{c|../serve/transtimes.py}}. Not ideal - it requires running the program from a specific directory, and, of course,&lt;br /&gt;
this is undocumented (as far as I can see anyway).&lt;br /&gt;
&lt;br /&gt;
The timing data is a map of timings against dialog; the example in the code is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# timings are a list, first tuple is times to cycle through, rest are exceptional count/time pairs&lt;br /&gt;
# &#039;CP650_1151_R_RPLY&#039;:  [(0.15, 0.25, 0.21, 0.17, 0.20, 0.16), (20, 2.3), (100, 28)],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Basically, it will cycle through the first tuple of timings, except when the count for a given dialog reaches the&lt;br /&gt;
first value in any of the following tuples. If it does (in this case, the 20th and 100th time a dialog is processed&lt;br /&gt;
within the server), it will use the timing associated with that number. Reasonably straightforward.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This seems the most sensible one to draw a &#039;proper&#039; version from. If we want to re-do the timing, then&lt;br /&gt;
we could branch from [[#pdserved|pdserved]] instead... it certainly needs changing a bit (the config is dire - a&lt;br /&gt;
hardcoded filename in a directory reached using a relative path... ugh), and it&#039;s quite simplistic, but it does&lt;br /&gt;
work.&lt;br /&gt;
&lt;br /&gt;
== pdservep ==&lt;br /&gt;
This is [[#pdserve|pdserve]] with more NPS handling (and fixed for Python3).&lt;br /&gt;
&lt;br /&gt;
The NPS changes in here appear to be included in [[#pdserved|pdserved]] too, so this and [[#pdserve|pdserve]], at&lt;br /&gt;
first glance, would seem to be obsolete.&lt;br /&gt;
&lt;br /&gt;
== pdshow ==&lt;br /&gt;
Shows and edits a base64-encoded file, extracting the dialog and direction from the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdshow.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a wrapper around a call to [[#pdedit|pdedit]] which extracts the dialog and direction from the filename,&lt;br /&gt;
rather than needing it specified explicitly.&lt;br /&gt;
&lt;br /&gt;
== pdstub ==&lt;br /&gt;
Stub server which provides more flexible lookup and response-modification than pdserve.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdstub &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
This program provides a basic server which serves PD, DCI and NPS. Rather than a straight NINo/Rundate lookup, it&lt;br /&gt;
uses search parameters to determine which response file to return for a request, and it allows replacement of data&lt;br /&gt;
in that response file with static parameters, or inputs derived from the request.&lt;br /&gt;
&lt;br /&gt;
It uses a single messages folder, rather than the separated responses folder of pdserve and each request/response&lt;br /&gt;
mapping is defined in a single line within the config file.&lt;br /&gt;
&lt;br /&gt;
== pdstubt ==&lt;br /&gt;
This is [[#pdstub|pdstub]] with a {{c|process_wait()}} function, which works exactly like the same function in&lt;br /&gt;
[[#pdservedt|pdservedt]].&lt;br /&gt;
&lt;br /&gt;
== pdstubtt ==&lt;br /&gt;
This is [[#pdstubt|pdstubt]] with a multi-threaded HTTP server. It&#039;s a fairly trivial change to the code; I haven&#039;t&lt;br /&gt;
looked through it to see if there are any thread localisation issues in there - I&#039;m assuming not, because this is&lt;br /&gt;
being used as is at the moment, and that would probably have been noticed by now.&lt;br /&gt;
&lt;br /&gt;
This seems to me to be the most mature of the pdstub implementations - multithreading the server is a no-brainer,&lt;br /&gt;
in my humble, and the timings can be ignored. It still has the problem of a hardcoded timing config, but that&lt;br /&gt;
shouldn&#039;t be too hard to fix in a less fragile manner.&lt;br /&gt;
&lt;br /&gt;
== pdtux ==&lt;br /&gt;
A Tuxedo server which advertises a few tux operations, namely:&lt;br /&gt;
* ping&lt;br /&gt;
* DCI913&lt;br /&gt;
* DCI923&lt;br /&gt;
* VMERCIS&lt;br /&gt;
* RESETCOUNTER&lt;br /&gt;
&lt;br /&gt;
This extracts the data out of the request packet and gets the data using [[#pddata|pddata.getninodata()]],&lt;br /&gt;
returning the resultant data (the whole thing for DCI calls, separated CIS header and W90 header for PDD calls).&lt;br /&gt;
&lt;br /&gt;
There are no arguments to this program, but it does require the installation of the &#039;tuxedo&#039; python module.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
And the non-&#039;pd&#039; python files:&lt;br /&gt;
&lt;br /&gt;
== certs ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Holds the paths to the various certificates used within cissim. 2 groups of cert and cacert files for connecting to&lt;br /&gt;
DCI and PD; 2 groups of cert and private key files for serving.&lt;br /&gt;
&lt;br /&gt;
Used in [[#pdcall|pdcall]], [[#pdserve|pdserve]] and [[#pdstub|pdstub]] programs, and in some test functions&lt;br /&gt;
in [[#sslutils|sslutils]].&lt;br /&gt;
&lt;br /&gt;
== checkport ==&lt;br /&gt;
&#039;&#039;Redundant&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Checks if it&#039;s possible to connect to {{c|localhost:9127}}. That&#039;s it really. &lt;br /&gt;
&lt;br /&gt;
Basically, a python version of:&lt;br /&gt;
 netstat -nap | grep &#039;:9127.*LISTEN&#039;&lt;br /&gt;
&lt;br /&gt;
== dci9n3rec ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Technically, this can be called from the command line, but it seems a bit pointless. It appears to read in a file&lt;br /&gt;
called &#039;in&#039; in the current directory and, uh, loads it into a DCI9n3 record structure and prints it. I guess it&#039;s&lt;br /&gt;
for testing purposes.&lt;br /&gt;
&lt;br /&gt;
Anyway, this contains the definition of a DCI913 or DCI923 record, packed to byte alignment for the fields, with&lt;br /&gt;
the 12 fields and their sizes defined as fixed length byte arrays.&lt;br /&gt;
&lt;br /&gt;
It&#039;s only used in [[#pdtux|pdtux]] for extracting the data from an incoming DCI struct. The equivalent for a PD&lt;br /&gt;
record is [[#w80construct|w80construct]]&lt;br /&gt;
&lt;br /&gt;
== extractodis ==&lt;br /&gt;
&#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Usage: extractodis.py &amp;lt;log_filename&amp;gt; [&amp;lt;PID&amp;gt;] [&amp;lt;starttime&amp;gt;] [&amp;lt;endtime&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
This is completely out there. So. It takes the filename and creates 3 shell scripts with names based on it, which&lt;br /&gt;
perform some function on the payload (base64-encoded ASCII). These scripts are:&lt;br /&gt;
* {{c|&amp;lt;filename&amp;gt;.write.sh}}: to write the transaction for ACS emulation (just writing the record out)&lt;br /&gt;
* {{c|&amp;lt;filename&amp;gt;.conv.sh}}: to write the transaction for CIS emulation (calling [[#CONVERT2E|pddump.py CONVERT2E]])&lt;br /&gt;
* {{c|&amp;lt;filename&amp;gt;.db.sh}}: to write the transaction to the &#039;database&#039; for serving (calling [[#pddb|pddb]])&lt;br /&gt;
&lt;br /&gt;
Aside from some very ropey python issues (mix of tabs and spaces in leading whitespace - very verboten in python),&lt;br /&gt;
it&#039;s just a very odd way of doing things.&lt;br /&gt;
&lt;br /&gt;
This is the oldschool format; it&#039;s dealing with the records as is, rather than moving them to the date/nino-based&lt;br /&gt;
database used by [[#pdserved|pdserved]] and beyond; the pddb output is used in the original&lt;br /&gt;
[[#pdserve|pdserve]] program too. It&#039;s still valid for the &#039;write.sh&#039;, I guess, but I suspect that&#039;s all.&lt;br /&gt;
&lt;br /&gt;
== fpcapprec ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
This was used in [[#pdtux|pdtux]], but is no longer used. The using has been deleted, so I can&#039;t see the context.&lt;br /&gt;
&lt;br /&gt;
== getfieldoffset ==&lt;br /&gt;
&#039;&#039;Test file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
I&#039;m pretty sure this is just testing that the [[#pdlayouts.pd|pdlayouts.getdialogfieldoffset()]] method is working&lt;br /&gt;
correctly.&lt;br /&gt;
&lt;br /&gt;
== key ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This provides a few constants for keycodes, used in [[#pdedit|pdedit]] and [[#pdscreen|pdscreen]].&lt;br /&gt;
&lt;br /&gt;
To be honest, it really needn&#039;t be here. The function key and some other constants are already defined in the curses&lt;br /&gt;
module; most of the rest are defined in the curses.ascii module. {{c|UP_LIST}} is home-made, but really doesn&#039;t&lt;br /&gt;
deserve its own file; any home-grown key values could go in the [[#pdscreen|pdscreen]] file.&lt;br /&gt;
&lt;br /&gt;
== loadninos ==&lt;br /&gt;
&#039;&#039;Library File&#039;&#039; and &#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Usage: loadninos.py &amp;lt;office-file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Used in [[#pdstub|pdstub]] and its variants.&lt;br /&gt;
&lt;br /&gt;
Loads NINOs from a CSV file (actually looks like a &#039;Whitespace-separated variables&#039; style file, though it has a&lt;br /&gt;
name of {{c|csvfile}} within the code). This looks for input in the form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 SVC     Office&lt;br /&gt;
 JSOV    109809&lt;br /&gt;
 JSRZ    107476&lt;br /&gt;
 JSFP    107038&lt;br /&gt;
 JSLH    103401&lt;br /&gt;
 JSKR    103838&lt;br /&gt;
 JSLF    102636&lt;br /&gt;
 JSGR    102805&lt;br /&gt;
 JSRT    100598&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above example is half-inched from the code. The code is ferociously simplistic, but I guess it does the job.&lt;br /&gt;
&lt;br /&gt;
Anyway, it takes the &#039;Office&#039; from the lines in the &#039;CSV&#039; file, strips the leading digit from it, then looks for&lt;br /&gt;
another &#039;csv&#039; file with that office number as a filename, in the same directory as the provided CSV file, so the&lt;br /&gt;
above will look for &#039;09809.csv&#039;, &#039;07476.csv&#039; etc. It will load that file, taking the first 8 chars of each line&lt;br /&gt;
as a NINo and then maps the office to that NINo, such that each NINo has the office number of the file that it&lt;br /&gt;
was loaded from mapped against it.&lt;br /&gt;
&lt;br /&gt;
This is used in [[#pdstub|pdstub]] to get the office for a particular NINo, which is then used as part of the&lt;br /&gt;
response in a DCI913 call. The stub loads the NINos using this function passing the {{c|OFFICECSVFILE}} config&lt;br /&gt;
parameter value to load them from. It doesn&#039;t handle errors well, but I guess once it&#039;s running, you don&#039;t&lt;br /&gt;
change it that much.&lt;br /&gt;
&lt;br /&gt;
== logextract ==&lt;br /&gt;
&#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Usage: logextract.py &amp;lt;logfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Extracts a {{c|DCI913CopyRecord}} from a logfile. It&#039;s a bit hacky - in the middle of it, it does some strange&lt;br /&gt;
stuff with the string &#039;127.0.0.1&#039;; I presume the logfile isn&#039;t really designed for extracting records from and&lt;br /&gt;
so this has to hardcode some messing around into it. It&#039;s very fragile - logfiles aren&#039;t typically structured&lt;br /&gt;
output (or, at least, not structured in this way).&lt;br /&gt;
&lt;br /&gt;
== npsload ==&lt;br /&gt;
&#039;&#039;Executable&#039;&#039; - this is an executable only; no part of it is called by other programs / libraries.&lt;br /&gt;
&lt;br /&gt;
 Usage: npsload &amp;lt;folder&amp;gt; &amp;lt;csvfile&amp;gt; &amp;lt;listfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loads the {{c|csvfile}} from {{c|folder}} (i.e. the file is just the filename, not the {{c|/path/to/file}}),&lt;br /&gt;
and writes all output, including the {{c|listfile}} in the same folder.&lt;br /&gt;
&lt;br /&gt;
The CSV file is defined as:&lt;br /&gt;
 Entry/ies  Description&lt;br /&gt;
 1          NINo&lt;br /&gt;
 2          Surname&lt;br /&gt;
 3          Office&lt;br /&gt;
 4          LOP 25x Past&lt;br /&gt;
 5-20       NUBS2 record x 4&lt;br /&gt;
 21-36      LOP record x 4&lt;br /&gt;
 37         Data not found flag&lt;br /&gt;
 38         BFM Return Code&lt;br /&gt;
 39         RDS Code&lt;br /&gt;
&lt;br /&gt;
Each NUBS2 record and LOP record is made up of 4 comma-separated entries, with the fields:&lt;br /&gt;
 Entry Description&lt;br /&gt;
 1     Year&lt;br /&gt;
 2     x25&lt;br /&gt;
 3     x50&lt;br /&gt;
 4     Priority&lt;br /&gt;
&lt;br /&gt;
This program loops through all the NINo entries, and writes an XML file for each one, calling it {{c|NPSrply.&amp;lt;nino&amp;gt;.xml}},&lt;br /&gt;
adding an entry into the {{c|listfile}} for each file it created. It adds a final &#039;NINO not found&#039; entry to the listfile&lt;br /&gt;
and exits.&lt;br /&gt;
&lt;br /&gt;
== paths ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contains the paths used for calls to PD, DCI and NPS, as well as a few functions which operate on and around those paths.&lt;br /&gt;
&lt;br /&gt;
This is used liberally throughout the rest of the CISSim suite.&lt;br /&gt;
&lt;br /&gt;
== ports ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This just holds all the ports for the CIS swimlanes and returns the appropriate ports for a given swimlane when asked, in the form {{c|(pdd-port, dci-port, host)}}.&lt;br /&gt;
&lt;br /&gt;
== selectserver ==&lt;br /&gt;
&#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
I have no idea what this is trying to do. It&#039;s messing around with servers and message queues, but I&#039;m a bit lost.&lt;br /&gt;
&lt;br /&gt;
== sslutils ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contains functions to call servers using SSL certificates. Used in [[#pdacs|pdacs]], [[#pdcall|pdcall]], [[#pdproxy|pdproxy]]&lt;br /&gt;
and [[#teststub|teststub]]&lt;br /&gt;
&lt;br /&gt;
== temp ==&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
Seems to be a copy of [[#pdserved|pdserved]] with some testing code in there.&lt;br /&gt;
&lt;br /&gt;
== teststub ==&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
Tests connecting to the CIS Sim using curl and a socket. Prints things. Not particularly useful.&lt;br /&gt;
&lt;br /&gt;
== utils ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
A variety of utility functions; apparently not used anywhere.&lt;br /&gt;
&lt;br /&gt;
== vmeutils ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039; and &#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Usage: vmeutils &amp;lt;D/B&amp;gt; &amp;lt;date&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some VME date functions and a small utility executable to convert a date into a VME date ({{c|&#039;B&#039;}}, obviously) or&lt;br /&gt;
a VME date into a date ({{c|&#039;D&#039;}}). A &#039;VME date&#039; in this context is the number of days since 29/02/1852.&lt;br /&gt;
&lt;br /&gt;
== w80construct ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Like [[#dci9n3rec|dci9n3rec]], this can be called from the command line, but it also seems a bit pointless.&lt;br /&gt;
I guess it&#039;s for testing purposes.&lt;br /&gt;
&lt;br /&gt;
Anyway, this contains the definition of a W80 record, packed to byte alignment for the fields, with the various fields&lt;br /&gt;
and their sizes defined mostly as fixed length byte arrays, though there are a few integer and long integer fields&lt;br /&gt;
defined too - these will be compiler-dependent, so I guess that&#039;s how the tux that it&#039;s interfacing with/mocking&lt;br /&gt;
works too?&lt;br /&gt;
&lt;br /&gt;
It&#039;s only used in [[#pdtux|pdtux]] for extracting the data from an incoming DCI struct. The equivalent for a DCI&lt;br /&gt;
record is [[#dci9n3rec|dci9n3rec]]&lt;br /&gt;
&lt;br /&gt;
= Files in pdlayouts =&lt;br /&gt;
&lt;br /&gt;
== pdlayouts/PDM ==&lt;br /&gt;
The &#039;PD Map&#039; contains the fields used in the CIS header and the W80 PD header, including their name, data type and length and&lt;br /&gt;
an optional &#039;style&#039; type argument which provides metadata for the field, &#039;&#039;eg.&#039;&#039; {{c|nino8}} indicates the first 8 chars of&lt;br /&gt;
a NINo, {{c|runtime8}} indicates that it contains a time in the format {{c|%H%M%S%f}}, {{c|vmedate}} indicates that the field&lt;br /&gt;
contains a &#039;VME date&#039;, ie. the number of days since 29/02/1852.&lt;br /&gt;
&lt;br /&gt;
These &#039;style&#039; arguments are used in {{c|pdutils.makerequestfile}} to autopopulate various fields for input based on the static&lt;br /&gt;
&#039;RUNDATE&#039; parameter value.&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=395</id>
		<title>Noctam/DWP/ACS Test Harness/Existing System/CISSIM/Command Line Tools</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=395"/>
		<updated>2021-10-19T08:26:49Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Filled out pretty much everything.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{nav/ACS Test Harness}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
There are many command line tools to do various things within the CISSIM / proxy / data management / testing stub / kitchen  sink application.&lt;br /&gt;
&lt;br /&gt;
This page tries to exhaustively go through all of them. It fails. But it continues to try.&lt;br /&gt;
= File formats =&lt;br /&gt;
There are a few file formats used here.&lt;br /&gt;
&lt;br /&gt;
== base64-ebcdic ==&lt;br /&gt;
EBCDIC data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
This is the form for most PD calls - the content is a record whose definition is held elsewhere (in COBOL copybook-ish form)&lt;br /&gt;
&lt;br /&gt;
Used as input and output to/from [[#pdutils|pdutils]] and [[#pdedit|pdedit]].&lt;br /&gt;
&lt;br /&gt;
== base64-ascii ==&lt;br /&gt;
ASCII data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
Just like [[#base64-ebcdic|base64-ebcdic]] except the text fields are encoded into ASCII rather than EBCDIC.&lt;br /&gt;
&lt;br /&gt;
This can be used as input to [[#pdutils|pdutils]] when using the {{c|CONVERT2E}} option to convert it to [[#base64-ebcdic|base64-ebcdic]], and output from [[#pdutils|pdutils]] using the {{c|CONVERT2A}} option.&lt;br /&gt;
&lt;br /&gt;
= Filename format =&lt;br /&gt;
Some of the following utilities expect the filename to be in one of a number of specific formats. They use this&lt;br /&gt;
format to embed information about the transaction that the file represents, later extracted by the programs to look up&lt;br /&gt;
related data and/or structures.&lt;br /&gt;
&lt;br /&gt;
== pdconvert formats ==&lt;br /&gt;
The [[#pdconvert|pdconvert]], [[#pdconvertone|pdconvertone]] and [[#pdconvertall|pdconvertall]] programs expect&lt;br /&gt;
the files to be named in one of two dot-separated formats; one with 4 &#039;parts&#039;, one with any other number of &#039;parts&#039;&lt;br /&gt;
as long they number at least 3. The 4 part format is represented by the regex:&lt;br /&gt;
&lt;br /&gt;
 ^(?P&amp;lt;dialognum&amp;gt;[^.]{0,6})\.[^.]*\.[^.]*\.(?P&amp;lt;direction&amp;gt;in|out)$&lt;br /&gt;
 &lt;br /&gt;
 eg. &amp;quot;DCI908.NINO.STUB.out&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The 4 dot-separated parts indicate that this is an &#039;R&#039; (read) mode transaction. A suffix of &#039;in&#039; indicates a &#039;RQST&#039; direction,&lt;br /&gt;
&#039;out&#039; indicates a &#039;RPLY&#039; direction. The dialog is extracted as the first 6 chars of the first part, the mode and the direction&lt;br /&gt;
separated by underscores, so the above example would yield:&lt;br /&gt;
 DCI908_R_RQST&lt;br /&gt;
&lt;br /&gt;
The &#039;any number above 2, except 4&#039; format (?) extracts more information from the filename:&lt;br /&gt;
 ^(?P&amp;lt;dialognum&amp;gt;[^.]*)\.[^.]{3}(?P&amp;lt;messageid&amp;gt;[^.]{4})(?P&amp;lt;txnmode&amp;gt;[^.]).*\.(?P&amp;lt;direction&amp;gt;in|out)$&lt;br /&gt;
 &lt;br /&gt;
 eg. &amp;quot;PD375.CIS6084RCURRINT.153250.634934c5c8d6.in&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This builds the dialog and transaction mode from the filename. The direction is mapped to &#039;RQST&#039; or &#039;RPLY&#039; where the filename&lt;br /&gt;
has &#039;in&#039; or &#039;out&#039;, and the dialog is built up as: {{c|&amp;lt;dialognum&amp;gt;_&amp;lt;messageid&amp;gt;_&amp;lt;txnmode&amp;gt;_&amp;lt;direction&amp;gt;}}. The above example&lt;br /&gt;
would end up with the dialog:&lt;br /&gt;
 PD375_6084_R_RQST&lt;br /&gt;
&lt;br /&gt;
= Programs =&lt;br /&gt;
&lt;br /&gt;
== pdutils ==&lt;br /&gt;
Primarily a library file, used throughout various calls from the daemon programs as well as other utilities.&lt;br /&gt;
It can, however, also be called directly from the command line.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdutils &amp;lt;DUMP/OUT/SAVE/CONVERT2E/CONVERT2A&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;requestfile/replyfile&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   Note that SAVE requires redirected input from an ASCII text string, such as &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
        and that CONVERT requires redirected input from B64 encoded ASCII data &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
=== DUMP ===&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This puts &#039;&#039;everything&#039;&#039; out - ie. all the fields, the fillers and the groups. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
It prefixes the field with the data structure (&#039;&#039;eg&#039;&#039; B4 for binary 4 bytes; X16 for char 16 bytes; N2 for numeric char 2 bytes).&lt;br /&gt;
&lt;br /&gt;
It suffixes the value with the hex value found for the field, separated into space-separated octets, wrapped in parantheses.&lt;br /&gt;
&lt;br /&gt;
=== OUT ===&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This only puts out the fields and fillers. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
=== SAVE ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
I have tweaked the code to work in Windows and... I don&#039;t really know what this does, i.e. I don&#039;t know what format the input file is expected to be in. It&#039;s not the same as the &#039;requestfile/replyfile&#039; used for DUMP and OUT, because that fails with the exception message: &#039;&#039;invalid literal for int() with base 10: &#039;AAAAMMPJ4&#039; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== CONVERT2E ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded ASCII record format to the output file, in base64-encoded EBCDIC record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
=== CONVERT2A ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded EBCDIC record format to the output file, in base64-encoded ASCII record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
== pdedit ==&lt;br /&gt;
Edits the PD and DCI call data via a curses interface, using the COBOL data layouts for the calls.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdedit &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;sourcefile&#039; in this case is the same as the &#039;requestfile/replyfile&#039; provided in pdutils, that is, a file containing base64-encoded EBCDIC data. The &#039;destfile&#039; is in the same format with the changes applied (assuming that you save inside pdedit).&lt;br /&gt;
&lt;br /&gt;
Intriguingly, it appears to ignore the &#039;RQST/RPLY&#039; in the dialog and effectively overwrites it with the RQST/RPLY argument given to the program.&lt;br /&gt;
Not really sure why... that dialog is a bit of a hack, really, I suspect just to avoid multiple keys or too much structure in the config.&lt;br /&gt;
&lt;br /&gt;
 PD350/1151/RQST/R&lt;br /&gt;
might have worked better, with a structured system, be it XML or JSON or YAML or whatever. Since I don&#039;t really understand which things would be better grouped together, I&#039;ll leave this as an idle thought for now.&lt;br /&gt;
&lt;br /&gt;
== pddb ==&lt;br /&gt;
Creates a database entry which effectively maps a response file onto a request.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddb &amp;lt;dialog&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt; &amp;lt;EBCDIC/ASCII&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The output is in the form:&lt;br /&gt;
 &amp;lt;dialog&amp;gt;:&amp;lt;response-file&amp;gt;:&amp;lt;input-field-name=value[;...]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for a PD350 1151 request, you might see something like:&lt;br /&gt;
 $ python cissim/pddb.py PD350_1151_R_RQST requests/pd350-request-e messages/PD350.CIS1151RSTRTDIA.AASTUB.out EBCDIC&lt;br /&gt;
 PD350_1151_R_RQST:PD350.CIS1151RSTRTDIA.AASTUB.out:H1151-NINO=ST000001;H1151-NINO-SFX-TX=A;H1151-RQST-DSS-DAYS=20190213;H1151-RQST-DIA-ID=PD350 ;H1151-RQST-USR-NS-LVL=0000;H1151-RQST-USR-LS-LVL=0000;H1151-RQST-USR-BUS-SYS-NO=43;H1151-DEPT-ID-TP=1;H1151-OFF-LOC-NO=04710;H1151-RQST-SPCFC-BUS-TP=85;&lt;br /&gt;
&lt;br /&gt;
These entries can be appended into a single file, with each entry on a separate line and work together to a form a readonly database of sorts, which the server can use to lookup the response to use based on the values of the inputs provided in the request.&lt;br /&gt;
&lt;br /&gt;
== pdserve ==&lt;br /&gt;
This is what uses the given &#039;database&#039; files from pddb to serve the data based on the requests.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserve &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
It takes a config file which is effectively made up of paths to the &#039;databases&#039; built up using pddb along with an (optional) SSL flag. Each pddb line in the config is something like:&lt;br /&gt;
 &amp;lt;path-to-db-file&amp;gt;:&amp;lt;folder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for example:&lt;br /&gt;
&lt;br /&gt;
configfile.ja030&lt;br /&gt;
 SSL=N&lt;br /&gt;
 pdbase/JA030_01.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_02.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_99.CIS.txt:pdbase&lt;br /&gt;
&lt;br /&gt;
pdserve will expect to find the response files with the names defined in the &#039;database&#039; within the folder specified in the config, so you could have multiple entries here pointing to different databases.&lt;br /&gt;
&lt;br /&gt;
The &#039;port&#039; here is the port it will listen on. This is analogous to a &#039;swimlane&#039; (&#039;&#039;&amp;lt;sigh&amp;gt;&#039;&#039;) and, indeed, the terms are used interchangeably in some places. The default port value used is &#039;&#039;9127&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The recommended way of running this is using {{c|nohup}} so that you can exit the shell and it will continue to run... something like:&lt;br /&gt;
 nohup python pdserve.py configfile.ja030 9130 &amp;gt;ja030.log &amp;amp;&lt;br /&gt;
&lt;br /&gt;
... and of course, the only way to kill it after doing that is by identifying the process that&#039;s running and using the {{c|kill}} command.&lt;br /&gt;
&lt;br /&gt;
Final thing. Quite important.&amp;lt;br/&amp;gt;&lt;br /&gt;
The version I have doesn&#039;t work.&lt;br /&gt;
&lt;br /&gt;
In Python 2:&lt;br /&gt;
  $ python2 ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 68&lt;br /&gt;
      print(s.server_version, end=&#039; &#039;)&lt;br /&gt;
                                 ^&lt;br /&gt;
  SyntaxError: invalid syntax&lt;br /&gt;
&lt;br /&gt;
In Python 3:&lt;br /&gt;
  $ python ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
  Traceback (most recent call last):&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 316, in &amp;lt;module&amp;gt;&lt;br /&gt;
      status = main()&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 260, in main&lt;br /&gt;
      if &#039;#&#039; in line:&lt;br /&gt;
  TypeError: a bytes-like object is required, not &#039;str&#039;&lt;br /&gt;
&lt;br /&gt;
It looks like it&#039;s been half-heartedly converted from 2 to 3, but untested. I&#039;m assuming that either nobody uses it, or it&#039;s been fixed in place wherever it is used and the changes haven&#039;t been reflected back to the source.&lt;br /&gt;
&lt;br /&gt;
== pdcall ==&lt;br /&gt;
(Incidentally, this was a bit messy to get working due to using pycurl, I had to {{c|apt install libcurl4-openssl-dev libssl-dev}} and {{c|pip install pycurl}} in order to get this to work on my Ubuntu machine - no idea what this will require on Mac, but be prepared for pain, given how little access we have.)&lt;br /&gt;
&lt;br /&gt;
This can be used to call the server and test that it&#039;s working correctly.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdcall &amp;lt;swimlane&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&amp;lt;swimlane&amp;gt;&#039; here is the port that the server is listening on.&lt;br /&gt;
&lt;br /&gt;
This opens the request file and displays it using [[#pdedit|pdedit]]. After editing and saving, it posts the updated request to the server, captures the response and then opens &#039;&#039;that&#039;&#039; in pdedit too so that you can see (and, indeed, edit) the response, before saving to the output file.&lt;br /&gt;
&lt;br /&gt;
At least, I think that&#039;s what it does - because I couldn&#039;t get [[#pdserve|pdserve]] running, I had very little to test, so this is conjecture and glancery.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
I&#039;ve just dumped all the &#039;pd&#039; python files here for further processing.&lt;br /&gt;
&lt;br /&gt;
== pdacs ==&lt;br /&gt;
Calls a running ACS instance with an edited request, storing the response into the required output file.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdacs &amp;lt;service&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This pops up a {{c|pdedit}} window to edit the request (actually saving the resultant file to the given location), then creates the&lt;br /&gt;
request by prepending the ACS input header, with the uppercased {{c|service}} embedded in it, to the input file contents.&lt;br /&gt;
&lt;br /&gt;
The ACS input header is fixed (service aside) and has the following content:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 0ed1249b558f||True|101307|            |DCP26PD350  |null|&amp;lt;service&amp;gt;|11606730|null|DWDDE662|2|1548331293|0|500|0|false|P|60|468|&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full input is saved to a file in the current directory called {{c|&amp;lt;requestfile&amp;gt;.acs}}. The response from ACS is saved into the&lt;br /&gt;
provided {{c|replyfile}}.&lt;br /&gt;
&lt;br /&gt;
== pdconvertall ==&lt;br /&gt;
Converts *.in files and corresponding *.out files from a source folder into a destination folder. &lt;br /&gt;
&lt;br /&gt;
 Usage: pdconvertall.py &amp;lt;sourcefolder&amp;gt; &amp;lt;targetfolder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the filename format is significant for this program and, natch, undocumented.&lt;br /&gt;
See [[#pdconvert formats|pdconvert formats]] for more details.&lt;br /&gt;
&lt;br /&gt;
This scans the {{c|sourcefolder}} for all files matching {{c|*.in}} which &#039;&#039;do not&#039;&#039; start with the characters {{c|NPS}} and&lt;br /&gt;
have corresponding {{c|*.out}} files and &#039;converts&#039; them to a text-based format for use with [[#pdserved|pdserved]].&lt;br /&gt;
&lt;br /&gt;
The conversion of the input file is almost identical to the processing done by calling [[#pdutils|pdutils OUT]] with the&lt;br /&gt;
dialog and direction specified explicitly, though this program picks up that information from the embedded data in the filename.&lt;br /&gt;
&lt;br /&gt;
The directory structure it creates is:&lt;br /&gt;
 &amp;lt;outputfolder&amp;gt;&lt;br /&gt;
  |- &amp;lt;dialog&amp;gt;&lt;br /&gt;
      |- &amp;lt;rundate-yyyyMMdd&amp;gt;&lt;br /&gt;
          |- &amp;lt;nino&amp;gt;.DATA&lt;br /&gt;
&lt;br /&gt;
The format is text-based in the style of the [[#pdutils|pdutils OUT]] format. The [[#pdserved|pdserved]] server then reads&lt;br /&gt;
from the directory when it is processing the requests and determining the responses to return. The files can be modified in&lt;br /&gt;
place, or new files can be placed there. The server will pick up any external changes made to these files.&lt;br /&gt;
 &lt;br /&gt;
== pdconvertone ==&lt;br /&gt;
This is a thin wrapper around [[#pdconvertall|pdconvertall]] which works for a single input and output file. That is, it&lt;br /&gt;
still expects a {{c|*.in}} and corresponding {{c|*.out}} file to convert, and it emits the output into the directory&lt;br /&gt;
structure described in [[#pdconvertall|pdconvertall]].&lt;br /&gt;
 Usage: pdconvertone.py &amp;lt;sourcespec&amp;gt; &amp;lt;targetfolder&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
This calls {{c|pdconvertall}} with the single file identified by {{c|sourcespec}}. Note that if the file begins with the&lt;br /&gt;
characters {{c|NPS}} or there is no corresponding {{c|*.out}} file, it will be skipped&lt;br /&gt;
&lt;br /&gt;
== pdconvert ==&lt;br /&gt;
Converts a single file into its text-based format, emitting the output to stdout.&lt;br /&gt;
 &lt;br /&gt;
 Usage: pdconvert.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This does not have the same restrictions as [[#pdconvertall|pdconvertall]] and [[#pdconvertone|pdconvertone]] - i.e.&lt;br /&gt;
it does not require corresponding {{c|*.in}} and {{c|*.out}} files, though the given file&#039;s filename must be one of those.&lt;br /&gt;
It will still not work for NPS files (though, unlike the above programs, it will try and probably crash and burn in the&lt;br /&gt;
attempt).&lt;br /&gt;
&lt;br /&gt;
== pddata ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This has a load of functions in it, only some of which I understand.&lt;br /&gt;
The main one appears to be {{c|getninodata}} which, typical cissim style, takes 10 arguments (interrobang?!) and has...&lt;br /&gt;
well, &#039;&#039;some&#039;&#039; documentation which concentrates on one or two arguments and expects a fairly solid understanding of&lt;br /&gt;
what it&#039;s doing before you start reading.&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to have to come back to this to try and grasp it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This technically can be executed, but it looks like the stuff in the main call is just development stuff - testing&lt;br /&gt;
other functions and such like.&lt;br /&gt;
&lt;br /&gt;
== pddump ==&lt;br /&gt;
This dumps the data from the given (base64-encoded EBCDIC) file to the console in text form with square brackets to enclose&lt;br /&gt;
the data values. Note: This uses the [[#pdconvert formats|pdconvert format]] for the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddump.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a call to [[#DUMP|pdutils DUMP]] which takes the dialog / direction arguments from the filename&lt;br /&gt;
format rather than requiring them to be stated explicitly.&lt;br /&gt;
&lt;br /&gt;
== pdout ==&lt;br /&gt;
This dumps the data from the given (base64-encoded EBCDIC) file to the console in text form with square brackets to enclose&lt;br /&gt;
the data values. Note: This uses the [[#pdconvert formats|pdconvert format]] for the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdout.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a call to [[#OUT|pdutils OUT]] which takes the dialog / direction arguments from the filename&lt;br /&gt;
&lt;br /&gt;
== pdparams ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contains a single function: {{c|processparams}}. This function also exists in [[#pdutils|pdutils]], and it looks like that&lt;br /&gt;
one is used but this one is not. I presume it&#039;s obsolete, though there&#039;s no indication of that in the code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== pdproxy ==&lt;br /&gt;
A very straightforward proxy which writes the request and response of any CIS calls made to it to files in the current&lt;br /&gt;
directory.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdproxy &amp;lt;swimlane&amp;gt; &amp;lt;configfile&amp;gt; &amp;lt;folder&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
The swimlane determines whether the &#039;real&#039; CIS is called or whether the &#039;SIM&#039; is called. Basically, if the {{c|swimlane}}&lt;br /&gt;
argument is in the ranges: 14-15 or 17-28 (both inclusive), onward calls from the proxy will go to CIS proper. Any other&lt;br /&gt;
value is treated as the port that the simulator is listening on and it will be connected to using that port number.&lt;br /&gt;
&lt;br /&gt;
== pdreadall ==&lt;br /&gt;
Reads all registered dialogs and calls them for the specified NINo and optional surname.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadall &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;folder&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
 &lt;br /&gt;
== pdreadoneedit ==&lt;br /&gt;
Calls a specified dialog in CIS (or a CIS simulator) for a given NINo and optional surname. This allows the editing of&lt;br /&gt;
the record to be sent in the request before the call is made. The input and output files are created (I &#039;&#039;think&#039;&#039;) in&lt;br /&gt;
the current directory with the appropriate filename format.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadoneedit &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== pdreadone ==&lt;br /&gt;
Calls a specified dialog in CIS (or a CIS simulator) for a given NINo and optional surname. This does not allow the&lt;br /&gt;
editing of the record to be sent in the request before the call is made. The input and output files are created (I&lt;br /&gt;
&#039;&#039;think&#039;&#039;) in the current directory with the appropriate filename format.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadone &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
 &lt;br /&gt;
== pdscreen ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This file contains a single class &#039;{{c|Textbox}}&#039; which provides the editing widget used in [[#pdedit|pdedit]] to&lt;br /&gt;
edit a value in a record file.&lt;br /&gt;
&lt;br /&gt;
== pdserved ==&lt;br /&gt;
An upgraded version of [[#pdserve|pdserve]] with NPS support and separate message directories.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserved.py &amp;lt;port&amp;gt; -P &amp;lt;pddfolder&amp;gt; -D &amp;lt;dcifolder&amp;gt; [-N &amp;lt;npsfolder&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Aside from working in Python3 and adding the NPS handling which was added in [[#pdservep|pdservep]], this primarily&lt;br /&gt;
implements the separation of the data directories into &#039;PD&#039;, &#039;DCI&#039; and &#039;NPS&#039; folders. These could all be the same&lt;br /&gt;
folder (I think), but the option is there now to have different ones for each type. Presumably, you might want&lt;br /&gt;
different PD responses for different services, but you want to use the same DCI/NPS responses each time, so this&lt;br /&gt;
saves on a load of copying and pasting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== pdservedt ==&lt;br /&gt;
[[#pdserved|pdserved]] with a {{c|process_wait()}} function, which loads the timing data from the hardcoded location&lt;br /&gt;
at {{c|../serve/transtimes.py}}. Not ideal - it requires running the program from a specific directory, and, of course,&lt;br /&gt;
this is undocumented (as far as I can see anyway).&lt;br /&gt;
&lt;br /&gt;
The timing data is a map of timings against dialog; the example in the code is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# timings are a list, first tuple is times to cycle through, rest are exceptional count/time pairs&lt;br /&gt;
# &#039;CP650_1151_R_RPLY&#039;:  [(0.15, 0.25, 0.21, 0.17, 0.20, 0.16), (20, 2.3), (100, 28)],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Basically, it will cycle through the first tuple of timings, except when the count for a given dialog reaches the&lt;br /&gt;
first value in any of the following tuples. If it does (in this case, the 20th and 100th time a dialog is processed&lt;br /&gt;
within the server), it will use the timing associated with that number. Reasonably straightforward.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This seems the most sensible one to draw a &#039;proper&#039; version from. If we want to re-do the timing, then&lt;br /&gt;
we could branch from [[#pdserved|pdserved]] instead... it certainly needs changing a bit (the config is dire - a&lt;br /&gt;
hardcoded filename in a directory reached using a relative path... ugh), and it&#039;s quite simplistic, but it does&lt;br /&gt;
work.&lt;br /&gt;
&lt;br /&gt;
== pdservep ==&lt;br /&gt;
This is [[#pdserve|pdserve]] with more NPS handling (and fixed for Python3).&lt;br /&gt;
&lt;br /&gt;
The NPS changes in here appear to be included in [[#pdserved|pdserved]] too, so this and [[#pdserve|pdserve]], at&lt;br /&gt;
first glance, would seem to be obsolete.&lt;br /&gt;
&lt;br /&gt;
== pdshow ==&lt;br /&gt;
Shows and edits a base64-encoded file, extracting the dialog and direction from the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdshow.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a wrapper around a call to [[#pdedit|pdedit]] which extracts the dialog and direction from the filename,&lt;br /&gt;
rather than needing it specified explicitly.&lt;br /&gt;
&lt;br /&gt;
== pdstub ==&lt;br /&gt;
Stub server which provides more flexible lookup and response-modification than pdserve.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdstub &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
This program provides a basic server which serves PD, DCI and NPS. Rather than a straight NINo/Rundate lookup, it&lt;br /&gt;
uses search parameters to determine which response file to return for a request, and it allows replacement of data&lt;br /&gt;
in that response file with static parameters, or inputs derived from the request.&lt;br /&gt;
&lt;br /&gt;
It uses a single messages folder, rather than the separated responses folder of pdserve and each request/response&lt;br /&gt;
mapping is defined in a single line within the config file.&lt;br /&gt;
&lt;br /&gt;
== pdstubt ==&lt;br /&gt;
This is [[#pdstub|pdstub]] with a {{c|process_wait()}} function, which works exactly like the same function in&lt;br /&gt;
[[#pdservedt|pdservedt]].&lt;br /&gt;
&lt;br /&gt;
== pdstubtt ==&lt;br /&gt;
This is [[#pdstubt|pdstubt]] with a multi-threaded HTTP server. It&#039;s a fairly trivial change to the code; I haven&#039;t&lt;br /&gt;
looked through it to see if there are any thread localisation issues in there - I&#039;m assuming not, because this is&lt;br /&gt;
being used as is at the moment, and that would probably have been noticed by now.&lt;br /&gt;
&lt;br /&gt;
This seems to me to be the most mature of the pdstub implementations - multithreading the server is a no-brainer,&lt;br /&gt;
in my humble, and the timings can be ignored. It still has the problem of a hardcoded timing config, but that&lt;br /&gt;
shouldn&#039;t be too hard to fix in a less fragile manner.&lt;br /&gt;
&lt;br /&gt;
== pdtux ==&lt;br /&gt;
A Tuxedo server which advertises a few tux operations, namely:&lt;br /&gt;
* ping&lt;br /&gt;
* DCI913&lt;br /&gt;
* DCI923&lt;br /&gt;
* VMERCIS&lt;br /&gt;
* RESETCOUNTER&lt;br /&gt;
&lt;br /&gt;
This extracts the data out of the request packet and gets the data using [[#pddata|pddata.getninodata()]],&lt;br /&gt;
returning the resultant data (the whole thing for DCI calls, separated CIS header and W90 header for PDD calls).&lt;br /&gt;
&lt;br /&gt;
There are no arguments to this program, but it does require the installation of the &#039;tuxedo&#039; python module.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
And the non-&#039;pd&#039; python files:&lt;br /&gt;
&lt;br /&gt;
== certs ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Holds the paths to the various certificates used within cissim. 2 groups of cert and cacert files for connecting to&lt;br /&gt;
DCI and PD; 2 groups of cert and private key files for serving.&lt;br /&gt;
&lt;br /&gt;
Used in [[#pdcall.py|pdcall]], [[#pdserve.py|pdserve]] and [[#pdstub.py|pdstub]] programs, and in some test functions&lt;br /&gt;
in [[#sslutils.py|sslutils]].&lt;br /&gt;
&lt;br /&gt;
== checkport ==&lt;br /&gt;
&#039;&#039;Redundant&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Checks if it&#039;s possible to connect to {{c|localhost:9127}}. That&#039;s it really. &lt;br /&gt;
&lt;br /&gt;
Basically, a python version of:&lt;br /&gt;
 netstat -nap | grep &#039;:9127.*LISTEN&#039;&lt;br /&gt;
&lt;br /&gt;
== dci9n3rec ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Technically, this can be called from the command line, but it seems a bit pointless. It appears to read in a file&lt;br /&gt;
called &#039;in&#039; in the current directory and, uh, loads it into a DCI9n3 record structure and prints it. I guess it&#039;s&lt;br /&gt;
for testing purposes.&lt;br /&gt;
&lt;br /&gt;
Anyway, this contains the definition of a DCI913 or DCI923 record, packed to byte alignment for the fields, with&lt;br /&gt;
the 12 fields and their sizes defined as fixed length byte arrays.&lt;br /&gt;
&lt;br /&gt;
It&#039;s only used in [[#pdtux.py|pdtux]] for extracting the data from an incoming DCI struct. The equivalent for a PD&lt;br /&gt;
record is [[#w80construct.py|w80construct]]&lt;br /&gt;
&lt;br /&gt;
== extractodis ==&lt;br /&gt;
&#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Usage: extractodis.py &amp;lt;log_filename&amp;gt; [&amp;lt;PID&amp;gt;] [&amp;lt;starttime&amp;gt;] [&amp;lt;endtime&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
This is completely out there. So. It takes the filename and creates 3 shell scripts with names based on it, which&lt;br /&gt;
perform some function on the payload (base64-encoded ASCII). These scripts are:&lt;br /&gt;
* {{c|&amp;lt;filename&amp;gt;.write.sh}}: to write the transaction for ACS emulation (just writing the record out)&lt;br /&gt;
* {{c|&amp;lt;filename&amp;gt;.conv.sh}}: to write the transaction for CIS emulation (calling [[#CONVERT2E|pddump.py CONVERT2E]])&lt;br /&gt;
* {{c|&amp;lt;filename&amp;gt;.db.sh}}: to write the transaction to the &#039;database&#039; for serving (calling [[#pddb.py|pddb.py]])&lt;br /&gt;
&lt;br /&gt;
Aside from some very ropey python issues (mix of tabs and spaces in leading whitespace - very verboten in python),&lt;br /&gt;
it&#039;s just a very odd way of doing things.&lt;br /&gt;
&lt;br /&gt;
This is the oldschool format; it&#039;s dealing with the records as is, rather than moving them to the date/nino-based&lt;br /&gt;
database used by [[#pdserved.py|pdserved]] and beyond; the pddb output is used in the original&lt;br /&gt;
[[#pdserve.py|pdserve]] program too. It&#039;s still valid for the &#039;write.sh&#039;, I guess, but I suspect that&#039;s all.&lt;br /&gt;
&lt;br /&gt;
== fpcapprec ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
This was used in [[#pdtux.py|pdtux]], but is no longer used. The using has been deleted, so I can&#039;t see the context.&lt;br /&gt;
&lt;br /&gt;
== getfieldoffset ==&lt;br /&gt;
&#039;&#039;Test file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
I&#039;m pretty sure this is just testing that the [[#pdlayouts.pd|pdlayouts.getdialogfieldoffset()]] method is working&lt;br /&gt;
correctly.&lt;br /&gt;
&lt;br /&gt;
== key ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This provides a few constants for keycodes, used in [[#pdedit.py|pdedit]] and [[#pdscreen.py|pdscreen.py]].&lt;br /&gt;
&lt;br /&gt;
To be honest, it really needn&#039;t be here. The function key and some other constants are already defined in the curses&lt;br /&gt;
module; most of the rest are defined in the curses.ascii module. {{c|UP_LIST}} is home-made, but really doesn&#039;t&lt;br /&gt;
deserve its own file; any home-grown key values could go in the [[#pdscreen.py|pdscreen]] file.&lt;br /&gt;
&lt;br /&gt;
== loadninos ==&lt;br /&gt;
&#039;&#039;Library File&#039;&#039; and &#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Usage: loadninos.py &amp;lt;office-file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Used in [[#pdstub|pdstub]] and its variants.&lt;br /&gt;
&lt;br /&gt;
Loads NINOs from a CSV file (actually looks like a &#039;Whitespace-separated variables&#039; style file, though it has a&lt;br /&gt;
name of {{c|csvfile}} within the code). This looks for input in the form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 SVC     Office&lt;br /&gt;
 JSOV    109809&lt;br /&gt;
 JSRZ    107476&lt;br /&gt;
 JSFP    107038&lt;br /&gt;
 JSLH    103401&lt;br /&gt;
 JSKR    103838&lt;br /&gt;
 JSLF    102636&lt;br /&gt;
 JSGR    102805&lt;br /&gt;
 JSRT    100598&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above example is half-inched from the code. The code is ferociously simplistic, but I guess it does the job.&lt;br /&gt;
&lt;br /&gt;
Anyway, it takes the &#039;Office&#039; from the lines in the &#039;CSV&#039; file, strips the leading digit from it, then looks for&lt;br /&gt;
another &#039;csv&#039; file with that office number as a filename, in the same directory as the provided CSV file, so the&lt;br /&gt;
above will look for &#039;09809.csv&#039;, &#039;07476.csv&#039; etc. It will load that file, taking the first 8 chars of each line&lt;br /&gt;
as a NINo and then maps the office to that NINo, such that each NINo has the office number of the file that it&lt;br /&gt;
was loaded from mapped against it.&lt;br /&gt;
&lt;br /&gt;
This is used in [[#pdstub|pdstub]] to get the office for a particular NINo, which is then used as part of the&lt;br /&gt;
response in a DCI913 call. The stub loads the NINos using this function passing the {{c|OFFICECSVFILE}} config&lt;br /&gt;
parameter value to load them from. It doesn&#039;t handle errors well, but I guess once it&#039;s running, you don&#039;t&lt;br /&gt;
change it that much.&lt;br /&gt;
&lt;br /&gt;
== logextract ==&lt;br /&gt;
&#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Usage: logextract.py &amp;lt;logfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Extracts a {{c|DCI913CopyRecord}} from a logfile. It&#039;s a bit hacky - in the middle of it, it does some strange&lt;br /&gt;
stuff with the string &#039;127.0.0.1&#039;; I presume the logfile isn&#039;t really designed for extracting records from and&lt;br /&gt;
so this has to hardcode some messing around into it. It&#039;s very fragile - logfiles aren&#039;t typically structured&lt;br /&gt;
output (or, at least, not structured in this way).&lt;br /&gt;
&lt;br /&gt;
== npsload ==&lt;br /&gt;
&#039;&#039;Executable&#039;&#039; - this is an executable only; no part of it is called by other programs / libraries.&lt;br /&gt;
&lt;br /&gt;
 Usage: npsload &amp;lt;folder&amp;gt; &amp;lt;csvfile&amp;gt; &amp;lt;listfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This loads the {{c|csvfile}} from {{c|folder}} (i.e. the file is just the filename, not the {{c|/path/to/file}}),&lt;br /&gt;
and writes all output, including the {{c|listfile}} in the same folder.&lt;br /&gt;
&lt;br /&gt;
The CSV file is defined as:&lt;br /&gt;
 Entry/ies  Description&lt;br /&gt;
 1          NINo&lt;br /&gt;
 2          Surname&lt;br /&gt;
 3          Office&lt;br /&gt;
 4          LOP 25x Past&lt;br /&gt;
 5-20       NUBS2 record x 4&lt;br /&gt;
 21-36      LOP record x 4&lt;br /&gt;
 37         Data not found flag&lt;br /&gt;
 38         BFM Return Code&lt;br /&gt;
 39         RDS Code&lt;br /&gt;
&lt;br /&gt;
Each NUBS2 record and LOP record is made up of 4 comma-separated entries, with the fields:&lt;br /&gt;
 Entry Description&lt;br /&gt;
 1     Year&lt;br /&gt;
 2     x25&lt;br /&gt;
 3     x50&lt;br /&gt;
 4     Priority&lt;br /&gt;
&lt;br /&gt;
This program loops through all the NINo entries, and writes an XML file for each one, calling it {{c|NPSrply.&amp;lt;nino&amp;gt;.xml}},&lt;br /&gt;
adding an entry into the {{c|listfile}} for each file it created. It adds a final &#039;NINO not found&#039; entry to the listfile&lt;br /&gt;
and exits.&lt;br /&gt;
&lt;br /&gt;
== paths ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contains the paths used for calls to PD, DCI and NPS, as well as a few functions which operate on and around those paths.&lt;br /&gt;
&lt;br /&gt;
This is used liberally throughout the rest of the CISSim suite.&lt;br /&gt;
&lt;br /&gt;
== ports ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This just holds all the ports for the CIS swimlanes and returns the appropriate ports for a given swimlane when asked, in the form {{c|(pdd-port, dci-port, host)}}.&lt;br /&gt;
&lt;br /&gt;
== selectserver ==&lt;br /&gt;
&#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
I have no idea what this is trying to do. It&#039;s messing around with servers and message queues, but I&#039;m a bit lost.&lt;br /&gt;
&lt;br /&gt;
== sslutils ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contains functions to call servers using SSL certificates. Used in [[#pdacs|pdacs]], [[#pdcall|pdcall]], [[#pdproxy|pdproxy]]&lt;br /&gt;
and [[#teststub|teststub]]&lt;br /&gt;
&lt;br /&gt;
== temp ==&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
Seems to be a copy of [[#pdserved|pdserved]] with some testing code in there.&lt;br /&gt;
&lt;br /&gt;
== teststub ==&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
Tests connecting to the CIS Sim using curl and a socket. Prints things. Not particularly useful.&lt;br /&gt;
&lt;br /&gt;
== utils ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
A variety of utility functions; apparently not used anywhere.&lt;br /&gt;
&lt;br /&gt;
== vmeutils ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039; and &#039;&#039;Executable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 Usage: vmeutils &amp;lt;D/B&amp;gt; &amp;lt;date&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some VME date functions and a small utility executable to convert a date into a VME date ({{c|&#039;B&#039;}}, obviously) or&lt;br /&gt;
a VME date into a date ({{c|&#039;D&#039;}}). A &#039;VME date&#039; in this context is the number of days since 29/02/1852.&lt;br /&gt;
&lt;br /&gt;
== w80construct ==&lt;br /&gt;
&#039;&#039;Library file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Like [[#dci9n3rec.py|dci9n3rec]], this can be called from the command line, but it also seems a bit pointless.&lt;br /&gt;
I guess it&#039;s for testing purposes.&lt;br /&gt;
&lt;br /&gt;
Anyway, this contains the definition of a W80 record, packed to byte alignment for the fields, with the various fields&lt;br /&gt;
and their sizes defined mostly as fixed length byte arrays, though there are a few integer and long integer fields&lt;br /&gt;
defined too - these will be compiler-dependent, so I guess that&#039;s how the tux that it&#039;s interfacing with/mocking&lt;br /&gt;
works too?&lt;br /&gt;
&lt;br /&gt;
It&#039;s only used in [[#pdtux.py|pdtux]] for extracting the data from an incoming DCI struct. The equivalent for a DCI&lt;br /&gt;
record is [[#dci9n3rec.py|dci9n3rec]]&lt;br /&gt;
&lt;br /&gt;
= Files in pdlayouts =&lt;br /&gt;
&lt;br /&gt;
== pdlayouts/PDM ==&lt;br /&gt;
The &#039;PD Map&#039; contains the fields used in the CIS header and the W80 PD header, including their name, data type and length and&lt;br /&gt;
an optional &#039;style&#039; type argument which provides metadata for the field, &#039;&#039;eg.&#039;&#039; {{c|nino8}} indicates the first 8 chars of&lt;br /&gt;
a NINo, {{c|runtime8}} indicates that it contains a time in the format {{c|%H%M%S%f}}, {{c|vmedate}} indicates that the field&lt;br /&gt;
contains a &#039;VME date&#039;, ie. the number of days since 29/02/1852.&lt;br /&gt;
&lt;br /&gt;
These &#039;style&#039; arguments are used in {{c|pdutils.makerequestfile}} to autopopulate various fields for input based on the static&lt;br /&gt;
&#039;RUNDATE&#039; parameter value.&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Template:Obsolete&amp;diff=394</id>
		<title>Template:Obsolete</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Template:Obsolete&amp;diff=394"/>
		<updated>2021-10-18T14:49:14Z</updated>

		<summary type="html">&lt;p&gt;Stuart: First draft of the obsolete template.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;span style=&amp;quot;color:red; font-weight:bold&amp;quot; title=&amp;quot;{{{1|}}}&amp;quot;&amp;gt;Obsolete&amp;lt;/span&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Description ==&lt;br /&gt;
Template to flag something as obsolete with an optional explanation.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
Just including this template will write a highlighted &#039;Obsolete&#039; label out in the current context.&lt;br /&gt;
It writes it out inline, so if you want it in its own paragraph in the context of the page, you must&lt;br /&gt;
create the paragraph for it to be in.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{obsolete}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
will output&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-code&amp;quot;&amp;gt;&lt;br /&gt;
{{obsolete}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;This class is now {{obsolete}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
will output&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-code&amp;quot;&amp;gt;&lt;br /&gt;
This class is now {{obsolete}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An optional parameter will add a &#039;title&#039; to the word which can provide some contextual information&lt;br /&gt;
about the obsolescence of the target.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{obsolete|Deprecated on 26/04/2019 because of reasons}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
will output&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-code&amp;quot;&amp;gt;&lt;br /&gt;
{{obsolete|Deprecated on 26/04/2019 because of reasons}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
(Hover over it to see the title text)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Template:Strike&amp;diff=393</id>
		<title>Template:Strike</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Template:Strike&amp;diff=393"/>
		<updated>2021-10-18T14:43:17Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Usage -&amp;gt; Description&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;div style=&amp;quot;display:inline; color:#777; cursor:default; text-decoration:line-through;&amp;quot; title=&amp;quot;{{{2|}}}&amp;quot;&amp;gt;{{{1}}}&amp;lt;/div&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Description ==&lt;br /&gt;
Template for striking out some text with an optional explanation&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
The following examples will show how to use this template.&lt;br /&gt;
&lt;br /&gt;
=== Basic Usage ===&lt;br /&gt;
The first parameter is the markup to show struck out.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{strike|Task 1: Write usage notes for &#039;&#039;Strike&#039;&#039; template}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will result in:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-code&amp;quot;&amp;gt;&lt;br /&gt;
{{strike|Task 1: Write usage notes for &#039;&#039;Strike&#039;&#039; template}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tooltip Parameter ===&lt;br /&gt;
A second parameter gives a &#039;tooltip&#039; active on the struck out content.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{strike|Task 2: Explain how to use the &#039;hover&#039; parameter|The second parameter will give a &#039;hover&#039; tool tip on the text}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
would display:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-code&amp;quot;&amp;gt;&lt;br /&gt;
{{strike|Task 2: Explain how to use the &#039;hover&#039; parameter|The second parameter will give a &#039;hover&#039; tool tip on the text}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hover over it to see the explanatory tooltip.&lt;br /&gt;
&lt;br /&gt;
=== Complex Markup ===&lt;br /&gt;
You can put any wiki markup into the text to display, eg.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{strike|&lt;br /&gt;
 * This is a list&lt;br /&gt;
 * of a number of&lt;br /&gt;
 * elements, including&lt;br /&gt;
 *# A numbered sublist&lt;br /&gt;
 *# with only two elements|&lt;br /&gt;
 List is now obsolete - actually wasn&#039;t much use in the first place}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will display:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-code&amp;quot;&amp;gt;&lt;br /&gt;
{{strike|&lt;br /&gt;
* This is a list&lt;br /&gt;
* of a number of&lt;br /&gt;
* elements, including&lt;br /&gt;
*# A numbered sublist&lt;br /&gt;
*# with only two elements|&lt;br /&gt;
List is now obsolete - actually wasn&#039;t much use in the first place}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=392</id>
		<title>Noctam/DWP/ACS Test Harness/Existing System/CISSIM/Command Line Tools</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=392"/>
		<updated>2021-10-18T09:30:59Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Expanded on pdserved and pdstub&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{nav/ACS Test Harness}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
There are many command line tools to do various things within the CISSIM / proxy / data management / testing stub / kitchen  sink application.&lt;br /&gt;
&lt;br /&gt;
This page tries to exhaustively go through all of them. It fails. But it continues to try.&lt;br /&gt;
= File formats =&lt;br /&gt;
There are a few file formats used here.&lt;br /&gt;
&lt;br /&gt;
== base64-ebcdic ==&lt;br /&gt;
EBCDIC data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
This is the form for most PD calls - the content is a record whose definition is held elsewhere (in COBOL copybook-ish form)&lt;br /&gt;
&lt;br /&gt;
Used as input and output to/from [[#pdutils|pdutils]] and [[#pdedit|pdedit]].&lt;br /&gt;
&lt;br /&gt;
== base64-ascii ==&lt;br /&gt;
ASCII data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
Just like [[#base64-ebcdic|base64-ebcdic]] except the text fields are encoded into ASCII rather than EBCDIC.&lt;br /&gt;
&lt;br /&gt;
This can be used as input to [[#pdutils|pdutils]] when using the {{c|CONVERT2E}} option to convert it to [[#base64-ebcdic|base64-ebcdic]], and output from [[#pdutils|pdutils]] using the {{c|CONVERT2A}} option.&lt;br /&gt;
&lt;br /&gt;
= Filename format =&lt;br /&gt;
Some of the following utilities expect the filename to be in one of a number of specific formats. They use this&lt;br /&gt;
format to embed information about the transaction that the file represents, later extracted by the programs to look up&lt;br /&gt;
related data and/or structures.&lt;br /&gt;
&lt;br /&gt;
== pdconvert formats ==&lt;br /&gt;
The [[#pdconvert|pdconvert]], [[#pdconvertone|pdconvertone]] and [[#pdconvertall|pdconvertall]] programs expect&lt;br /&gt;
the files to be named in one of two dot-separated formats; one with 4 &#039;parts&#039;, one with any other number of &#039;parts&#039;&lt;br /&gt;
as long they number at least 3. The 4 part format is represented by the regex:&lt;br /&gt;
&lt;br /&gt;
 ^(?P&amp;lt;dialognum&amp;gt;[^.]{0,6})\.[^.]*\.[^.]*\.(?P&amp;lt;direction&amp;gt;in|out)$&lt;br /&gt;
 &lt;br /&gt;
 eg. &amp;quot;DCI908.NINO.STUB.out&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The 4 dot-separated parts indicate that this is an &#039;R&#039; (read) mode transaction. A suffix of &#039;in&#039; indicates a &#039;RQST&#039; direction,&lt;br /&gt;
&#039;out&#039; indicates a &#039;RPLY&#039; direction. The dialog is extracted as the first 6 chars of the first part, the mode and the direction&lt;br /&gt;
separated by underscores, so the above example would yield:&lt;br /&gt;
 DCI908_R_RQST&lt;br /&gt;
&lt;br /&gt;
The &#039;any number above 2, except 4&#039; format (?) extracts more information from the filename:&lt;br /&gt;
 ^(?P&amp;lt;dialognum&amp;gt;[^.]*)\.[^.]{3}(?P&amp;lt;messageid&amp;gt;[^.]{4})(?P&amp;lt;txnmode&amp;gt;[^.]).*\.(?P&amp;lt;direction&amp;gt;in|out)$&lt;br /&gt;
 &lt;br /&gt;
 eg. &amp;quot;PD375.CIS6084RCURRINT.153250.634934c5c8d6.in&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This builds the dialog and transaction mode from the filename. The direction is mapped to &#039;RQST&#039; or &#039;RPLY&#039; where the filename&lt;br /&gt;
has &#039;in&#039; or &#039;out&#039;, and the dialog is built up as: {{c|&amp;lt;dialognum&amp;gt;_&amp;lt;messageid&amp;gt;_&amp;lt;txnmode&amp;gt;_&amp;lt;direction&amp;gt;}}. The above example&lt;br /&gt;
would end up with the dialog:&lt;br /&gt;
 PD375_6084_R_RQST&lt;br /&gt;
&lt;br /&gt;
= Programs =&lt;br /&gt;
&lt;br /&gt;
== pdutils ==&lt;br /&gt;
Primarily a library file, used throughout various calls from the daemon programs as well as other utilities.&lt;br /&gt;
It can, however, also be called directly from the command line.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdutils &amp;lt;DUMP/OUT/SAVE/CONVERT2E/CONVERT2A&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;requestfile/replyfile&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   Note that SAVE requires redirected input from an ASCII text string, such as &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
        and that CONVERT requires redirected input from B64 encoded ASCII data &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
=== DUMP ===&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This puts &#039;&#039;everything&#039;&#039; out - ie. all the fields, the fillers and the groups. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
It prefixes the field with the data structure (&#039;&#039;eg&#039;&#039; B4 for binary 4 bytes; X16 for char 16 bytes; N2 for numeric char 2 bytes).&lt;br /&gt;
&lt;br /&gt;
It suffixes the value with the hex value found for the field, separated into space-separated octets, wrapped in parantheses.&lt;br /&gt;
&lt;br /&gt;
=== OUT ===&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This only puts out the fields and fillers. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
=== SAVE ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
I have tweaked the code to work in Windows and... I don&#039;t really know what this does, i.e. I don&#039;t know what format the input file is expected to be in. It&#039;s not the same as the &#039;requestfile/replyfile&#039; used for DUMP and OUT, because that fails with the exception message: &#039;&#039;invalid literal for int() with base 10: &#039;AAAAMMPJ4&#039; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== CONVERT2E ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded ASCII record format to the output file, in base64-encoded EBCDIC record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
=== CONVERT2A ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded EBCDIC record format to the output file, in base64-encoded ASCII record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
== pdedit ==&lt;br /&gt;
Edits the PD and DCI call data via a curses interface, using the COBOL data layouts for the calls.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdedit &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;sourcefile&#039; in this case is the same as the &#039;requestfile/replyfile&#039; provided in pdutils, that is, a file containing base64-encoded EBCDIC data. The &#039;destfile&#039; is in the same format with the changes applied (assuming that you save inside pdedit).&lt;br /&gt;
&lt;br /&gt;
Intriguingly, it appears to ignore the &#039;RQST/RPLY&#039; in the dialog and effectively overwrites it with the RQST/RPLY argument given to the program.&lt;br /&gt;
Not really sure why... that dialog is a bit of a hack, really, I suspect just to avoid multiple keys or too much structure in the config.&lt;br /&gt;
&lt;br /&gt;
 PD350/1151/RQST/R&lt;br /&gt;
might have worked better, with a structured system, be it XML or JSON or YAML or whatever. Since I don&#039;t really understand which things would be better grouped together, I&#039;ll leave this as an idle thought for now.&lt;br /&gt;
&lt;br /&gt;
== pddb ==&lt;br /&gt;
Creates a database entry which effectively maps a response file onto a request.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddb &amp;lt;dialog&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt; &amp;lt;EBCDIC/ASCII&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The output is in the form:&lt;br /&gt;
 &amp;lt;dialog&amp;gt;:&amp;lt;response-file&amp;gt;:&amp;lt;input-field-name=value[;...]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for a PD350 1151 request, you might see something like:&lt;br /&gt;
 $ python cissim/pddb.py PD350_1151_R_RQST requests/pd350-request-e messages/PD350.CIS1151RSTRTDIA.AASTUB.out EBCDIC&lt;br /&gt;
 PD350_1151_R_RQST:PD350.CIS1151RSTRTDIA.AASTUB.out:H1151-NINO=ST000001;H1151-NINO-SFX-TX=A;H1151-RQST-DSS-DAYS=20190213;H1151-RQST-DIA-ID=PD350 ;H1151-RQST-USR-NS-LVL=0000;H1151-RQST-USR-LS-LVL=0000;H1151-RQST-USR-BUS-SYS-NO=43;H1151-DEPT-ID-TP=1;H1151-OFF-LOC-NO=04710;H1151-RQST-SPCFC-BUS-TP=85;&lt;br /&gt;
&lt;br /&gt;
These entries can be appended into a single file, with each entry on a separate line and work together to a form a readonly database of sorts, which the server can use to lookup the response to use based on the values of the inputs provided in the request.&lt;br /&gt;
&lt;br /&gt;
== pdserve ==&lt;br /&gt;
This is what uses the given &#039;database&#039; files from pddb to serve the data based on the requests.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserve &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
It takes a config file which is effectively made up of paths to the &#039;databases&#039; built up using pddb along with an (optional) SSL flag. Each pddb line in the config is something like:&lt;br /&gt;
 &amp;lt;path-to-db-file&amp;gt;:&amp;lt;folder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for example:&lt;br /&gt;
&lt;br /&gt;
configfile.ja030&lt;br /&gt;
 SSL=N&lt;br /&gt;
 pdbase/JA030_01.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_02.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_99.CIS.txt:pdbase&lt;br /&gt;
&lt;br /&gt;
pdserve will expect to find the response files with the names defined in the &#039;database&#039; within the folder specified in the config, so you could have multiple entries here pointing to different databases.&lt;br /&gt;
&lt;br /&gt;
The &#039;port&#039; here is the port it will listen on. This is analogous to a &#039;swimlane&#039; (&#039;&#039;&amp;lt;sigh&amp;gt;&#039;&#039;) and, indeed, the terms are used interchangeably in some places. The default port value used is &#039;&#039;9127&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The recommended way of running this is using {{c|nohup}} so that you can exit the shell and it will continue to run... something like:&lt;br /&gt;
 nohup python pdserve.py configfile.ja030 9130 &amp;gt;ja030.log &amp;amp;&lt;br /&gt;
&lt;br /&gt;
... and of course, the only way to kill it after doing that is by identifying the process that&#039;s running and using the {{c|kill}} command.&lt;br /&gt;
&lt;br /&gt;
Final thing. Quite important.&amp;lt;br/&amp;gt;&lt;br /&gt;
The version I have doesn&#039;t work.&lt;br /&gt;
&lt;br /&gt;
In Python 2:&lt;br /&gt;
  $ python2 ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 68&lt;br /&gt;
      print(s.server_version, end=&#039; &#039;)&lt;br /&gt;
                                 ^&lt;br /&gt;
  SyntaxError: invalid syntax&lt;br /&gt;
&lt;br /&gt;
In Python 3:&lt;br /&gt;
  $ python ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
  Traceback (most recent call last):&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 316, in &amp;lt;module&amp;gt;&lt;br /&gt;
      status = main()&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 260, in main&lt;br /&gt;
      if &#039;#&#039; in line:&lt;br /&gt;
  TypeError: a bytes-like object is required, not &#039;str&#039;&lt;br /&gt;
&lt;br /&gt;
It looks like it&#039;s been half-heartedly converted from 2 to 3, but untested. I&#039;m assuming that either nobody uses it, or it&#039;s been fixed in place wherever it is used and the changes haven&#039;t been reflected back to the source.&lt;br /&gt;
&lt;br /&gt;
== pdcall ==&lt;br /&gt;
(Incidentally, this was a bit messy to get working due to using pycurl, I had to {{c|apt install libcurl4-openssl-dev libssl-dev}} and {{c|pip install pycurl}} in order to get this to work on my Ubuntu machine - no idea what this will require on Mac, but be prepared for pain, given how little access we have.)&lt;br /&gt;
&lt;br /&gt;
This can be used to call the server and test that it&#039;s working correctly.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdcall &amp;lt;swimlane&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&amp;lt;swimlane&amp;gt;&#039; here is the port that the server is listening on.&lt;br /&gt;
&lt;br /&gt;
This opens the request file and displays it using [[#pdedit|pdedit]]. After editing and saving, it posts the updated request to the server, captures the response and then opens &#039;&#039;that&#039;&#039; in pdedit too so that you can see (and, indeed, edit) the response, before saving to the output file.&lt;br /&gt;
&lt;br /&gt;
At least, I think that&#039;s what it does - because I couldn&#039;t get [[#pdserve|pdserve]] running, I had very little to test, so this is conjecture and glancery.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
I&#039;ve just dumped all the &#039;pd&#039; python files here for further processing.&lt;br /&gt;
&lt;br /&gt;
== pdacs ==&lt;br /&gt;
Calls a running ACS instance with an edited request, storing the response into the required output file.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdacs &amp;lt;service&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This pops up a {{c|pdedit}} window to edit the request (actually saving the resultant file to the given location), then creates the&lt;br /&gt;
request by prepending the ACS input header, with the uppercased {{c|service}} embedded in it, to the input file contents.&lt;br /&gt;
&lt;br /&gt;
The ACS input header is fixed (service aside) and has the following content:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 0ed1249b558f||True|101307|            |DCP26PD350  |null|&amp;lt;service&amp;gt;|11606730|null|DWDDE662|2|1548331293|0|500|0|false|P|60|468|&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full input is saved to a file in the current directory called {{c|&amp;lt;requestfile&amp;gt;.acs}}. The response from ACS is saved into the&lt;br /&gt;
provided {{c|replyfile}}.&lt;br /&gt;
&lt;br /&gt;
== pdconvertall ==&lt;br /&gt;
Converts *.in files and corresponding *.out files from a source folder into a destination folder. &lt;br /&gt;
&lt;br /&gt;
 Usage: pdconvertall.py &amp;lt;sourcefolder&amp;gt; &amp;lt;targetfolder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the filename format is significant for this program and, natch, undocumented.&lt;br /&gt;
See [[#pdconvert formats|pdconvert formats]] for more details.&lt;br /&gt;
&lt;br /&gt;
This scans the {{c|sourcefolder}} for all files matching {{c|*.in}} which &#039;&#039;do not&#039;&#039; start with the characters {{c|NPS}} and&lt;br /&gt;
have corresponding {{c|*.out}} files and &#039;converts&#039; them to a text-based format for use with [[#pdserved|pdserved]].&lt;br /&gt;
&lt;br /&gt;
The conversion of the input file is almost identical to the processing done by calling [[#pdutils|pdutils OUT]] with the&lt;br /&gt;
dialog and direction specified explicitly, though this program picks up that information from the embedded data in the filename.&lt;br /&gt;
&lt;br /&gt;
The directory structure it creates is:&lt;br /&gt;
 &amp;lt;outputfolder&amp;gt;&lt;br /&gt;
  |- &amp;lt;dialog&amp;gt;&lt;br /&gt;
      |- &amp;lt;rundate-yyyyMMdd&amp;gt;&lt;br /&gt;
          |- &amp;lt;nino&amp;gt;.DATA&lt;br /&gt;
&lt;br /&gt;
The format is text-based in the style of the [[#pdutils|pdutils OUT]] format. The [[#pdserved|pdserved]] server then reads&lt;br /&gt;
from the directory when it is processing the requests and determining the responses to return. The files can be modified in&lt;br /&gt;
place, or new files can be placed there. The server will pick up any external changes made to these files.&lt;br /&gt;
 &lt;br /&gt;
== pdconvertone ==&lt;br /&gt;
This is a thin wrapper around [[#pdconvertall|pdconvertall]] which works for a single input and output file. That is, it&lt;br /&gt;
still expects a {{c|*.in}} and corresponding {{c|*.out}} file to convert, and it emits the output into the directory&lt;br /&gt;
structure described in [[#pdconvertall|pdconvertall]].&lt;br /&gt;
 Usage: pdconvertone.py &amp;lt;sourcespec&amp;gt; &amp;lt;targetfolder&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
This calls {{c|pdconvertall}} with the single file identified by {{c|sourcespec}}. Note that if the file begins with the&lt;br /&gt;
characters {{c|NPS}} or there is no corresponding {{c|*.out}} file, it will be skipped&lt;br /&gt;
&lt;br /&gt;
== pdconvert ==&lt;br /&gt;
Converts a single file into its text-based format, emitting the output to stdout.&lt;br /&gt;
 &lt;br /&gt;
 Usage: pdconvert.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This does not have the same restrictions as [[#pdconvertall|pdconvertall]] and [[#pdconvertone|pdconvertone]] - i.e.&lt;br /&gt;
it does not require corresponding {{c|*.in}} and {{c|*.out}} files, though the given file&#039;s filename must be one of those.&lt;br /&gt;
It will still not work for NPS files (though, unlike the above programs, it will try and probably crash and burn in the&lt;br /&gt;
attempt).&lt;br /&gt;
&lt;br /&gt;
== pddata ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This has a load of functions in it, only some of which I understand.&lt;br /&gt;
The main one appears to be {{c|getninodata}} which, typical cissim style, takes 10 arguments (interrobang?!) and has...&lt;br /&gt;
well, &#039;&#039;some&#039;&#039; documentation which concentrates on one or two arguments and expects a fairly solid understanding of&lt;br /&gt;
what it&#039;s doing before you start reading.&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to have to come back to this to try and grasp it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This technically can be executed, but it looks like the stuff in the main call is just development stuff - testing&lt;br /&gt;
other functions and such like.&lt;br /&gt;
&lt;br /&gt;
== pddump ==&lt;br /&gt;
This dumps the data from the given (base64-encoded EBCDIC) file to the console in text form with square brackets to enclose&lt;br /&gt;
the data values. Note: This uses the [[#pdconvert formats|pdconvert format]] for the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddump.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a call to [[#DUMP|pdutils DUMP]] which takes the dialog / direction arguments from the filename&lt;br /&gt;
format rather than requiring them to be stated explicitly.&lt;br /&gt;
&lt;br /&gt;
== pdout ==&lt;br /&gt;
This dumps the data from the given (base64-encoded EBCDIC) file to the console in text form with square brackets to enclose&lt;br /&gt;
the data values. Note: This uses the [[#pdconvert formats|pdconvert format]] for the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdout.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a call to [[#OUT|pdutils OUT]] which takes the dialog / direction arguments from the filename&lt;br /&gt;
&lt;br /&gt;
== pdparams ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contains a single function: {{c|processparams}}. This function also exists in [[#pdutils|pdutils]], and it looks like that&lt;br /&gt;
one is used but this one is not. I presume it&#039;s obsolete, though there&#039;s no indication of that in the code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== pdproxy ==&lt;br /&gt;
A very straightforward proxy which writes the request and response of any CIS calls made to it to files in the current&lt;br /&gt;
directory.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdproxy &amp;lt;swimlane&amp;gt; &amp;lt;configfile&amp;gt; &amp;lt;folder&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
The swimlane determines whether the &#039;real&#039; CIS is called or whether the &#039;SIM&#039; is called. Basically, if the {{c|swimlane}}&lt;br /&gt;
argument is in the ranges: 14-15 or 17-28 (both inclusive), onward calls from the proxy will go to CIS proper. Any other&lt;br /&gt;
value is treated as the port that the simulator is listening on and it will be connected to using that port number.&lt;br /&gt;
&lt;br /&gt;
== pdreadall ==&lt;br /&gt;
Reads all registered dialogs and calls them for the specified NINo and optional surname.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadall &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;folder&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
 &lt;br /&gt;
== pdreadoneedit ==&lt;br /&gt;
Calls a specified dialog in CIS (or a CIS simulator) for a given NINo and optional surname. This allows the editing of&lt;br /&gt;
the record to be sent in the request before the call is made. The input and output files are created (I &#039;&#039;think&#039;&#039;) in&lt;br /&gt;
the current directory with the appropriate filename format.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadoneedit &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== pdreadone ==&lt;br /&gt;
Calls a specified dialog in CIS (or a CIS simulator) for a given NINo and optional surname. This does not allow the&lt;br /&gt;
editing of the record to be sent in the request before the call is made. The input and output files are created (I&lt;br /&gt;
&#039;&#039;think&#039;&#039;) in the current directory with the appropriate filename format.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadone &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
 &lt;br /&gt;
== pdscreen ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This file contains a single class &#039;{{c|Textbox}}&#039; which provides the editing widget used in [[#pdedit|pdedit]] to&lt;br /&gt;
edit a value in a record file.&lt;br /&gt;
&lt;br /&gt;
== pdserved ==&lt;br /&gt;
An upgraded version of [[#pdserve|pdserve]] with NPS support and separate message directories.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserved.py &amp;lt;port&amp;gt; -P &amp;lt;pddfolder&amp;gt; -D &amp;lt;dcifolder&amp;gt; [-N &amp;lt;npsfolder&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Aside from working in Python3 and adding the NPS handling which was added in [[#pdservep|pdservep]], this primarily&lt;br /&gt;
implements the separation of the data directories into &#039;PD&#039;, &#039;DCI&#039; and &#039;NPS&#039; folders. These could all be the same&lt;br /&gt;
folder (I think), but the option is there now to have different ones for each type. Presumably, you might want&lt;br /&gt;
different PD responses for different services, but you want to use the same DCI/NPS responses each time, so this&lt;br /&gt;
saves on a load of copying and pasting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== pdservedt ==&lt;br /&gt;
[[#pdserved|pdserved]] with a {{c|process_wait()}} function, which loads the timing data from the hardcoded location&lt;br /&gt;
at {{c|../serve/transtimes.py}}. Not ideal - it requires running the program from a specific directory, and, of course,&lt;br /&gt;
this is undocumented (as far as I can see anyway).&lt;br /&gt;
&lt;br /&gt;
The timing data is a map of timings against dialog; the example in the code is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# timings are a list, first tuple is times to cycle through, rest are exceptional count/time pairs&lt;br /&gt;
# &#039;CP650_1151_R_RPLY&#039;:  [(0.15, 0.25, 0.21, 0.17, 0.20, 0.16), (20, 2.3), (100, 28)],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Basically, it will cycle through the first tuple of timings, except when the count for a given dialog reaches the&lt;br /&gt;
first value in any of the following tuples. If it does (in this case, the 20th and 100th time a dialog is processed&lt;br /&gt;
within the server), it will use the timing associated with that number. Reasonably straightforward.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This seems the most sensible one to draw a &#039;proper&#039; version from. If we want to re-do the timing, then&lt;br /&gt;
we could branch from [[#pdserved|pdserved]] instead... it certainly needs changing a bit (the config is dire - a&lt;br /&gt;
hardcoded filename in a directory reached using a relative path... ugh), and it&#039;s quite simplistic, but it does&lt;br /&gt;
work.&lt;br /&gt;
&lt;br /&gt;
== pdservep ==&lt;br /&gt;
This is [[#pdserve|pdserve]] with more NPS handling (and fixed for Python3).&lt;br /&gt;
&lt;br /&gt;
The NPS changes in here appear to be included in [[#pdserved|pdserved]] too, so this and [[#pdserve|pdserve]], at&lt;br /&gt;
first glance, would seem to be obsolete.&lt;br /&gt;
&lt;br /&gt;
== pdshow ==&lt;br /&gt;
Shows and edits a base64-encoded file, extracting the dialog and direction from the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdshow.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a wrapper around a call to [[#pdedit|pdedit]] which extracts the dialog and direction from the filename,&lt;br /&gt;
rather than needing it specified explicitly.&lt;br /&gt;
&lt;br /&gt;
== pdstub ==&lt;br /&gt;
Stub server which provides more flexible lookup and response-modification than pdserve.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdstub &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
This program provides a basic server which serves PD, DCI and NPS. Rather than a straight NINo/Rundate lookup, it&lt;br /&gt;
uses search parameters to determine which response file to return for a request, and it allows replacement of data&lt;br /&gt;
in that response file with static parameters, or inputs derived from the request.&lt;br /&gt;
&lt;br /&gt;
It uses a single messages folder, rather than the separated responses folder of pdserve and each request/response&lt;br /&gt;
mapping is defined in a single line within the config file.&lt;br /&gt;
&lt;br /&gt;
== pdstubt ==&lt;br /&gt;
This is [[#pdstub|pdstub]] with a {{c|process_wait()}} function, which works exactly like the same function in&lt;br /&gt;
[[#pdservedt|pdservedt]].&lt;br /&gt;
&lt;br /&gt;
== pdstubtt ==&lt;br /&gt;
This is [[#pdstubt|pdstubt]] with a multi-threaded HTTP server. It&#039;s a fairly trivial change to the code; I haven&#039;t&lt;br /&gt;
looked through it to see if there are any thread localisation issues in there - I&#039;m assuming not, because this is&lt;br /&gt;
being used as is at the moment, and that would probably have been noticed by now.&lt;br /&gt;
&lt;br /&gt;
This seems to me to be the most mature of the pdstub implementations - multithreading the server is a no-brainer,&lt;br /&gt;
in my humble, and the timings can be ignored. It still has the problem of a hardcoded timing config, but that&lt;br /&gt;
shouldn&#039;t be too hard to fix in a less fragile manner.&lt;br /&gt;
&lt;br /&gt;
== pdtux ==&lt;br /&gt;
A Tuxedo server which advertises a few tux operations, namely:&lt;br /&gt;
* ping&lt;br /&gt;
* DCI913&lt;br /&gt;
* DCI923&lt;br /&gt;
* VMERCIS&lt;br /&gt;
* RESETCOUNTER&lt;br /&gt;
&lt;br /&gt;
This extracts the data out of the request packet and gets the data using [[#pddata|pddata.getninodata()]],&lt;br /&gt;
returning the resultant data (the whole thing for DCI calls, separated CIS header and W90 header for PDD calls).&lt;br /&gt;
&lt;br /&gt;
There are no arguments to this program, but it does require the installation of the &#039;tuxedo&#039; python module.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
And the non-&#039;pd&#039; python files:&lt;br /&gt;
&lt;br /&gt;
== certs ==&lt;br /&gt;
== checkport ==&lt;br /&gt;
== dci9n3rec ==&lt;br /&gt;
== extractodis ==&lt;br /&gt;
== fpcapprec ==&lt;br /&gt;
== getfieldoffset ==&lt;br /&gt;
== key ==&lt;br /&gt;
== loadninos ==&lt;br /&gt;
== logextract ==&lt;br /&gt;
== npsload ==&lt;br /&gt;
== paths ==&lt;br /&gt;
== ports ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This just holds all the ports for the CIS swimlanes and returns the appropriate ports for a given swimlane when asked, in the form {{c|(pdd-port, dci-port, host)}}.&lt;br /&gt;
&lt;br /&gt;
== selectserver ==&lt;br /&gt;
== sslutils ==&lt;br /&gt;
== temp ==&lt;br /&gt;
== teststub ==&lt;br /&gt;
== utils ==&lt;br /&gt;
== vmeutils ==&lt;br /&gt;
== w80construct ==&lt;br /&gt;
&lt;br /&gt;
= Files in pdlayouts =&lt;br /&gt;
&lt;br /&gt;
== pdlayouts/PDM ==&lt;br /&gt;
The &#039;PD Map&#039; contains the fields used in the CIS header and the W80 PD header, including their name, data type and length and&lt;br /&gt;
an optional &#039;style&#039; type argument which provides metadata for the field, &#039;&#039;eg.&#039;&#039; {{c|nino8}} indicates the first 8 chars of&lt;br /&gt;
a NINo, {{c|runtime8}} indicates that it contains a time in the format {{c|%H%M%S%f}}, {{c|vmedate}} indicates that the field&lt;br /&gt;
contains a &#039;VME date&#039;, ie. the number of days since 29/02/1852.&lt;br /&gt;
&lt;br /&gt;
These &#039;style&#039; arguments are used in {{c|pdutils.makerequestfile}} to autopopulate various fields for input based on the static&lt;br /&gt;
&#039;RUNDATE&#039; parameter value.&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=391</id>
		<title>Noctam/DWP/ACS Test Harness/Existing System/CISSIM/Command Line Tools</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=391"/>
		<updated>2021-10-15T12:32:53Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Updated with initial pdserve/pdstub findings&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{nav/ACS Test Harness}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
There are many command line tools to do various things within the CISSIM / proxy / data management / testing stub / kitchen  sink application.&lt;br /&gt;
&lt;br /&gt;
This page tries to exhaustively go through all of them. It fails. But it continues to try.&lt;br /&gt;
= File formats =&lt;br /&gt;
There are a few file formats used here.&lt;br /&gt;
&lt;br /&gt;
== base64-ebcdic ==&lt;br /&gt;
EBCDIC data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
This is the form for most PD calls - the content is a record whose definition is held elsewhere (in COBOL copybook-ish form)&lt;br /&gt;
&lt;br /&gt;
Used as input and output to/from [[#pdutils|pdutils]] and [[#pdedit|pdedit]].&lt;br /&gt;
&lt;br /&gt;
== base64-ascii ==&lt;br /&gt;
ASCII data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
Just like [[#base64-ebcdic|base64-ebcdic]] except the text fields are encoded into ASCII rather than EBCDIC.&lt;br /&gt;
&lt;br /&gt;
This can be used as input to [[#pdutils|pdutils]] when using the {{c|CONVERT2E}} option to convert it to [[#base64-ebcdic|base64-ebcdic]], and output from [[#pdutils|pdutils]] using the {{c|CONVERT2A}} option.&lt;br /&gt;
&lt;br /&gt;
= Filename format =&lt;br /&gt;
Some of the following utilities expect the filename to be in one of a number of specific formats. They use this&lt;br /&gt;
format to embed information about the transaction that the file represents, later extracted by the programs to look up&lt;br /&gt;
related data and/or structures.&lt;br /&gt;
&lt;br /&gt;
== pdconvert formats ==&lt;br /&gt;
The [[#pdconvert|pdconvert]], [[#pdconvertone|pdconvertone]] and [[#pdconvertall|pdconvertall]] programs expect&lt;br /&gt;
the files to be named in one of two dot-separated formats; one with 4 &#039;parts&#039;, one with any other number of &#039;parts&#039;&lt;br /&gt;
as long they number at least 3. The 4 part format is represented by the regex:&lt;br /&gt;
&lt;br /&gt;
 ^(?P&amp;lt;dialognum&amp;gt;[^.]{0,6})\.[^.]*\.[^.]*\.(?P&amp;lt;direction&amp;gt;in|out)$&lt;br /&gt;
 &lt;br /&gt;
 eg. &amp;quot;DCI908.NINO.STUB.out&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The 4 dot-separated parts indicate that this is an &#039;R&#039; (read) mode transaction. A suffix of &#039;in&#039; indicates a &#039;RQST&#039; direction,&lt;br /&gt;
&#039;out&#039; indicates a &#039;RPLY&#039; direction. The dialog is extracted as the first 6 chars of the first part, the mode and the direction&lt;br /&gt;
separated by underscores, so the above example would yield:&lt;br /&gt;
 DCI908_R_RQST&lt;br /&gt;
&lt;br /&gt;
The &#039;any number above 2, except 4&#039; format (?) extracts more information from the filename:&lt;br /&gt;
 ^(?P&amp;lt;dialognum&amp;gt;[^.]*)\.[^.]{3}(?P&amp;lt;messageid&amp;gt;[^.]{4})(?P&amp;lt;txnmode&amp;gt;[^.]).*\.(?P&amp;lt;direction&amp;gt;in|out)$&lt;br /&gt;
 &lt;br /&gt;
 eg. &amp;quot;PD375.CIS6084RCURRINT.153250.634934c5c8d6.in&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This builds the dialog and transaction mode from the filename. The direction is mapped to &#039;RQST&#039; or &#039;RPLY&#039; where the filename&lt;br /&gt;
has &#039;in&#039; or &#039;out&#039;, and the dialog is built up as: {{c|&amp;lt;dialognum&amp;gt;_&amp;lt;messageid&amp;gt;_&amp;lt;txnmode&amp;gt;_&amp;lt;direction&amp;gt;}}. The above example&lt;br /&gt;
would end up with the dialog:&lt;br /&gt;
 PD375_6084_R_RQST&lt;br /&gt;
&lt;br /&gt;
= Programs =&lt;br /&gt;
&lt;br /&gt;
== pdutils ==&lt;br /&gt;
Primarily a library file, used throughout various calls from the daemon programs as well as other utilities.&lt;br /&gt;
It can, however, also be called directly from the command line.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdutils &amp;lt;DUMP/OUT/SAVE/CONVERT2E/CONVERT2A&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;requestfile/replyfile&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   Note that SAVE requires redirected input from an ASCII text string, such as &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
        and that CONVERT requires redirected input from B64 encoded ASCII data &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
=== DUMP ===&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This puts &#039;&#039;everything&#039;&#039; out - ie. all the fields, the fillers and the groups. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
It prefixes the field with the data structure (&#039;&#039;eg&#039;&#039; B4 for binary 4 bytes; X16 for char 16 bytes; N2 for numeric char 2 bytes).&lt;br /&gt;
&lt;br /&gt;
It suffixes the value with the hex value found for the field, separated into space-separated octets, wrapped in parantheses.&lt;br /&gt;
&lt;br /&gt;
=== OUT ===&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This only puts out the fields and fillers. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
=== SAVE ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
I have tweaked the code to work in Windows and... I don&#039;t really know what this does, i.e. I don&#039;t know what format the input file is expected to be in. It&#039;s not the same as the &#039;requestfile/replyfile&#039; used for DUMP and OUT, because that fails with the exception message: &#039;&#039;invalid literal for int() with base 10: &#039;AAAAMMPJ4&#039; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== CONVERT2E ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded ASCII record format to the output file, in base64-encoded EBCDIC record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
=== CONVERT2A ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded EBCDIC record format to the output file, in base64-encoded ASCII record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
== pdedit ==&lt;br /&gt;
Edits the PD and DCI call data via a curses interface, using the COBOL data layouts for the calls.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdedit &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;sourcefile&#039; in this case is the same as the &#039;requestfile/replyfile&#039; provided in pdutils, that is, a file containing base64-encoded EBCDIC data. The &#039;destfile&#039; is in the same format with the changes applied (assuming that you save inside pdedit).&lt;br /&gt;
&lt;br /&gt;
Intriguingly, it appears to ignore the &#039;RQST/RPLY&#039; in the dialog and effectively overwrites it with the RQST/RPLY argument given to the program.&lt;br /&gt;
Not really sure why... that dialog is a bit of a hack, really, I suspect just to avoid multiple keys or too much structure in the config.&lt;br /&gt;
&lt;br /&gt;
 PD350/1151/RQST/R&lt;br /&gt;
might have worked better, with a structured system, be it XML or JSON or YAML or whatever. Since I don&#039;t really understand which things would be better grouped together, I&#039;ll leave this as an idle thought for now.&lt;br /&gt;
&lt;br /&gt;
== pddb ==&lt;br /&gt;
Creates a database entry which effectively maps a response file onto a request.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddb &amp;lt;dialog&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt; &amp;lt;EBCDIC/ASCII&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The output is in the form:&lt;br /&gt;
 &amp;lt;dialog&amp;gt;:&amp;lt;response-file&amp;gt;:&amp;lt;input-field-name=value[;...]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for a PD350 1151 request, you might see something like:&lt;br /&gt;
 $ python cissim/pddb.py PD350_1151_R_RQST requests/pd350-request-e messages/PD350.CIS1151RSTRTDIA.AASTUB.out EBCDIC&lt;br /&gt;
 PD350_1151_R_RQST:PD350.CIS1151RSTRTDIA.AASTUB.out:H1151-NINO=ST000001;H1151-NINO-SFX-TX=A;H1151-RQST-DSS-DAYS=20190213;H1151-RQST-DIA-ID=PD350 ;H1151-RQST-USR-NS-LVL=0000;H1151-RQST-USR-LS-LVL=0000;H1151-RQST-USR-BUS-SYS-NO=43;H1151-DEPT-ID-TP=1;H1151-OFF-LOC-NO=04710;H1151-RQST-SPCFC-BUS-TP=85;&lt;br /&gt;
&lt;br /&gt;
These entries can be appended into a single file, with each entry on a separate line and work together to a form a readonly database of sorts, which the server can use to lookup the response to use based on the values of the inputs provided in the request.&lt;br /&gt;
&lt;br /&gt;
== pdserve ==&lt;br /&gt;
This is what uses the given &#039;database&#039; files from pddb to serve the data based on the requests.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserve &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
It takes a config file which is effectively made up of paths to the &#039;databases&#039; built up using pddb along with an (optional) SSL flag. Each pddb line in the config is something like:&lt;br /&gt;
 &amp;lt;path-to-db-file&amp;gt;:&amp;lt;folder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for example:&lt;br /&gt;
&lt;br /&gt;
configfile.ja030&lt;br /&gt;
 SSL=N&lt;br /&gt;
 pdbase/JA030_01.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_02.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_99.CIS.txt:pdbase&lt;br /&gt;
&lt;br /&gt;
pdserve will expect to find the response files with the names defined in the &#039;database&#039; within the folder specified in the config, so you could have multiple entries here pointing to different databases.&lt;br /&gt;
&lt;br /&gt;
The &#039;port&#039; here is the port it will listen on. This is analogous to a &#039;swimlane&#039; (&#039;&#039;&amp;lt;sigh&amp;gt;&#039;&#039;) and, indeed, the terms are used interchangeably in some places. The default port value used is &#039;&#039;9127&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The recommended way of running this is using {{c|nohup}} so that you can exit the shell and it will continue to run... something like:&lt;br /&gt;
 nohup python pdserve.py configfile.ja030 9130 &amp;gt;ja030.log &amp;amp;&lt;br /&gt;
&lt;br /&gt;
... and of course, the only way to kill it after doing that is by identifying the process that&#039;s running and using the {{c|kill}} command.&lt;br /&gt;
&lt;br /&gt;
Final thing. Quite important.&amp;lt;br/&amp;gt;&lt;br /&gt;
The version I have doesn&#039;t work.&lt;br /&gt;
&lt;br /&gt;
In Python 2:&lt;br /&gt;
  $ python2 ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 68&lt;br /&gt;
      print(s.server_version, end=&#039; &#039;)&lt;br /&gt;
                                 ^&lt;br /&gt;
  SyntaxError: invalid syntax&lt;br /&gt;
&lt;br /&gt;
In Python 3:&lt;br /&gt;
  $ python ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
  Traceback (most recent call last):&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 316, in &amp;lt;module&amp;gt;&lt;br /&gt;
      status = main()&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 260, in main&lt;br /&gt;
      if &#039;#&#039; in line:&lt;br /&gt;
  TypeError: a bytes-like object is required, not &#039;str&#039;&lt;br /&gt;
&lt;br /&gt;
It looks like it&#039;s been half-heartedly converted from 2 to 3, but untested. I&#039;m assuming that either nobody uses it, or it&#039;s been fixed in place wherever it is used and the changes haven&#039;t been reflected back to the source.&lt;br /&gt;
&lt;br /&gt;
== pdcall ==&lt;br /&gt;
(Incidentally, this was a bit messy to get working due to using pycurl, I had to {{c|apt install libcurl4-openssl-dev libssl-dev}} and {{c|pip install pycurl}} in order to get this to work on my Ubuntu machine - no idea what this will require on Mac, but be prepared for pain, given how little access we have.)&lt;br /&gt;
&lt;br /&gt;
This can be used to call the server and test that it&#039;s working correctly.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdcall &amp;lt;swimlane&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&amp;lt;swimlane&amp;gt;&#039; here is the port that the server is listening on.&lt;br /&gt;
&lt;br /&gt;
This opens the request file and displays it using [[#pdedit|pdedit]]. After editing and saving, it posts the updated request to the server, captures the response and then opens &#039;&#039;that&#039;&#039; in pdedit too so that you can see (and, indeed, edit) the response, before saving to the output file.&lt;br /&gt;
&lt;br /&gt;
At least, I think that&#039;s what it does - because I couldn&#039;t get [[#pdserve|pdserve]] running, I had very little to test, so this is conjecture and glancery.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
I&#039;ve just dumped all the &#039;pd&#039; python files here for further processing.&lt;br /&gt;
&lt;br /&gt;
== pdacs ==&lt;br /&gt;
Calls a running ACS instance with an edited request, storing the response into the required output file.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdacs &amp;lt;service&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This pops up a {{c|pdedit}} window to edit the request (actually saving the resultant file to the given location), then creates the&lt;br /&gt;
request by prepending the ACS input header, with the uppercased {{c|service}} embedded in it, to the input file contents.&lt;br /&gt;
&lt;br /&gt;
The ACS input header is fixed (service aside) and has the following content:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 0ed1249b558f||True|101307|            |DCP26PD350  |null|&amp;lt;service&amp;gt;|11606730|null|DWDDE662|2|1548331293|0|500|0|false|P|60|468|&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full input is saved to a file in the current directory called {{c|&amp;lt;requestfile&amp;gt;.acs}}. The response from ACS is saved into the&lt;br /&gt;
provided {{c|replyfile}}.&lt;br /&gt;
&lt;br /&gt;
== pdconvertall ==&lt;br /&gt;
Converts *.in files and corresponding *.out files from a source folder into a destination folder. &lt;br /&gt;
&lt;br /&gt;
 Usage: pdconvertall.py &amp;lt;sourcefolder&amp;gt; &amp;lt;targetfolder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the filename format is significant for this program and, natch, undocumented.&lt;br /&gt;
See [[#pdconvert formats|pdconvert formats]] for more details.&lt;br /&gt;
&lt;br /&gt;
This scans the {{c|sourcefolder}} for all files matching {{c|*.in}} which &#039;&#039;do not&#039;&#039; start with the characters {{c|NPS}} and&lt;br /&gt;
have corresponding {{c|*.out}} files and &#039;converts&#039; them to a text-based format for use with [[#pdserved|pdserved]].&lt;br /&gt;
&lt;br /&gt;
The conversion of the input file is almost identical to the processing done by calling [[#pdutils|pdutils OUT]] with the&lt;br /&gt;
dialog and direction specified explicitly, though this program picks up that information from the embedded data in the filename.&lt;br /&gt;
&lt;br /&gt;
The directory structure it creates is:&lt;br /&gt;
 &amp;lt;outputfolder&amp;gt;&lt;br /&gt;
  |- &amp;lt;dialog&amp;gt;&lt;br /&gt;
      |- &amp;lt;rundate-yyyyMMdd&amp;gt;&lt;br /&gt;
          |- &amp;lt;nino&amp;gt;.DATA&lt;br /&gt;
&lt;br /&gt;
The format is text-based in the style of the [[#pdutils|pdutils OUT]] format. The [[#pdserved|pdserved]] server then reads&lt;br /&gt;
from the directory when it is processing the requests and determining the responses to return. The files can be modified in&lt;br /&gt;
place, or new files can be placed there. The server will pick up any external changes made to these files.&lt;br /&gt;
 &lt;br /&gt;
== pdconvertone ==&lt;br /&gt;
This is a thin wrapper around [[#pdconvertall|pdconvertall]] which works for a single input and output file. That is, it&lt;br /&gt;
still expects a {{c|*.in}} and corresponding {{c|*.out}} file to convert, and it emits the output into the directory&lt;br /&gt;
structure described in [[#pdconvertall|pdconvertall]].&lt;br /&gt;
 Usage: pdconvertone.py &amp;lt;sourcespec&amp;gt; &amp;lt;targetfolder&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
This calls {{c|pdconvertall}} with the single file identified by {{c|sourcespec}}. Note that if the file begins with the&lt;br /&gt;
characters {{c|NPS}} or there is no corresponding {{c|*.out}} file, it will be skipped&lt;br /&gt;
&lt;br /&gt;
== pdconvert ==&lt;br /&gt;
Converts a single file into its text-based format, emitting the output to stdout.&lt;br /&gt;
 &lt;br /&gt;
 Usage: pdconvert.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This does not have the same restrictions as [[#pdconvertall|pdconvertall]] and [[#pdconvertone|pdconvertone]] - i.e.&lt;br /&gt;
it does not require corresponding {{c|*.in}} and {{c|*.out}} files, though the given file&#039;s filename must be one of those.&lt;br /&gt;
It will still not work for NPS files (though, unlike the above programs, it will try and probably crash and burn in the&lt;br /&gt;
attempt).&lt;br /&gt;
&lt;br /&gt;
== pddata ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This has a load of functions in it, only some of which I understand.&lt;br /&gt;
The main one appears to be {{c|getninodata}} which, typical cissim style, takes 10 arguments (interrobang?!) and has...&lt;br /&gt;
well, &#039;&#039;some&#039;&#039; documentation which concentrates on one or two arguments and expects a fairly solid understanding of&lt;br /&gt;
what it&#039;s doing before you start reading.&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to have to come back to this to try and grasp it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This technically can be executed, but it looks like the stuff in the main call is just development stuff - testing&lt;br /&gt;
other functions and such like.&lt;br /&gt;
&lt;br /&gt;
== pddump ==&lt;br /&gt;
This dumps the data from the given (base64-encoded EBCDIC) file to the console in text form with square brackets to enclose&lt;br /&gt;
the data values. Note: This uses the [[#pdconvert formats|pdconvert format]] for the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddump.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a call to [[#DUMP|pdutils DUMP]] which takes the dialog / direction arguments from the filename&lt;br /&gt;
format rather than requiring them to be stated explicitly.&lt;br /&gt;
&lt;br /&gt;
== pdout ==&lt;br /&gt;
This dumps the data from the given (base64-encoded EBCDIC) file to the console in text form with square brackets to enclose&lt;br /&gt;
the data values. Note: This uses the [[#pdconvert formats|pdconvert format]] for the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdout.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a call to [[#OUT|pdutils OUT]] which takes the dialog / direction arguments from the filename&lt;br /&gt;
&lt;br /&gt;
== pdparams ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contains a single function: {{c|processparams}}. This function also exists in [[#pdutils|pdutils]], and it looks like that&lt;br /&gt;
one is used but this one is not. I presume it&#039;s obsolete, though there&#039;s no indication of that in the code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== pdproxy ==&lt;br /&gt;
A very straightforward proxy which writes the request and response of any CIS calls made to it to files in the current&lt;br /&gt;
directory.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdproxy &amp;lt;swimlane&amp;gt; &amp;lt;configfile&amp;gt; &amp;lt;folder&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
The swimlane determines whether the &#039;real&#039; CIS is called or whether the &#039;SIM&#039; is called. Basically, if the {{c|swimlane}}&lt;br /&gt;
argument is in the ranges: 14-15 or 17-28 (both inclusive), onward calls from the proxy will go to CIS proper. Any other&lt;br /&gt;
value is treated as the port that the simulator is listening on and it will be connected to using that port number.&lt;br /&gt;
&lt;br /&gt;
== pdreadall ==&lt;br /&gt;
Reads all registered dialogs and calls them for the specified NINo and optional surname.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadall &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;folder&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
 &lt;br /&gt;
== pdreadoneedit ==&lt;br /&gt;
Calls a specified dialog in CIS (or a CIS simulator) for a given NINo and optional surname. This allows the editing of&lt;br /&gt;
the record to be sent in the request before the call is made. The input and output files are created (I &#039;&#039;think&#039;&#039;) in&lt;br /&gt;
the current directory with the appropriate filename format.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadoneedit &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== pdreadone ==&lt;br /&gt;
Calls a specified dialog in CIS (or a CIS simulator) for a given NINo and optional surname. This does not allow the&lt;br /&gt;
editing of the record to be sent in the request before the call is made. The input and output files are created (I&lt;br /&gt;
&#039;&#039;think&#039;&#039;) in the current directory with the appropriate filename format.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadone &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
 &lt;br /&gt;
== pdscreen ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This file contains a single class &#039;{{c|Textbox}}&#039; which provides the editing widget used in [[#pdedit|pdedit]] to&lt;br /&gt;
edit a value in a record file.&lt;br /&gt;
&lt;br /&gt;
== pdserved ==&lt;br /&gt;
An upgraded version of [[#pdserve|pdserve]]. I&#039;ll examine the differences shortly - there are quite a lot.&lt;br /&gt;
&lt;br /&gt;
{{todo|Analyse differences between pdserve and pdserved.}}&lt;br /&gt;
&lt;br /&gt;
== pdservedt ==&lt;br /&gt;
[[#pdserved|pdserved]] with a {{c|process_wait()}} function, which loads the timing data from the hardcoded location&lt;br /&gt;
at {{c|../serve/transtimes.py}}. Not ideal - it requires running the program from a specific directory, and, of course,&lt;br /&gt;
this is undocumented (as far as I can see anyway).&lt;br /&gt;
&lt;br /&gt;
The timing data is a map of timings against dialog; the example in the code is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# timings are a list, first tuple is times to cycle through, rest are exceptional count/time pairs&lt;br /&gt;
# &#039;CP650_1151_R_RPLY&#039;:  [(0.15, 0.25, 0.21, 0.17, 0.20, 0.16), (20, 2.3), (100, 28)],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Basically, it will cycle through the first tuple of timings, except when the count for a given dialog reaches the&lt;br /&gt;
first value in any of the following tuples. If it does (in this case, the 20th and 100th time a dialog is processed&lt;br /&gt;
within the server), it will use the timing associated with that number. Reasonably straightforward.&lt;br /&gt;
&lt;br /&gt;
== pdservep ==&lt;br /&gt;
This is [[#pdserve|pdserve]] with more NPS handling (and fixed for Python3).&lt;br /&gt;
&lt;br /&gt;
The NPS changes in here appear to be included in [[#pdserved|pdserved]] too, so this and [[#pdserve|pdserve]], at&lt;br /&gt;
first glance, would seem to be obsolete.&lt;br /&gt;
&lt;br /&gt;
== pdshow ==&lt;br /&gt;
Shows and edits a base64-encoded file, extracting the dialog and direction from the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdshow.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a wrapper around a call to [[#pdedit|pdedit]] which extracts the dialog and direction from the filename,&lt;br /&gt;
rather than needing it specified explicitly.&lt;br /&gt;
&lt;br /&gt;
== pdstub ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== pdstubt ==&lt;br /&gt;
This is [[#pdstub|pdstub]] with a {{c|process_wait()}} function, which works exactly like the same function in&lt;br /&gt;
[[#pdservedt|pdservedt]].&lt;br /&gt;
&lt;br /&gt;
== pdstubtt ==&lt;br /&gt;
This is [[#pdstubt|pdstubt]] with a multi-threaded HTTP server. It&#039;s a fairly trivial change to the code; I haven&#039;t&lt;br /&gt;
looked through it to see if there are any thread localisation issues in there - I&#039;m assuming not, because this is&lt;br /&gt;
being used as is at the moment, and that would probably have been noticed by now.&lt;br /&gt;
&lt;br /&gt;
This seems to me to be the most mature of the pdstub implementations - multithreading the server is a no-brainer,&lt;br /&gt;
in my humble, and the timings can be ignored. It still has the problem of a hardcoded timing config, but that&lt;br /&gt;
shouldn&#039;t be too hard to fix in a less fragile manner.&lt;br /&gt;
&lt;br /&gt;
== pdtux ==&lt;br /&gt;
A Tuxedo server which advertises a few tux operations, namely:&lt;br /&gt;
* ping&lt;br /&gt;
* DCI913&lt;br /&gt;
* DCI923&lt;br /&gt;
* VMERCIS&lt;br /&gt;
* RESETCOUNTER&lt;br /&gt;
&lt;br /&gt;
This extracts the data out of the request packet and gets the data using [[#pddata|pddata.getninodata()]],&lt;br /&gt;
returning the resultant data (the whole thing for DCI calls, separated CIS header and W90 header for PDD calls).&lt;br /&gt;
&lt;br /&gt;
There are no arguments to this program, but it does require the installation of the &#039;tuxedo&#039; python module.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
And the non-&#039;pd&#039; python files:&lt;br /&gt;
&lt;br /&gt;
== certs ==&lt;br /&gt;
== checkport ==&lt;br /&gt;
== dci9n3rec ==&lt;br /&gt;
== extractodis ==&lt;br /&gt;
== fpcapprec ==&lt;br /&gt;
== getfieldoffset ==&lt;br /&gt;
== key ==&lt;br /&gt;
== loadninos ==&lt;br /&gt;
== logextract ==&lt;br /&gt;
== npsload ==&lt;br /&gt;
== paths ==&lt;br /&gt;
== ports ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This just holds all the ports for the CIS swimlanes and returns the appropriate ports for a given swimlane when asked, in the form {{c|(pdd-port, dci-port, host)}}.&lt;br /&gt;
&lt;br /&gt;
== selectserver ==&lt;br /&gt;
== sslutils ==&lt;br /&gt;
== temp ==&lt;br /&gt;
== teststub ==&lt;br /&gt;
== utils ==&lt;br /&gt;
== vmeutils ==&lt;br /&gt;
== w80construct ==&lt;br /&gt;
&lt;br /&gt;
= Files in pdlayouts =&lt;br /&gt;
&lt;br /&gt;
== pdlayouts/PDM ==&lt;br /&gt;
The &#039;PD Map&#039; contains the fields used in the CIS header and the W80 PD header, including their name, data type and length and&lt;br /&gt;
an optional &#039;style&#039; type argument which provides metadata for the field, &#039;&#039;eg.&#039;&#039; {{c|nino8}} indicates the first 8 chars of&lt;br /&gt;
a NINo, {{c|runtime8}} indicates that it contains a time in the format {{c|%H%M%S%f}}, {{c|vmedate}} indicates that the field&lt;br /&gt;
contains a &#039;VME date&#039;, ie. the number of days since 29/02/1852.&lt;br /&gt;
&lt;br /&gt;
These &#039;style&#039; arguments are used in {{c|pdutils.makerequestfile}} to autopopulate various fields for input based on the static&lt;br /&gt;
&#039;RUNDATE&#039; parameter value.&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=390</id>
		<title>Noctam/DWP/ACS Test Harness/Existing System/CISSIM/Command Line Tools</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=390"/>
		<updated>2021-10-14T20:52:08Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added most of the stuff - just the server/stub programs and non-PD ones left to do.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{nav/ACS Test Harness}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
There are many command line tools to do various things within the CISSIM / proxy / data management / testing stub / kitchen  sink application.&lt;br /&gt;
&lt;br /&gt;
This page tries to exhaustively go through all of them. It fails. But it continues to try.&lt;br /&gt;
= File formats =&lt;br /&gt;
There are a few file formats used here.&lt;br /&gt;
&lt;br /&gt;
== base64-ebcdic ==&lt;br /&gt;
EBCDIC data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
This is the form for most PD calls - the content is a record whose definition is held elsewhere (in COBOL copybook-ish form)&lt;br /&gt;
&lt;br /&gt;
Used as input and output to/from [[#pdutils|pdutils]] and [[#pdedit|pdedit]].&lt;br /&gt;
&lt;br /&gt;
== base64-ascii ==&lt;br /&gt;
ASCII data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
Just like [[#base64-ebcdic|base64-ebcdic]] except the text fields are encoded into ASCII rather than EBCDIC.&lt;br /&gt;
&lt;br /&gt;
This can be used as input to [[#pdutils|pdutils]] when using the {{c|CONVERT2E}} option to convert it to [[#base64-ebcdic|base64-ebcdic]], and output from [[#pdutils|pdutils]] using the {{c|CONVERT2A}} option.&lt;br /&gt;
&lt;br /&gt;
= Filename format =&lt;br /&gt;
Some of the following utilities expect the filename to be in one of a number of specific formats. They use this&lt;br /&gt;
format to embed information about the transaction that the file represents, later extracted by the programs to look up&lt;br /&gt;
related data and/or structures.&lt;br /&gt;
&lt;br /&gt;
== pdconvert formats ==&lt;br /&gt;
The [[#pdconvert|pdconvert]], [[#pdconvertone|pdconvertone]] and [[#pdconvertall|pdconvertall]] programs expect&lt;br /&gt;
the files to be named in one of two dot-separated formats; one with 4 &#039;parts&#039;, one with any other number of &#039;parts&#039;&lt;br /&gt;
as long they number at least 3. The 4 part format is represented by the regex:&lt;br /&gt;
&lt;br /&gt;
 ^(?P&amp;lt;dialognum&amp;gt;[^.]{0,6})\.[^.]*\.[^.]*\.(?P&amp;lt;direction&amp;gt;in|out)$&lt;br /&gt;
 &lt;br /&gt;
 eg. &amp;quot;DCI908.NINO.STUB.out&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The 4 dot-separated parts indicate that this is an &#039;R&#039; (read) mode transaction. A suffix of &#039;in&#039; indicates a &#039;RQST&#039; direction,&lt;br /&gt;
&#039;out&#039; indicates a &#039;RPLY&#039; direction. The dialog is extracted as the first 6 chars of the first part, the mode and the direction&lt;br /&gt;
separated by underscores, so the above example would yield:&lt;br /&gt;
 DCI908_R_RQST&lt;br /&gt;
&lt;br /&gt;
The &#039;any number above 2, except 4&#039; format (?) extracts more information from the filename:&lt;br /&gt;
 ^(?P&amp;lt;dialognum&amp;gt;[^.]*)\.[^.]{3}(?P&amp;lt;messageid&amp;gt;[^.]{4})(?P&amp;lt;txnmode&amp;gt;[^.]).*\.(?P&amp;lt;direction&amp;gt;in|out)$&lt;br /&gt;
 &lt;br /&gt;
 eg. &amp;quot;PD375.CIS6084RCURRINT.153250.634934c5c8d6.in&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This builds the dialog and transaction mode from the filename. The direction is mapped to &#039;RQST&#039; or &#039;RPLY&#039; where the filename&lt;br /&gt;
has &#039;in&#039; or &#039;out&#039;, and the dialog is built up as: {{c|&amp;lt;dialognum&amp;gt;_&amp;lt;messageid&amp;gt;_&amp;lt;txnmode&amp;gt;_&amp;lt;direction&amp;gt;}}. The above example&lt;br /&gt;
would end up with the dialog:&lt;br /&gt;
 PD375_6084_R_RQST&lt;br /&gt;
&lt;br /&gt;
= Programs =&lt;br /&gt;
&lt;br /&gt;
== pdutils ==&lt;br /&gt;
Primarily a library file, used throughout various calls from the daemon programs as well as other utilities.&lt;br /&gt;
It can, however, also be called directly from the command line.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdutils &amp;lt;DUMP/OUT/SAVE/CONVERT2E/CONVERT2A&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;requestfile/replyfile&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   Note that SAVE requires redirected input from an ASCII text string, such as &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
        and that CONVERT requires redirected input from B64 encoded ASCII data &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
=== DUMP ===&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This puts &#039;&#039;everything&#039;&#039; out - ie. all the fields, the fillers and the groups. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
It prefixes the field with the data structure (&#039;&#039;eg&#039;&#039; B4 for binary 4 bytes; X16 for char 16 bytes; N2 for numeric char 2 bytes).&lt;br /&gt;
&lt;br /&gt;
It suffixes the value with the hex value found for the field, separated into space-separated octets, wrapped in parantheses.&lt;br /&gt;
&lt;br /&gt;
=== OUT ===&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This only puts out the fields and fillers. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
=== SAVE ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
I have tweaked the code to work in Windows and... I don&#039;t really know what this does, i.e. I don&#039;t know what format the input file is expected to be in. It&#039;s not the same as the &#039;requestfile/replyfile&#039; used for DUMP and OUT, because that fails with the exception message: &#039;&#039;invalid literal for int() with base 10: &#039;AAAAMMPJ4&#039; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== CONVERT2E ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded ASCII record format to the output file, in base64-encoded EBCDIC record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
=== CONVERT2A ===&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded EBCDIC record format to the output file, in base64-encoded ASCII record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
== pdedit ==&lt;br /&gt;
Edits the PD and DCI call data via a curses interface, using the COBOL data layouts for the calls.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdedit &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;sourcefile&#039; in this case is the same as the &#039;requestfile/replyfile&#039; provided in pdutils, that is, a file containing base64-encoded EBCDIC data. The &#039;destfile&#039; is in the same format with the changes applied (assuming that you save inside pdedit).&lt;br /&gt;
&lt;br /&gt;
Intriguingly, it appears to ignore the &#039;RQST/RPLY&#039; in the dialog and effectively overwrites it with the RQST/RPLY argument given to the program.&lt;br /&gt;
Not really sure why... that dialog is a bit of a hack, really, I suspect just to avoid multiple keys or too much structure in the config.&lt;br /&gt;
&lt;br /&gt;
 PD350/1151/RQST/R&lt;br /&gt;
might have worked better, with a structured system, be it XML or JSON or YAML or whatever. Since I don&#039;t really understand which things would be better grouped together, I&#039;ll leave this as an idle thought for now.&lt;br /&gt;
&lt;br /&gt;
== pddb ==&lt;br /&gt;
Creates a database entry which effectively maps a response file onto a request.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddb &amp;lt;dialog&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt; &amp;lt;EBCDIC/ASCII&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The output is in the form:&lt;br /&gt;
 &amp;lt;dialog&amp;gt;:&amp;lt;response-file&amp;gt;:&amp;lt;input-field-name=value[;...]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for a PD350 1151 request, you might see something like:&lt;br /&gt;
 $ python cissim/pddb.py PD350_1151_R_RQST requests/pd350-request-e messages/PD350.CIS1151RSTRTDIA.AASTUB.out EBCDIC&lt;br /&gt;
 PD350_1151_R_RQST:PD350.CIS1151RSTRTDIA.AASTUB.out:H1151-NINO=ST000001;H1151-NINO-SFX-TX=A;H1151-RQST-DSS-DAYS=20190213;H1151-RQST-DIA-ID=PD350 ;H1151-RQST-USR-NS-LVL=0000;H1151-RQST-USR-LS-LVL=0000;H1151-RQST-USR-BUS-SYS-NO=43;H1151-DEPT-ID-TP=1;H1151-OFF-LOC-NO=04710;H1151-RQST-SPCFC-BUS-TP=85;&lt;br /&gt;
&lt;br /&gt;
These entries can be appended into a single file, with each entry on a separate line and work together to a form a readonly database of sorts, which the server can use to lookup the response to use based on the values of the inputs provided in the request.&lt;br /&gt;
&lt;br /&gt;
== pdserve ==&lt;br /&gt;
This is what uses the given &#039;database&#039; files from pddb to serve the data based on the requests.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserve &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
It takes a config file which is effectively made up of paths to the &#039;databases&#039; built up using pddb along with an (optional) SSL flag. Each pddb line in the config is something like:&lt;br /&gt;
 &amp;lt;path-to-db-file&amp;gt;:&amp;lt;folder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for example:&lt;br /&gt;
&lt;br /&gt;
configfile.ja030&lt;br /&gt;
 SSL=N&lt;br /&gt;
 pdbase/JA030_01.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_02.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_99.CIS.txt:pdbase&lt;br /&gt;
&lt;br /&gt;
pdserve will expect to find the response files with the names defined in the &#039;database&#039; within the folder specified in the config, so you could have multiple entries here pointing to different databases.&lt;br /&gt;
&lt;br /&gt;
The &#039;port&#039; here is the port it will listen on. This is analogous to a &#039;swimlane&#039; (&#039;&#039;&amp;lt;sigh&amp;gt;&#039;&#039;) and, indeed, the terms are used interchangeably in some places. The default port value used is &#039;&#039;9127&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The recommended way of running this is using {{c|nohup}} so that you can exit the shell and it will continue to run... something like:&lt;br /&gt;
 nohup python pdserve.py configfile.ja030 9130 &amp;gt;ja030.log &amp;amp;&lt;br /&gt;
&lt;br /&gt;
... and of course, the only way to kill it after doing that is by identifying the process that&#039;s running and using the {{c|kill}} command.&lt;br /&gt;
&lt;br /&gt;
Final thing. Quite important.&amp;lt;br/&amp;gt;&lt;br /&gt;
The version I have doesn&#039;t work.&lt;br /&gt;
&lt;br /&gt;
In Python 2:&lt;br /&gt;
  $ python2 ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 68&lt;br /&gt;
      print(s.server_version, end=&#039; &#039;)&lt;br /&gt;
                                 ^&lt;br /&gt;
  SyntaxError: invalid syntax&lt;br /&gt;
&lt;br /&gt;
In Python 3:&lt;br /&gt;
  $ python ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
  Traceback (most recent call last):&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 316, in &amp;lt;module&amp;gt;&lt;br /&gt;
      status = main()&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 260, in main&lt;br /&gt;
      if &#039;#&#039; in line:&lt;br /&gt;
  TypeError: a bytes-like object is required, not &#039;str&#039;&lt;br /&gt;
&lt;br /&gt;
It looks like it&#039;s been half-heartedly converted from 2 to 3, but untested. I&#039;m assuming that either nobody uses it, or it&#039;s been fixed in place wherever it is used and the changes haven&#039;t been reflected back to the source.&lt;br /&gt;
&lt;br /&gt;
== pdcall ==&lt;br /&gt;
(Incidentally, this was a bit messy to get working due to using pycurl, I had to {{c|apt install libcurl4-openssl-dev libssl-dev}} and {{c|pip install pycurl}} in order to get this to work on my Ubuntu machine - no idea what this will require on Mac, but be prepared for pain, given how little access we have.)&lt;br /&gt;
&lt;br /&gt;
This can be used to call the server and test that it&#039;s working correctly.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdcall &amp;lt;swimlane&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&amp;lt;swimlane&amp;gt;&#039; here is the port that the server is listening on.&lt;br /&gt;
&lt;br /&gt;
This opens the request file and displays it using [[#pdedit|pdedit]]. After editing and saving, it posts the updated request to the server, captures the response and then opens &#039;&#039;that&#039;&#039; in pdedit too so that you can see (and, indeed, edit) the response, before saving to the output file.&lt;br /&gt;
&lt;br /&gt;
At least, I think that&#039;s what it does - because I couldn&#039;t get [[#pdserve|pdserve]] running, I had very little to test, so this is conjecture and glancery.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
I&#039;ve just dumped all the &#039;pd&#039; python files here for further processing.&lt;br /&gt;
&lt;br /&gt;
== pdacs ==&lt;br /&gt;
Calls a running ACS instance with an edited request, storing the response into the required output file.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdacs &amp;lt;service&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This pops up a {{c|pdedit}} window to edit the request (actually saving the resultant file to the given location), then creates the&lt;br /&gt;
request by prepending the ACS input header, with the uppercased {{c|service}} embedded in it, to the input file contents.&lt;br /&gt;
&lt;br /&gt;
The ACS input header is fixed (service aside) and has the following content:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 0ed1249b558f||True|101307|            |DCP26PD350  |null|&amp;lt;service&amp;gt;|11606730|null|DWDDE662|2|1548331293|0|500|0|false|P|60|468|&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full input is saved to a file in the current directory called {{c|&amp;lt;requestfile&amp;gt;.acs}}. The response from ACS is saved into the&lt;br /&gt;
provided {{c|replyfile}}.&lt;br /&gt;
&lt;br /&gt;
== pdconvertall ==&lt;br /&gt;
Converts *.in files and corresponding *.out files from a source folder into a destination folder. &lt;br /&gt;
&lt;br /&gt;
 Usage: pdconvertall.py &amp;lt;sourcefolder&amp;gt; &amp;lt;targetfolder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the filename format is significant for this program and, natch, undocumented.&lt;br /&gt;
See [[#pdconvert formats|pdconvert formats]] for more details.&lt;br /&gt;
&lt;br /&gt;
This scans the {{c|sourcefolder}} for all files matching {{c|*.in}} which &#039;&#039;do not&#039;&#039; start with the characters {{c|NPS}} and&lt;br /&gt;
have corresponding {{c|*.out}} files and &#039;converts&#039; them to a text-based format for use with [[#pdserved|pdserved]].&lt;br /&gt;
&lt;br /&gt;
The conversion of the input file is almost identical to the processing done by calling [[#pdutils|pdutils OUT]] with the&lt;br /&gt;
dialog and direction specified explicitly, though this program picks up that information from the embedded data in the filename.&lt;br /&gt;
&lt;br /&gt;
The directory structure it creates is:&lt;br /&gt;
 &amp;lt;outputfolder&amp;gt;&lt;br /&gt;
  |- &amp;lt;dialog&amp;gt;&lt;br /&gt;
      |- &amp;lt;rundate-yyyyMMdd&amp;gt;&lt;br /&gt;
          |- &amp;lt;nino&amp;gt;.DATA&lt;br /&gt;
&lt;br /&gt;
The format is text-based in the style of the [[#pdutils|pdutils OUT]] format. The [[#pdserved|pdserved]] server then reads&lt;br /&gt;
from the directory when it is processing the requests and determining the responses to return. The files can be modified in&lt;br /&gt;
place, or new files can be placed there. The server will pick up any external changes made to these files.&lt;br /&gt;
 &lt;br /&gt;
== pdconvertone ==&lt;br /&gt;
This is a thin wrapper around [[#pdconvertall|pdconvertall]] which works for a single input and output file. That is, it&lt;br /&gt;
still expects a {{c|*.in}} and corresponding {{c|*.out}} file to convert, and it emits the output into the directory&lt;br /&gt;
structure described in [[#pdconvertall|pdconvertall]].&lt;br /&gt;
 Usage: pdconvertone.py &amp;lt;sourcespec&amp;gt; &amp;lt;targetfolder&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
This calls {{c|pdconvertall}} with the single file identified by {{c|sourcespec}}. Note that if the file begins with the&lt;br /&gt;
characters {{c|NPS}} or there is no corresponding {{c|*.out}} file, it will be skipped&lt;br /&gt;
&lt;br /&gt;
== pdconvert ==&lt;br /&gt;
Converts a single file into its text-based format, emitting the output to stdout.&lt;br /&gt;
 &lt;br /&gt;
 Usage: pdconvert.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This does not have the same restrictions as [[#pdconvertall|pdconvertall]] and [[#pdconvertone|pdconvertone]] - i.e.&lt;br /&gt;
it does not require corresponding {{c|*.in}} and {{c|*.out}} files, though the given file&#039;s filename must be one of those.&lt;br /&gt;
It will still not work for NPS files (though, unlike the above programs, it will try and probably crash and burn in the&lt;br /&gt;
attempt).&lt;br /&gt;
&lt;br /&gt;
== pddata ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This has a load of functions in it, only some of which I understand.&lt;br /&gt;
The main one appears to be {{c|getninodata}} which, typical cissim style, takes 10 arguments (interrobang?!) and has...&lt;br /&gt;
well, &#039;&#039;some&#039;&#039; documentation which concentrates on one or two arguments and expects a fairly solid understanding of&lt;br /&gt;
what it&#039;s doing before you start reading.&lt;br /&gt;
&lt;br /&gt;
I&#039;m going to have to come back to this to try and grasp it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This technically can be executed, but it looks like the stuff in the main call is just development stuff - testing&lt;br /&gt;
other functions and such like.&lt;br /&gt;
&lt;br /&gt;
== pddump ==&lt;br /&gt;
This dumps the data from the given (base64-encoded EBCDIC) file to the console in text form with square brackets to enclose&lt;br /&gt;
the data values. Note: This uses the [[#pdconvert formats|pdconvert format]] for the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddump.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a call to [[#DUMP|pdutils DUMP]] which takes the dialog / direction arguments from the filename&lt;br /&gt;
format rather than requiring them to be stated explicitly.&lt;br /&gt;
&lt;br /&gt;
== pdout ==&lt;br /&gt;
This dumps the data from the given (base64-encoded EBCDIC) file to the console in text form with square brackets to enclose&lt;br /&gt;
the data values. Note: This uses the [[#pdconvert formats|pdconvert format]] for the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdout.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a call to [[#OUT|pdutils OUT]] which takes the dialog / direction arguments from the filename&lt;br /&gt;
&lt;br /&gt;
== pdparams ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contains a single function: {{c|processparams}}. This function also exists in [[#pdutils|pdutils]], and it looks like that&lt;br /&gt;
one is used but this one is not. I presume it&#039;s obsolete, though there&#039;s no indication of that in the code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== pdproxy ==&lt;br /&gt;
A very straightforward proxy which writes the request and response of any CIS calls made to it to files in the current&lt;br /&gt;
directory.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdproxy &amp;lt;swimlane&amp;gt; &amp;lt;configfile&amp;gt; &amp;lt;folder&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
The swimlane determines whether the &#039;real&#039; CIS is called or whether the &#039;SIM&#039; is called. Basically, if the {{c|swimlane}}&lt;br /&gt;
argument is in the ranges: 14-15 or 17-28 (both inclusive), onward calls from the proxy will go to CIS proper. Any other&lt;br /&gt;
value is treated as the port that the simulator is listening on and it will be connected to using that port number.&lt;br /&gt;
&lt;br /&gt;
== pdreadall ==&lt;br /&gt;
Reads all registered dialogs and calls them for the specified NINo and optional surname.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadall &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;folder&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
 &lt;br /&gt;
== pdreadoneedit ==&lt;br /&gt;
Calls a specified dialog in CIS (or a CIS simulator) for a given NINo and optional surname. This allows the editing of&lt;br /&gt;
the record to be sent in the request before the call is made. The input and output files are created (I &#039;&#039;think&#039;&#039;) in&lt;br /&gt;
the current directory with the appropriate filename format.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadoneedit &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== pdreadone ==&lt;br /&gt;
Calls a specified dialog in CIS (or a CIS simulator) for a given NINo and optional surname. This does not allow the&lt;br /&gt;
editing of the record to be sent in the request before the call is made. The input and output files are created (I&lt;br /&gt;
&#039;&#039;think&#039;&#039;) in the current directory with the appropriate filename format.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdreadone &amp;lt;swimlane&amp;gt; &amp;lt;paramfile&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;nino&amp;gt; [&amp;lt;surname&amp;gt;]&lt;br /&gt;
 &lt;br /&gt;
== pdscreen ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This file contains a single class &#039;{{c|Textbox}}&#039; which provides the editing widget used in [[#pdedit|pdedit]] to&lt;br /&gt;
edit a value in a record file.&lt;br /&gt;
&lt;br /&gt;
== pdserved ==&lt;br /&gt;
== pdservedt ==&lt;br /&gt;
== pdservep ==&lt;br /&gt;
== pdshow ==&lt;br /&gt;
Shows and edits a base64-encoded file, extracting the dialog and direction from the filename.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdshow.py &amp;lt;pdfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a wrapper around a call to [[#pdedit|pdedit]] which extracts the dialog and direction from the filename,&lt;br /&gt;
rather than needing it specified explicitly.&lt;br /&gt;
&lt;br /&gt;
== pdstub ==&lt;br /&gt;
== pdstubt ==&lt;br /&gt;
== pdstubtt ==&lt;br /&gt;
&lt;br /&gt;
== pdtux ==&lt;br /&gt;
A Tuxedo server which advertises a few tux operations, namely:&lt;br /&gt;
* ping&lt;br /&gt;
* DCI913&lt;br /&gt;
* DCI923&lt;br /&gt;
* VMERCIS&lt;br /&gt;
* RESETCOUNTER&lt;br /&gt;
&lt;br /&gt;
This extracts the data out of the request packet and gets the data using [[#pddata|pddata.getninodata()]],&lt;br /&gt;
returning the resultant data (the whole thing for DCI calls, separated CIS header and W90 header for PDD calls).&lt;br /&gt;
&lt;br /&gt;
There are no arguments to this program, but it does require the installation of the &#039;tuxedo&#039; python module.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
And the non-&#039;pd&#039; python files:&lt;br /&gt;
&lt;br /&gt;
== certs ==&lt;br /&gt;
== checkport ==&lt;br /&gt;
== dci9n3rec ==&lt;br /&gt;
== extractodis ==&lt;br /&gt;
== fpcapprec ==&lt;br /&gt;
== getfieldoffset ==&lt;br /&gt;
== key ==&lt;br /&gt;
== loadninos ==&lt;br /&gt;
== logextract ==&lt;br /&gt;
== npsload ==&lt;br /&gt;
== paths ==&lt;br /&gt;
== ports ==&lt;br /&gt;
&#039;&#039;Library file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This just holds all the ports for the CIS swimlanes and returns the appropriate ports for a given swimlane when asked, in the form {{c|(pdd-port, dci-port, host)}}.&lt;br /&gt;
&lt;br /&gt;
== selectserver ==&lt;br /&gt;
== sslutils ==&lt;br /&gt;
== temp ==&lt;br /&gt;
== teststub ==&lt;br /&gt;
== utils ==&lt;br /&gt;
== vmeutils ==&lt;br /&gt;
== w80construct ==&lt;br /&gt;
&lt;br /&gt;
= Files in pdlayouts =&lt;br /&gt;
&lt;br /&gt;
== pdlayouts/PDM ==&lt;br /&gt;
The &#039;PD Map&#039; contains the fields used in the CIS header and the W80 PD header, including their name, data type and length and&lt;br /&gt;
an optional &#039;style&#039; type argument which provides metadata for the field, &#039;&#039;eg.&#039;&#039; {{c|nino8}} indicates the first 8 chars of&lt;br /&gt;
a NINo, {{c|runtime8}} indicates that it contains a time in the format {{c|%H%M%S%f}}, {{c|vmedate}} indicates that the field&lt;br /&gt;
contains a &#039;VME date&#039;, ie. the number of days since 29/02/1852.&lt;br /&gt;
&lt;br /&gt;
These &#039;style&#039; arguments are used in {{c|pdutils.makerequestfile}} to autopopulate various fields for input based on the static&lt;br /&gt;
&#039;RUNDATE&#039; parameter value.&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=389</id>
		<title>Noctam/DWP/ACS Test Harness/Existing System/CISSIM/Command Line Tools</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=389"/>
		<updated>2021-10-12T00:13:55Z</updated>

		<summary type="html">&lt;p&gt;Stuart: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{nav/ACS Test Harness}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
There are many command line tools to do various things within the CISSIM / proxy / data management / testing stub / kitchen  sink application.&lt;br /&gt;
&lt;br /&gt;
This page tries to exhaustively go through all of them. It fails. But it continues to try.&lt;br /&gt;
= File formats =&lt;br /&gt;
There are a few file formats used here.&lt;br /&gt;
&lt;br /&gt;
== base64-ebcdic ==&lt;br /&gt;
EBCDIC data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
This is the form for most PD calls - the content is a record whose definition is held elsewhere (in COBOL copybook-ish form)&lt;br /&gt;
&lt;br /&gt;
Used as input and output to/from [[#pdutils|pdutils]] and [[#pdedit|pdedit]].&lt;br /&gt;
&lt;br /&gt;
== base64-ascii ==&lt;br /&gt;
ASCII data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
Just like [[#base64-ebcdic|base64-ebcdic]] except the text fields are encoded into ASCII rather than EBCDIC.&lt;br /&gt;
&lt;br /&gt;
This can be used as input to [[#pdutils|pdutils]] when using the {{c|CONVERT2E}} option to convert it to [[#base64-ebcdic|base64-ebcdic]], and output from [[#pdutils|pdutils]] using the {{c|CONVERT2A}} option.&lt;br /&gt;
&lt;br /&gt;
= pdutils =&lt;br /&gt;
Primarily a library file, used throughout various calls from the daemon programs as well as other utilities.&lt;br /&gt;
It can, however, also be called directly from the command line.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdutils &amp;lt;DUMP/OUT/SAVE/CONVERT2E/CONVERT2A&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;requestfile/replyfile&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   Note that SAVE requires redirected input from an ASCII text string, such as &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
        and that CONVERT requires redirected input from B64 encoded ASCII data &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
== DUMP ==&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This puts &#039;&#039;everything&#039;&#039; out - ie. all the fields, the fillers and the groups. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
It prefixes the field with the data structure (&#039;&#039;eg&#039;&#039; B4 for binary 4 bytes; X16 for char 16 bytes; N2 for numeric char 2 bytes).&lt;br /&gt;
&lt;br /&gt;
It suffixes the value with the hex value found for the field, separated into space-separated octets, wrapped in parantheses.&lt;br /&gt;
&lt;br /&gt;
== OUT ==&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This only puts out the fields and fillers. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
== SAVE ==&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
I have tweaked the code to work in Windows and... I don&#039;t really know what this does, i.e. I don&#039;t know what format the input file is expected to be in. It&#039;s not the same as the &#039;requestfile/replyfile&#039; used for DUMP and OUT, because that fails with the exception message: &#039;&#039;invalid literal for int() with base 10: &#039;AAAAMMPJ4&#039; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== CONVERT2E ==&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded ASCII record format to the output file, in base64-encoded EBCDIC record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
== CONVERT2A ==&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded EBCDIC record format to the output file, in base64-encoded ASCII record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
= pdedit =&lt;br /&gt;
Edits the PD and DCI call data via a curses interface, using the COBOL data layouts for the calls.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdedit &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;sourcefile&#039; in this case is the same as the &#039;requestfile/replyfile&#039; provided in pdutils, that is, a file containing base64-encoded EBCDIC data. The &#039;destfile&#039; is in the same format with the changes applied (assuming that you save inside pdedit).&lt;br /&gt;
&lt;br /&gt;
Intriguingly, it appears to ignore the &#039;RQST/RPLY&#039; in the dialog and effectively overwrites it with the RQST/RPLY argument given to the program.&lt;br /&gt;
Not really sure why... that dialog is a bit of a hack, really, I suspect just to avoid multiple keys or too much structure in the config.&lt;br /&gt;
&lt;br /&gt;
 PD350/1151/RQST/R&lt;br /&gt;
might have worked better, with a structured system, be it XML or JSON or YAML or whatever. Since I don&#039;t really understand which things would be better grouped together, I&#039;ll leave this as an idle thought for now.&lt;br /&gt;
&lt;br /&gt;
= pddb =&lt;br /&gt;
Creates a database entry which effectively maps a response file onto a request.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddb &amp;lt;dialog&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt; &amp;lt;EBCDIC/ASCII&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The output is in the form:&lt;br /&gt;
 &amp;lt;dialog&amp;gt;:&amp;lt;response-file&amp;gt;:&amp;lt;input-field-name=value[;...]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for a PD350 1151 request, you might see something like:&lt;br /&gt;
 $ python cissim/pddb.py PD350_1151_R_RQST requests/pd350-request-e messages/PD350.CIS1151RSTRTDIA.AASTUB.out EBCDIC&lt;br /&gt;
 PD350_1151_R_RQST:PD350.CIS1151RSTRTDIA.AASTUB.out:H1151-NINO=ST000001;H1151-NINO-SFX-TX=A;H1151-RQST-DSS-DAYS=20190213;H1151-RQST-DIA-ID=PD350 ;H1151-RQST-USR-NS-LVL=0000;H1151-RQST-USR-LS-LVL=0000;H1151-RQST-USR-BUS-SYS-NO=43;H1151-DEPT-ID-TP=1;H1151-OFF-LOC-NO=04710;H1151-RQST-SPCFC-BUS-TP=85;&lt;br /&gt;
&lt;br /&gt;
These entries can be appended into a single file, with each entry on a separate line and work together to a form a readonly database of sorts, which the server can use to lookup the response to use based on the values of the inputs provided in the request.&lt;br /&gt;
&lt;br /&gt;
= pdserve =&lt;br /&gt;
This is what uses the given &#039;database&#039; files from pddb to serve the data based on the requests.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserve &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
It takes a config file which is effectively made up of paths to the &#039;databases&#039; built up using pddb along with an (optional) SSL flag. Each pddb line in the config is something like:&lt;br /&gt;
 &amp;lt;path-to-db-file&amp;gt;:&amp;lt;folder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for example:&lt;br /&gt;
&lt;br /&gt;
configfile.ja030&lt;br /&gt;
 SSL=N&lt;br /&gt;
 pdbase/JA030_01.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_02.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_99.CIS.txt:pdbase&lt;br /&gt;
&lt;br /&gt;
pdserve will expect to find the response files with the names defined in the &#039;database&#039; within the folder specified in the config, so you could have multiple entries here pointing to different databases.&lt;br /&gt;
&lt;br /&gt;
The &#039;port&#039; here is the port it will listen on. This is analogous to a &#039;swimlane&#039; (&#039;&#039;&amp;lt;sigh&amp;gt;&#039;&#039;) and, indeed, the terms are used interchangeably in some places. The default port value used is &#039;&#039;9127&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The recommended way of running this is using {{c|nohup}} so that you can exit the shell and it will continue to run... something like:&lt;br /&gt;
 nohup python pdserve.py configfile.ja030 9130 &amp;gt;ja030.log &amp;amp;&lt;br /&gt;
&lt;br /&gt;
... and of course, the only way to kill it after doing that is by identifying the process that&#039;s running and using the {{c|kill}} command.&lt;br /&gt;
&lt;br /&gt;
Final thing. Quite important.&amp;lt;br/&amp;gt;&lt;br /&gt;
The version I have doesn&#039;t work.&lt;br /&gt;
&lt;br /&gt;
In Python 2:&lt;br /&gt;
  $ python2 ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 68&lt;br /&gt;
      print(s.server_version, end=&#039; &#039;)&lt;br /&gt;
                                 ^&lt;br /&gt;
  SyntaxError: invalid syntax&lt;br /&gt;
&lt;br /&gt;
In Python 3:&lt;br /&gt;
  $ python ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
  Traceback (most recent call last):&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 316, in &amp;lt;module&amp;gt;&lt;br /&gt;
      status = main()&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 260, in main&lt;br /&gt;
      if &#039;#&#039; in line:&lt;br /&gt;
  TypeError: a bytes-like object is required, not &#039;str&#039;&lt;br /&gt;
&lt;br /&gt;
It looks like it&#039;s been half-heartedly converted from 2 to 3, but untested. I&#039;m assuming that either nobody uses it, or it&#039;s been fixed in place wherever it is used and the changes haven&#039;t been reflected back to the source.&lt;br /&gt;
&lt;br /&gt;
= pdcall =&lt;br /&gt;
(Incidentally, this was a bit messy to get working due to using pycurl, I had to {{c|apt install libcurl4-openssl-dev libssl-dev}} and {{c|pip install pycurl}} in order to get this to work on my Ubuntu machine - no idea what this will require on Mac, but be prepared for pain, given how little access we have.)&lt;br /&gt;
&lt;br /&gt;
This can be used to call the server and test that it&#039;s working correctly.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdcall &amp;lt;swimlane&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&amp;lt;swimlane&amp;gt;&#039; here is the port that the server is listening on.&lt;br /&gt;
&lt;br /&gt;
This opens the request file and displays it using [[#pdedit|pdedit]]. After editing and saving, it posts the updated request to the server, captures the response and then opens &#039;&#039;that&#039;&#039; in pdedit too so that you can see (and, indeed, edit) the response, before saving to the output file.&lt;br /&gt;
&lt;br /&gt;
At least, I think that&#039;s what it does - because I couldn&#039;t get [[#pdserve|pdserve]] running, I had very little to test, so this is conjecture and glancery.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
I&#039;ve just dumped all the &#039;pd&#039; python files here for further processing.&lt;br /&gt;
&lt;br /&gt;
= pdacs =&lt;br /&gt;
&lt;br /&gt;
 Usage: pdacs &amp;lt;service&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= pdconvertall =&lt;br /&gt;
= pdconvertone =&lt;br /&gt;
= pdconvert =&lt;br /&gt;
= pddata =&lt;br /&gt;
= pddump =&lt;br /&gt;
= pdout =&lt;br /&gt;
= pdparams =&lt;br /&gt;
= pdproxy =&lt;br /&gt;
= pdreadall =&lt;br /&gt;
= pdreadoneedit =&lt;br /&gt;
= pdreadone =&lt;br /&gt;
= pdscreen =&lt;br /&gt;
= pdserved =&lt;br /&gt;
= pdservedt =&lt;br /&gt;
= pdservep =&lt;br /&gt;
= pdshow =&lt;br /&gt;
= pdstub =&lt;br /&gt;
= pdstubt =&lt;br /&gt;
= pdstubtt =&lt;br /&gt;
= pdtux =&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
And the non-&#039;pd&#039; python files:&lt;br /&gt;
&lt;br /&gt;
= certs =&lt;br /&gt;
= checkport =&lt;br /&gt;
= dci9n3rec =&lt;br /&gt;
= extractodis =&lt;br /&gt;
= fpcapprec =&lt;br /&gt;
= getfieldoffset =&lt;br /&gt;
= key =&lt;br /&gt;
= loadninos =&lt;br /&gt;
= logextract =&lt;br /&gt;
= npsload =&lt;br /&gt;
= paths =&lt;br /&gt;
= ports =&lt;br /&gt;
Library file.&lt;br /&gt;
&lt;br /&gt;
This just holds all the ports for the CIS swimlanes and returns the appropriate ports for a given swimlane when asked, in the form {{c|(pdd-port, dci-port, host)}}.&lt;br /&gt;
&lt;br /&gt;
= selectserver =&lt;br /&gt;
= sslutils =&lt;br /&gt;
= temp =&lt;br /&gt;
= teststub =&lt;br /&gt;
= utils =&lt;br /&gt;
= vmeutils =&lt;br /&gt;
= w80construct =&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=388</id>
		<title>Noctam/DWP/ACS Test Harness/Existing System/CISSIM/Command Line Tools</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=388"/>
		<updated>2021-10-11T15:48:20Z</updated>

		<summary type="html">&lt;p&gt;Stuart: Added placeholders for the other python files in the cissim directory&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{nav/ACS Test Harness}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
There are many command line tools to do various things within the CISSIM / proxy / data management / testing stub / kitchen  sink application.&lt;br /&gt;
&lt;br /&gt;
This page tries to exhaustively go through all of them. It fails. But it continues to try.&lt;br /&gt;
= File formats =&lt;br /&gt;
There are a few file formats used here.&lt;br /&gt;
&lt;br /&gt;
== base64-ebcdic ==&lt;br /&gt;
EBCDIC data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
This is the form for most PD calls - the content is a record whose definition is held elsewhere (in COBOL copybook-ish form)&lt;br /&gt;
&lt;br /&gt;
Used as input and output to/from [[#pdutils|pdutils]] and [[#pdedit|pdedit]].&lt;br /&gt;
&lt;br /&gt;
== base64-ascii ==&lt;br /&gt;
ASCII data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
Just like [[#base64-ebcdic|base64-ebcdic]] except the text fields are encoded into ASCII rather than EBCDIC.&lt;br /&gt;
&lt;br /&gt;
This can be used as input to [[#pdutils|pdutils]] when using the {{c|CONVERT2E}} option to convert it to [[#base64-ebcdic|base64-ebcdic]], and output from [[#pdutils|pdutils]] using the {{c|CONVERT2A}} option.&lt;br /&gt;
&lt;br /&gt;
= pdutils =&lt;br /&gt;
Primarily a library file, used throughout various calls from the daemon programs as well as other utilities.&lt;br /&gt;
It can, however, also be called directly from the command line.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdutils &amp;lt;DUMP/OUT/SAVE/CONVERT2E/CONVERT2A&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;requestfile/replyfile&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   Note that SAVE requires redirected input from an ASCII text string, such as &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
        and that CONVERT requires redirected input from B64 encoded ASCII data &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
== DUMP ==&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This puts &#039;&#039;everything&#039;&#039; out - ie. all the fields, the fillers and the groups. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
It prefixes the field with the data structure (&#039;&#039;eg&#039;&#039; B4 for binary 4 bytes; X16 for char 16 bytes; N2 for numeric char 2 bytes).&lt;br /&gt;
&lt;br /&gt;
It suffixes the value with the hex value found for the field, separated into space-separated octets, wrapped in parantheses.&lt;br /&gt;
&lt;br /&gt;
== OUT ==&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This only puts out the fields and fillers. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
== SAVE ==&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
I have tweaked the code to work in Windows and... I don&#039;t really know what this does, i.e. I don&#039;t know what format the input file is expected to be in. It&#039;s not the same as the &#039;requestfile/replyfile&#039; used for DUMP and OUT, because that fails with the exception message: &#039;&#039;invalid literal for int() with base 10: &#039;AAAAMMPJ4&#039; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== CONVERT2E ==&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded ASCII record format to the output file, in base64-encoded EBCDIC record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
== CONVERT2A ==&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded EBCDIC record format to the output file, in base64-encoded ASCII record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
= pdedit =&lt;br /&gt;
Edits the PD and DCI call data via a curses interface, using the COBOL data layouts for the calls.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdedit &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;sourcefile&#039; in this case is the same as the &#039;requestfile/replyfile&#039; provided in pdutils, that is, a file containing base64-encoded EBCDIC data. The &#039;destfile&#039; is in the same format with the changes applied (assuming that you save inside pdedit).&lt;br /&gt;
&lt;br /&gt;
Intriguingly, it appears to ignore the &#039;RQST/RPLY&#039; in the dialog and effectively overwrites it with the RQST/RPLY argument given to the program.&lt;br /&gt;
Not really sure why... that dialog is a bit of a hack, really, I suspect just to avoid multiple keys or too much structure in the config.&lt;br /&gt;
&lt;br /&gt;
 PD350/1151/RQST/R&lt;br /&gt;
might have worked better, with a structured system, be it XML or JSON or YAML or whatever. Since I don&#039;t really understand which things would be better grouped together, I&#039;ll leave this as an idle thought for now.&lt;br /&gt;
&lt;br /&gt;
= pddb =&lt;br /&gt;
Creates a database entry which effectively maps a response file onto a request.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddb &amp;lt;dialog&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt; &amp;lt;EBCDIC/ASCII&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The output is in the form:&lt;br /&gt;
 &amp;lt;dialog&amp;gt;:&amp;lt;response-file&amp;gt;:&amp;lt;input-field-name=value[;...]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for a PD350 1151 request, you might see something like:&lt;br /&gt;
 $ python cissim/pddb.py PD350_1151_R_RQST requests/pd350-request-e messages/PD350.CIS1151RSTRTDIA.AASTUB.out EBCDIC&lt;br /&gt;
 PD350_1151_R_RQST:PD350.CIS1151RSTRTDIA.AASTUB.out:H1151-NINO=ST000001;H1151-NINO-SFX-TX=A;H1151-RQST-DSS-DAYS=20190213;H1151-RQST-DIA-ID=PD350 ;H1151-RQST-USR-NS-LVL=0000;H1151-RQST-USR-LS-LVL=0000;H1151-RQST-USR-BUS-SYS-NO=43;H1151-DEPT-ID-TP=1;H1151-OFF-LOC-NO=04710;H1151-RQST-SPCFC-BUS-TP=85;&lt;br /&gt;
&lt;br /&gt;
These entries can be appended into a single file, with each entry on a separate line and work together to a form a readonly database of sorts, which the server can use to lookup the response to use based on the values of the inputs provided in the request.&lt;br /&gt;
&lt;br /&gt;
= pdserve =&lt;br /&gt;
This is what uses the given &#039;database&#039; files from pddb to serve the data based on the requests.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserve &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
It takes a config file which is effectively made up of paths to the &#039;databases&#039; built up using pddb along with an (optional) SSL flag. Each pddb line in the config is something like:&lt;br /&gt;
 &amp;lt;path-to-db-file&amp;gt;:&amp;lt;folder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for example:&lt;br /&gt;
&lt;br /&gt;
configfile.ja030&lt;br /&gt;
 SSL=N&lt;br /&gt;
 pdbase/JA030_01.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_02.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_99.CIS.txt:pdbase&lt;br /&gt;
&lt;br /&gt;
pdserve will expect to find the response files with the names defined in the &#039;database&#039; within the folder specified in the config, so you could have multiple entries here pointing to different databases.&lt;br /&gt;
&lt;br /&gt;
The &#039;port&#039; here is the port it will listen on. This is analogous to a &#039;swimlane&#039; (&#039;&#039;&amp;lt;sigh&amp;gt;&#039;&#039;) and, indeed, the terms are used interchangeably in some places. The default port value used is &#039;&#039;9127&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The recommended way of running this is using {{c|nohup}} so that you can exit the shell and it will continue to run... something like:&lt;br /&gt;
 nohup python pdserve.py configfile.ja030 9130 &amp;gt;ja030.log &amp;amp;&lt;br /&gt;
&lt;br /&gt;
... and of course, the only way to kill it after doing that is by identifying the process that&#039;s running and using the {{c|kill}} command.&lt;br /&gt;
&lt;br /&gt;
Final thing. Quite important.&amp;lt;br/&amp;gt;&lt;br /&gt;
The version I have doesn&#039;t work.&lt;br /&gt;
&lt;br /&gt;
In Python 2:&lt;br /&gt;
  $ python2 ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 68&lt;br /&gt;
      print(s.server_version, end=&#039; &#039;)&lt;br /&gt;
                                 ^&lt;br /&gt;
  SyntaxError: invalid syntax&lt;br /&gt;
&lt;br /&gt;
In Python 3:&lt;br /&gt;
  $ python ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
  Traceback (most recent call last):&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 316, in &amp;lt;module&amp;gt;&lt;br /&gt;
      status = main()&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 260, in main&lt;br /&gt;
      if &#039;#&#039; in line:&lt;br /&gt;
  TypeError: a bytes-like object is required, not &#039;str&#039;&lt;br /&gt;
&lt;br /&gt;
It looks like it&#039;s been half-heartedly converted from 2 to 3, but untested. I&#039;m assuming that either nobody uses it, or it&#039;s been fixed in place wherever it is used and the changes haven&#039;t been reflected back to the source.&lt;br /&gt;
&lt;br /&gt;
= pdcall =&lt;br /&gt;
(Incidentally, this was a bit messy to get working due to using pycurl, I had to {{c|apt install libcurl4-openssl-dev libssl-dev}} and {{c|pip install pycurl}} in order to get this to work on my Ubuntu machine - no idea what this will require on Mac, but be prepared for pain, given how little access we have.)&lt;br /&gt;
&lt;br /&gt;
This can be used to call the server and test that it&#039;s working correctly.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdcall &amp;lt;swimlane&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&amp;lt;swimlane&amp;gt;&#039; here is the port that the server is listening on.&lt;br /&gt;
&lt;br /&gt;
This opens the request file and displays it using [[#pdedit|pdedit]]. After editing and saving, it posts the updated request to the server, captures the response and then opens &#039;&#039;that&#039;&#039; in pdedit too so that you can see (and, indeed, edit) the response, before saving to the output file.&lt;br /&gt;
&lt;br /&gt;
At least, I think that&#039;s what it does - because I couldn&#039;t get [[#pdserve|pdserve]] running, I had very little to test, so this is conjecture and glancery.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
I&#039;ve just dumped all the &#039;pd&#039; python files here for further processing.&lt;br /&gt;
&lt;br /&gt;
= pdacs =&lt;br /&gt;
= pdconvertall =&lt;br /&gt;
= pdconvertone =&lt;br /&gt;
= pdconvert =&lt;br /&gt;
= pddata =&lt;br /&gt;
= pddump =&lt;br /&gt;
= pdout =&lt;br /&gt;
= pdparams =&lt;br /&gt;
= pdproxy =&lt;br /&gt;
= pdreadall =&lt;br /&gt;
= pdreadoneedit =&lt;br /&gt;
= pdreadone =&lt;br /&gt;
= pdscreen =&lt;br /&gt;
= pdserved =&lt;br /&gt;
= pdservedt =&lt;br /&gt;
= pdservep =&lt;br /&gt;
= pdshow =&lt;br /&gt;
= pdstub =&lt;br /&gt;
= pdstubt =&lt;br /&gt;
= pdstubtt =&lt;br /&gt;
= pdtux =&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
And the non-&#039;pd&#039; python files:&lt;br /&gt;
&lt;br /&gt;
= certs =&lt;br /&gt;
= checkport =&lt;br /&gt;
= dci9n3rec =&lt;br /&gt;
= extractodis =&lt;br /&gt;
= fpcapprec =&lt;br /&gt;
= getfieldoffset =&lt;br /&gt;
= key =&lt;br /&gt;
= loadninos =&lt;br /&gt;
= logextract =&lt;br /&gt;
= npsload =&lt;br /&gt;
= paths =&lt;br /&gt;
= ports =&lt;br /&gt;
= selectserver =&lt;br /&gt;
= sslutils =&lt;br /&gt;
= temp =&lt;br /&gt;
= teststub =&lt;br /&gt;
= utils =&lt;br /&gt;
= vmeutils =&lt;br /&gt;
= w80construct =&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=387</id>
		<title>Noctam/DWP/ACS Test Harness/Existing System/CISSIM/Command Line Tools</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=387"/>
		<updated>2021-10-11T15:38:30Z</updated>

		<summary type="html">&lt;p&gt;Stuart: /* pdserve */ Spacing&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{nav/ACS Test Harness}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
There are many command line tools to do various things within the CISSIM / proxy / data management / testing stub / kitchen  sink application.&lt;br /&gt;
&lt;br /&gt;
This page tries to exhaustively go through all of them. It fails. But it continues to try.&lt;br /&gt;
= File formats =&lt;br /&gt;
There are a few file formats used here.&lt;br /&gt;
&lt;br /&gt;
== base64-ebcdic ==&lt;br /&gt;
EBCDIC data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
This is the form for most PD calls - the content is a record whose definition is held elsewhere (in COBOL copybook-ish form)&lt;br /&gt;
&lt;br /&gt;
Used as input and output to/from [[#pdutils|pdutils]] and [[#pdedit|pdedit]].&lt;br /&gt;
&lt;br /&gt;
== base64-ascii ==&lt;br /&gt;
ASCII data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
Just like [[#base64-ebcdic|base64-ebcdic]] except the text fields are encoded into ASCII rather than EBCDIC.&lt;br /&gt;
&lt;br /&gt;
This can be used as input to [[#pdutils|pdutils]] when using the {{c|CONVERT2E}} option to convert it to [[#base64-ebcdic|base64-ebcdic]], and output from [[#pdutils|pdutils]] using the {{c|CONVERT2A}} option.&lt;br /&gt;
&lt;br /&gt;
= pdutils =&lt;br /&gt;
Primarily a library file, used throughout various calls from the daemon programs as well as other utilities.&lt;br /&gt;
It can, however, also be called directly from the command line.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdutils &amp;lt;DUMP/OUT/SAVE/CONVERT2E/CONVERT2A&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;requestfile/replyfile&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   Note that SAVE requires redirected input from an ASCII text string, such as &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
        and that CONVERT requires redirected input from B64 encoded ASCII data &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
== DUMP ==&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This puts &#039;&#039;everything&#039;&#039; out - ie. all the fields, the fillers and the groups. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
It prefixes the field with the data structure (&#039;&#039;eg&#039;&#039; B4 for binary 4 bytes; X16 for char 16 bytes; N2 for numeric char 2 bytes).&lt;br /&gt;
&lt;br /&gt;
It suffixes the value with the hex value found for the field, separated into space-separated octets, wrapped in parantheses.&lt;br /&gt;
&lt;br /&gt;
== OUT ==&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This only puts out the fields and fillers. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
== SAVE ==&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
I have tweaked the code to work in Windows and... I don&#039;t really know what this does, i.e. I don&#039;t know what format the input file is expected to be in. It&#039;s not the same as the &#039;requestfile/replyfile&#039; used for DUMP and OUT, because that fails with the exception message: &#039;&#039;invalid literal for int() with base 10: &#039;AAAAMMPJ4&#039; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== CONVERT2E ==&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded ASCII record format to the output file, in base64-encoded EBCDIC record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
== CONVERT2A ==&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded EBCDIC record format to the output file, in base64-encoded ASCII record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
= pdedit =&lt;br /&gt;
Edits the PD and DCI call data via a curses interface, using the COBOL data layouts for the calls.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdedit &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;sourcefile&#039; in this case is the same as the &#039;requestfile/replyfile&#039; provided in pdutils, that is, a file containing base64-encoded EBCDIC data. The &#039;destfile&#039; is in the same format with the changes applied (assuming that you save inside pdedit).&lt;br /&gt;
&lt;br /&gt;
Intriguingly, it appears to ignore the &#039;RQST/RPLY&#039; in the dialog and effectively overwrites it with the RQST/RPLY argument given to the program.&lt;br /&gt;
Not really sure why... that dialog is a bit of a hack, really, I suspect just to avoid multiple keys or too much structure in the config.&lt;br /&gt;
&lt;br /&gt;
 PD350/1151/RQST/R&lt;br /&gt;
might have worked better, with a structured system, be it XML or JSON or YAML or whatever. Since I don&#039;t really understand which things would be better grouped together, I&#039;ll leave this as an idle thought for now.&lt;br /&gt;
&lt;br /&gt;
= pddb =&lt;br /&gt;
Creates a database entry which effectively maps a response file onto a request.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddb &amp;lt;dialog&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt; &amp;lt;EBCDIC/ASCII&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The output is in the form:&lt;br /&gt;
 &amp;lt;dialog&amp;gt;:&amp;lt;response-file&amp;gt;:&amp;lt;input-field-name=value[;...]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for a PD350 1151 request, you might see something like:&lt;br /&gt;
 $ python cissim/pddb.py PD350_1151_R_RQST requests/pd350-request-e messages/PD350.CIS1151RSTRTDIA.AASTUB.out EBCDIC&lt;br /&gt;
 PD350_1151_R_RQST:PD350.CIS1151RSTRTDIA.AASTUB.out:H1151-NINO=ST000001;H1151-NINO-SFX-TX=A;H1151-RQST-DSS-DAYS=20190213;H1151-RQST-DIA-ID=PD350 ;H1151-RQST-USR-NS-LVL=0000;H1151-RQST-USR-LS-LVL=0000;H1151-RQST-USR-BUS-SYS-NO=43;H1151-DEPT-ID-TP=1;H1151-OFF-LOC-NO=04710;H1151-RQST-SPCFC-BUS-TP=85;&lt;br /&gt;
&lt;br /&gt;
These entries can be appended into a single file, with each entry on a separate line and work together to a form a readonly database of sorts, which the server can use to lookup the response to use based on the values of the inputs provided in the request.&lt;br /&gt;
&lt;br /&gt;
= pdserve =&lt;br /&gt;
This is what uses the given &#039;database&#039; files from pddb to serve the data based on the requests.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserve &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
It takes a config file which is effectively made up of paths to the &#039;databases&#039; built up using pddb along with an (optional) SSL flag. Each pddb line in the config is something like:&lt;br /&gt;
 &amp;lt;path-to-db-file&amp;gt;:&amp;lt;folder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for example:&lt;br /&gt;
&lt;br /&gt;
configfile.ja030&lt;br /&gt;
 SSL=N&lt;br /&gt;
 pdbase/JA030_01.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_02.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_99.CIS.txt:pdbase&lt;br /&gt;
&lt;br /&gt;
pdserve will expect to find the response files with the names defined in the &#039;database&#039; within the folder specified in the config, so you could have multiple entries here pointing to different databases.&lt;br /&gt;
&lt;br /&gt;
The &#039;port&#039; here is the port it will listen on. This is analogous to a &#039;swimlane&#039; (&#039;&#039;&amp;lt;sigh&amp;gt;&#039;&#039;) and, indeed, the terms are used interchangeably in some places. The default port value used is &#039;&#039;9127&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The recommended way of running this is using {{c|nohup}} so that you can exit the shell and it will continue to run... something like:&lt;br /&gt;
 nohup python pdserve.py configfile.ja030 9130 &amp;gt;ja030.log &amp;amp;&lt;br /&gt;
&lt;br /&gt;
... and of course, the only way to kill it after doing that is by identifying the process that&#039;s running and using the {{c|kill}} command.&lt;br /&gt;
&lt;br /&gt;
Final thing. Quite important.&amp;lt;br/&amp;gt;&lt;br /&gt;
The version I have doesn&#039;t work.&lt;br /&gt;
&lt;br /&gt;
In Python 2:&lt;br /&gt;
  $ python2 ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 68&lt;br /&gt;
      print(s.server_version, end=&#039; &#039;)&lt;br /&gt;
                                 ^&lt;br /&gt;
  SyntaxError: invalid syntax&lt;br /&gt;
&lt;br /&gt;
In Python 3:&lt;br /&gt;
  $ python ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
  Traceback (most recent call last):&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 316, in &amp;lt;module&amp;gt;&lt;br /&gt;
      status = main()&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 260, in main&lt;br /&gt;
      if &#039;#&#039; in line:&lt;br /&gt;
  TypeError: a bytes-like object is required, not &#039;str&#039;&lt;br /&gt;
&lt;br /&gt;
It looks like it&#039;s been half-heartedly converted from 2 to 3, but untested. I&#039;m assuming that either nobody uses it, or it&#039;s been fixed in place wherever it is used and the changes haven&#039;t been reflected back to the source.&lt;br /&gt;
&lt;br /&gt;
= pdcall =&lt;br /&gt;
(Incidentally, this was a bit messy to get working due to using pycurl, I had to {{c|apt install libcurl4-openssl-dev libssl-dev}} and {{c|pip install pycurl}} in order to get this to work on my Ubuntu machine - no idea what this will require on Mac, but be prepared for pain, given how little access we have.)&lt;br /&gt;
&lt;br /&gt;
This can be used to call the server and test that it&#039;s working correctly.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdcall &amp;lt;swimlane&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&amp;lt;swimlane&amp;gt;&#039; here is the port that the server is listening on.&lt;br /&gt;
&lt;br /&gt;
This opens the request file and displays it using [[#pdedit|pdedit]]. After editing and saving, it posts the updated request to the server, captures the response and then opens &#039;&#039;that&#039;&#039; in pdedit too so that you can see (and, indeed, edit) the response, before saving to the output file.&lt;br /&gt;
&lt;br /&gt;
At least, I think that&#039;s what it does - because I couldn&#039;t get [[#pdserve|pdserve]] running, I had very little to test, so this is conjecture and glancery.&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
	<entry>
		<id>https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=386</id>
		<title>Noctam/DWP/ACS Test Harness/Existing System/CISSIM/Command Line Tools</title>
		<link rel="alternate" type="text/html" href="https://wiki.panglossian.net/wiki/index.php?title=Noctam/DWP/ACS_Test_Harness/Existing_System/CISSIM/Command_Line_Tools&amp;diff=386"/>
		<updated>2021-10-11T15:38:08Z</updated>

		<summary type="html">&lt;p&gt;Stuart: /* pdserve */ Added missing error for pdserve/python2&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{nav/ACS Test Harness}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
There are many command line tools to do various things within the CISSIM / proxy / data management / testing stub / kitchen  sink application.&lt;br /&gt;
&lt;br /&gt;
This page tries to exhaustively go through all of them. It fails. But it continues to try.&lt;br /&gt;
= File formats =&lt;br /&gt;
There are a few file formats used here.&lt;br /&gt;
&lt;br /&gt;
== base64-ebcdic ==&lt;br /&gt;
EBCDIC data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
This is the form for most PD calls - the content is a record whose definition is held elsewhere (in COBOL copybook-ish form)&lt;br /&gt;
&lt;br /&gt;
Used as input and output to/from [[#pdutils|pdutils]] and [[#pdedit|pdedit]].&lt;br /&gt;
&lt;br /&gt;
== base64-ascii ==&lt;br /&gt;
ASCII data and binary fields encoded into base64.&lt;br /&gt;
&lt;br /&gt;
Just like [[#base64-ebcdic|base64-ebcdic]] except the text fields are encoded into ASCII rather than EBCDIC.&lt;br /&gt;
&lt;br /&gt;
This can be used as input to [[#pdutils|pdutils]] when using the {{c|CONVERT2E}} option to convert it to [[#base64-ebcdic|base64-ebcdic]], and output from [[#pdutils|pdutils]] using the {{c|CONVERT2A}} option.&lt;br /&gt;
&lt;br /&gt;
= pdutils =&lt;br /&gt;
Primarily a library file, used throughout various calls from the daemon programs as well as other utilities.&lt;br /&gt;
It can, however, also be called directly from the command line.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdutils &amp;lt;DUMP/OUT/SAVE/CONVERT2E/CONVERT2A&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;requestfile/replyfile&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
   Note that SAVE requires redirected input from an ASCII text string, such as &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
        and that CONVERT requires redirected input from B64 encoded ASCII data &#039;&amp;lt; &amp;lt;datafile&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
== DUMP ==&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This puts &#039;&#039;everything&#039;&#039; out - ie. all the fields, the fillers and the groups. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
It prefixes the field with the data structure (&#039;&#039;eg&#039;&#039; B4 for binary 4 bytes; X16 for char 16 bytes; N2 for numeric char 2 bytes).&lt;br /&gt;
&lt;br /&gt;
It suffixes the value with the hex value found for the field, separated into space-separated octets, wrapped in parantheses.&lt;br /&gt;
&lt;br /&gt;
== OUT ==&lt;br /&gt;
Dumps the structure of a request found in a base64-encoded EBCDIC file out to the console.&lt;br /&gt;
&lt;br /&gt;
This only puts out the fields and fillers. The values are wrapped into square brackets the appropriate size for capturing the data for the field. Binary values have leading zeroes trimmed; all char values are displayed as found.&lt;br /&gt;
&lt;br /&gt;
== SAVE ==&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
I have tweaked the code to work in Windows and... I don&#039;t really know what this does, i.e. I don&#039;t know what format the input file is expected to be in. It&#039;s not the same as the &#039;requestfile/replyfile&#039; used for DUMP and OUT, because that fails with the exception message: &#039;&#039;invalid literal for int() with base 10: &#039;AAAAMMPJ4&#039; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== CONVERT2E ==&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded ASCII record format to the output file, in base64-encoded EBCDIC record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
== CONVERT2A ==&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; this doesn&#039;t work on Windows, because it uses [https://docs.python.org/3/library/select.html#select.select select.select()] to ensure that stdin is available, and that function only works on file descriptors on POSIX systems.&lt;br /&gt;
&lt;br /&gt;
Uses a &#039;hidden&#039; fifth argument, i.e. it expects the input file to be provided on stdin. The {{c|&amp;lt;requestfile/replyfile&amp;gt;}} argument is, in this case, an &#039;&#039;output&#039;&#039; file.&lt;br /&gt;
&lt;br /&gt;
This converts input from stdin, in base64-encoded EBCDIC record format to the output file, in base64-encoded ASCII record format. This is the exact mirror of {{c|CONVERT2A}}.&lt;br /&gt;
&lt;br /&gt;
Note: This only works for PD data, not DCI or NPS (which are only ever required in ASCII-based encodings).&lt;br /&gt;
&lt;br /&gt;
= pdedit =&lt;br /&gt;
Edits the PD and DCI call data via a curses interface, using the COBOL data layouts for the calls.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdedit &amp;lt;dialog&amp;gt; &amp;lt;RQST/RPLY&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;sourcefile&#039; in this case is the same as the &#039;requestfile/replyfile&#039; provided in pdutils, that is, a file containing base64-encoded EBCDIC data. The &#039;destfile&#039; is in the same format with the changes applied (assuming that you save inside pdedit).&lt;br /&gt;
&lt;br /&gt;
Intriguingly, it appears to ignore the &#039;RQST/RPLY&#039; in the dialog and effectively overwrites it with the RQST/RPLY argument given to the program.&lt;br /&gt;
Not really sure why... that dialog is a bit of a hack, really, I suspect just to avoid multiple keys or too much structure in the config.&lt;br /&gt;
&lt;br /&gt;
 PD350/1151/RQST/R&lt;br /&gt;
might have worked better, with a structured system, be it XML or JSON or YAML or whatever. Since I don&#039;t really understand which things would be better grouped together, I&#039;ll leave this as an idle thought for now.&lt;br /&gt;
&lt;br /&gt;
= pddb =&lt;br /&gt;
Creates a database entry which effectively maps a response file onto a request.&lt;br /&gt;
&lt;br /&gt;
 Usage: pddb &amp;lt;dialog&amp;gt; &amp;lt;sourcefile&amp;gt; &amp;lt;destfile&amp;gt; &amp;lt;EBCDIC/ASCII&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The output is in the form:&lt;br /&gt;
 &amp;lt;dialog&amp;gt;:&amp;lt;response-file&amp;gt;:&amp;lt;input-field-name=value[;...]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for a PD350 1151 request, you might see something like:&lt;br /&gt;
 $ python cissim/pddb.py PD350_1151_R_RQST requests/pd350-request-e messages/PD350.CIS1151RSTRTDIA.AASTUB.out EBCDIC&lt;br /&gt;
 PD350_1151_R_RQST:PD350.CIS1151RSTRTDIA.AASTUB.out:H1151-NINO=ST000001;H1151-NINO-SFX-TX=A;H1151-RQST-DSS-DAYS=20190213;H1151-RQST-DIA-ID=PD350 ;H1151-RQST-USR-NS-LVL=0000;H1151-RQST-USR-LS-LVL=0000;H1151-RQST-USR-BUS-SYS-NO=43;H1151-DEPT-ID-TP=1;H1151-OFF-LOC-NO=04710;H1151-RQST-SPCFC-BUS-TP=85;&lt;br /&gt;
&lt;br /&gt;
These entries can be appended into a single file, with each entry on a separate line and work together to a form a readonly database of sorts, which the server can use to lookup the response to use based on the values of the inputs provided in the request.&lt;br /&gt;
&lt;br /&gt;
= pdserve =&lt;br /&gt;
This is what uses the given &#039;database&#039; files from pddb to serve the data based on the requests.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdserve &amp;lt;configfile&amp;gt; [&amp;lt;port&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
It takes a config file which is effectively made up of paths to the &#039;databases&#039; built up using pddb along with an (optional) SSL flag. Each pddb line in the config is something like:&lt;br /&gt;
 &amp;lt;path-to-db-file&amp;gt;:&amp;lt;folder&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for example:&lt;br /&gt;
&lt;br /&gt;
configfile.ja030&lt;br /&gt;
 SSL=N&lt;br /&gt;
 pdbase/JA030_01.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_02.CIS.txt:pdbase&lt;br /&gt;
 pdbase/JA030_99.CIS.txt:pdbase&lt;br /&gt;
&lt;br /&gt;
pdserve will expect to find the response files with the names defined in the &#039;database&#039; within the folder specified in the config, so you could have multiple entries here pointing to different databases.&lt;br /&gt;
&lt;br /&gt;
The &#039;port&#039; here is the port it will listen on. This is analogous to a &#039;swimlane&#039; (&#039;&#039;&amp;lt;sigh&amp;gt;&#039;&#039;) and, indeed, the terms are used interchangeably in some places. The default port value used is &#039;&#039;9127&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The recommended way of running this is using {{c|nohup}} so that you can exit the shell and it will continue to run... something like:&lt;br /&gt;
 nohup python pdserve.py configfile.ja030 9130 &amp;gt;ja030.log &amp;amp;&lt;br /&gt;
&lt;br /&gt;
... and of course, the only way to kill it after doing that is by identifying the process that&#039;s running and using the {{c|kill}} command.&lt;br /&gt;
&lt;br /&gt;
Final thing. Quite important.&amp;lt;br/&amp;gt;&lt;br /&gt;
The version I have doesn&#039;t work.&lt;br /&gt;
&lt;br /&gt;
In Python 2:&lt;br /&gt;
  $ python2 ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 68&lt;br /&gt;
      print(s.server_version, end=&#039; &#039;)&lt;br /&gt;
                                 ^&lt;br /&gt;
  &lt;br /&gt;
  SyntaxError: invalid syntax&lt;br /&gt;
&lt;br /&gt;
In Python 3:&lt;br /&gt;
  $ python ../cissim/pdserve.py pdserve.test.config 9927&lt;br /&gt;
  Traceback (most recent call last):&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 316, in &amp;lt;module&amp;gt;&lt;br /&gt;
      status = main()&lt;br /&gt;
    File &amp;quot;../cissim/pdserve.py&amp;quot;, line 260, in main&lt;br /&gt;
      if &#039;#&#039; in line:&lt;br /&gt;
  TypeError: a bytes-like object is required, not &#039;str&#039;&lt;br /&gt;
&lt;br /&gt;
It looks like it&#039;s been half-heartedly converted from 2 to 3, but untested. I&#039;m assuming that either nobody uses it, or it&#039;s been fixed in place wherever it is used and the changes haven&#039;t been reflected back to the source.&lt;br /&gt;
&lt;br /&gt;
= pdcall =&lt;br /&gt;
(Incidentally, this was a bit messy to get working due to using pycurl, I had to {{c|apt install libcurl4-openssl-dev libssl-dev}} and {{c|pip install pycurl}} in order to get this to work on my Ubuntu machine - no idea what this will require on Mac, but be prepared for pain, given how little access we have.)&lt;br /&gt;
&lt;br /&gt;
This can be used to call the server and test that it&#039;s working correctly.&lt;br /&gt;
&lt;br /&gt;
 Usage: pdcall &amp;lt;swimlane&amp;gt; &amp;lt;dialog&amp;gt; &amp;lt;requestfile&amp;gt; &amp;lt;replyfile&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&amp;lt;swimlane&amp;gt;&#039; here is the port that the server is listening on.&lt;br /&gt;
&lt;br /&gt;
This opens the request file and displays it using [[#pdedit|pdedit]]. After editing and saving, it posts the updated request to the server, captures the response and then opens &#039;&#039;that&#039;&#039; in pdedit too so that you can see (and, indeed, edit) the response, before saving to the output file.&lt;br /&gt;
&lt;br /&gt;
At least, I think that&#039;s what it does - because I couldn&#039;t get [[#pdserve|pdserve]] running, I had very little to test, so this is conjecture and glancery.&lt;/div&gt;</summary>
		<author><name>Stuart</name></author>
	</entry>
</feed>