newsticker: offer deletion of old groups file.
[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,
ae940284 4;; 2005, 2006, 2007, 2008, 2009 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
46f6fa95 102(defcustom ifconfig-program-options
c2e6c8d1
PJ
103 (list
104 (if (eq system-type 'windows-nt)
105 "/all" "-a"))
2f7dc12d 106 "Options for the ifconfig program."
8749abea 107 :group 'net-utils
c2e6c8d1 108 :type '(repeat string))
8749abea 109
e69ec721
GM
110(defcustom iwconfig-program "iwconfig"
111 "Program to print wireless network configuration information."
112 :group 'net-utils
beaa23bc
GM
113 :type 'string
114 :version "23.1")
e69ec721 115
cd6ef82d
GM
116(define-obsolete-variable-alias 'ipconfig-program-options
117 'ifconfig-program-options "22.2")
118
e69ec721 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
240(defconst 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
8749abea
GM
262;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
263;; Utility functions
264;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
265
266;; Simplified versions of some at-point functions from ffap.el.
267;; It's not worth loading all of ffap just for these.
268(defun net-utils-machine-at-point ()
269 (let ((pt (point)))
270 (buffer-substring-no-properties
271 (save-excursion
272 (skip-chars-backward "-a-zA-Z0-9.")
273 (point))
274 (save-excursion
275 (skip-chars-forward "-a-zA-Z0-9.")
276 (skip-chars-backward "." pt)
277 (point)))))
278
279(defun net-utils-url-at-point ()
280 (let ((pt (point)))
281 (buffer-substring-no-properties
282 (save-excursion
283 (skip-chars-backward "--:=&?$+@-Z_a-z~#,%")
284 (skip-chars-forward "^A-Za-z0-9" pt)
285 (point))
286 (save-excursion
287 (skip-chars-forward "--:=&?$+@-Z_a-z~#,%")
288 (skip-chars-backward ":;.,!?" pt)
289 (point)))))
290
291
292(defun net-utils-remove-ctrl-m-filter (process output-string)
293 "Remove trailing control Ms."
294 (let ((old-buffer (current-buffer))
295 (filtered-string output-string))
296 (unwind-protect
297 (let ((moving))
298 (set-buffer (process-buffer process))
299 (setq moving (= (point) (process-mark process)))
ddb62bf1 300
8749abea
GM
301 (while (string-match "\r" filtered-string)
302 (setq filtered-string
303 (replace-match "" nil nil filtered-string)))
304
305 (save-excursion
306 ;; Insert the text, moving the process-marker.
307 (goto-char (process-mark process))
308 (insert filtered-string)
309 (set-marker (process-mark process) (point)))
310 (if moving (goto-char (process-mark process))))
311 (set-buffer old-buffer))))
ddb62bf1 312
20f28123 313(defun net-utils-run-program (name header program args)
8749abea 314 "Run a network information program."
20f28123
JB
315 (let ((buf (get-buffer-create (concat "*" name "*"))))
316 (set-buffer buf)
317 (erase-buffer)
318 (insert header "\n")
319 (set-process-filter
320 (apply 'start-process name buf program args)
321 'net-utils-remove-ctrl-m-filter)
322 (display-buffer buf)
323 buf))
8749abea
GM
324
325;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
326;; Wrappers for external network programs
327;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
328
329;;;###autoload
330(defun traceroute (target)
331 "Run traceroute program for TARGET."
332 (interactive "sTarget: ")
ddb62bf1 333 (let ((options
8749abea
GM
334 (if traceroute-program-options
335 (append traceroute-program-options (list target))
336 (list target))))
337 (net-utils-run-program
338 (concat "Traceroute" " " target)
339 (concat "** Traceroute ** " traceroute-program " ** " target)
340 traceroute-program
c2e6c8d1 341 options)))
8749abea
GM
342
343;;;###autoload
344(defun ping (host)
345 "Ping HOST.
ddb62bf1 346If your system's ping continues until interrupted, you can try setting
8749abea 347`ping-program-options'."
ddb62bf1 348 (interactive
8749abea 349 (list (read-from-minibuffer "Ping host: " (net-utils-machine-at-point))))
ddb62bf1 350 (let ((options
8749abea
GM
351 (if ping-program-options
352 (append ping-program-options (list host))
353 (list host))))
354 (net-utils-run-program
355 (concat "Ping" " " host)
356 (concat "** Ping ** " ping-program " ** " host)
357 ping-program
c2e6c8d1 358 options)))
8749abea
GM
359
360;;;###autoload
46f6fa95
RS
361(defun ifconfig ()
362 "Run ifconfig program."
8749abea
GM
363 (interactive)
364 (net-utils-run-program
46f6fa95
RS
365 "Ifconfig"
366 (concat "** Ifconfig ** " ifconfig-program " ** ")
367 ifconfig-program
368 ifconfig-program-options))
8749abea 369
46f6fa95 370;; Windows uses this name.
8749abea 371;;;###autoload
46f6fa95 372(defalias 'ipconfig 'ifconfig)
8749abea 373
e69ec721
GM
374;;;###autoload
375(defun iwconfig ()
376 "Run iwconfig program."
377 (interactive)
378 (net-utils-run-program
379 "Iwconfig"
380 (concat "** Iwconfig ** " iwconfig-program " ** ")
381 iwconfig-program
382 iwconfig-program-options))
383
8749abea
GM
384;;;###autoload
385(defun netstat ()
386 "Run netstat program."
387 (interactive)
388 (net-utils-run-program
389 "Netstat"
390 (concat "** Netstat ** " netstat-program " ** ")
391 netstat-program
c2e6c8d1 392 netstat-program-options))
8749abea
GM
393
394;;;###autoload
395(defun arp ()
2f7dc12d 396 "Run arp program."
8749abea
GM
397 (interactive)
398 (net-utils-run-program
399 "Arp"
400 (concat "** Arp ** " arp-program " ** ")
401 arp-program
c2e6c8d1 402 arp-program-options))
8749abea
GM
403
404;;;###autoload
405(defun route ()
2f7dc12d 406 "Run route program."
8749abea
GM
407 (interactive)
408 (net-utils-run-program
409 "Route"
410 (concat "** Route ** " route-program " ** ")
411 route-program
c2e6c8d1 412 route-program-options))
8749abea
GM
413
414;; FIXME -- Needs to be a process filter
415;; (defun netstat-with-filter (filter)
416;; "Run netstat program."
417;; (interactive "sFilter: ")
418;; (netstat)
419;; (set-buffer (get-buffer "*Netstat*"))
420;; (goto-char (point-min))
c2e6c8d1 421;; (delete-matching-lines filter))
8749abea
GM
422
423;;;###autoload
424(defun nslookup-host (host)
425 "Lookup the DNS information for HOST."
426 (interactive
427 (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point))))
ddb62bf1 428 (let ((options
8749abea
GM
429 (if nslookup-program-options
430 (append nslookup-program-options (list host))
431 (list host))))
432 (net-utils-run-program
433 "Nslookup"
434 (concat "** "
435 (mapconcat 'identity
436 (list "Nslookup" host nslookup-program)
437 " ** "))
438 nslookup-program
c2e6c8d1 439 options)))
8749abea
GM
440
441;;;###autoload
442(defun nslookup ()
443 "Run nslookup program."
444 (interactive)
8749abea 445 (comint-run nslookup-program)
c2e6c8d1 446 (nslookup-mode))
8749abea 447
cbbe9a37
GM
448(defvar comint-prompt-regexp)
449(defvar comint-input-autoexpand)
450
451(autoload 'comint-mode "comint" nil t)
452
8749abea 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
cbbe9a37
GM
480 options)))
481
482(autoload 'ffap-string-at-point "ffap")
ac8a1898 483
8749abea 484;;;###autoload
5daebfbb 485(defun run-dig (host)
8749abea
GM
486 "Run dig program."
487 (interactive
488 (list
cbbe9a37
GM
489 (read-from-minibuffer "Lookup host: "
490 (or (ffap-string-at-point 'machine) ""))))
8749abea
GM
491 (net-utils-run-program
492 "Dig"
493 (concat "** "
494 (mapconcat 'identity
495 (list "Dig" host dig-program)
496 " ** "))
497 dig-program
c2e6c8d1 498 (list host)))
8749abea 499
cbbe9a37
GM
500(autoload 'comint-exec "comint")
501
8749abea
GM
502;; This is a lot less than ange-ftp, but much simpler.
503;;;###autoload
504(defun ftp (host)
505 "Run ftp program."
ddb62bf1 506 (interactive
8749abea 507 (list
ddb62bf1 508 (read-from-minibuffer
8749abea 509 "Ftp to Host: " (net-utils-machine-at-point))))
8749abea
GM
510 (let ((buf (get-buffer-create (concat "*ftp [" host "]*"))))
511 (set-buffer buf)
8fb051f9 512 (ftp-mode)
8749abea
GM
513 (comint-exec buf (concat "ftp-" host) ftp-program nil
514 (if ftp-program-options
515 (append (list host) ftp-program-options)
516 (list host)))
8fb051f9 517 (pop-to-buffer buf)))
8749abea 518
8fb051f9 519(define-derived-mode ftp-mode comint-mode "FTP"
8749abea 520 "Major mode for interacting with the ftp program."
8749abea 521 (setq comint-prompt-regexp ftp-prompt-regexp)
8749abea 522 (setq comint-input-autoexpand t)
8fb051f9
MB
523 ;; Only add the password-prompting hook if it's not already in the
524 ;; global hook list. This stands a small chance of losing, if it's
525 ;; later removed from the global list (very small, since any
526 ;; password prompts will probably immediately follow the initial
527 ;; connection), but it's better than getting prompted twice for the
528 ;; same password.
529 (unless (memq 'comint-watch-for-password-prompt
530 (default-value 'comint-output-filter-functions))
531 (add-hook 'comint-output-filter-functions 'comint-watch-for-password-prompt
c2e6c8d1 532 nil t)))
8749abea 533
8749abea
GM
534;; Occasionally useful
535(define-key ftp-mode-map "\t" 'comint-dynamic-complete)
536
537(defun smbclient (host service)
538 "Connect to SERVICE on HOST via SMB."
ddb62bf1 539 (interactive
8749abea 540 (list
ddb62bf1 541 (read-from-minibuffer
8749abea
GM
542 "Connect to Host: " (net-utils-machine-at-point))
543 (read-from-minibuffer "SMB Service: ")))
8749abea
GM
544 (let* ((name (format "smbclient [%s\\%s]" host service))
545 (buf (get-buffer-create (concat "*" name "*")))
546 (service-name (concat "\\\\" host "\\" service)))
547 (set-buffer buf)
8fb051f9 548 (smbclient-mode)
8749abea
GM
549 (comint-exec buf name smbclient-program nil
550 (if smbclient-program-options
551 (append (list service-name) smbclient-program-options)
552 (list service-name)))
8fb051f9 553 (pop-to-buffer buf)))
8749abea
GM
554
555(defun smbclient-list-shares (host)
556 "List services on HOST."
ddb62bf1 557 (interactive
8749abea 558 (list
ddb62bf1 559 (read-from-minibuffer
c2e6c8d1 560 "Connect to Host: " (net-utils-machine-at-point))))
8749abea
GM
561 (let ((buf (get-buffer-create (format "*SMB Shares on %s*" host))))
562 (set-buffer buf)
8749abea 563 (smbclient-mode)
8fb051f9
MB
564 (comint-exec buf "smbclient-list-shares"
565 smbclient-program nil (list "-L" host))
566 (pop-to-buffer buf)))
ddb62bf1 567
8fb051f9 568(define-derived-mode smbclient-mode comint-mode "smbclient"
8749abea 569 "Major mode for interacting with the smbclient program."
8749abea 570 (setq comint-prompt-regexp smbclient-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
584;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
585;; Network Connections
586;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
587
588;; Full list is available at:
350ca08d 589;; http://www.iana.org/assignments/port-numbers
ddb62bf1 590(defvar network-connection-service-alist
8749abea
GM
591 (list
592 (cons 'echo 7)
593 (cons 'active-users 11)
594 (cons 'daytime 13)
595 (cons 'chargen 19)
596 (cons 'ftp 21)
597 (cons 'telnet 23)
598 (cons 'smtp 25)
599 (cons 'time 37)
600 (cons 'whois 43)
601 (cons 'gopher 70)
602 (cons 'finger 79)
603 (cons 'www 80)
604 (cons 'pop2 109)
605 (cons 'pop3 110)
606 (cons 'sun-rpc 111)
607 (cons 'nntp 119)
608 (cons 'ntp 123)
609 (cons 'netbios-name 137)
610 (cons 'netbios-data 139)
611 (cons 'irc 194)
612 (cons 'https 443)
c2e6c8d1 613 (cons 'rlogin 513))
8749abea 614 "Alist of services and associated TCP port numbers.
9d551c66
RS
615This list is not complete.")
616
20f28123
JB
617;; Workhorse routine
618(defun run-network-program (process-name host port &optional initial-string)
619 (let ((tcp-connection)
620 (buf))
621 (setq buf (get-buffer-create (concat "*" process-name "*")))
8749abea 622 (set-buffer buf)
ddb62bf1 623 (or
8749abea 624 (setq tcp-connection
20f28123
JB
625 (open-network-stream process-name buf host port))
626 (error "Could not open connection to %s" host))
8749abea
GM
627 (erase-buffer)
628 (set-marker (process-mark tcp-connection) (point-min))
629 (set-process-filter tcp-connection 'net-utils-remove-ctrl-m-filter)
20f28123 630 (and initial-string
ddb62bf1 631 (process-send-string tcp-connection
20f28123 632 (concat initial-string "\r\n")))
8749abea
GM
633 (display-buffer buf)))
634
635;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
636;; Simple protocols
637;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
638
086d5b87
GM
639(defcustom finger-X.500-host-regexps nil
640 "A list of regular expressions matching host names.
641If a host name passed to `finger' matches one of these regular
642expressions, it is assumed to be a host that doesn't accept
643queries of the form USER@HOST, and wants a query containing USER only."
644 :group 'net-utils
645 :type '(repeat regexp)
646 :version "21.1")
647
8749abea
GM
648;; Finger protocol
649;;;###autoload
650(defun finger (user host)
651 "Finger USER on HOST."
652 ;; One of those great interactive statements that's actually
653 ;; longer than the function call! The idea is that if the user
654 ;; uses a string like "pbreton@cs.umb.edu", we won't ask for the
655 ;; host name. If we don't see an "@", we'll prompt for the host.
656 (interactive
657 (let* ((answer (read-from-minibuffer "Finger User: "
658 (net-utils-url-at-point)))
659 (index (string-match (regexp-quote "@") answer)))
660 (if index
086d5b87
GM
661 (list (substring answer 0 index)
662 (substring answer (1+ index)))
663 (list answer
664 (read-from-minibuffer "At Host: "
665 (net-utils-machine-at-point))))))
666 (let* ((user-and-host (concat user "@" host))
667 (process-name (concat "Finger [" user-and-host "]"))
668 (regexps finger-X.500-host-regexps)
669 found)
ac8a1898
PB
670 (and regexps
671 (while (not (string-match (car regexps) host))
672 (setq regexps (cdr regexps)))
673 (when regexps
674 (setq user-and-host user)))
ddb62bf1
PB
675 (run-network-program
676 process-name
677 host
8749abea 678 (cdr (assoc 'finger network-connection-service-alist))
086d5b87 679 user-and-host)))
8749abea
GM
680
681(defcustom whois-server-name "rs.internic.net"
682 "Default host name for the whois service."
683 :group 'net-utils
c2e6c8d1 684 :type 'string)
8749abea
GM
685
686(defcustom whois-server-list
687 '(("whois.arin.net") ; Networks, ASN's, and related POC's (numbers)
688 ("rs.internic.net") ; domain related info
da888ddf 689 ("whois.publicinterestregistry.net")
8749abea
GM
690 ("whois.abuse.net")
691 ("whois.apnic.net")
692 ("nic.ddn.mil")
693 ("whois.nic.mil")
694 ("whois.nic.gov")
695 ("whois.ripe.net"))
696 "A list of whois servers that can be queried."
697 :group 'net-utils
698 :type '(repeat (list string)))
699
da888ddf
RF
700;; FIXME: modern whois clients include a much better tld <-> whois server
701;; list, Emacs should probably avoid specifying the server as the client
702;; will DTRT anyway... -rfr
8749abea
GM
703(defcustom whois-server-tld
704 '(("rs.internic.net" . "com")
da888ddf 705 ("whois.publicinterestregistry.net" . "org")
8749abea
GM
706 ("whois.ripe.net" . "be")
707 ("whois.ripe.net" . "de")
708 ("whois.ripe.net" . "dk")
709 ("whois.ripe.net" . "it")
710 ("whois.ripe.net" . "fi")
711 ("whois.ripe.net" . "fr")
712 ("whois.ripe.net" . "uk")
713 ("whois.apnic.net" . "au")
714 ("whois.apnic.net" . "ch")
715 ("whois.apnic.net" . "hk")
716 ("whois.apnic.net" . "jp")
717 ("whois.nic.gov" . "gov")
718 ("whois.nic.mil" . "mil"))
719 "Alist to map top level domains to whois servers."
720 :group 'net-utils
721 :type '(repeat (cons string string)))
722
723(defcustom whois-guess-server t
724 "If non-nil then whois will try to deduce the appropriate whois
725server from the query. If the query doesn't look like a domain or hostname
da888ddf 726then the server named by `whois-server-name' is used."
8749abea
GM
727 :group 'net-utils
728 :type 'boolean)
729
730(defun whois-get-tld (host)
731 "Return the top level domain of `host', or nil if it isn't a domain name."
732 (let ((i (1- (length host)))
733 (max-len (- (length host) 5)))
734 (while (not (or (= i max-len) (char-equal (aref host i) ?.)))
735 (setq i (1- i)))
736 (if (= i max-len)
737 nil
738 (substring host (1+ i)))))
739
740;; Whois protocol
741;;;###autoload
742(defun whois (arg search-string)
743 "Send SEARCH-STRING to server defined by the `whois-server-name' variable.
744If `whois-guess-server' is non-nil, then try to deduce the correct server
745from SEARCH-STRING. With argument, prompt for whois server."
746 (interactive "P\nsWhois: ")
747 (let* ((whois-apropos-host (if whois-guess-server
748 (rassoc (whois-get-tld search-string)
749 whois-server-tld)
750 nil))
751 (server-name (if whois-apropos-host
752 (car whois-apropos-host)
753 whois-server-name))
754 (host
755 (if arg
756 (completing-read "Whois server name: "
757 whois-server-list nil nil "whois.")
758 server-name)))
ddb62bf1 759 (run-network-program
8749abea
GM
760 "Whois"
761 host
762 (cdr (assoc 'whois network-connection-service-alist))
c2e6c8d1 763 search-string)))
8749abea
GM
764
765(defcustom whois-reverse-lookup-server "whois.arin.net"
766 "Server which provides inverse DNS mapping."
767 :group 'net-utils
c2e6c8d1 768 :type 'string)
8749abea
GM
769
770;;;###autoload
771(defun whois-reverse-lookup ()
772 (interactive)
773 (let ((whois-server-name whois-reverse-lookup-server))
774 (call-interactively 'whois)))
775
776;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
777;;; General Network connection
778;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
779
76540917 780;; Using a derived mode gives us keymaps, hooks, etc.
ddb62bf1 781(define-derived-mode
76540917 782 network-connection-mode comint-mode "Network-Connection"
c2e6c8d1 783 "Major mode for interacting with the network-connection program.")
76540917
PB
784
785(defun network-connection-mode-setup (host service)
96c01bd4
RS
786 (make-local-variable 'network-connection-host)
787 (setq network-connection-host host)
788 (make-local-variable 'network-connection-service)
ad21495f 789 (setq network-connection-service service))
76540917 790
8749abea
GM
791;;;###autoload
792(defun network-connection-to-service (host service)
793 "Open a network connection to SERVICE on HOST."
ddb62bf1 794 (interactive
8749abea
GM
795 (list
796 (read-from-minibuffer "Host: " (net-utils-machine-at-point))
ddb62bf1
PB
797 (completing-read "Service: "
798 (mapcar
799 (function
8749abea
GM
800 (lambda (elt)
801 (list (symbol-name (car elt)))))
802 network-connection-service-alist))))
ddb62bf1
PB
803 (network-connection
804 host
c2e6c8d1 805 (cdr (assoc (intern service) network-connection-service-alist))))
8749abea
GM
806
807;;;###autoload
808(defun network-connection (host port)
809 "Open a network connection to HOST on PORT."
810 (interactive "sHost: \nnPort: ")
811 (network-service-connection host (number-to-string port)))
812
813(defun network-service-connection (host service)
814 "Open a network connection to SERVICE on HOST."
c2e6c8d1
PJ
815 (let* ((process-name (concat "Network Connection [" host " " service "]"))
816 (portnum (string-to-number service))
817 (buf (get-buffer-create (concat "*" process-name "*"))))
8749abea 818 (or (zerop portnum) (setq service portnum))
ddb62bf1 819 (make-comint
8749abea
GM
820 process-name
821 (cons host service))
76540917
PB
822 (set-buffer buf)
823 (network-connection-mode)
824 (network-connection-mode-setup host service)
c2e6c8d1 825 (pop-to-buffer buf)))
8749abea 826
cbbe9a37
GM
827(defvar comint-input-ring)
828
ddb62bf1
PB
829(defun network-connection-reconnect ()
830 "Reconnect a network connection, preserving the old input ring."
831 (interactive)
832 (let ((proc (get-buffer-process (current-buffer)))
833 (old-comint-input-ring comint-input-ring)
834 (host network-connection-host)
c2e6c8d1 835 (service network-connection-service))
ddb62bf1
PB
836 (if (not (or (not proc)
837 (eq (process-status proc) 'closed)))
838 (message "Still connected")
839 (goto-char (point-max))
840 (insert (format "Reopening connection to %s\n" host))
841 (network-connection host
c2e6c8d1
PJ
842 (if (numberp service)
843 service
844 (cdr (assoc service network-connection-service-alist))))
ddb62bf1 845 (and old-comint-input-ring
c2e6c8d1 846 (setq comint-input-ring old-comint-input-ring)))))
ddb62bf1 847
8749abea
GM
848(provide 'net-utils)
849
cbee283d 850;; arch-tag: 97119e91-9edb-4376-838b-bf7058fa1314
8749abea 851;;; net-utils.el ends here