+(defun epg-find-configuration (protocol &optional force)
+ "Find or create a usable configuration to handle PROTOCOL.
+This function first looks at the existing configuration found by
+the previous invocation of this function, unless FORCE is non-nil.
+
+Then it walks through `epg-config--program-alist'. If
+`epg-gpg-program' or `epg-gpgsm-program' is already set with
+custom, use it. Otherwise, it tries the programs listed in the
+entry until the version requirement is met."
+ (let ((entry (assq protocol epg-config--program-alist)))
+ (unless entry
+ (error "Unknown protocol %S" protocol))
+ (cl-destructuring-bind (symbol constructor . alist)
+ (cdr entry)
+ (or (and (not force) (alist-get protocol epg--configurations))
+ ;; If the executable value is already set with M-x
+ ;; customize, use it without checking.
+ (if (get symbol 'saved-value)
+ (let ((configuration (funcall constructor (symbol-value symbol))))
+ (push (cons protocol configuration) epg--configurations)
+ configuration)
+ (catch 'found
+ (dolist (program-version alist)
+ (let ((executable (executable-find (car program-version))))
+ (when executable
+ (let ((configuration
+ (funcall constructor executable)))
+ (when (ignore-errors
+ (epg-check-configuration configuration
+ (cdr program-version))
+ t)
+ (push (cons protocol configuration) epg--configurations)
+ (throw 'found configuration))))))))))))
+
+;; Create an `epg-configuration' object for `gpg', using PROGRAM.
+(defun epg-config--make-gpg-configuration (program)