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