wlmscpfs(1)

wlmscpfs(1) β€” the DICOM Basic Worklist Management SCP (data-files edition) πŸ’…βœ¨

okay so bestie, picture this: you're running the wlmscpfs application and it is literally the icon, the moment, the main character of Basic Worklist Management. Grab a strawberry πŸ“ and let's get into it.


✨ NAME ✨

wlmscpfs β€” DICOM Basic Worklist Management SCP (based on data files). no cap, that's the whole vibe.


🌸 SYNOPSIS 🌸

wlmscpfs [options] port

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so the wlmscpfs application implements a Service Class Provider (SCP) for the Basic Worklist Management Service. basically it's out here doing the most. πŸ‘‘

The application will listen on a specified TCP/IP port for incoming association requests from a Worklist Management SCU. so it's just sitting there, waiting, being gorgeous. In case an association was acknowledged and a worklist query was received, the wlmscpfs application will query particular files in a certain directory (which can be specified through corresponding program options) on the file system for corresponding worklist information, and it will send this information back to the calling Worklist Management SCU. like a little mail carrier but make it medical imaging πŸ’Œ

Aside from dealing with Worklist Management queries, the wlmscpfs application also supports the Verification Service Class as an SCP. multi-talented fr fr.


πŸ’– PARAMETERS πŸ’–

  • port β€” tcp/ip port number to listen on. that's the port bestie, the one you listen on πŸŽ€

✨ OPTIONS ✨

general options πŸ’…

  • -h, --help β€” print this help text and exit. classic.
  • --version β€” print version information and exit. slay.
  • --arguments β€” print expanded command line arguments. for the nosy girlies.
  • -q, --quiet β€” quiet mode, print no warnings and errors. shhh 🀫
  • -v, --verbose β€” verbose mode, print processing details. tell me everything πŸ”₯
  • -d, --debug β€” debug mode, print debug information. we love a detail-oriented queen.
  • -ll, --log-level [l]evel: string constant β€” (fatal, error, warn, info, debug, trace) use level l for the logger. pick your vibe.
  • -lc, --log-config [f]ilename: string β€” use config file f for the logger. config me up.

multi-process options 🧚

  • -s, --single-process β€” single process mode. solo energy.
  • --fork β€” fork child process for each association (default). it's giving family tree 🌳

input options πŸ’œ

general:

  • -dfp, --data-files-path [p]ath: string (default: .) β€” path to worklist data files. where the data lives, periodt.

handling of worklist files:

  • -efr, --enable-file-reject β€” enable rejection of incomplete worklist files (default). not me accepting anything less than perfect πŸ™ˆ
  • -dfr, --disable-file-reject β€” disable rejection of incomplete worklist files. be chill about it.

processing options 🌈

returned character set:

  • -cs0, --return-no-char-set β€” return no specific character set (default). no preference, we love that.
  • -cs1, --return-iso-ir-100 β€” return specific character set ISO IR 100. iconic choice.
  • -csk, --keep-char-set β€” return character set provided in file. keep it as it came, lowkey respectful.

handling of return key attributes:

  • +ear, --enable-all-return β€” accept any (non-sequence) attribute on main dataset level as return key. accepting everyone into the group chat.
  • -ear, --disable-all-return β€” accept supported return keys only (default). exclusive club, iykyk.

other processing options:

  • -nse, --no-sq-expansion β€” disable expansion of empty sequences in C-FIND request messages. keep it contained bestie.

network options ⭐

IP protocol version:

  • -i4, --ipv4 β€” use IPv4 only (default). classic IPv4.
  • -i6, --ipv6 β€” use IPv6 only. new gen energy.
  • -i0, --ip-auto β€” use IPv6/IPv4 dual stack. why not both πŸ’…

preferred network transfer syntaxes:

  • +x=, --prefer-uncompr β€” prefer explicit VR local byte order (default). the go-to.
  • +xe, --prefer-little β€” prefer explicit VR little endian TS. little endian bestie.
  • +xb, --prefer-big β€” prefer explicit VR big endian TS. big energy.
  • +xd, --prefer-deflated β€” prefer deflated explicit VR little endian TS. compressed and cute.
  • +xi, --implicit β€” accept implicit VR little endian TS only. strict queen.

network host access control (tcp wrapper):

  • -ac, --access-full β€” accept connections from any host (default). open door policy 🫢
  • +ac, --access-control β€” enforce host access control rules. rules are rules.

post-1993 value representations:

  • +u, --enable-new-vr β€” enable support for new VRs (UN/UT) (default). new VRs are slaying.
  • -u, --disable-new-vr β€” disable support for new VRs, convert to OB. throwback mode.

deflate compression level (only with --prefer-deflated):

  • +cl, --compression-level [l]evel: integer (default: 6) β€” 0=uncompressed, 1=fastest, 9=best compression. choose your compression journey.

other network options:

  • -ta, --acse-timeout [s]econds: integer (default: 30) β€” timeout for ACSE messages. patience is a virtue.
  • -td, --dimse-timeout [s]econds: integer (default: unlimited) β€” timeout for DIMSE messages. no limits πŸ¦‹
  • --max-associations [a]ssocs: integer (default: 50) β€” limit maximum number of parallel associations. set boundaries bestie.
  • --refuse β€” refuse association. not today.
  • --reject β€” reject association if no implementation class UID. no UID no entry πŸ’€
  • --no-fail β€” don't fail on an invalid query. grace under pressure.
  • --sleep-before [s]econds: integer β€” sleep s seconds before find (default: 0). beauty rest 😴
  • --sleep-after [s]econds: integer β€” sleep s seconds after find (default: 0). post-find nap.
  • --sleep-during [s]econds: integer β€” sleep s seconds during find (default: 0). multitasking nap.
  • -pdu, --max-pdu [n]umber of bytes: integer (4096..131072) β€” set max receive pdu to n bytes (default: 16384). pdu has a limit, respect it.
  • -dhl, --disable-host-lookup β€” disable hostname lookup. no reverse psychology here.

transport layer security (TLS) options πŸ”₯

transport protocol stack:

  • -tls, --disable-tls β€” use normal TCP/IP connection (default). plain and simple.
  • +tls, --enable-tls [p]rivate key file, [c]ertificate file: string β€” use authenticated secure TLS connection. secure the bag πŸ”’

private key password (only with --enable-tls):

  • +ps, --std-passwd β€” prompt user to type password on stdin (default). type it in bestie.
  • +pw, --use-passwd [p]assword: string β€” use specified password. password specified, we move.
  • -pw, --null-passwd β€” use empty string as password. risky but okay.

key and certificate file format:

  • -pem, --pem-keys β€” read keys and certificates as PEM file (default). PEM is that girl.
  • -der, --der-keys β€” read keys and certificates as DER file. DER representation, we respect it.

certification authority:

  • +cf, --add-cert-file [f]ilename: string β€” add certificate file to list of certificates. add it to the roster.
  • +cd, --add-cert-dir [d]irectory: string β€” add certificates in d to list of certificates. bring the whole directory.
  • +crl, --add-crl-file [f]ilename: string β€” add certificate revocation list file (implies --enable-crl-vfy). revocation nation.
  • +crv, --enable-crl-vfy β€” enable leaf CRL verification. verify the leaves πŸƒ
  • +cra, --enable-crl-all β€” enable full chain CRL verification. verify the whole chain.

security profile:

  • +ph, --list-profiles β€” list supported TLS profiles and exit. profile drop πŸ“‹
  • +pg, --profile-8996 β€” BCP 195 RFC 8996 TLS Profile (default). the standard.
  • +pm, --profile-8996-mod β€” Modified BCP 195 RFC 8996 TLS Profile.
    • # only available if underlying TLS library supports
    • # all TLS features required for this profile
  • +py, --profile-bcp195-nd β€” Non-downgrading BCP 195 TLS Profile (retired). retired but not forgotten.
  • +px, --profile-bcp195 β€” BCP 195 TLS Profile (retired). retired icon.
  • +pz, --profile-bcp195-ex β€” Extended BCP 195 TLS Profile (retired). extended retirement.
  • +pb, --profile-basic β€” Basic TLS Secure Transport Connection Profile (retired).
    • # only available if underlying TLS library supports 3DES
  • +pa, --profile-aes β€” AES TLS Secure Transport Connection Profile (retired). AES ate.
  • +pn, --profile-null β€” Authenticated unencrypted communication (retired, was used in IHE ATNA). null but not forgotten.

ciphersuite:

  • +cc, --list-ciphers β€” list supported TLS ciphersuites and exit. cipher reveal ✨
  • +cs, --cipher [c]iphersuite name: string β€” add ciphersuite to list of negotiated suites. negotiate the vibe.
  • +dp, --dhparam [f]ilename: string β€” read DH parameters for DH/DSS ciphersuites. parameters bestie.

server name indication:

  • --no-sni β€” do not use SNI (default). no SNI, no problem.
  • --expect-sni [s]erver name: string β€” expect requests for server name s. expect the expected.

pseudo random generator:

  • +rs, --seed [f]ilename: string β€” seed random generator with contents of f. plant the seed 🌱
  • +ws, --write-seed β€” write back modified seed (only with --seed). write it back.
  • +wf, --write-seed-file [f]ilename: string (only with --seed) β€” write modified seed to file f. file it away.

peer authentication:

  • -rc, --require-peer-cert β€” verify peer certificate, fail if absent (default). no cert no entry.
  • -vc, --verify-peer-cert β€” verify peer certificate if present. if you have it, we check it.
  • -ic, --ignore-peer-cert β€” don't verify peer certificate. trust fall 🫢

output options 🌸

general:

  • -rfp, --request-file-path [p]ath: string β€” path to store request files to. where the receipts go.
  • -rff, --request-file-format [f]ormat: string (default: #t.dump) β€” request file name format. formatted for the gods.

πŸ’œ NOTES πŸ’œ

The semantic impacts of the above mentioned options is clear for the majority of options. Some particular options, however, are so specific that they need detailed descriptions which will be given in this passage. okay so let's break it down, bestie.

The returned character set options are intended for situations in which the wlmscpfs application will return attribute values which are not composed of characters from the DICOM default character repertoire. In such cases, for example option --return-iso-ir-100 can be used to specify that a response to a modality's worklist management C-FIND request shall contain DICOM's Specific Character Set attribute (0008,0005) with a corresponding value, indicating the character repertoire from which the characters of returned attribute values were taken (in this example the repertoire ISO IR 100). Please note that the wlmscpfs application will not make sure that all returned values are actually made up of this character repertoire; the application expects this to be the case. so it's trusting you, don't betray it 😭

In general, the Specific Character Set attribute (0008,0005) will only be included in the C-FIND response if it contains any attributes that are affected by the character set, i.e. for value representations PN, LO, LT, SH, ST and UT. those are the girlies that care about character set. πŸ‘‘

Please note that a C-FIND request which is handled by this application may contain DICOM's Specific Character Set attribute (0008,0005), but this application will never use this attribute's value for matching. it's not a match girl, it's just there. Besides, the question if DICOM's Specific Character Set attribute (0008,0005) will be contained in a C-FIND response which is returned by this application is always determined by the returned character set option which was specified when this application was started. so whatever you picked at startup, that's the vibe. periodt. πŸ’…

okay so bestie, about --enable-file-reject and --disable-file-reject 🫢 these two are literally the on/off switch for the file rejection mechanism, and what that mechanism does is make sure only complete worklist files get used during the matching process. no half-baked files sneaking into your match, periodt πŸ’…

and what even counts as "complete"?? great question πŸŽ€ a worklist file is considered complete if it contains all the necessary type 1 information that the SCP might have to return to an SCU in a C-FIND response message. that's the vibe check the file has to pass, no cap ✨

iykyk: Table K.6-1 in part 4 annex K of the DICOM standard is the receipt 🧾 β€” it lists all the corresponding type 1 attributes (peep the column "Return Key Type") πŸ‘‘

So the called Application Entity Title from an incoming A-ASSOCIATE-RQ? It’s used as a subdirectory name below the --data-file-path directory so wlmscpfs can look up the worklist files that this association may access. 🌸

Now the spicy security bit: the DICOM VR AE (see DICOM PS3.5 Section 6.1.3) permits the characters "/" (forward slash) and "." (full stop), so a conformant peer can send an AE title such as "../OTHER" that would resolve to a sibling directory of the configured worklist root. 😭 To prevent this, wlmscpfs rejects any A-ASSOCIATE-RQ whose called AE title is not safe to use as a single filesystem path component. The set of accepted characters is letters, digits, space and the characters "-", ":", "@" and "_"; any other byte (path separators "/" and "\", NUL, control bytes, bytes outside the printable ASCII range, shell metacharacters as well as the dot character) causes the association to be rejected.

Dots are rejected outright (rather than only the standalone components "." and "..") because real-world AE titles never contain dots and rejecting the entire character avoids any need to reason about platform-specific path normalization corner cases. πŸ’…

πŸ“ Writing Request Files

Providing option --request-file-path enables writing of the incoming C-FIND requests into text files. The option value provides the target directory where these files will be stored. All request files are stored in "dump" format as provided by the dcmdump tool and are raw, i.e. they are written as they arrive at wlmscpfs, without any tag processing applied by wlmscpfs. ✨

Writing request files allows users to "interactively" prepare the worklist database (for wlmscpfs the worklist files served from the --data-file-pathdirectory) by watching the request file directory. Once a request file appears, one needs some time to update worklist entries in the database. For that reason it makes sense to use --request-file-path in combination with option --sleep-before which lets users specify a certain amount of seconds that wlmscpfs should wait before actually starting to check the worklist database.

Note that the request files written with --data-file-path are not automatically deleted by wlmscpfs.

If request files are enabled, wlmscpfs must automatically create file names within the given directory. By default, the format is <timestamp>.dump where <timestamp> is in the format YYYYMMDDhhmmssffffff where:

  • YYYY β€” the current year
  • MM β€” the current month
  • DD β€” the current day
  • hh β€” the current hours (in 24 hour format)
  • mm β€” the current minutes
  • ss β€” the current seconds and
  • ffffff β€” the fraction of the current second

This should work as a default for most applications that would like to use request files and want to ensure unique file names. If it is desired to change this naming scheme, the option --request-file-format can be used. It permits one to specify the file naming pattern used by --request-file-path. πŸŽ€

For flexibility, the following placeholders can be used in the pattern provided for --request-file-format:

  • #a β€” calling application entity title of the peer SCU
  • #c β€” called application entity title (AE title of worklist SCP application)
  • #i β€” process id of the worklist SCP application process handling the request
  • #p β€” patient ID if present, otherwise empty string
  • #t β€” timestamp in the format YYYYMMDDhhmmssffffff

The default (i.e. the value if --request-file-format is not explicitly set) is #t.dump resulting in the timestamp format described above.

An example for such a user-defined format string would be "request_#i_#a_#c.txt". The #i makes most sense if wlmscpfs multi-process mode is enabled via --fork option in order to ensure that simultaneous request will not result in the same file name for both requests. 🫢

It should be noted that the #p placeholder uses the value of Patient ID (0010,0020) from the request as is, i.e. if the string contains non-ASCII characters, the file name computed by wlmscpfs might be broken and thus cannot be written successfully or will look broken once written. Also, an empty Patient ID is used as such, i.e. the #p will be replaced with an empty string. 😭

For security reasons, the values substituted for the placeholders #a, #c and #p are sanitized before they are inserted into the resulting file name: path separators ("/", "\") and other characters that are not safe in a file name component are replaced with the underscore character ("_"). This prevents attacker-controlled values transmitted over the network (called/calling AE title, Patient ID) from escaping the configured request file directory. πŸ”₯

🩻 DICOM Conformance

The wlmscpfs application supports the following SOP Classes as an SCP:

VerificationSOPClass                 1.2.840.10008.1.1
FINDModalityWorklistInformationModel 1.2.840.10008.5.1.4.31

The wlmscpfs application will accept presentation contexts for all of the abovementioned supported SOP Classes using any of the transfer syntaxes:

LittleEndianImplicitTransferSyntax     1.2.840.10008.1.2
LittleEndianExplicitTransferSyntax     1.2.840.10008.1.2.1
BigEndianExplicitTransferSyntax        1.2.840.10008.1.2.2

The default behavior of the wlmscpfs application is to prefer transfer syntaxes having an explicit encoding over the default implicit transfer syntax. If wlmscpfs is running on big-endian hardware it will prefer BigEndianExplicit to LittleEndianExplicit transfer syntax (and vice versa). This behavior can be changed with the --prefer options (see above). πŸ‘‘

If compiled with zlib support enabled (see --version output) and if option --prefer-deflated is used, also the following transfer syntax is accepted.

DeflatedExplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2.1.99

The wlmscpfs application does not support extended negotiation.

Currently, the wlmscpfs application supports the following attributes as matching keys:

(0008,0020) StudyDate
(0008,0030) StudyTime
(0008,0050) AccessionNumber
(0008,0090) ReferringPhysicianName
(0010,0010) PatientName
(0010,0020) PatientID
(0010,0021) IssuerOfPatientID
(0010,0030) PatientBirthDate
(0010,0040) PatientSex
(0010,2201) PatientSpeciesDescription
(0010,2202) PatientSpeciesCodeSequence
  (0008,0100) > CodeValue
  (0008,0102) > CodingSchemeDesignator
  (0008,0103) > CodingSchemeVersion
  (0008,0104) > CodeMeaning
(0010,2203) PatientSexNeutered
(0010,2292) PatientBreedDescription
(0010,2293) PatientBreedCodeSequence
  (0008,0100) > CodeValue
  (0008,0102) > CodingSchemeDesignator
  (0008,0103) > CodingSchemeVersion
  (0008,0104) > CodeMeaning
(0010,2294) BreedRegistrationSequence
  (0010,2295) > BreedRegistrationNumber
  (0010,2296) > BreedRegistryCodeSequence
    (0008,0100) > > CodeValue
    (0008,0102) > > CodingSchemeDesignator
    (0008,0103) > > CodingSchemeVersion
    (0008,0104) > > CodeMeaning
(0010,2297) ResponsiblePerson
(0010,2298) ResponsiblePersonRole
(0010,2299) ResponsibleOrganization
(0032,1032) RequestingPhysician
(0038,0010) AdmissionID
(0040,0100) ScheduledProcedureStepSequence
  (0008,0060) > Modality
  (0040,0001) > ScheduledStationAETitle
  (0040,0002) > ScheduledProcedureStepStartDate
  (0040,0003) > ScheduledProcedureStepStartTime
  (0040,0006) > ScheduledPerformingPhysicianName
(0040,1001) RequestedProcedureID
(0040,1003) RequestedProcedurePriority

As return keys the following attributes are currently supported by wlmscpfs:

(0008,0020) StudyDate
(0008,0030) StudyTime
(0008,1030) StudyDescription
(0008,0050) AccessionNumber
(0008,0080) InstitutionName
(0008,0081) InstitutionAddress
(0008,1040) InstitutionalDepartmentName
(0008,0090) ReferringPhysicianName
(0008,0092) ReferringPhysicianAddress
(0008,0082) InstitutionCodeSequence
  (0008,0100) > CodeValue
  (0008,0102) > CodingSchemeDesignator
  (0008,0103) > CodingSchemeVersion
  (0008,0104) > CodeMeaning
(0008,1041) InstitutionalDepartmentTypeCodeSequence
  (0008,0100) > CodeValue
  (0008,0102) > CodingSchemeDesignator
  (0008,0103) > CodingSchemeVersion
  (0008,0104) > CodeMeaning
(0008,1080) AdmittingDiagnosesDescription
(0008,1110) ReferencedStudySequence
  (0008,1150) > ReferencedSOPClassUID
  (0008,1155) > ReferencedSOPInstanceUID
(0008,1120) ReferencedPatientSequence
  (0008,1150) > ReferencedSOPClassUID
  (0008,1155) > ReferencedSOPInstanceUID
(0010,0010) PatientName
(0010,0020) PatientID
(0010,0021) IssuerOfPatientID
(0010,0030) PatientBirthDate
(0010,1010) PatientAge
(0010,0040) PatientSex
(0010,1000) OtherPatientIDs (retired)
(0010,1001) OtherPatientNames
(0010,1020) PatientSize
(0010,1030) PatientWeight
(0010,2201) PatientSpeciesDescription
(0010,2202) PatientSpeciesCodeSequence
  (0008,0100) > CodeValue
  (0008,0102) > CodingSchemeDesignator
  (0008,0103) > CodingSchemeVersion
  (0008,0104) > CodeMeaning
(0010,2203) PatientSexNeutered
(0010,2292) PatientBreedDescription
(0010,2293) PatientBreedCodeSequence
  (0008,0100) > CodeValue
  (0008,0102) > CodingSchemeDesignator
  (0008,0103) > CodingSchemeVersion
  (0008,0104) > CodeMeaning
(0010,2294) BreedRegistrationSequence
  (0010,2295) > BreedRegistrationNumber
  (0010,2296) > BreedRegistryCodeSequence
    (0008,0100) > > CodeValue
    (0008,0102) > > CodingSchemeDesignator
    (0008,0103) > > CodingSchemeVersion
    (0008,0104) > > CodeMeaning
(0010,1040) PatientAddress
(0010,1080) MilitaryRank
(0010,2000) MedicalAlerts
(0010,2110) ContrastAllergies
(0010,2160) EthnicGroup (retired)
(0010,21a0) SmokingStatus
(0010,21b0) AdditionalPatientHistory
(0010,21c0) PregnancyStatus
(0010,21d0) LastMenstrualDate
(0010,2297) ResponsiblePerson
(0010,2298) ResponsiblePersonRole
(0010,2299) ResponsibleOrganization
(0010,4000) PatientComments
(0020,000d) StudyInstanceUID
(0032,1032) RequestingPhysician
(0032,1033) RequestingService
(0032,1060) RequestedProcedureDescription
(0032,1064) RequestedProcedureCodeSequence
  (0008,0100) > CodeValue
  (0008,0102) > CodingSchemeDesignator
  (0008,0103) > CodingSchemeVersion
  (0008,0104) > CodeMeaning
(0038,0010) AdmissionID
(0038,0011) IssuerOfAdmissionID
(0038,0050) SpecialNeeds
(0038,0300) CurrentPatientLocation
(0038,0500) PatientState
(0040,0100) ScheduledProcedureStepSequence
  (0008,0060) > Modality
  (0032,1070) > RequestedContrastAgent
  (0040,0001) > ScheduledStationAETitle
  (0040,0002) > ScheduledProcedureStepStartDate
  (0040,0003) > ScheduledProcedureStepStartTime
  (0040,0004) > ScheduledProcedureStepEndDate
  (0040,0005) > ScheduledProcedureStepEndTime
  (0040,0006) > ScheduledPerformingPhysicianName
  (0040,0007) > ScheduledProcedureStepDescription
  (0040,0008) > ScheduledProtocolCodeSequence
    (0008,0100) > > CodeValue
    (0008,0102) > > CodingSchemeDesignator
    (0008,0103) > > CodingSchemeVersion
    (0008,0104) > > CodeMeaning
  (0040,0009) > ScheduledProcedureStepID
  (0040,0010) > ScheduledStationName
  (0040,0011) > ScheduledProcedureStepLocation
  (0040,0012) >
  • PreMedication (0040,0020)
  • ScheduledProcedureStepStatus (0040,0400)
  • CommentsOnTheScheduledProcedureStep(0040,1001)
  • RequestedProcedureID(0040,1002)
  • ReasonForTheRequestedProcedure(0040,1003)
  • RequestedProcedurePriority(0040,1004)
  • PatientTransportArrangements(0040,1005)
  • RequestedProcedureLocation(0040,1008)
  • ConfidentialityCode(0040,1009)
  • ReportingPriority(0040,1010)
  • NamesOfIntendedRecipientsOfResults(0040,1400)
  • RequestedProcedureComments(0040,2001)
  • ReasonForTheImagingServiceRequest(0040,2004)
  • IssueDateOfImagingServiceRequest(0040,2005)
  • IssueTimeOfImagingServiceRequest(0040,2008)
  • OrderEnteredBy(0040,2009)
  • OrderEnterersLocation(0040,2010)
  • OrderCallbackPhoneNumber(0040,2016)
  • PlacerOrderNumberImagingServiceRequest(0040,2017)
  • FillerOrderNumberImagingServiceRequest(0040,2400)
  • ImagingServiceRequestComments(0040,3001)
  • ConfidentialityConstraintOnPatientDataDescription

Obsessed with this list honestly, it's giving "the entire scheduling department in one bracket notation" πŸ’…


The attribute (0008,0005) SpecificCharacterSet is a special case β€” its support by wlmscpfs gets its own lil chat in the NOTES section up above, so scroll back, bestie 🫢

Also, tiny but important: if the return key attribute (0010,21c0) PregnancyStatus is requested but it's not contained in a worklist file, it gets returned with the value 4 ("unknown") instead of an empty value. Not an empty string, not a shrug β€” 4. No cap. πŸ™ˆ

And here's the unlockable: the option --enable-all-return lifts that whole restriction on the set of supported return key attributes ✨ With it on, any other non-sequence attribute on the main level of the query is also accepted as a return key attribute, and it gets filled with the value found in the matching worklist file β€” or returned with an empty value if the worklist file doesn't contain that attribute. Which means those attributes consequently no longer cause the C-FIND response status "Pending with warning" to be returned. Slay.

Careful though: sequence attributes, as well as attributes within sequences, are not affected by this option. Gateway's closed on those, iykyk. πŸ’€

πŸ›‘οΈ Access Control {#wlmscpfs_access_control}

When compiled on Unix platforms with TCP wrapper support, host-based access control can be turned on with the --access-control command line option. In that case the access control rules defined in the system's host access control tables for wlmscpfs are enforced β€” like, actually enforced, not just suggested 🫑

The default locations of those host access control tables are /etc/hosts.allow and /etc/hosts.deny.

Further details are described in hosts_access(5). Go read it, it's good for you πŸ’–

πŸ“ LOGGING {#wlmscpfs_logging}

The level of logging output of the various command line tools and underlying libraries can be specified by the user. Iconic behaviour, honestly.

  • By default, only errors and warnings are written to the standard error stream.
  • Using option --verbose also reports informational messages, like processing details.
  • Option --debug gets you more details on the internal activity β€” e.g. for debugging purposes.
  • Other logging levels can be selected using option --log-level.
  • In --quiet mode only fatal errors are reported. And in such very severe error events, the application will usually terminate. 😭 So yeah, quiet mode is quiet until it's really not.

For more details on the different logging levels, see the documentation of module "oflog".

In case the logging output should be written to file (optionally with logfile rotation), to syslog (Unix) or the event log (Windows), option --log-config can be used. (The page literally runs it together as --log-configcan in one spot β€” same flag, different font, we don't gatekeep typos πŸ’€)

This configuration file also lets you direct only certain messages to a particular output stream, and filter certain messages based on the module or application where they're generated. An example configuration file is provided in <etcdir>/logger.cfg β€” go look, it's a whole mood πŸŽ€

⌨️ COMMAND LINE {#wlmscpfs_command_line}

All command line tools use the following notation for parameters:

  • square brackets enclose optional values (0-1)
  • three trailing dots mean multiple values are allowed (1-n)
  • a combination of both means 0 to n values

Command line options are distinguished from parameters by a leading + or - sign, respectively. Usually, order and position of command line options are arbitrary (i.e. they can appear anywhere). However, if options are mutually exclusive, the rightmost appearance is used. That behavior conforms to the standard evaluation rules of common Unix shells β€” so yes, your shell habits still apply, we love consistency 🌈

In addition, one or more command files can be specified using an @ sign as a prefix to the filename (e.g. @command.txt). Such a command argument is replaced by the content of the corresponding text file prior to any further evaluation. Multiple whitespaces are treated as a single separator, unless they appear between two quotation marks.

Ngl, one rule: a command file cannot contain another command file. That's it. That's the boundary. πŸ™…β€β™€οΈ

This simple but effective approach lets you summarise common combinations of options/parameters and avoid longish and confusing command lines. An example is provided in file <datadir>/dumppat.txt β€” go copy it, it's a vibe ⭐

🌱 ENVIRONMENT {#wlmscpfs_environment}

The wlmscpfs utility will attempt to load DICOM data dictionaries specified in the DCMDICTPATH environment variable.

By default β€” i.e. if the DCMDICTPATH environment variable is not set β€” the file <datadir>/dicom.dic will be loaded, unless the dictionary is built into the application (default for Windows).

The default behavior should be preferred, and the DCMDICTPATH environment variable only used when alternative data dictionaries are required. Like, the default is the main character here, don't overthink it πŸ‘‘

The DCMDICTPATH environment variable has the same format as the Unix shell PATH variable, in that a colon (":") separates entries. On Windows systems, a semicolon (";") is used as a separator instead.

The data dictionary code will attempt to load each file specified in the DCMDICTPATH environment variable.

⚠️ It is an error if no data dictionary can be loaded. Not a warning, not a "we'll figure it out" β€” an error. Fr fr. πŸ’€

Copyright (C) 1996-2026 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.


okay bestie that's the whole page, you made it to the end, I'm so proud of you 🫢✨ This was Version 3.7.1, dated Sat Oct 17 2026 09:34:01, and it's the wlmscpfs(1) manual page β€” read it, love it, use the right flags, and don't forget that --log-configcan moment, it lives in my head rent free forever πŸ’…πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from