+ (forward-line 1)
+ (delete-region (point) (point-max)))
+ proc))
+
+(defun nntp-open-via-rlogin-and-netcat (buffer)
+ "Open a connection to an nntp server through an intermediate host.
+First rlogin to the remote host, and then connect to the real news
+server from there using the netcat command.
+
+Please refer to the following variables to customize the connection:
+- `nntp-pre-command',
+- `nntp-via-rlogin-command',
+- `nntp-via-rlogin-command-switches',
+- `nntp-via-user-name',
+- `nntp-via-address',
+- `nntp-netcat-command',
+- `nntp-netcat-switches',
+- `nntp-address',
+- `nntp-port-number'."
+ (let ((command `(,@(when nntp-pre-command
+ (list nntp-pre-command))
+ ,nntp-via-rlogin-command
+ ,@nntp-via-rlogin-command-switches
+ ,@(when nntp-via-user-name
+ (list "-l" nntp-via-user-name))
+ ,nntp-via-address
+ ,nntp-netcat-command
+ ,@nntp-netcat-switches
+ ,nntp-address
+ ,(nntp-service-to-port nntp-port-number))))
+ ;; A non-nil connection type results in mightily odd behavior where
+ ;; (process-send-string proc "\^M") ends up sending a "\n" to the
+ ;; ssh process. --Stef
+ ;; Also a nil connection allow ssh-askpass to work under X11.
+ (let ((process-connection-type nil))
+ (apply 'start-process "nntpd" buffer command))))
+
+(defun nntp-open-netcat-stream (buffer)
+ "Open a connection to an nntp server through netcat.
+I.e. use the `nc' command rather than Emacs's builtin networking code.
+
+Please refer to the following variables to customize the connection:
+- `nntp-pre-command',
+- `nntp-netcat-command',
+- `nntp-netcat-switches',
+- `nntp-address',
+- `nntp-port-number'."
+ (let ((command `(,nntp-netcat-command
+ ,@nntp-netcat-switches
+ ,nntp-address
+ ,(nntp-service-to-port nntp-port-number))))
+ (and nntp-pre-command (push nntp-pre-command command))
+ (let ((process-connection-type nil)) ;See `nntp-open-via-rlogin-and-netcat'.
+ (apply 'start-process "nntpd" buffer command))))
+
+
+(defun nntp-open-via-telnet-and-telnet (buffer)
+ "Open a connection to an nntp server through an intermediate host.
+First telnet the remote host, and then telnet the real news server
+from there.
+
+Please refer to the following variables to customize the connection:
+- `nntp-pre-command',
+- `nntp-via-telnet-command',
+- `nntp-via-telnet-switches',
+- `nntp-via-address',
+- `nntp-via-envuser',
+- `nntp-via-user-name',
+- `nntp-via-user-password',
+- `nntp-via-shell-prompt',
+- `nntp-telnet-command',
+- `nntp-telnet-switches',
+- `nntp-address',
+- `nntp-port-number',
+- `nntp-end-of-line'."
+ (with-current-buffer buffer
+ (erase-buffer)
+ (let ((command `(,nntp-via-telnet-command ,@nntp-via-telnet-switches))
+ (case-fold-search t)
+ proc)
+ (and nntp-pre-command (push nntp-pre-command command))
+ (setq proc (apply 'start-process "nntpd" buffer command))
+ (when (memq (process-status proc) '(open run))
+ (nntp-wait-for-string "^r?telnet")
+ (process-send-string proc "set escape \^X\n")
+ (cond
+ ((and nntp-via-envuser nntp-via-user-name)
+ (process-send-string proc (concat "open " "-l" nntp-via-user-name
+ nntp-via-address "\n")))
+ (t
+ (process-send-string proc (concat "open " nntp-via-address
+ "\n"))))
+ (when (not nntp-via-envuser)
+ (nntp-wait-for-string "^\r*.?login:")
+ (process-send-string proc
+ (concat
+ (or nntp-via-user-name
+ (setq nntp-via-user-name
+ (read-string "login: ")))
+ "\n")))
+ (nntp-wait-for-string "^\r*.?password:")
+ (process-send-string proc
+ (concat
+ (or nntp-via-user-password
+ (setq nntp-via-user-password
+ (read-passwd "Password: ")))
+ "\n"))
+ (nntp-wait-for-string nntp-via-shell-prompt)
+ (let ((real-telnet-command `("exec"
+ ,nntp-telnet-command
+ ,@nntp-telnet-switches
+ ,nntp-address
+ ,(nntp-service-to-port nntp-port-number))))
+ (process-send-string proc
+ (concat (mapconcat 'identity
+ real-telnet-command " ")
+ "\n")))
+ (nntp-wait-for-string "^\r*20[01]")
+ (beginning-of-line)
+ (delete-region (point-min) (point))
+ (process-send-string proc "\^]")
+ (nntp-wait-for-string "^r?telnet")
+ (process-send-string proc "mode character\n")
+ (accept-process-output proc 1)
+ (sit-for 1)
+ (goto-char (point-min))
+ (forward-line 1)
+ (delete-region (point) (point-max)))
+ proc)))
+
+;; Marks handling
+
+(defun nntp-marks-directory (server)
+ (expand-file-name server nntp-marks-directory))
+
+(defvar nntp-server-to-method-cache nil
+ "Alist of servers and select methods.")
+
+(defun nntp-group-pathname (server group &optional file)
+ "Return an absolute file name of FILE for GROUP on SERVER."
+ (let ((method (cdr (assoc server nntp-server-to-method-cache))))
+ (unless method
+ (push (cons server (setq method (or (gnus-server-to-method server)
+ (gnus-find-method-for-group group))))
+ nntp-server-to-method-cache))
+ (nnmail-group-pathname
+ (mm-decode-coding-string group
+ (inline (gnus-group-name-charset method group)))
+ (nntp-marks-directory server)
+ file)))
+
+(defun nntp-possibly-create-directory (group server)
+ (let ((dir (nntp-group-pathname server group))
+ (file-name-coding-system nnmail-pathname-coding-system))
+ (unless (file-exists-p dir)
+ (make-directory (directory-file-name dir) t)
+ (nnheader-message 5 "Creating nntp marks directory %s" dir))))
+
+(autoload 'time-less-p "time-date")
+
+(defun nntp-marks-changed-p (group server)
+ (let ((file (nntp-group-pathname server group nntp-marks-file-name))
+ (file-name-coding-system nnmail-pathname-coding-system))
+ (if (null (gnus-gethash file nntp-marks-modtime))
+ t ;; never looked at marks file, assume it has changed
+ (time-less-p (gnus-gethash file nntp-marks-modtime)
+ (nth 5 (file-attributes file))))))
+
+(defun nntp-save-marks (group server)
+ (let ((file-name-coding-system nnmail-pathname-coding-system)
+ (file (nntp-group-pathname server group nntp-marks-file-name)))
+ (condition-case err
+ (progn
+ (nntp-possibly-create-directory group server)
+ (with-temp-file file
+ (erase-buffer)
+ (gnus-prin1 nntp-marks)
+ (insert "\n"))
+ (gnus-sethash file
+ (nth 5 (file-attributes file))
+ nntp-marks-modtime))
+ (error (or (gnus-yes-or-no-p
+ (format "Could not write to %s (%s). Continue? " file err))
+ (error "Cannot write to %s (%s)" file err))))))
+
+(defun nntp-open-marks (group server)
+ (let ((file (nntp-group-pathname server group nntp-marks-file-name))
+ (file-name-coding-system nnmail-pathname-coding-system))
+ (if (file-exists-p file)
+ (condition-case err
+ (with-temp-buffer
+ (gnus-sethash file (nth 5 (file-attributes file))
+ nntp-marks-modtime)
+ (nnheader-insert-file-contents file)
+ (setq nntp-marks (read (current-buffer)))
+ (dolist (el gnus-article-unpropagated-mark-lists)
+ (setq nntp-marks (gnus-remassoc el nntp-marks))))
+ (error (or (gnus-yes-or-no-p
+ (format "Error reading nntp marks file %s (%s). Continuing will use marks from .newsrc.eld. Continue? " file err))
+ (error "Cannot read nntp marks file %s (%s)" file err))))
+ ;; User didn't have a .marks file. Probably first time
+ ;; user of the .marks stuff. Bootstrap it from .newsrc.eld.
+ (let ((info (gnus-get-info
+ (gnus-group-prefixed-name
+ group
+ (gnus-server-to-method (format "nntp:%s" server)))))
+ (decoded-name (mm-decode-coding-string
+ group
+ (gnus-group-name-charset
+ (gnus-server-to-method server) group))))
+ (nnheader-message 7 "Bootstrapping marks for %s..." decoded-name)
+ (setq nntp-marks (gnus-info-marks info))
+ (push (cons 'read (gnus-info-read info)) nntp-marks)
+ (dolist (el gnus-article-unpropagated-mark-lists)
+ (setq nntp-marks (gnus-remassoc el nntp-marks)))
+ (nntp-save-marks group server)
+ (nnheader-message 7 "Bootstrapping marks for %s...done"
+ decoded-name)))))