Silence write-region.
[elisp/epg.git] / epg.el
diff --git a/epg.el b/epg.el
index d1d9160..843e463 100644 (file)
--- a/epg.el
+++ b/epg.el
@@ -406,6 +406,19 @@ This function is for internal use only."
        (setcdr entry value)
       (epg-context-set-result context (cons (cons name value) result)))))
 
+(defun epg-signature-to-string (signature)
+  (format "%s signature from %s %s%s"
+         (capitalize (symbol-name (epg-signature-status signature)))
+         (epg-signature-key-id signature)
+         (epg-signature-user-id signature)
+         (if (epg-signature-validity signature)
+             (format " (trust %s)"
+                     (epg-signature-validity signature))
+           "")))
+
+(defun epg-verify-result-to-string (verify-result)
+  (mapconcat #'epg-signature-to-string verify-result "\n"))
+
 (defun epg-start (context args)
   "Start `epg-gpg-program' in a subprocess with given ARGS."
   (let* ((args (append (list "--no-tty"
@@ -539,35 +552,68 @@ This function is for internal use only."
 (defun epg-status-GET_HIDDEN (process string)
   (if (and epg-key-id
           (string-match "\\`passphrase\\." string))
-    (let ((passphrase
-          (funcall
-           (if (consp (epg-context-passphrase-callback epg-context))
-               (car (epg-context-passphrase-callback epg-context))
-             (epg-context-passphrase-callback epg-context))
-           epg-key-id
-           (if (consp (epg-context-passphrase-callback epg-context))
-               (cdr (epg-context-passphrase-callback epg-context)))))
-         string)
-      (if passphrase
-         (unwind-protect
-             (progn
-               (setq string (concat passphrase "\n"))
-               (fillarray passphrase 0)
-               (setq passphrase nil)
-               (process-send-string process string))
-           (if string
-               (fillarray string 0)))))))
+      (let (inhibit-quit
+           passphrase
+           passphrase-with-new-line)
+       (unwind-protect
+           (condition-case nil
+               (progn
+                 (setq passphrase
+                       (funcall
+                        (if (consp (epg-context-passphrase-callback
+                                    epg-context))
+                            (car (epg-context-passphrase-callback
+                                  epg-context))
+                          (epg-context-passphrase-callback epg-context))
+                        epg-key-id
+                        (if (consp (epg-context-passphrase-callback
+                                    epg-context))
+                            (cdr (epg-context-passphrase-callback
+                                  epg-context)))))
+                 (when passphrase
+                   (setq passphrase-with-new-line (concat passphrase "\n"))
+                   (fillarray passphrase 0)
+                   (setq passphrase nil)
+                   (process-send-string process passphrase-with-new-line)))
+             (quit
+              (epg-context-set-result-for
+               epg-context 'error
+               (cons 'quit
+                     (epg-context-result-for epg-context 'error)))
+              (delete-process process)))
+         (if passphrase
+             (fillarray passphrase 0))
+         (if passphrase-with-new-line
+             (fillarray passphrase-with-new-line 0))))))
 
 (defun epg-status-GET_BOOL (process string)
-  (let ((entry (assoc string epg-prompt-alist)))
-    (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
-       (process-send-string process "y\n")
-      (process-send-string process "n\n"))))
+  (let ((entry (assoc string epg-prompt-alist))
+       inhibit-quit)
+    (condition-case nil
+      (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
+         (process-send-string process "y\n")
+       (process-send-string process "n\n"))
+      (quit
+       (epg-context-set-result-for
+       epg-context 'error
+       (cons 'quit
+             (epg-context-result-for epg-context 'error)))
+       (delete-process process)))))
 
 (defun epg-status-GET_LINE (process string)
-  (let* ((entry (assoc string epg-prompt-alist))
-        (string (read-string (if entry (cdr entry) (concat string ": ")))))
-    (process-send-string process (concat string "\n"))))
+  (let ((entry (assoc string epg-prompt-alist))
+       inhibit-quit)
+    (condition-case nil
+       (process-send-string
+        process
+        (concat (read-string (if entry (cdr entry) (concat string ": ")))
+                "\n"))
+      (quit
+       (epg-context-set-result-for
+       epg-context 'error
+       (cons 'quit
+             (epg-context-result-for epg-context 'error)))
+       (delete-process process)))))
 
 (defun epg-status-GOODSIG (process string)
   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
@@ -947,7 +993,7 @@ If PLAIN is nil, it returns the result as a string."
        (coding-system-for-write 'binary))
     (unwind-protect
        (progn
-         (write-region cipher nil input-file)
+         (write-region cipher nil input-file nil 'quiet)
          (epg-context-set-output-file context
                                       (epg-make-temp-file "epg-output"))
          (epg-start-decrypt context (epg-make-data-from-file input-file))
@@ -1035,7 +1081,7 @@ For a normal or a clear text signature, SIGNED-TEXT should be nil."
          (if signed-text
              (progn
                (setq input-file (epg-make-temp-file "epg-signature"))
-               (write-region signature nil input-file)
+               (write-region signature nil input-file nil 'quiet)
                (epg-start-verify context
                                  (epg-make-data-from-file input-file)
                                  (epg-make-data-from-string signed-text)))
@@ -1161,8 +1207,8 @@ If you are unsure, use synchronous version of this function
                     (if (epg-data-file plain)
                         (list (epg-data-file plain)))))
   (if sign
-      (epg-wait-for-status context '("BEGIN_SIGNING")))
-  (epg-wait-for-status context '("BEGIN_ENCRYPTION"))
+      (epg-wait-for-status context '("BEGIN_SIGNING"))
+    (epg-wait-for-status context '("BEGIN_ENCRYPTION")))
   (if (and (epg-data-string plain)
           (eq (process-status (epg-context-process context)) 'run))
       (process-send-string (epg-context-process context)
@@ -1241,7 +1287,8 @@ If you are unsure, use synchronous version of this function
        (epg-start-export-keys context keys)
        (epg-wait-for-completion context)
        (if (epg-context-result-for context 'error)
-           (error "Export keys failed"))
+           (error "Export keys failed: %S"
+                  (epg-context-result-for context 'error)))
        (unless file
          (epg-read-output context)))
     (unless file
@@ -1279,7 +1326,8 @@ If you are unsure, use synchronous version of this function
            (epg-flush context))
        (epg-wait-for-completion context)
        (if (epg-context-result-for context 'error)
-           (error "Import keys failed"))
+           (error "Import keys failed: %S"
+                  (epg-context-result-for context 'error)))
        (epg-read-output context))
     (epg-reset context)))
 
@@ -1317,10 +1365,42 @@ If you are unsure, use synchronous version of this function
   "Delete KEYS from the key ring."
   (unwind-protect
       (progn
-       (epg-start-delete-keys context keys)
+       (epg-start-delete-keys context keys allow-secret)
+       (epg-wait-for-completion context)
+       (if (epg-context-result-for context 'error)
+           (error "Delete keys failed: %S"
+                  (epg-context-result-for context 'error))))
+    (epg-reset context)))
+
+;;;###autoload
+(defun epg-start-sign-keys (context keys &optional local)
+  "Initiate an sign keys operation.
+
+If you use this function, you will need to wait for the completion of
+`epg-gpg-program' by using `epg-wait-for-completion' and call
+`epg-reset' to clear a temporaly output file.
+If you are unsure, use synchronous version of this function
+`epg-sign-keys' instead."
+  (epg-context-set-result context nil)
+  (epg-start context (cons (if local
+                              "--lsign-key"
+                            "--sign-key")
+                          (mapcar
+                           (lambda (key)
+                             (epg-sub-key-id
+                              (car (epg-key-sub-key-list key))))
+                           keys))))
+
+;;;###autoload
+(defun epg-sign-keys (context keys &optional local)
+  "Sign KEYS from the key ring."
+  (unwind-protect
+      (progn
+       (epg-start-sign-keys context keys local)
        (epg-wait-for-completion context)
        (if (epg-context-result-for context 'error)
-           (error "Delete key failed")))
+           (error "Sign keys failed: %S"
+                  (epg-context-result-for context 'error))))
     (epg-reset context)))
 
 (provide 'epg)