Add 2012 to FSF copyright years for Emacs files
[bpt/emacs.git] / lisp / net / net-utils.el
CommitLineData
e8af40ee 1;;; net-utils.el --- network functions
8749abea 2
acaf905b 3;; Copyright (C) 1998-2012 Free Software Foundation, Inc.
a84f13fb 4
8749abea
GM
5;; Author: Peter Breton <pbreton@cs.umb.edu>
6;; Created: Sun Mar 16 1997
c2e6c8d1 7;; Keywords: network comm
8749abea
GM
8
9;; This file is part of GNU Emacs.
10
874a927a 11;; GNU Emacs is free software: you can redistribute it and/or modify
8749abea 12;; it under the terms of the GNU General Public License as published by
874a927a
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
8749abea
GM
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
874a927a 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
8749abea
GM
23
24;;; Commentary:
c2e6c8d1 25
8749abea
GM
26;;
27;; There are three main areas of functionality:
ddb62bf1 28;;
8749abea
GM
29;; * Wrap common network utility programs (ping, traceroute, netstat,
30;; nslookup, arp, route). Note that these wrappers are of the diagnostic
31;; functions of these programs only.
ddb62bf1 32;;
8749abea 33;; * Implement some very basic protocols in Emacs Lisp (finger and whois)
ddb62bf1 34;;
8749abea
GM
35;; * Support connections to HOST/PORT, generally for debugging and the like.
36;; In other words, for doing much the same thing as "telnet HOST PORT", and
37;; then typing commands.
38;;
39;; PATHS
40;;
41;; On some systems, some of these programs are not in normal user path,
ddb62bf1 42;; but rather in /sbin, /usr/sbin, and so on.
8749abea
GM
43
44
45;;; Code:
8749abea
GM
46
47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
48;; Customization Variables
49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
50
51(defgroup net-utils nil
52 "Network utility functions."
53 :prefix "net-utils-"
54 :group 'comm
c2e6c8d1 55 :version "20.3")
8749abea 56
17731c39 57(defcustom net-utils-remove-ctl-m (memq system-type '(windows-nt msdos))
8749abea
GM
58 "If non-nil, remove control-Ms from output."
59 :group 'net-utils
c2e6c8d1 60 :type 'boolean)
8749abea 61
ddb62bf1
PB
62(defcustom traceroute-program
63 (if (eq system-type 'windows-nt)
8749abea
GM
64 "tracert"
65 "traceroute")
66 "Program to trace network hops to a destination."
67 :group 'net-utils
c2e6c8d1 68 :type 'string)
8749abea
GM
69
70(defcustom traceroute-program-options nil
71 "Options for the traceroute program."
72 :group 'net-utils
c2e6c8d1 73 :type '(repeat string))
8749abea
GM
74
75(defcustom ping-program "ping"
76 "Program to send network test packets to a host."
77 :group 'net-utils
c2e6c8d1 78 :type 'string)
8749abea 79
c2e6c8d1 80;; On GNU/Linux and Irix, the system's ping program seems to send packets
8749abea 81;; indefinitely unless told otherwise
ddb62bf1 82(defcustom ping-program-options
17731c39 83 (and (memq system-type '(gnu/linux irix))
8749abea
GM
84 (list "-c" "4"))
85 "Options for the ping program.
86These options can be used to limit how many ICMP packets are emitted."
87 :group 'net-utils
c2e6c8d1 88 :type '(repeat string))
8749abea 89
cd6ef82d
GM
90(define-obsolete-variable-alias 'ipconfig-program 'ifconfig-program "22.2")
91
46f6fa95 92(defcustom ifconfig-program
8749abea
GM
93 (if (eq system-type 'windows-nt)
94 "ipconfig"
95 "ifconfig")
96 "Program to print network configuration information."
97 :group 'net-utils
c2e6c8d1 98 :type 'string)
8749abea 99
af3ccb5c
GM
100(define-obsolete-variable-alias 'ipconfig-program-options
101 'ifconfig-program-options "22.2")
102
46f6fa95 103(defcustom ifconfig-program-options
c2e6c8d1
PJ
104 (list
105 (if (eq system-type 'windows-nt)
106 "/all" "-a"))
2f7dc12d 107 "Options for the ifconfig program."
8749abea 108 :group 'net-utils
c2e6c8d1 109 :type '(repeat string))
8749abea 110
e69ec721
GM
111(defcustom iwconfig-program "iwconfig"
112 "Program to print wireless network configuration information."
113 :group 'net-utils
beaa23bc
GM
114 :type 'string
115 :version "23.1")
e69ec721
GM
116
117(defcustom iwconfig-program-options nil
20f28123 118 "Options for the iwconfig program."
e69ec721 119 :group 'net-utils
beaa23bc
GM
120 :type '(repeat string)
121 :version "23.1")
e69ec721 122
2f7dc12d 123(defcustom netstat-program "netstat"
8749abea
GM
124 "Program to print network statistics."
125 :group 'net-utils
c2e6c8d1 126 :type 'string)
8749abea 127
ddb62bf1 128(defcustom netstat-program-options
8749abea 129 (list "-a")
2f7dc12d 130 "Options for the netstat program."
8749abea 131 :group 'net-utils
c2e6c8d1 132 :type '(repeat string))
8749abea 133
2f7dc12d 134(defcustom arp-program "arp"
8749abea
GM
135 "Program to print IP to address translation tables."
136 :group 'net-utils
c2e6c8d1 137 :type 'string)
8749abea 138
ddb62bf1 139(defcustom arp-program-options
8749abea 140 (list "-a")
2f7dc12d 141 "Options for the arp program."
8749abea 142 :group 'net-utils
c2e6c8d1 143 :type '(repeat string))
8749abea 144
ddb62bf1 145(defcustom route-program
8749abea
GM
146 (if (eq system-type 'windows-nt)
147 "route"
148 "netstat")
149 "Program to print routing tables."
150 :group 'net-utils
c2e6c8d1 151 :type 'string)
8749abea 152
ddb62bf1 153(defcustom route-program-options
8749abea
GM
154 (if (eq system-type 'windows-nt)
155 (list "print")
156 (list "-r"))
2f7dc12d 157 "Options for the route program."
8749abea 158 :group 'net-utils
c2e6c8d1 159 :type '(repeat string))
8749abea 160
2f7dc12d 161(defcustom nslookup-program "nslookup"
8749abea
GM
162 "Program to interactively query DNS information."
163 :group 'net-utils
c2e6c8d1 164 :type 'string)
8749abea 165
2f7dc12d
JB
166(defcustom nslookup-program-options nil
167 "Options for the nslookup program."
8749abea 168 :group 'net-utils
c2e6c8d1 169 :type '(repeat string))
8749abea
GM
170
171(defcustom nslookup-prompt-regexp "^> "
8fb051f9
MB
172 "Regexp to match the nslookup prompt.
173
174This variable is only used if the variable
980cc247 175`comint-use-prompt-regexp' is non-nil."
8749abea 176 :group 'net-utils
c2e6c8d1 177 :type 'regexp)
8749abea 178
2f7dc12d 179(defcustom dig-program "dig"
8749abea
GM
180 "Program to query DNS information."
181 :group 'net-utils
c2e6c8d1 182 :type 'string)
8749abea
GM
183
184(defcustom ftp-program "ftp"
2f7dc12d 185 "Program to run to do FTP transfers."
8749abea 186 :group 'net-utils
c2e6c8d1 187 :type 'string)
8749abea
GM
188
189(defcustom ftp-program-options nil
2f7dc12d 190 "Options for the ftp program."
8749abea 191 :group 'net-utils
c2e6c8d1 192 :type '(repeat string))
8749abea
GM
193
194(defcustom ftp-prompt-regexp "^ftp>"
8fb051f9
MB
195 "Regexp which matches the FTP program's prompt.
196
197This variable is only used if the variable
980cc247 198`comint-use-prompt-regexp' is non-nil."
8749abea 199 :group 'net-utils
c2e6c8d1 200 :type 'regexp)
8749abea
GM
201
202(defcustom smbclient-program "smbclient"
203 "Smbclient program."
204 :group 'net-utils
c2e6c8d1 205 :type 'string)
8749abea
GM
206
207(defcustom smbclient-program-options nil
2f7dc12d 208 "Options for the smbclient program."
8749abea 209 :group 'net-utils
c2e6c8d1 210 :type '(repeat string))
8749abea
GM
211
212(defcustom smbclient-prompt-regexp "^smb: \>"
8fb051f9
MB
213 "Regexp which matches the smbclient program's prompt.
214
215This variable is only used if the variable
980cc247 216`comint-use-prompt-regexp' is non-nil."
8749abea 217 :group 'net-utils
c2e6c8d1 218 :type 'regexp)
8749abea 219
2f7dc12d 220(defcustom dns-lookup-program "host"
ac8a1898
PB
221 "Program to interactively query DNS information."
222 :group 'net-utils
2f7dc12d 223 :type 'string)
ac8a1898 224
2f7dc12d
JB
225(defcustom dns-lookup-program-options nil
226 "Options for the dns-lookup program."
ac8a1898 227 :group 'net-utils
2f7dc12d 228 :type '(repeat string))
ac8a1898 229
76540917
PB
230;; Internal variables
231(defvar network-connection-service nil)
232(defvar network-connection-host nil)
233
8749abea
GM
234;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
235;; Nslookup goodies
236;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
237
ce299d55 238(defvar nslookup-font-lock-keywords
cbbe9a37
GM
239 (list
240 (list "^[A-Za-z0-9 _]+:" 0 'font-lock-type-face)
241 (list "\\<\\(SOA\\|NS\\|MX\\|A\\|CNAME\\)\\>"
242 1 'font-lock-keyword-face)
243 ;; Dotted quads
244 (list
245 (mapconcat 'identity
246 (make-list 4 "[0-9]+")
247 "\\.")
248 0 'font-lock-variable-name-face)
249 ;; Host names
250 (list
251 (let ((host-expression "[-A-Za-z0-9]+"))
252 (concat
253 (mapconcat 'identity
254 (make-list 2 host-expression)
255 "\\.")
256 "\\(\\." host-expression "\\)*"))
257 0 'font-lock-variable-name-face))
3478046b 258 "Expressions to font-lock for nslookup.")
8749abea 259
ce299d55
CY
260;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
261;; General network utilities mode
262;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
263
264(defvar net-utils-font-lock-keywords
265 (list
266 ;; Dotted quads
267 (list
268 (mapconcat 'identity (make-list 4 "[0-9]+") "\\.")
269 0 'font-lock-variable-name-face)
270 ;; Simple rfc4291 addresses
271 (list (concat
272 "\\( \\([[:xdigit:]]+\\(:\\|::\\)\\)+[[:xdigit:]]+\\)"
273 "\\|"
274 "\\(::[[:xdigit:]]+\\)")
275 0 'font-lock-variable-name-face)
276 ;; Host names
277 (list
278 (let ((host-expression "[-A-Za-z0-9]+"))
279 (concat
280 (mapconcat 'identity (make-list 2 host-expression) "\\.")
281 "\\(\\." host-expression "\\)*"))
282 0 'font-lock-variable-name-face))
283 "Expressions to font-lock for general network utilities.")
284
285(define-derived-mode net-utils-mode special-mode "NetworkUtil"
286 "Major mode for interacting with an external network utility."
287 (set (make-local-variable 'font-lock-defaults)
288 '((net-utils-font-lock-keywords))))
289
8749abea
GM
290;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
291;; Utility functions
292;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
293
294;; Simplified versions of some at-point functions from ffap.el.
295;; It's not worth loading all of ffap just for these.
296(defun net-utils-machine-at-point ()
297 (let ((pt (point)))
298 (buffer-substring-no-properties
299 (save-excursion
300 (skip-chars-backward "-a-zA-Z0-9.")
301 (point))
302 (save-excursion
303 (skip-chars-forward "-a-zA-Z0-9.")
304 (skip-chars-backward "." pt)
305 (point)))))
306
307(defun net-utils-url-at-point ()
308 (let ((pt (point)))
309 (buffer-substring-no-properties
310 (save-excursion
311 (skip-chars-backward "--:=&?$+@-Z_a-z~#,%")
312 (skip-chars-forward "^A-Za-z0-9" pt)
313 (point))
314 (save-excursion
315 (skip-chars-forward "--:=&?$+@-Z_a-z~#,%")
316 (skip-chars-backward ":;.,!?" pt)
317 (point)))))
318
8749abea
GM
319(defun net-utils-remove-ctrl-m-filter (process output-string)
320 "Remove trailing control Ms."
321 (let ((old-buffer (current-buffer))
322 (filtered-string output-string))
323 (unwind-protect
324 (let ((moving))
325 (set-buffer (process-buffer process))
ce299d55
CY
326 (let ((inhibit-read-only t))
327 (setq moving (= (point) (process-mark process)))
328
329 (while (string-match "\r" filtered-string)
330 (setq filtered-string
331 (replace-match "" nil nil filtered-string)))
332
333 (save-excursion
334 ;; Insert the text, moving the process-marker.
335 (goto-char (process-mark process))
336 (insert filtered-string)
337 (set-marker (process-mark process) (point))))
8749abea
GM
338 (if moving (goto-char (process-mark process))))
339 (set-buffer old-buffer))))
ddb62bf1 340
20f28123 341(defun net-utils-run-program (name header program args)
8749abea 342 "Run a network information program."
20f28123
JB
343 (let ((buf (get-buffer-create (concat "*" name "*"))))
344 (set-buffer buf)
345 (erase-buffer)
346 (insert header "\n")
347 (set-process-filter
348 (apply 'start-process name buf program args)
349 'net-utils-remove-ctrl-m-filter)
350 (display-buffer buf)
351 buf))
8749abea 352
ce299d55
CY
353;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
354;; General network utilities (diagnostic)
355;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
356
357(defun net-utils-run-simple (buffer-name program-name args)
358 "Run a network utility for diagnostic output only."
359 (interactive)
360 (when (get-buffer buffer-name)
361 (kill-buffer buffer-name))
362 (get-buffer-create buffer-name)
363 (with-current-buffer buffer-name
364 (net-utils-mode)
365 (set-process-filter
366 (apply 'start-process (format "%s" program-name)
367 buffer-name program-name args)
368 'net-utils-remove-ctrl-m-filter)
369 (goto-char (point-min)))
370 (display-buffer buffer-name))
371
372;;;###autoload
5a0c3f56
JB
373(defun ifconfig ()
374 "Run ifconfig and display diagnostic output."
375 (interactive)
376 (net-utils-run-simple
377 (format "*%s*" ifconfig-program)
378 ifconfig-program
ce299d55
CY
379 ifconfig-program-options))
380
381(defalias 'ipconfig 'ifconfig)
382
383;;;###autoload
5a0c3f56
JB
384(defun iwconfig ()
385 "Run iwconfig and display diagnostic output."
386 (interactive)
387 (net-utils-run-simple
388 (format "*%s*" iwconfig-program)
389 iwconfig-program
ce299d55
CY
390 iwconfig-program-options))
391
392;;;###autoload
393(defun netstat ()
5a0c3f56 394 "Run netstat and display diagnostic output."
ce299d55
CY
395 (interactive)
396 (net-utils-run-simple
397 (format "*%s*" netstat-program)
398 netstat-program
399 netstat-program-options))
400
401;;;###autoload
402(defun arp ()
5a0c3f56 403 "Run arp and display diagnostic output."
ce299d55
CY
404 (interactive)
405 (net-utils-run-simple
406 (format "*%s*" arp-program)
407 arp-program
408 arp-program-options))
409
410;;;###autoload
411(defun route ()
412 "Run route and display diagnostic output."
413 (interactive)
414 (net-utils-run-simple
415 (format "*%s*" route-program)
416 route-program
417 route-program-options))
418
8749abea
GM
419;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
420;; Wrappers for external network programs
421;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
422
423;;;###autoload
424(defun traceroute (target)
425 "Run traceroute program for TARGET."
426 (interactive "sTarget: ")
ddb62bf1 427 (let ((options
8749abea
GM
428 (if traceroute-program-options
429 (append traceroute-program-options (list target))
430 (list target))))
431 (net-utils-run-program
432 (concat "Traceroute" " " target)
433 (concat "** Traceroute ** " traceroute-program " ** " target)
434 traceroute-program
c2e6c8d1 435 options)))
8749abea
GM
436
437;;;###autoload
438(defun ping (host)
439 "Ping HOST.
ddb62bf1 440If your system's ping continues until interrupted, you can try setting
8749abea 441`ping-program-options'."
ddb62bf1 442 (interactive
8749abea 443 (list (read-from-minibuffer "Ping host: " (net-utils-machine-at-point))))
ddb62bf1 444 (let ((options
8749abea
GM
445 (if ping-program-options
446 (append ping-program-options (list host))
447 (list host))))
448 (net-utils-run-program
449 (concat "Ping" " " host)
450 (concat "** Ping ** " ping-program " ** " host)
451 ping-program
c2e6c8d1 452 options)))
8749abea 453
8749abea
GM
454;; FIXME -- Needs to be a process filter
455;; (defun netstat-with-filter (filter)
456;; "Run netstat program."
457;; (interactive "sFilter: ")
458;; (netstat)
459;; (set-buffer (get-buffer "*Netstat*"))
460;; (goto-char (point-min))
c2e6c8d1 461;; (delete-matching-lines filter))
8749abea
GM
462
463;;;###autoload
464(defun nslookup-host (host)
465 "Lookup the DNS information for HOST."
466 (interactive
467 (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point))))
ddb62bf1 468 (let ((options
8749abea
GM
469 (if nslookup-program-options
470 (append nslookup-program-options (list host))
471 (list host))))
472 (net-utils-run-program
473 "Nslookup"
474 (concat "** "
475 (mapconcat 'identity
476 (list "Nslookup" host nslookup-program)
477 " ** "))
478 nslookup-program
c2e6c8d1 479 options)))
8749abea
GM
480
481;;;###autoload
482(defun nslookup ()
483 "Run nslookup program."
484 (interactive)
a2e01f7e 485 (switch-to-buffer (make-comint "nslookup" nslookup-program))
c2e6c8d1 486 (nslookup-mode))
8749abea 487
cbbe9a37
GM
488(defvar comint-prompt-regexp)
489(defvar comint-input-autoexpand)
490
491(autoload 'comint-mode "comint" nil t)
492
b016851c
SM
493(defvar nslookup-mode-map
494 (let ((map (make-sparse-keymap)))
495 (define-key map "\t" 'comint-dynamic-complete)
496 map))
497
8749abea 498;; Using a derived mode gives us keymaps, hooks, etc.
8fb051f9 499(define-derived-mode nslookup-mode comint-mode "Nslookup"
8749abea 500 "Major mode for interacting with the nslookup program."
ddb62bf1 501 (set
8749abea
GM
502 (make-local-variable 'font-lock-defaults)
503 '((nslookup-font-lock-keywords)))
8749abea 504 (setq comint-prompt-regexp nslookup-prompt-regexp)
c2e6c8d1 505 (setq comint-input-autoexpand t))
8749abea 506
ac8a1898
PB
507;;;###autoload
508(defun dns-lookup-host (host)
509 "Lookup the DNS information for HOST (name or IP address)."
510 (interactive
511 (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point))))
512 (let ((options
513 (if dns-lookup-program-options
514 (append dns-lookup-program-options (list host))
515 (list host))))
516 (net-utils-run-program
517 (concat "DNS Lookup [" host "]")
518 (concat "** "
519 (mapconcat 'identity
520 (list "DNS Lookup" host dns-lookup-program)
521 " ** "))
522 dns-lookup-program
cbbe9a37
GM
523 options)))
524
525(autoload 'ffap-string-at-point "ffap")
ac8a1898 526
8749abea 527;;;###autoload
5daebfbb 528(defun run-dig (host)
8749abea
GM
529 "Run dig program."
530 (interactive
531 (list
cbbe9a37
GM
532 (read-from-minibuffer "Lookup host: "
533 (or (ffap-string-at-point 'machine) ""))))
8749abea
GM
534 (net-utils-run-program
535 "Dig"
536 (concat "** "
537 (mapconcat 'identity
538 (list "Dig" host dig-program)
539 " ** "))
540 dig-program
c2e6c8d1 541 (list host)))
8749abea 542
cbbe9a37
GM
543(autoload 'comint-exec "comint")
544
8749abea
GM
545;; This is a lot less than ange-ftp, but much simpler.
546;;;###autoload
547(defun ftp (host)
548 "Run ftp program."
ddb62bf1 549 (interactive
8749abea 550 (list
ddb62bf1 551 (read-from-minibuffer
8749abea 552 "Ftp to Host: " (net-utils-machine-at-point))))
8749abea
GM
553 (let ((buf (get-buffer-create (concat "*ftp [" host "]*"))))
554 (set-buffer buf)
8fb051f9 555 (ftp-mode)
8749abea
GM
556 (comint-exec buf (concat "ftp-" host) ftp-program nil
557 (if ftp-program-options
558 (append (list host) ftp-program-options)
559 (list host)))
8fb051f9 560 (pop-to-buffer buf)))
8749abea 561
b016851c
SM
562(defvar ftp-mode-map
563 (let ((map (make-sparse-keymap)))
564 ;; Occasionally useful
565 (define-key map "\t" 'comint-dynamic-complete)
566 map))
567
8fb051f9 568(define-derived-mode ftp-mode comint-mode "FTP"
8749abea 569 "Major mode for interacting with the ftp program."
8749abea 570 (setq comint-prompt-regexp ftp-prompt-regexp)
8749abea 571 (setq comint-input-autoexpand t)
8fb051f9
MB
572 ;; Only add the password-prompting hook if it's not already in the
573 ;; global hook list. This stands a small chance of losing, if it's
574 ;; later removed from the global list (very small, since any
575 ;; password prompts will probably immediately follow the initial
576 ;; connection), but it's better than getting prompted twice for the
577 ;; same password.
578 (unless (memq 'comint-watch-for-password-prompt
579 (default-value 'comint-output-filter-functions))
580 (add-hook 'comint-output-filter-functions 'comint-watch-for-password-prompt
c2e6c8d1 581 nil t)))
8749abea 582
8749abea
GM
583(defun smbclient (host service)
584 "Connect to SERVICE on HOST via SMB."
ddb62bf1 585 (interactive
8749abea 586 (list
ddb62bf1 587 (read-from-minibuffer
8749abea
GM
588 "Connect to Host: " (net-utils-machine-at-point))
589 (read-from-minibuffer "SMB Service: ")))
8749abea
GM
590 (let* ((name (format "smbclient [%s\\%s]" host service))
591 (buf (get-buffer-create (concat "*" name "*")))
592 (service-name (concat "\\\\" host "\\" service)))
593 (set-buffer buf)
8fb051f9 594 (smbclient-mode)
8749abea
GM
595 (comint-exec buf name smbclient-program nil
596 (if smbclient-program-options
597 (append (list service-name) smbclient-program-options)
598 (list service-name)))
8fb051f9 599 (pop-to-buffer buf)))
8749abea
GM
600
601(defun smbclient-list-shares (host)
602 "List services on HOST."
ddb62bf1 603 (interactive
8749abea 604 (list
ddb62bf1 605 (read-from-minibuffer
c2e6c8d1 606 "Connect to Host: " (net-utils-machine-at-point))))
8749abea
GM
607 (let ((buf (get-buffer-create (format "*SMB Shares on %s*" host))))
608 (set-buffer buf)
8749abea 609 (smbclient-mode)
8fb051f9
MB
610 (comint-exec buf "smbclient-list-shares"
611 smbclient-program nil (list "-L" host))
612 (pop-to-buffer buf)))
ddb62bf1 613
8fb051f9 614(define-derived-mode smbclient-mode comint-mode "smbclient"
8749abea 615 "Major mode for interacting with the smbclient program."
8749abea 616 (setq comint-prompt-regexp smbclient-prompt-regexp)
8749abea 617 (setq comint-input-autoexpand t)
8fb051f9
MB
618 ;; Only add the password-prompting hook if it's not already in the
619 ;; global hook list. This stands a small chance of losing, if it's
620 ;; later removed from the global list (very small, since any
621 ;; password prompts will probably immediately follow the initial
622 ;; connection), but it's better than getting prompted twice for the
623 ;; same password.
624 (unless (memq 'comint-watch-for-password-prompt
625 (default-value 'comint-output-filter-functions))
626 (add-hook 'comint-output-filter-functions 'comint-watch-for-password-prompt
c2e6c8d1 627 nil t)))
8749abea 628
8749abea
GM
629
630;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
631;; Network Connections
632;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
633
634;; Full list is available at:
350ca08d 635;; http://www.iana.org/assignments/port-numbers
ddb62bf1 636(defvar network-connection-service-alist
8749abea
GM
637 (list
638 (cons 'echo 7)
639 (cons 'active-users 11)
640 (cons 'daytime 13)
641 (cons 'chargen 19)
642 (cons 'ftp 21)
643 (cons 'telnet 23)
644 (cons 'smtp 25)
645 (cons 'time 37)
646 (cons 'whois 43)
647 (cons 'gopher 70)
648 (cons 'finger 79)
649 (cons 'www 80)
650 (cons 'pop2 109)
651 (cons 'pop3 110)
652 (cons 'sun-rpc 111)
653 (cons 'nntp 119)
654 (cons 'ntp 123)
655 (cons 'netbios-name 137)
656 (cons 'netbios-data 139)
657 (cons 'irc 194)
658 (cons 'https 443)
c2e6c8d1 659 (cons 'rlogin 513))
8749abea 660 "Alist of services and associated TCP port numbers.
9d551c66
RS
661This list is not complete.")
662
20f28123
JB
663;; Workhorse routine
664(defun run-network-program (process-name host port &optional initial-string)
665 (let ((tcp-connection)
666 (buf))
667 (setq buf (get-buffer-create (concat "*" process-name "*")))
8749abea 668 (set-buffer buf)
ddb62bf1 669 (or
8749abea 670 (setq tcp-connection
20f28123
JB
671 (open-network-stream process-name buf host port))
672 (error "Could not open connection to %s" host))
8749abea
GM
673 (erase-buffer)
674 (set-marker (process-mark tcp-connection) (point-min))
675 (set-process-filter tcp-connection 'net-utils-remove-ctrl-m-filter)
20f28123 676 (and initial-string
ddb62bf1 677 (process-send-string tcp-connection
20f28123 678 (concat initial-string "\r\n")))
8749abea
GM
679 (display-buffer buf)))
680
681;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
682;; Simple protocols
683;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
684
086d5b87
GM
685(defcustom finger-X.500-host-regexps nil
686 "A list of regular expressions matching host names.
687If a host name passed to `finger' matches one of these regular
688expressions, it is assumed to be a host that doesn't accept
689queries of the form USER@HOST, and wants a query containing USER only."
690 :group 'net-utils
691 :type '(repeat regexp)
692 :version "21.1")
693
8749abea
GM
694;; Finger protocol
695;;;###autoload
696(defun finger (user host)
697 "Finger USER on HOST."
698 ;; One of those great interactive statements that's actually
699 ;; longer than the function call! The idea is that if the user
700 ;; uses a string like "pbreton@cs.umb.edu", we won't ask for the
701 ;; host name. If we don't see an "@", we'll prompt for the host.
702 (interactive
703 (let* ((answer (read-from-minibuffer "Finger User: "
704 (net-utils-url-at-point)))
705 (index (string-match (regexp-quote "@") answer)))
706 (if index
086d5b87
GM
707 (list (substring answer 0 index)
708 (substring answer (1+ index)))
709 (list answer
710 (read-from-minibuffer "At Host: "
711 (net-utils-machine-at-point))))))
712 (let* ((user-and-host (concat user "@" host))
713 (process-name (concat "Finger [" user-and-host "]"))
714 (regexps finger-X.500-host-regexps)
715 found)
ac8a1898
PB
716 (and regexps
717 (while (not (string-match (car regexps) host))
718 (setq regexps (cdr regexps)))
719 (when regexps
720 (setq user-and-host user)))
ddb62bf1
PB
721 (run-network-program
722 process-name
723 host
8749abea 724 (cdr (assoc 'finger network-connection-service-alist))
086d5b87 725 user-and-host)))
8749abea
GM
726
727(defcustom whois-server-name "rs.internic.net"
728 "Default host name for the whois service."
729 :group 'net-utils
c2e6c8d1 730 :type 'string)
8749abea
GM
731
732(defcustom whois-server-list
733 '(("whois.arin.net") ; Networks, ASN's, and related POC's (numbers)
734 ("rs.internic.net") ; domain related info
da888ddf 735 ("whois.publicinterestregistry.net")
8749abea
GM
736 ("whois.abuse.net")
737 ("whois.apnic.net")
738 ("nic.ddn.mil")
739 ("whois.nic.mil")
740 ("whois.nic.gov")
741 ("whois.ripe.net"))
742 "A list of whois servers that can be queried."
743 :group 'net-utils
744 :type '(repeat (list string)))
745
da888ddf
RF
746;; FIXME: modern whois clients include a much better tld <-> whois server
747;; list, Emacs should probably avoid specifying the server as the client
748;; will DTRT anyway... -rfr
8749abea
GM
749(defcustom whois-server-tld
750 '(("rs.internic.net" . "com")
da888ddf 751 ("whois.publicinterestregistry.net" . "org")
8749abea
GM
752 ("whois.ripe.net" . "be")
753 ("whois.ripe.net" . "de")
754 ("whois.ripe.net" . "dk")
755 ("whois.ripe.net" . "it")
756 ("whois.ripe.net" . "fi")
757 ("whois.ripe.net" . "fr")
758 ("whois.ripe.net" . "uk")
759 ("whois.apnic.net" . "au")
760 ("whois.apnic.net" . "ch")
761 ("whois.apnic.net" . "hk")
762 ("whois.apnic.net" . "jp")
763 ("whois.nic.gov" . "gov")
764 ("whois.nic.mil" . "mil"))
765 "Alist to map top level domains to whois servers."
766 :group 'net-utils
767 :type '(repeat (cons string string)))
768
769(defcustom whois-guess-server t
770 "If non-nil then whois will try to deduce the appropriate whois
771server from the query. If the query doesn't look like a domain or hostname
da888ddf 772then the server named by `whois-server-name' is used."
8749abea
GM
773 :group 'net-utils
774 :type 'boolean)
775
776(defun whois-get-tld (host)
777 "Return the top level domain of `host', or nil if it isn't a domain name."
778 (let ((i (1- (length host)))
779 (max-len (- (length host) 5)))
780 (while (not (or (= i max-len) (char-equal (aref host i) ?.)))
781 (setq i (1- i)))
782 (if (= i max-len)
783 nil
784 (substring host (1+ i)))))
785
786;; Whois protocol
787;;;###autoload
788(defun whois (arg search-string)
789 "Send SEARCH-STRING to server defined by the `whois-server-name' variable.
790If `whois-guess-server' is non-nil, then try to deduce the correct server
791from SEARCH-STRING. With argument, prompt for whois server."
792 (interactive "P\nsWhois: ")
793 (let* ((whois-apropos-host (if whois-guess-server
794 (rassoc (whois-get-tld search-string)
795 whois-server-tld)
796 nil))
797 (server-name (if whois-apropos-host
798 (car whois-apropos-host)
799 whois-server-name))
800 (host
801 (if arg
802 (completing-read "Whois server name: "
803 whois-server-list nil nil "whois.")
804 server-name)))
ddb62bf1 805 (run-network-program
8749abea
GM
806 "Whois"
807 host
808 (cdr (assoc 'whois network-connection-service-alist))
c2e6c8d1 809 search-string)))
8749abea
GM
810
811(defcustom whois-reverse-lookup-server "whois.arin.net"
812 "Server which provides inverse DNS mapping."
813 :group 'net-utils
c2e6c8d1 814 :type 'string)
8749abea
GM
815
816;;;###autoload
817(defun whois-reverse-lookup ()
818 (interactive)
819 (let ((whois-server-name whois-reverse-lookup-server))
820 (call-interactively 'whois)))
821
822;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
823;;; General Network connection
824;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
825
76540917 826;; Using a derived mode gives us keymaps, hooks, etc.
ddb62bf1 827(define-derived-mode
76540917 828 network-connection-mode comint-mode "Network-Connection"
c2e6c8d1 829 "Major mode for interacting with the network-connection program.")
76540917
PB
830
831(defun network-connection-mode-setup (host service)
96c01bd4
RS
832 (make-local-variable 'network-connection-host)
833 (setq network-connection-host host)
834 (make-local-variable 'network-connection-service)
ad21495f 835 (setq network-connection-service service))
76540917 836
8749abea
GM
837;;;###autoload
838(defun network-connection-to-service (host service)
839 "Open a network connection to SERVICE on HOST."
ddb62bf1 840 (interactive
8749abea
GM
841 (list
842 (read-from-minibuffer "Host: " (net-utils-machine-at-point))
ddb62bf1
PB
843 (completing-read "Service: "
844 (mapcar
845 (function
8749abea
GM
846 (lambda (elt)
847 (list (symbol-name (car elt)))))
848 network-connection-service-alist))))
ddb62bf1
PB
849 (network-connection
850 host
c2e6c8d1 851 (cdr (assoc (intern service) network-connection-service-alist))))
8749abea
GM
852
853;;;###autoload
854(defun network-connection (host port)
855 "Open a network connection to HOST on PORT."
856 (interactive "sHost: \nnPort: ")
857 (network-service-connection host (number-to-string port)))
858
859(defun network-service-connection (host service)
860 "Open a network connection to SERVICE on HOST."
c2e6c8d1
PJ
861 (let* ((process-name (concat "Network Connection [" host " " service "]"))
862 (portnum (string-to-number service))
863 (buf (get-buffer-create (concat "*" process-name "*"))))
8749abea 864 (or (zerop portnum) (setq service portnum))
ddb62bf1 865 (make-comint
8749abea
GM
866 process-name
867 (cons host service))
76540917
PB
868 (set-buffer buf)
869 (network-connection-mode)
870 (network-connection-mode-setup host service)
c2e6c8d1 871 (pop-to-buffer buf)))
8749abea 872
cbbe9a37
GM
873(defvar comint-input-ring)
874
ddb62bf1
PB
875(defun network-connection-reconnect ()
876 "Reconnect a network connection, preserving the old input ring."
877 (interactive)
878 (let ((proc (get-buffer-process (current-buffer)))
879 (old-comint-input-ring comint-input-ring)
880 (host network-connection-host)
c2e6c8d1 881 (service network-connection-service))
ddb62bf1
PB
882 (if (not (or (not proc)
883 (eq (process-status proc) 'closed)))
884 (message "Still connected")
885 (goto-char (point-max))
886 (insert (format "Reopening connection to %s\n" host))
887 (network-connection host
c2e6c8d1
PJ
888 (if (numberp service)
889 service
890 (cdr (assoc service network-connection-service-alist))))
ddb62bf1 891 (and old-comint-input-ring
c2e6c8d1 892 (setq comint-input-ring old-comint-input-ring)))))
ddb62bf1 893
8749abea
GM
894(provide 'net-utils)
895
896;;; net-utils.el ends here