Initial Commit
[packages] / xemacs-packages / net-utils / net-utils.el
1 ;;; net-utils.el --- Network functions
2
3 ;; Author:  Peter Breton <pbreton@cs.umb.edu>
4 ;; Created: Sun Mar 16 1997
5 ;; Version: $Id: net-utils.el,v 1.5 2007-03-06 14:02:59 viteno Exp $
6 ;; Keywords: 
7 ;; Time-stamp: <Monday Mar  5, 2007 14:14:13 steve>
8
9 ;;; Commentary:
10 ;;
11 ;; There are three main areas of functionality:
12 ;; 
13 ;; * Wrap common network utility programs (ping, traceroute, netstat,
14 ;; nslookup, arp, route). Note that these wrappers are of the diagnostic
15 ;; functions of these programs only.
16 ;; 
17 ;; * Implement some very basic protocols in Emacs Lisp (finger and whois)
18 ;; 
19 ;; * Support connections to HOST/PORT, generally for debugging and the like.
20 ;; In other words, for doing much the same thing as "telnet HOST PORT", and
21 ;; then typing commands.
22
23 ;;; Change log:
24 ;;
25 ;; Revision 1.1  1998/03/26 03:39:21  steveb
26 ;; New file net-utils.el.
27 ;;
28 ;; Revision 1.5  1998/03/11 00:27:18  pbreton
29 ;; Changed name to net-utils
30 ;; Added AUTOLOAD comments
31 ;; Added net-utils-version variable
32 ;; Don't use /usr/sbin/ping anymore, depend on ping-program-options
33 ;; ping-program-options default set for Linux
34 ;; Finger can now take USER@HOST as an argument
35 ;; network-service-connection is no longer interactive
36 ;;
37 ;; Revision 1.4  1998/03/06 03:57:03  pbreton
38 ;; Changed defvars to defcustoms
39 ;; Use /usr/sbin/ping (if it exists) instead of ping
40 ;; Fixed typo in traceroute-program
41 ;; Fontlock is no longer required
42 ;;
43 ;; Revision 1.2  1998/03/05 12:05:15  pbreton
44 ;; Posted to gnu.emacs.sources
45 ;;
46 ;; Revision 1.1  1998/03/05 11:31:28  pbreton
47 ;; Initial revision
48 ;;
49 ;;
50 ;; AUTOLOADS
51 ;;
52 ;; Put these in your .emacs, or just require the whole file. 
53 ;; 
54 ;; (autoload 'traceroute                    "net-utils" nil t)
55 ;; (autoload 'ping                          "net-utils" nil t)
56 ;; (autoload 'ipconfig                      "net-utils" nil t)
57 ;; (autoload 'arp                           "net-utils" nil t)
58 ;; (autoload 'route                         "net-utils" nil t)
59 ;; (autoload 'netstat                       "net-utils" nil t)
60 ;; (autoload 'nslookup                      "net-utils" nil t)
61 ;; (autoload 'nslookup-host                 "net-utils" nil t)
62 ;; (autoload 'finger                        "net-utils" nil t)
63 ;; (autoload 'whois                         "net-utils" nil t)
64 ;; (autoload 'network-connection            "net-utils" nil t)
65 ;; (autoload 'network-connection-to-service "net-utils" nil t)
66
67
68 ;;; Code:
69 (eval-when-compile
70   (require 'comint)
71   (require 'font-lock)
72   (autoload 'ffap-string-at-point "ffap"))
73
74 (defconst net-utils-version (substring "$Revision: 1.5 $" 11 -2)
75   "The version number of net-utils (as string).  The complete RCS id is:
76
77   $Id: net-utils.el,v 1.5 2007-03-06 14:02:59 viteno Exp $")
78
79 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
80 ;; Customization Variables
81 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
82
83 (defgroup net-utils nil
84   "Network utility functions."
85   :prefix "dirtrack-"
86   :group 'shell
87   )
88
89 (defcustom net-utils-remove-ctl-m 
90   (member system-type (list 'windows-nt 'msdos))
91   "If non-nil, remove control-Ms from output."
92   :group 'net-utils
93   :type  'boolean
94   )
95
96 (defcustom traceroute-program  
97   (if (eq system-type 'windows-nt) 
98       "tracert"
99     "traceroute")
100   "Program to trace network hops to a destination."
101   :group 'net-utils
102   :type  'string
103   )
104
105 (defcustom traceroute-program-options nil
106   "Options for the traceroute program."
107   :group 'net-utils
108   :type  '(repeat string)
109   )
110
111 (defcustom ping-program "ping"
112   "Program to send network test packets to a host."
113   :group 'net-utils
114   :type  'string
115   )
116
117 ;; On Linux and Irix, the system's ping program seems to send packets
118 ;; indefinitely unless told otherwise
119 (defcustom ping-program-options 
120   (and (memq system-type (list 'linux 'gnu/linux 'irix))
121        (list "-c" "4"))
122   "Options for the ping program.
123 These options can be used to limit how many ICMP packets are emitted."
124   :group 'net-utils
125   :type  '(repeat string)
126   )
127
128 (defcustom ipconfig-program  
129   (if (eq system-type 'windows-nt)
130       "ipconfig"
131     "ifconfig")
132   "Program to print network configuration information."
133   :group 'net-utils
134   :type  'string
135   )
136
137 (defcustom ipconfig-program-options
138    (list    
139     (if (eq system-type 'windows-nt)
140         "/all" "-a"))
141   "Options for ipconfig-program."
142   :group 'net-utils
143   :type  '(repeat string)
144   )
145
146 (defcustom netstat-program  "netstat"
147   "Program to print network statistics."
148   :group 'net-utils
149   :type  'string
150   )
151
152 (defcustom netstat-program-options nil
153   "Options for netstat-program."
154   :group 'net-utils
155   :type  '(repeat string)
156   )
157
158 (defcustom arp-program  "arp"
159   "Program to print IP to address translation tables."
160   :group 'net-utils
161   :type  'string
162   )
163
164 (defcustom arp-program-options 
165   (list "-a")
166   "Options for arp-program."
167   :group 'net-utils
168   :type  '(repeat string)
169   )
170
171 (defcustom route-program  
172   (if (eq system-type 'windows-nt)
173       "route"
174     "netstat")
175   "Program to print routing tables."
176   :group 'net-utils
177   :type  'string
178   )
179
180 (defcustom route-program-options 
181   (if (eq system-type 'windows-nt)
182       (list "print")
183     (list "-r"))
184   "Options for route-program."
185   :group 'net-utils
186   :type  '(repeat string)
187   )
188
189 (defcustom nslookup-program  "nslookup"
190   "Program to interactively query DNS information."
191   :group 'net-utils
192   :type  'string
193   )
194
195 (defcustom nslookup-program-options  nil
196   "List of options to pass to the nslookup program."
197   :group 'net-utils
198   :type  '(repeat string)
199   )
200
201 (defcustom nslookup-prompt-regexp "^> "
202   "Regexp to match the nslookup prompt."
203   :group 'net-utils
204   :type  'regexp
205   )
206
207 (defcustom ftp-program "ftp"
208   "Progam to run to do FTP transfers."
209   :group 'net-utils
210   :type  'string
211   )
212
213 (defcustom ftp-program-options nil
214   "List of options to pass to the FTP program."
215   :group 'net-utils
216   :type  '(repeat string)
217   )
218
219 (defcustom ftp-prompt-regexp "^ftp>"
220   "Regexp which matches the FTP program's prompt."
221   :group 'net-utils
222   :type  'regexp
223   )
224
225 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
226 ;; Nslookup goodies
227 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
228
229 (defconst nslookup-font-lock-keywords
230   (and window-system
231        (progn
232          (require 'font-lock)
233          (list
234           (list nslookup-prompt-regexp 0 font-lock-reference-face)
235           (list "^[A-Za-z0-9 _]+:"     0 font-lock-type-face)
236           (list "\\<\\(SOA\\|NS\\|MX\\|A\\|CNAME\\)\\>" 
237                 1 font-lock-keyword-face)
238           ;; Dotted quads
239           (list 
240            (mapconcat 'identity
241                       (make-list 4 "[0-9]+")
242                       "\\.")
243            0 font-lock-variable-name-face)
244           ;; Host names
245           (list 
246            (let ((host-expression "[-A-Za-z0-9]+"))
247              (concat 
248               (mapconcat 'identity
249                          (make-list 2 host-expression)
250                          "\\.")
251               "\\(\\." host-expression "\\)*")
252              )
253            0 font-lock-variable-name-face)
254           )))
255          "Expressions to font-lock for nslookup.")
256
257 (defvar nslookup-abbrev-table (make-abbrev-table)
258   "Abbrev table for nslookup.")
259
260 (define-abbrev nslookup-abbrev-table "e"   "exit")
261 (define-abbrev nslookup-abbrev-table "f"   "finger")
262 (define-abbrev nslookup-abbrev-table "h"   "help")
263 (define-abbrev nslookup-abbrev-table "lse" "lserver")
264 (define-abbrev nslookup-abbrev-table "r"   "root")
265 (define-abbrev nslookup-abbrev-table "s"   "set")
266 (define-abbrev nslookup-abbrev-table "se"  "server")
267 (define-abbrev nslookup-abbrev-table "v"   "viewer")
268
269 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
270 ;; FTP goodies
271 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
272
273 (defvar ftp-abbrev-table (make-abbrev-table)
274   "Abbrev table for ftp.")
275
276 (define-abbrev ftp-abbrev-table "q"    "quit")
277 (define-abbrev ftp-abbrev-table "g"    "get")
278 (define-abbrev ftp-abbrev-table "p"    "prompt")
279 (define-abbrev ftp-abbrev-table "anon" "anonymous")
280
281 (defconst ftp-font-lock-keywords
282   (and window-system
283        (progn
284          (require 'font-lock)
285          (list
286           (list ftp-prompt-regexp 0 font-lock-reference-face)))))
287
288
289 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
290 ;; Utility functions
291 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
292
293 (defun net-utils-remove-ctrl-m-filter (process output-string)
294   "Remove trailing control Ms."
295   (let ((old-buffer (current-buffer))
296         (filtered-string output-string))
297     (unwind-protect
298         (let ((moving))
299           (set-buffer (process-buffer process))
300           (setq moving (= (point) (process-mark process)))
301           
302           (while (string-match "\r" filtered-string)
303                (setq filtered-string
304                      (replace-match "" nil nil filtered-string)))
305
306           (save-excursion
307             ;; Insert the text, moving the process-marker.
308             (goto-char (process-mark process))
309             (insert filtered-string)
310             (set-marker (process-mark process) (point)))
311           (if moving (goto-char (process-mark process))))
312       (set-buffer old-buffer))))
313   
314 (defmacro net-utils-run-program (name header program &rest args)
315   "Run a network information program."
316   (` 
317    (let ((buf (get-buffer-create (concat "*" (, name) "*"))))
318      (set-buffer buf)
319      (erase-buffer)
320      (insert (, header) "\n")
321      (set-process-filter 
322       (apply 'start-process (, name) buf (, program) (,@ args))
323       'net-utils-remove-ctrl-m-filter)
324      (display-buffer buf))))
325
326 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
327 ;; Wrappers for external network programs
328 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
329 ;;;###autoload
330 (defun traceroute (target)
331   "Run traceroute program for TARGET."
332   (interactive "sTarget: ")
333   (let ((options 
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
341      options
342      )))
343
344 ;;;###autoload
345 (defun ping (host)
346   "Ping HOST.
347 If your system's ping continues until interrupted, you can try setting 
348 `ping-program-options'."
349   (interactive 
350    (list
351     (progn
352       (require 'ffap)
353       (read-from-minibuffer 
354        "Ping host: " 
355        (or (ffap-string-at-point 'machine) "")))))
356   (let ((options 
357          (if ping-program-options
358              (append ping-program-options (list host))
359            (list host))))
360     (net-utils-run-program
361      (concat "Ping" " " host)
362      (concat "** Ping ** " ping-program " ** " host)
363      ping-program
364      options
365      )))
366
367 ;;;###autoload
368 (defun ipconfig ()
369   "Run ipconfig program."
370   (interactive)
371   (net-utils-run-program
372    "Ipconfig"
373    (concat "** Ipconfig ** " ipconfig-program " ** ")
374    ipconfig-program
375    ipconfig-program-options
376    ))
377
378 ;; This is the normal name on most Unixes.
379 ;;;###autoload
380 (defalias 'ifconfig 'ipconfig) 
381
382 ;;;###autoload
383 (defun netstat ()
384   "Run netstat program."
385   (interactive)
386   (net-utils-run-program
387    "Netstat"
388    (concat "** Netstat ** " netstat-program " ** ")
389    netstat-program
390    netstat-program-options
391    ))
392
393 ;;;###autoload
394 (defun arp ()
395   "Run the arp program."
396   (interactive)
397   (net-utils-run-program
398    "Arp"
399    (concat "** Arp ** " arp-program " ** ")
400    arp-program
401    arp-program-options
402    ))
403
404 ;;;###autoload
405 (defun route ()
406   "Run the route program."
407   (interactive)
408   (net-utils-run-program
409    "Route"
410    (concat "** Route ** " route-program " ** ")
411    route-program
412    route-program-options
413    ))
414
415 ;; FIXME -- Needs to be a process filter
416 ;; (defun netstat-with-filter (filter)
417 ;;   "Run netstat program."
418 ;;   (interactive "sFilter: ")
419 ;;   (netstat)
420 ;;   (set-buffer (get-buffer "*Netstat*"))
421 ;;   (goto-char (point-min))
422 ;;   (delete-matching-lines filter)
423 ;;   )
424
425 ;;;###autoload
426 (defun nslookup-host (host)
427   "Lookup the DNS information for HOST."
428   (interactive
429    (list
430     (read-from-minibuffer 
431      "Lookup host: " 
432      (or (ffap-string-at-point 'machine) ""))))
433   (let ((options 
434          (if nslookup-program-options
435              (append nslookup-program-options (list host))
436            (list host))))
437     (net-utils-run-program
438      "Nslookup"
439      (concat "** "
440       (mapconcat 'identity
441                 (list "Nslookup" host nslookup-program)
442                 " ** "))
443      nslookup-program
444      options
445      )))
446
447 ;;;###autoload
448 (defun nslookup ()
449   "Run nslookup program."
450   (interactive)
451   (comint-run nslookup-program)
452   (set-process-filter (get-buffer-process "*nslookup*")
453    'net-utils-remove-ctrl-m-filter)
454   (set 
455    (make-local-variable 'font-lock-defaults)
456    '((nslookup-font-lock-keywords)))
457   (set 
458    (make-local-variable 'local-abbrev-table)
459    nslookup-abbrev-table)
460   (abbrev-mode t)
461   (make-local-variable 'comint-prompt-regexp)
462   (setq comint-prompt-regexp nslookup-prompt-regexp)
463   )
464
465 ;; This is a lot less than ange-ftp, but much simpler.
466 ;;;###autoload
467 (defun ftp (host)
468   "Run ftp program."
469   (interactive "sFtp to Host: ")
470   (let ((buf (get-buffer-create (concat "*ftp [" host "]*"))))
471     (set-buffer buf)
472     (comint-mode)
473     (comint-exec buf (concat "ftp-" host) ftp-program nil
474                  (if ftp-program-options
475                      (append (list host) ftp-program-options)
476                    (list host)))
477     (set 
478      (make-local-variable 'font-lock-defaults)
479      '((ftp-font-lock-keywords)))
480
481     (make-local-variable 'comint-prompt-regexp)
482     (setq comint-prompt-regexp ftp-prompt-regexp)
483
484     ;; Already buffer local!
485     (setq comint-output-filter-functions
486           (list 'comint-watch-for-password-prompt))
487     (set 
488      (make-local-variable 'local-abbrev-table)
489      ftp-abbrev-table)
490     (abbrev-mode t)
491     (switch-to-buffer-other-window buf)
492     ))
493
494 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
495 ;; Network Connections
496 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
497
498 ;; Full list is available at:
499 ;; ftp://ftp.isi.edu/in-notes/iana/assignments/port-numbers
500 (defvar network-connection-service-alist 
501   (list
502     (cons 'echo          7)
503     (cons 'active-users 11)
504     (cons 'daytime      13)
505     (cons 'chargen      19)
506     (cons 'ftp          21)
507     (cons 'telnet       23)
508     (cons 'smtp         25)
509     (cons 'time         37)
510     (cons 'whois        43)
511     (cons 'gopher       70)
512     (cons 'finger       79)
513     (cons 'www          80)
514     (cons 'pop2         109)
515     (cons 'pop3         110)
516     (cons 'sun-rpc      111)
517     (cons 'nntp         119)
518     (cons 'ntp          123)
519     (cons 'netbios-name 137)
520     (cons 'netbios-data 139)
521     (cons 'irc          194)
522     (cons 'https        443)
523     (cons 'rlogin       513)
524     )
525   "Alist of services and associated TCP port numbers.
526 This list in not complete.")
527
528 ;; Workhorse macro
529 (defmacro run-network-program (process-name host port 
530                                             &optional initial-string)
531   (`
532    (let ((tcp-connection)
533          (buf)
534          )
535     (setq buf (get-buffer-create (concat "*" (, process-name) "*")))
536     (set-buffer buf)
537     (or 
538      (setq tcp-connection
539            (open-network-stream 
540             (, process-name)
541             buf
542             (, host)
543             (, port)
544             ))
545      (error "Could not open connection to %s" (, host)))
546     (erase-buffer)
547     (set-marker (process-mark tcp-connection) (point-min))
548     (set-process-filter tcp-connection 'net-utils-remove-ctrl-m-filter)
549     (and (, initial-string)
550          (process-send-string tcp-connection 
551                               (concat (, initial-string) "\r\n")))
552     (display-buffer buf))))
553
554 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
555 ;; Simple protocols
556 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
557
558 ;; Finger protocol
559 ;;;###autoload
560 (defun finger (user host)
561   "Finger USER on HOST."
562   ;; One of those great interactive statements that's actually
563   ;; longer than the function call! The idea is that if the user
564   ;; uses a string like "pbreton@cs.umb.edu", we won't ask for the
565   ;; host name. If we don't see an "@", we'll prompt for the host.
566   (interactive
567     (progn
568       (require 'ffap)
569       (let* ((answer (read-from-minibuffer "Finger User: " 
570                                            (ffap-string-at-point 'url))) 
571              (index  (string-match (regexp-quote "@") answer))
572              )
573         (if index
574             (list 
575              (substring answer 0 index)
576              (substring answer (1+ index)))
577           (list
578            answer
579            (read-from-minibuffer 
580             "At Host: " 
581             (or (ffap-string-at-point 'machine) "")))))))
582   (let* (
583          (user-and-host (concat user "@" host))
584          (process-name 
585           (concat "Finger [" user-and-host "]"))
586          )
587     (run-network-program 
588      process-name 
589      host 
590      (cdr (assoc 'finger network-connection-service-alist))
591      user-and-host
592      )))
593
594 (defcustom whois-server-name "whois.internic.net"
595   "Host name for the whois service."
596   :group 'net-utils
597   :type  'string
598   )
599
600 ;; Whois protocol
601 ;;;###autoload
602 (defun whois (arg search-string)
603   "Send SEARCH-STRING to server defined by the `whois-server-name' variable.
604 With argument, prompt for whois server."
605   (interactive "P\nsWhois: ")
606   (let ((host 
607          (if arg
608              (read-from-minibuffer "Whois server name: ")
609            whois-server-name))
610         )
611     (run-network-program 
612      "Whois"
613      host
614      (cdr (assoc 'whois network-connection-service-alist))
615      search-string
616      )))
617
618 (defcustom whois-reverse-lookup-server "whois.arin.net"
619   "Server which provides inverse DNS mapping."
620   :group 'net-utils
621   :type  'string
622   )
623
624 ;;;###autoload
625 (defun whois-reverse-lookup ()
626   (interactive)
627   (let ((whois-server-name whois-reverse-lookup-server))
628     (call-interactively 'whois)))
629
630 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
631 ;;; General Network connection
632 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
633
634 ;;;###autoload
635 (defun network-connection-to-service (host service)
636   "Open a network connection to SERVICE on HOST."
637   (interactive 
638    (list
639     (progn
640       (require 'ffap)
641       (read-from-minibuffer "Host: " 
642                             (ffap-string-at-point 'machine)))
643     (completing-read "Service: " 
644                      (mapcar 
645                       (function 
646                        (lambda (elt)
647                          (list (symbol-name (car elt)))))
648                       network-connection-service-alist))))
649   (network-connection 
650    host 
651    (cdr (assoc (intern service) network-connection-service-alist)))
652   )
653
654 ;;;###autoload
655 (defun network-connection (host port)
656   "Open a network connection to HOST on PORT."
657   (interactive "sHost: \nnPort: ")
658   (network-service-connection host (number-to-string port)))
659
660 (defun network-service-connection (host service)
661   "Open a network connection to SERVICE on HOST."
662   (let (
663         (process-name (concat "Network Connection [" host " " service "]"))
664         (portnum (string-to-number service))
665         )
666     (or (zerop portnum) (setq service portnum))
667     (make-comint 
668      process-name
669      (cons host service))
670     (pop-to-buffer (get-buffer (concat "*" process-name "*")))
671     ))
672
673 (provide 'net-utils)
674
675 ;;; net-utils.el ends here