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