]> Kevux Git Server - kevux-tools/commitdiff
Progress: Begin adding GPGME support.
authorKevin Day <Kevin@kevux.org>
Tue, 13 Jan 2026 04:41:06 +0000 (22:41 -0600)
committerKevin Day <Kevin@kevux.org>
Tue, 13 Jan 2026 04:41:06 +0000 (22:41 -0600)
The GPGME is not really that good.
It calls the user space GNUPG program `gpg`.

This is clunky and nasty.

The project also handles memory poorly.
Thanks to utilizing it, the `tacocat` now exists with reachable memory.

```
==17190== HEAP SUMMARY:
==17190==     in use at exit: 1,189 bytes in 39 blocks
==17190==   total heap usage: 124 allocs, 85 frees, 42,076 bytes allocated
```

I should look into other projects as well once I get GPGME fully setup and working.
Projects like libgit2 or even trying to directly use libgcrypt.

14 files changed:
data/build/tacocat/defines
data/build/tacocat/settings
data/build/tacocat/settings.tacocat
sources/c/program/kevux/tools/tacocat/main/common/define.h
sources/c/program/kevux/tools/tacocat/main/common/type.c
sources/c/program/kevux/tools/tacocat/main/common/type.h
sources/c/program/kevux/tools/tacocat/main/gpgme.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/gpgme.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/print/error.c
sources/c/program/kevux/tools/tacocat/main/print/gpgme.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/print/gpgme.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/process.c
sources/c/program/kevux/tools/tacocat/main/tacocat.h
sources/c/program/kevux/tools/tacocat/tacocat/main.c

index 6950822c78c8eb8c9d974343f41b8e3b969788ab..27fc8c1ccfdba66b07eff1ab2fb72e70b3852324 100644 (file)
@@ -1,4 +1,7 @@
 # fss-0000
 
 _di_thread_support_ Disable thread support, handling signals without using a separate thread.
+
+_en_gpgme_support_ Enable use of GPGME for providing encryption during message transfer.
+
 _kt_resolve_default_kevux_ Default to Kevux DNS resolution methods rather than classic DNS resolution methods.
index da1cb83d872f821e8574e9207486be0e1dabe86d..ded54bcba1dba8e3a866ff8cf5e5f3b2691dca01 100644 (file)
@@ -10,6 +10,7 @@
 #   - fanalyzer:         Compile using GCC's -fanalyzer compile time option.
 #   - flex_arrays:       Use GCC strict flex arrays (supported by GCC version 13 or greater).
 #   - gcc:               Use GCC specific settings.
+#   - gpgme:             Enable the use of GPGME.
 #   - individual:        Compile using per project (individual) libraries, does not handle thread or threadless cases.
 #   - individual_thread: This is required when compiling in individual mode with "thread" mode.
 #   - level:             Compile using per level libraries.
@@ -29,8 +30,8 @@ version_micro 5
 version_file micro
 version_target minor
 
-modes android clang coverage debug fanalyzer flex_arrays gcc individual individual_thread level monolithic pinephone test thread threadless
-modes_default debug gcc monolithic thread
+modes android clang coverage debug fanalyzer flex_arrays gcc gpgme individual individual_thread level monolithic pinephone test thread threadless
+modes_default debug gcc gpgme monolithic thread
 
 build_compiler gcc
 build_compiler-clang clang
@@ -45,6 +46,7 @@ build_libraries_shared-individual -lf_abstruse -lf_color -lf_compare -lf_console
 build_libraries_shared-individual_thread -lf_thread
 build_libraries_shared-level -lfll_2 -lfll_1 -lfll_0
 build_libraries_shared-monolithic -lfll
+build_libraries_shared-gpgme -lgpgme -lassuan -lgpg-error
 
 build_libraries_static -l:libc.a
 build_libraries_static-individual -l:libfll_error.a -l:libfll_fss.a -l:libfll_print.a -l:libfll_program.a
@@ -53,6 +55,7 @@ build_libraries_static-individual -l:libf_abstruse.a -l:libf_color.a -l:libf_com
 build_libraries_static-individual_thread -l:libf_thread.a
 build_libraries_static-level -l:libfll_2.a -l:libfll_1.a -l:libfll_0.a
 build_libraries_static-monolithic -l:libfll.a
+build_libraries_static-gpgme -l:libgpgme.a -l:libassuan.a -l:libgpg-error.a
 
 build_sources_headers common.h common/define.h common/enumeration.h common/string.h common/type.h
 build_sources_headers print/error.h print/message.h print/verbose.h print/warning.h
@@ -60,12 +63,16 @@ build_sources_headers packet.h process.h receive.h send.h signal.h tacocat.h thr
 build_sources_headers receive/step/check.h receive/step/control.h receive/step/done.h receive/step/extract.h receive/step/find.h receive/step/next.h receive/step/packet.h receive/step/write.h
 build_sources_headers send/step/build.h send/step/check.h send/step/done.h send/step/encode.h send/step/file.h send/step/header.h send/step/packet.h send/step/size.h send/step/wait.h
 
+build_sources_headers-gpgme gpgme.h print/gpgme.h
+
 build_sources_library common.c common/define.c common/enumeration.c common/string.c common/type.c
 build_sources_library print/error.c print/message.c print/verbose.c print/warning.c
 build_sources_library packet.c process.c receive.c send.c signal.c tacocat.c thread.c
 build_sources_library receive/step/check.c receive/step/control.c receive/step/done.c receive/step/extract.c receive/step/find.c receive/step/next.c receive/step/packet.c receive/step/write.c
 build_sources_library send/step/build.c send/step/check.c send/step/done.c send/step/encode.c send/step/file.c send/step/header.c send/step/packet.c send/step/size.c send/step/wait.c
 
+build_sources_library-gpgme gpgme.c print/gpgme.c
+
 build_sources_documentation man
 
 build_static no
@@ -91,6 +98,7 @@ environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY L
 defines -D_libcap_legacy_only_
 defines-android -D_di_f_thread_attribute_affinity_get_ -D_di_f_thread_attribute_affinity_set_ -D_di_f_thread_attribute_concurrency_get_ -D_di_f_thread_attribute_concurrency_set_ -D_di_f_thread_attribute_default_get_ -D_di_f_thread_attribute_default_set_ -D_di_f_thread_cancel_test_ -D_di_f_thread_join_try_ -D_di_f_thread_join_timed_ -D_pthread_mutex_prioceiling_unsupported_ -D_di_f_thread_semaphore_file_close_ -D_di_f_thread_semaphore_file_open_ -D_di_f_thread_semaphore_file_delete_ -D_di_f_thread_cancel_type_set_  -D_di_f_thread_mutex_consistent_ -D_di_f_thread_mutex_attribute_robust_get_ -D_di_f_thread_mutex_attribute_robust_set_ -D_pthread_kill_as_pthread_cancel_
 defines-clang -D_clang_not_a_compile_time_constant_workaround_
+defines-gpgme -D_en_gpgme_support_
 defines-pinephone -D_di_f_thread_mutex_priority_ceiling_get_ -D_di_f_thread_mutex_priority_ceiling_set_ -D_di_f_thread_mutex_attribute_priority_ceiling_get_ -D_di_f_thread_mutex_attribute_priority_ceiling_set_
 defines-threadless -D_di_thread_support_
 defines-thread -D_pthread_attr_unsupported_ -D_pthread_sigqueue_unsupported_
index c5f8c5daf73607b469b9e4336c6b59c9007e9174..702f9d617ad7410ac95a1ec9e780b6abf0c775e1 100644 (file)
@@ -10,6 +10,7 @@
 #   - fanalyzer:         Compile using GCC's -fanalyzer compile time option.
 #   - flex_arrays:       Use GCC strict flex arrays (supported by GCC version 13 or greater).
 #   - gcc:               Use GCC specific settings.
+#   - gpgme:             Enable the use of GPGME.
 #   - individual:        Compile using per project (individual) libraries, does not handle thread or threadless cases.
 #   - individual_thread: This is required when compiling in individual mode with "thread" mode.
 #   - level:             Compile using per level libraries.
@@ -29,8 +30,8 @@ version_micro 5
 version_file micro
 version_target minor
 
-modes android clang coverage debug fanalyzer flex_arrays gcc individual individual_thread level monolithic pinephone test thread threadless
-modes_default debug gcc monolithic thread
+modes android clang coverage debug fanalyzer flex_arrays gcc gpgme individual individual_thread level monolithic pinephone test thread threadless
+modes_default debug gcc gpgme monolithic thread
 
 build_compiler gcc
 build_compiler-clang clang
@@ -45,6 +46,7 @@ build_libraries_shared-individual -lf_abstruse -lf_color -lf_compare -lf_console
 build_libraries_shared-individual_thread -lf_thread
 build_libraries_shared-level -lfll_2 -lfll_1 -lfll_0
 build_libraries_shared-monolithic -lfll
+build_libraries_shared-gpgme -lgpgme -lassuan -lgpg-error
 
 build_libraries_static -l:libc.a -l:libtacocat.a
 build_libraries_static-individual -l:libfll_error.a -l:libfll_fss.a -l:libfll_print.a -l:libfll_program.a
@@ -53,6 +55,7 @@ build_libraries_static-individual -l:libf_abstruse.a -l:libf_color.a -l:libf_com
 build_libraries_static-individual_thread -l:libf_thread.a
 build_libraries_static-level -l:libfll_2.a -l:libfll_1.a -l:libfll_0.a
 build_libraries_static-monolithic -l:libfll.a
+build_libraries_static-gpgme -l:libgpgme.a -l:libassuan.a -l:libgpg-error.a
 
 build_sources_headers tacocat.h string.h
 
@@ -86,6 +89,7 @@ defines -D_libcap_legacy_only_
 defines-android -D_di_f_thread_attribute_affinity_get_ -D_di_f_thread_attribute_affinity_set_ -D_di_f_thread_attribute_concurrency_get_ -D_di_f_thread_attribute_concurrency_set_ -D_di_f_thread_attribute_default_get_ -D_di_f_thread_attribute_default_set_ -D_di_f_thread_cancel_test_ -D_di_f_thread_join_try_ -D_di_f_thread_join_timed_ -D_pthread_mutex_prioceiling_unsupported_ -D_di_f_thread_semaphore_file_close_ -D_di_f_thread_semaphore_file_open_ -D_di_f_thread_semaphore_file_delete_ -D_di_f_thread_cancel_type_set_  -D_di_f_thread_mutex_consistent_ -D_di_f_thread_mutex_attribute_robust_get_ -D_di_f_thread_mutex_attribute_robust_set_ -D_pthread_kill_as_pthread_cancel_
 defines-clang -D_clang_not_a_compile_time_constant_workaround_
 defines-debug -D_en_f_status_debug_
+defines-gpgme -D_en_gpgme_support_
 defines-pinephone -D_di_f_thread_mutex_priority_ceiling_get_ -D_di_f_thread_mutex_priority_ceiling_set_ -D_di_f_thread_mutex_attribute_priority_ceiling_get_ -D_di_f_thread_mutex_attribute_priority_ceiling_set_
 defines-threadless -D_di_thread_support_
 defines-thread -D_pthread_attr_unsupported_ -D_pthread_sigqueue_unsupported_
index 13a4e70044e1fbac283f3321dd61f300dfcf3fd9..98bc7eef98fc67a114934c5411e2af73642a8fea 100644 (file)
@@ -174,6 +174,7 @@ extern "C" {
  * kt_tacocat_main_flag_*_d:
  *   - none:                   No flags set.
  *   - copyright:              Print copyright.
+ *   - encrypt:                Enable encryption (such as GPGME).
  *   - headers:                Print headers on send or receive.
  *   - help:                   Print help.
  *   - max_buffer:             When set, a maximum buffer on receive is enforced.
@@ -198,15 +199,16 @@ extern "C" {
 #ifndef _di_kt_tacocat_main_flag_d_
   #define kt_tacocat_main_flag_none_d                   0x0
   #define kt_tacocat_main_flag_copyright_d              0x1
-  #define kt_tacocat_main_flag_headers_d                0x2
-  #define kt_tacocat_main_flag_help_d                   0x4
-  #define kt_tacocat_main_flag_max_buffer_d             0x8
-  #define kt_tacocat_main_flag_receive_d                0x10
-  #define kt_tacocat_main_flag_resolve_classic_d        0x20
-  #define kt_tacocat_main_flag_resolve_kevux_d          0x40
-  #define kt_tacocat_main_flag_send_d                   0x80
-  #define kt_tacocat_main_flag_version_d                0x100
-  #define kt_tacocat_main_flag_version_copyright_help_d 0x105
+  #define kt_tacocat_main_flag_encrypt_d                0x2
+  #define kt_tacocat_main_flag_headers_d                0x4
+  #define kt_tacocat_main_flag_help_d                   0x8
+  #define kt_tacocat_main_flag_max_buffer_d             0x10
+  #define kt_tacocat_main_flag_receive_d                0x20
+  #define kt_tacocat_main_flag_resolve_classic_d        0x40
+  #define kt_tacocat_main_flag_resolve_kevux_d          0x80
+  #define kt_tacocat_main_flag_send_d                   0x100
+  #define kt_tacocat_main_flag_version_d                0x200
+  #define kt_tacocat_main_flag_version_copyright_help_d 0x209
 #endif // _di_kt_tacocat_main_flag_d_
 
 /**
index 561d08385108d0f418690773da570fd6e8fda3ce..b77e389d4a71055ffd2700950449edb6a3e63dc6 100644 (file)
@@ -37,6 +37,19 @@ extern "C" {
   }
 #endif // _di_kt_tacocat_setting_delete_
 
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_gpgme_delete_)
+  void kt_tacocat_gpgme_delete(kt_tacocat_gpgme_t * const gpgme) {
+
+    if (!gpgme) return;
+
+    gpgme_release(gpgme->control);
+
+    // @todo
+
+    gpgme->version = f_string_empty_s.string;
+  }
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_gpgme_delete_)
+
 #ifndef _di_kt_tacocat_socket_sets_delete_callback_
   f_status_t kt_tacocat_socket_sets_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
 
index e7e1ff6cdc68012388ce5f1d537ef3f7ddfb55bb..5f9c1447b85069ea2db32f3bb67cd23351cc0f50 100644 (file)
@@ -26,55 +26,56 @@ extern "C" {
 /**
  * A set of all socket related properties.
  *
- * size_block: The size in bytes to used to represent a block when sending or receiving packets.
- * size_done:  The size in bytes that are done being processed (generally used by send/write).
- * size_total: The size in bytes tht represent the entire size to be processed (size_done should eventually equal this).
- *
- * flag:  A set of flags.
- * step:  The current step the socket set is operating under (this is either a send or receive step define depending on whether or not flag has the send bit set).
- * retry: The current number of retries performed.
- * part:  The current active part number.
- * port:  The current port number for the socket.
- *
- * file:   The file structure.
- * socket: Socket structure.
- * status: The status of the socket operations.
- *
- * range:                       A generic range, often used for FSS processing.
- * objects:                     An array of FSS Objects.
- * objects_header:              An array of FSS Objects, for the Header section.
- * objects_signature:           An array of FSS Objects, for the Signature section.
- * contents:                    An array of FSS Contents.
- * contents_header:             An array of FSS Contents, for the Header section.
- * contents_signature:          An array of FSS Contents, for the Signature section.
- * objects_delimits:            An array of FSS Object delimits.
- * objects_delimits_header:     An array of FSS Object delimits, for the Header section.
- * objects_delimits_signature:  An array of FSS Object delimits, for the Signature section.
- * contents_delimits:           An array of FSS Content delimits.
- * contents_delimits_header:    An array of FSS Content delimits, for the Header section.
- * contents_delimits_signature: An array of FSS Content delimits, for the Signature section.
- * parts:                       An array of numbers where each index represents a part number.
- * objects_quoted_header:       An array of FSS Objects quoted flags, for the Header section.
- * objects_quoted_signature:    An array of FSS Objects quoted flags, for the Header section.
- * contents_quoted_header:      An array of FSS Content quoted flags, for the Header section.
- * contents_quoted_signature:   An array of FSS Content quoted flags, for the Header section.
- * comments:                    An array of FSS comments.
- * state:                       Basic state information, usually passed to the FSS functions.
- *
- * as:          A custom name to use for the file rather than the actual file name.
- * buffer:      A buffer for sending or receiving data between clients.
- * cache:       A cache used for various purposes, but primarily for the building of the send packet.
- * client:      A single client address for some network connection.
- * header:      A buffer used for the header part and possibly the reset of a packet, except for the actual payload.
- * id:          The identifier.
- * name:        A file name for reading from or writing to.
- * network:     A network name for the socket.
- * time:        A representation of time added for informative purposes to the packet (in a human friendly format).
- * packet:      The simple packet range representing the parts of the packet for use during processing.
- * write_state: State data for the packet write operation.
- *
- * abstruses: The abstruse header map array, used for building the headers when sending a response.
- * headers:   The map of the headers after being processed for use when buulding the headers when sending a response.
+ * Properties:
+ *   - size_block: The size in bytes to used to represent a block when sending or receiving packets.
+ *   - size_done:  The size in bytes that are done being processed (generally used by send/write).
+ *   - size_total: The size in bytes tht represent the entire size to be processed (size_done should eventually equal this).
+ *
+ *   - flag:  A set of flags.
+ *   - step:  The current step the socket set is operating under (this is either a send or receive step define depending on whether or not flag has the send bit set).
+ *   - retry: The current number of retries performed.
+ *   - part:  The current active part number.
+ *   - port:  The current port number for the socket.
+ *
+ *   - file:   The file structure.
+ *   - socket: Socket structure.
+ *   - status: The status of the socket operations.
+ *
+ *   - range:                       A generic range, often used for FSS processing.
+ *   - objects:                     An array of FSS Objects.
+ *   - objects_header:              An array of FSS Objects, for the Header section.
+ *   - objects_signature:           An array of FSS Objects, for the Signature section.
+ *   - contents:                    An array of FSS Contents.
+ *   - contents_header:             An array of FSS Contents, for the Header section.
+ *   - contents_signature:          An array of FSS Contents, for the Signature section.
+ *   - objects_delimits:            An array of FSS Object delimits.
+ *   - objects_delimits_header:     An array of FSS Object delimits, for the Header section.
+ *   - objects_delimits_signature:  An array of FSS Object delimits, for the Signature section.
+ *   - contents_delimits:           An array of FSS Content delimits.
+ *   - contents_delimits_header:    An array of FSS Content delimits, for the Header section.
+ *   - contents_delimits_signature: An array of FSS Content delimits, for the Signature section.
+ *   - parts:                       An array of numbers where each index represents a part number.
+ *   - objects_quoted_header:       An array of FSS Objects quoted flags, for the Header section.
+ *   - objects_quoted_signature:    An array of FSS Objects quoted flags, for the Header section.
+ *   - contents_quoted_header:      An array of FSS Content quoted flags, for the Header section.
+ *   - contents_quoted_signature:   An array of FSS Content quoted flags, for the Header section.
+ *   - comments:                    An array of FSS comments.
+ *   - state:                       Basic state information, usually passed to the FSS functions.
+ *
+ *   - as:          A custom name to use for the file rather than the actual file name.
+ *   - buffer:      A buffer for sending or receiving data between clients.
+ *   - cache:       A cache used for various purposes, but primarily for the building of the send packet.
+ *   - client:      A single client address for some network connection.
+ *   - header:      A buffer used for the header part and possibly the reset of a packet, except for the actual payload.
+ *   - id:          The identifier.
+ *   - name:        A file name for reading from or writing to.
+ *   - network:     A network name for the socket.
+ *   - time:        A representation of time added for informative purposes to the packet (in a human friendly format).
+ *   - packet:      The simple packet range representing the parts of the packet for use during processing.
+ *   - write_state: State data for the packet write operation.
+ *
+ *   - abstruses: The abstruse header map array, used for building the headers when sending a response.
+ *   - headers:   The map of the headers after being processed for use when buulding the headers when sending a response.
  */
 #ifndef _di_kt_tacocat_socket_set_t_
   typedef struct {
@@ -274,9 +275,10 @@ extern "C" {
 /**
  * An array of socket sets.
  *
- * array: The array of socket sets.
- * used:  Total number of allocated spaces used.
- * size:  Total amount of allocated space.
+ * Properties:
+ *   - array: The array of socket sets.
+ *   - used:  Total number of allocated spaces used.
+ *   - size:  Total amount of allocated space.
  */
 #ifndef _di_kt_tacocat_socket_sets_t_
   typedef struct {
@@ -323,23 +325,24 @@ extern "C" {
  * This is passed to the program-specific main entry point to designate program settings.
  * These program settings are often processed from the program arguments (often called the command line arguments).
  *
- * flag:           Flags passed to the main function.
- * interval:       The poll interval to use.
- * interval_fast:  A poll interval to use when needing the interval to be short.
- * max_buffer:     The maximum buffer size to use on receive.
- * active_receive: The number of active receive processes, after initial connection is established.
- * active_send:    The number of active send processes, after initial connection is established.
+ * Properties:
+ *   - flag:           Flags passed to the main function.
+ *   - interval:       The poll interval to use.
+ *   - interval_fast:  A poll interval to use when needing the interval to be short.
+ *   - max_buffer:     The maximum buffer size to use on receive.
+ *   - active_receive: The number of active receive processes, after initial connection is established.
+ *   - active_send:    The number of active send processes, after initial connection is established.
  *
- * status_receive: A status used exclusively by the receive thread.
- * status_send:    A status used exclusively by the send thread.
+ *   - status_receive: A status used exclusively by the receive thread.
+ *   - status_send:    A status used exclusively by the send thread.
  *
- * state: The state data used when processing data.
+ *   - state: The state data used when processing data.
  *
- * receive_polls: An array of sockets to poll for receiving data, specifically for passing to f_file_poll().
- * send_polls:    An array of sockets to poll for sending data, specifically for passing to f_file_poll().
+ *   - receive_polls: An array of sockets to poll for receiving data, specifically for passing to f_file_poll().
+ *   - send_polls:    An array of sockets to poll for sending data, specifically for passing to f_file_poll().
  *
- * receive: The socket set for receiving data receive clients.
- * send:    The socket set for sending data send clients.
+ *   - receive: The socket set for receiving data receive clients.
+ *   - send:    The socket set for sending data send clients.
  */
 #ifndef _di_kt_tacocat_setting_t_
   typedef struct {
@@ -382,9 +385,10 @@ extern "C" {
 /**
  * The TacocaT caches.
  *
- * peek: A static cache intended to be used for performing a peek on a given network stream.
+ * Properties:
+ *   - peek: A static cache intended to be used for performing a peek on a given network stream.
  *
- * buffer: A string buffer used for caching purposes.
+ *   - buffer: A string buffer used for caching purposes.
  */
 #ifndef _di_kt_tacocat_cache_t_
   typedef struct {
@@ -402,7 +406,8 @@ extern "C" {
 /**
  * The TacocaT callbacks.
  *
- * setting_load_send_receive: Process loading the settings regarding send and receive, handling DNS resolution and file opening as needed.
+ * Properties:
+ *   - setting_load_send_receive: Process loading the settings regarding send and receive, handling DNS resolution and file opening as needed.
  */
 #ifndef _di_kt_tacocat_call_t_
   typedef struct {
@@ -416,6 +421,10 @@ extern "C" {
 
 /**
  * The main thread settings.
+ *
+ * Properties:
+ *   - id_receive: The receive identifier.
+ *   - id_send:    The send identifier.
  */
 #ifndef _di_kt_tacocat_thread_t_
   typedef struct {
@@ -430,14 +439,47 @@ extern "C" {
 #endif // _di_kt_tacocat_thread_t_
 
 /**
+ * The GPGME data.
+ *
+ * Properties:
+ *   - control: The GPGME control data.
+ *   - data:    The GPGME regular data.
+ *   - engine:  The GPGME engine inforrmation data.
+ *   - error:   The GPGME error data.
+ *
+ *   - version: The GPGME reported version.
+ */
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_gpgme_t_)
+  typedef struct {
+    gpgme_ctx_t control;
+    gpgme_data_t data;
+    gpgme_engine_info_t engine;
+    gpgme_error_t error;
+
+    f_string_constant_t version;
+  } kt_tacocat_gpgme_t;
+
+  #define kt_tacocat_gpgme_t_initialize { \
+    .control = 0, \
+    .data    = 0, \
+    .engine  = 0, \
+    .error   = 0, \
+    .version = f_string_empty_s.string, \
+  }
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_gpgme_t_)
+
+/**
  * The main program data as a single structure.
  *
- * program: The main program data.
+ * Properties:
+ *   - program: The main program data.
+ *
+ *   - cache:   The program cache.
+ *   - call:    The program call backs.
+ *   - setting: The settings data.
+ *   - thread:  The program thread data.
  *
- * cache:   The program cache.
- * call:    The program call backs.
- * setting: The settings data.
- * thread:  The program thread data.
+ *   - gpgme: The GPGME data, if supported.
  */
 #ifndef _di_kt_tacocat_main_t_
   struct kt_tacocat_main_t_ {
@@ -447,15 +489,30 @@ extern "C" {
     kt_tacocat_call_t call;
     kt_tacocat_setting_t setting;
     kt_tacocat_thread_t thread;
+
+    #ifdef _en_gpgme_support_
+      kt_tacocat_gpgme_t gpgme;
+    #endif // _en_gpgme_support_
   };
 
-  #define kt_tacocat_main_t_initialize { \
-    .program  = fll_program_data_t_initialize, \
-    .cache    = kt_tacocat_cache_t_initialize, \
-    .call     = kt_tacocat_call_t_initialize, \
-    .setting  = kt_tacocat_setting_t_initialize, \
-    .thread   = kt_tacocat_thread_t_initialize, \
-  }
+  #ifdef _en_gpgme_support_
+    #define kt_tacocat_main_t_initialize { \
+      .program  = fll_program_data_t_initialize, \
+      .cache    = kt_tacocat_cache_t_initialize, \
+      .call     = kt_tacocat_call_t_initialize, \
+      .setting  = kt_tacocat_setting_t_initialize, \
+      .thread   = kt_tacocat_thread_t_initialize, \
+      .gpgme    = kt_tacocat_gpgme_t_initialize, \
+    }
+  #else
+    #define kt_tacocat_main_t_initialize { \
+      .program  = fll_program_data_t_initialize, \
+      .cache    = kt_tacocat_cache_t_initialize, \
+      .call     = kt_tacocat_call_t_initialize, \
+      .setting  = kt_tacocat_setting_t_initialize, \
+      .thread   = kt_tacocat_thread_t_initialize, \
+    }
+  #endif // _en_gpgme_support_
 #endif // _di_kt_tacocat_main_t_
 
 /**
@@ -499,6 +556,18 @@ extern "C" {
 #endif // _di_kt_tacocat_setting_delete_
 
 /**
+ * Delete the gpgme data.
+ *
+ * @param gpgme
+ *   The gpgme data.
+ *
+ *   Must not be NULL.
+ */
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_gpgme_delete_)
+  extern void kt_tacocat_gpgme_delete(kt_tacocat_gpgme_t * const gpgme);
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_gpgme_delete_)
+
+/**
  * A call back intended to be passed to f_memory_arrays_resize() for an kt_tacocat_socket_sets_t structure.
  *
  * This is only called when shrinking the array and generally should perform deallocations.
diff --git a/sources/c/program/kevux/tools/tacocat/main/gpgme.c b/sources/c/program/kevux/tools/tacocat/main/gpgme.c
new file mode 100644 (file)
index 0000000..d84ada4
--- /dev/null
@@ -0,0 +1,42 @@
+#include "tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_gpgme_setup_)
+  void kt_tacocat_gpgme_setup(kt_tacocat_main_t * const main) {
+
+    if (!main) return;
+
+    kt_tacocat_gpgme_t * const gpgme = &main->gpgme;
+
+    gpgme->version = gpgme_check_version(0);
+
+    gpgme->error = gpgme_new(&gpgme->control);
+
+    if (gpgme->error) {
+      main->setting.state.status = F_status_set_error(F_failure);
+
+      kt_tacocat_print_gpgme_error(&main->program.error, F_status_debug_source_d);
+
+      return;
+    }
+
+    gpgme->error = gpgme_engine_check_version(GPGME_PROTOCOL_OPENPGP);
+
+    if (gpgme->error) {
+      main->setting.state.status = F_status_set_error(F_failure);
+
+      kt_tacocat_print_gpgme_error(&main->program.error, F_status_debug_source_d);
+
+      return;
+    }
+
+    main->setting.state.status = F_okay;
+  }
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_gpgme_setup_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/gpgme.h b/sources/c/program/kevux/tools/tacocat/main/gpgme.h
new file mode 100644 (file)
index 0000000..0a42f3b
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ */
+#ifndef _kt_tacocat_main_gpgme_h
+#define _kt_tacocat_main_gpgme_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform GPGME setup.
+ *
+ * For available GPGME protocols, see: https://www.gnupg.org/documentation/manuals/gpgme/Protocols-and-Engines.html .
+ *
+ * For GPGME signal handling, see: https://www.gnupg.org/documentation/manuals/gpgme/Signal-Handling.html .
+ * > If you do install a signal handler for SIGPIPE, you must be prepared to handle any SIGPIPE events that occur due to GPGME writing to a defunct pipe.
+ * > Furthermore, if your application is multi-threaded, and you install a signal action for SIGPIPE, you must make sure you do this either before gpgme_check_version is called or afterwards.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ *     F_failure (with error bit) on gpgme_check_version() error.
+ *
+ * @see gpgme_check_version()
+ */
+#if defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_gpgme_setup_)
+  extern void kt_tacocat_gpgme_setup(kt_tacocat_main_t * const main);
+#endif // defined(_en_gpgme_support_) && !defined(_di_kt_tacocat_gpgme_setup_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_main_gpgme_h
index 8b6ddc635feccc6627bfe92d2ae4ed5cec071208..4a1c547081880fbc6ecff2a61252a3a908cbd040 100644 (file)
@@ -50,9 +50,9 @@ extern "C" {
 
     fl_print_format("%[%QNetwork error on%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable);
-    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable);
-    fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, name, print->set->notable);
     fl_print_format(f_string_format_sentence_end_quote_s.string, print->to, print->set->error, print->set->error, f_string_eol_s);
 
@@ -74,9 +74,9 @@ extern "C" {
 
     fl_print_format("%[%QFile '%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable);
-    fl_print_format(" %[' for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[' for '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable);
-    fl_print_format(" %[ for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[ for '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable);
     fl_print_format("%[', the maximum size is%] ", print->to, print->set->error, print->set->error);
     fl_print_format("%[%ul%]", print->to, print->set->notable, size_expect, print->set->notable);
@@ -100,7 +100,7 @@ extern "C" {
 
     fl_print_format("%[%QNetwork on%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable);
-    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable);
     fl_print_format("%[' is busy.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
 
@@ -120,9 +120,9 @@ extern "C" {
 
     fl_print_format("%[%QNetwork on%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable);
-    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable);
-    fl_print_format("%[' failed to receive data or write to file '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[' failed to receive data or write to file '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, name, print->set->notable);
     fl_print_format(f_string_format_sentence_end_quote_s.string, print->to, print->set->error, print->set->error, f_string_eol_s);
 
@@ -144,9 +144,9 @@ extern "C" {
 
     fl_print_format("%[%QNetwork on%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable);
-    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable);
-    fl_print_format("%[' failed to send data or read from file '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[' failed to send data or read from file '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, name, print->set->notable);
     fl_print_format(f_string_format_sentence_end_quote_s.string, print->to, print->set->error, print->set->error, f_string_eol_s);
 
@@ -168,15 +168,15 @@ extern "C" {
 
     fl_print_format("%[%QNetwork packet header on%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable);
-    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable);
-    fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, name, print->set->notable);
-    fl_print_format("%[' is invalid for Object '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[' is invalid for Object '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_range_single_s.string, print->to, print->set->notable, buffer, object, print->set->notable);
-    fl_print_format("%[' and Content '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[' and Content '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_range_single_s.string, print->to, print->set->notable, buffer, content, print->set->notable);
-    fl_print_format("%[' with a status code of %]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[' with a status code of %]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_ul_single_s.string, print->to, print->set->notable, F_status_set_fine(status), print->set->notable);
     fl_print_format(f_string_format_sentence_end_s.string, print->to, print->set->error, print->set->error, f_string_eol_s);
 
@@ -196,11 +196,11 @@ extern "C" {
 
     fl_print_format("%[%QNetwork packet is invalid for%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable);
-    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable);
 
     if (name.used) {
-      fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+      fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error);
       fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, name, print->set->notable);
     }
 
@@ -222,9 +222,9 @@ extern "C" {
 
     fl_print_format("%[%QMax retry on failure reached while trying to%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, kt_tacocat_receive_s, print->set->notable);
-    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, set->network, print->set->notable);
-    fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, set->name, print->set->notable);
     fl_print_format("%['", print->to, print->set->error);
 
@@ -250,9 +250,9 @@ extern "C" {
 
     fl_print_format("%[%QMax retry on failure reached while trying to%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, kt_tacocat_send_s, print->set->notable);
-    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, set->network, print->set->notable);
-    fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, set->name, print->set->notable);
     fl_print_format(f_string_format_sentence_end_quote_s.string, print->to, print->set->error, print->set->error, f_string_eol_s);
 
@@ -272,11 +272,11 @@ extern "C" {
 
     fl_print_format("%[%QNetwork on%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable);
-    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable);
     fl_print_format("%[', the received packet is too large (expecting%] ", print->to, print->set->error, print->set->error);
     fl_print_format("%[%ul%]", print->to, print->set->notable, size_expect, print->set->notable);
-    fl_print_format(" %[bytes but instead got%] ", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[bytes but instead got%] ", print->to, print->set->error, print->set->error);
     fl_print_format("%[%ul%]", print->to, print->set->notable, size_got, print->set->notable);
     fl_print_format("%[ bytes).%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
 
@@ -296,11 +296,11 @@ extern "C" {
 
     fl_print_format("%[%QNetwork on%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable);
-    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable);
     fl_print_format("%[', the received packet is too small (expecting%] ", print->to, print->set->error, print->set->error);
     fl_print_format("%[%ul%]", print->to, print->set->notable, size_expect, print->set->notable);
-    fl_print_format(" %[bytes but instead got%] ", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[bytes but instead got%] ", print->to, print->set->error, print->set->error);
     fl_print_format("%[%ul%]", print->to, print->set->notable, size_got, print->set->notable);
     fl_print_format("%[ bytes).%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
 
@@ -320,11 +320,11 @@ extern "C" {
 
     fl_print_format("%[%QThe parameter%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_QQ_single_s.string, print->to, print->set->notable, f_console_symbol_long_normal_s, kt_tacocat_long_resolve_s, print->set->notable);
-    fl_print_format(" %[may only be either '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[may only be either '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, kt_tacocat_classic_s, print->set->notable);
-    fl_print_format("%' or '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%' or '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, kt_tacocat_kevux_s, print->set->notable);
-    fl_print_format(" %[' but '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[' but '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, unknown, print->set->notable);
     fl_print_format("%[' is given.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
 
@@ -348,7 +348,7 @@ extern "C" {
 
     fl_print_format("%[%QUnknown or invalid port number%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format(f_string_format_Q_range_single_s.string, print->to, print->set->notable, address, range, print->set->notable);
-    fl_print_format(" %[from the address '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[from the address '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, address, print->set->notable);
     fl_print_format(f_string_format_sentence_end_quote_s.string, print->to, print->set->error, print->set->error, f_string_eol_s);
 
@@ -368,7 +368,7 @@ extern "C" {
 
     fl_print_format("%[%QUnsupported protocol%] ", print->to, print->set->error, print->prefix, print->set->error);
     fl_print_format("%[%ul%]", print->to, print->set->notable, protocol, print->set->notable);
-    fl_print_format(" %[while processing '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format(" %[while processing '%]", print->to, print->set->error, print->set->error);
     fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, name, print->set->notable);
     fl_print_format(f_string_format_sentence_end_quote_s.string, print->to, print->set->error, print->set->error, f_string_eol_s);
 
diff --git a/sources/c/program/kevux/tools/tacocat/main/print/gpgme.c b/sources/c/program/kevux/tools/tacocat/main/print/gpgme.c
new file mode 100644 (file)
index 0000000..68b0a7c
--- /dev/null
@@ -0,0 +1,40 @@
+#include "../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_print_gpgme_error_
+  f_status_t kt_tacocat_print_gpgme_error(fl_print_t * const print, const f_string_t debug) {
+
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    kt_tacocat_main_t * const main = (kt_tacocat_main_t *) print->custom;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("%[%QGPGME error:%] ", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format(f_string_format_S_single_s.string, print->to, print->set->notable, gpgme_strerror(main->gpgme.error), print->set->notable);
+    fl_print_format(" %[(%]", print->to, print->set->error, print->set->error);
+    fl_print_format(f_string_format_S_single_s.string, print->to, print->set->notable, gpgme_strsource(main->gpgme.error), print->set->notable);
+    fl_print_format("%[)", print->to, print->set->error);
+
+    if (debug && *debug) {
+      fl_print_format(macro_fll_error_s(019_debug_open), print->to, print->context);
+      fl_print_format(f_string_format_S_single_s.string, print->to, print->notable, debug, print->notable);
+      fl_print_format(macro_fll_error_s(020_debug_close), print->to, print->context);
+    }
+
+    fl_print_format(".%]%r", print->to, print->context, f_string_eol_s);
+
+
+    f_file_stream_unlock(print->to);
+
+    return F_okay;
+  }
+#endif // _di_kt_tacocat_print_gpgme_error_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/print/gpgme.h b/sources/c/program/kevux/tools/tacocat/main/print/gpgme.h
new file mode 100644 (file)
index 0000000..e83e160
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the print gpgme functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_print_gpgme_h
+#define _kt_tacocat_print_gpgme_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print GPGME related error message regarding some failure.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This requires print.custom to be fake_main_t.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param debug
+ *   (optional) The debug details, such as file, line number, and function.
+ *
+ *   Set to NULL to disable.
+ *
+ * @return
+ *   F_okay on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ *
+ * @see fll_error_print()
+ */
+#ifndef _di_kt_tacocat_print_gpgme_error_
+  extern f_status_t kt_tacocat_print_gpgme_error(fl_print_t * const print, const f_string_t debug);
+#endif // _di_kt_tacocat_print_gpgme_error_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_print_gpgme_h
index 26939e1535a708f275be92fd9fb3a5a8e9580c55..5ea2fb80fa73cae8c82de923ae27c06343c6e2ac 100644 (file)
@@ -11,6 +11,13 @@ extern "C" {
     if (F_status_is_error(kt_tacocat_process_socket_set_error_has(main, kt_tacocat_long_receive_s, main->setting.receive, &main->setting.status_receive))) return;
     if (F_status_is_error(kt_tacocat_process_socket_set_error_has(main, kt_tacocat_long_send_s, main->setting.send, &main->setting.status_send))) return;
 
+    #ifdef _en_gpgme_support_
+      if (main->setting.flag & kt_tacocat_main_flag_encrypt_d) {
+        kt_tacocat_gpgme_setup(main);
+        if (F_status_is_error(main->setting.state.status)) return;
+      }
+    #endif // _en_gpgme_support_
+
     #ifdef _di_thread_support_
       // @todo implement fork and wait for both receive and send.
     #else
@@ -58,6 +65,10 @@ extern "C" {
     if (F_status_is_error_not(main->setting.state.status)) {
       main->setting.state.status = F_okay;
     }
+
+    #ifdef _en_gpgme_support_
+      kt_tacocat_gpgme_delete(&main->gpgme);
+    #endif // _en_gpgme_support_
   }
 #endif // _di_kt_tacocat_process_main_
 
index b3343986502382cc905ff9702955f14cd984aeb0..fcc12c9ddc498ecf7c692436c16d7df5bfd378cf 100644 (file)
 #include <time.h>
 #include <unistd.h>
 
+// Other includes.
+#ifdef _en_gpgme_support_
+  #include <gpgme.h>
+#endif // _en_gpgme_support_
+
 // FLL-0 includes.
 #include <fll/level_0/type.h>
 #include <fll/level_0/status.h>
 #include <program/kevux/tools/tacocat/main/signal.h>
 #include <program/kevux/tools/tacocat/main/thread.h>
 
+#ifdef _en_gpgme_support_
+  #include <program/kevux/tools/tacocat/main/gpgme.h>
+  #include <program/kevux/tools/tacocat/main/print/gpgme.h>
+#endif // _en_gpgme_support_
+
 #ifdef __cplusplus
 extern "C" {
 #endif
index 43aee807218d1da8965069e91b803214a80ec3b4..26479c61241af6e9df9250066dce5300594f505e 100644 (file)
@@ -30,6 +30,12 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
 
   data.call.setting_load_send_receive = kt_tacocat_setting_load_send_receive;
 
+  #ifdef _en_gpgme_support_
+    data.setting.flag |= kt_tacocat_main_flag_encrypt_d;
+  #else
+    data.setting.flag &= ~kt_tacocat_main_flag_encrypt_d;
+  #endif // _en_gpgme_support_
+
   if (f_pipe_input_exists()) {
     data.program.pipe = fll_program_data_pipe_input_e;
   }