Mercurial > hg > xemacs-beta
annotate lib-src/gnuserv.c @ 5353:38e24b8be4ea
Improve the lexical scoping in #'block, #'return-from.
lisp/ChangeLog addition:
2011-02-07 Aidan Kehoe <kehoea@parhasard.net>
* bytecomp.el:
* bytecomp.el (byte-compile-initial-macro-environment):
Shadow `block', `return-from' here, we implement them differently
when byte-compiling.
* bytecomp.el (byte-compile-active-blocks): New.
* bytecomp.el (byte-compile-block-1): New.
* bytecomp.el (byte-compile-return-from-1): New.
* bytecomp.el (return-from-1): New.
* bytecomp.el (block-1): New.
These are two aliases that exist to have their own associated
byte-compile functions, which functions implement `block' and
`return-from'.
* cl-extra.el (cl-macroexpand-all):
Fix a bug here when macros in the environment have been compiled.
* cl-macs.el (block):
* cl-macs.el (return):
* cl-macs.el (return-from):
Be more careful about lexical scope in these macros.
* cl.el:
* cl.el ('cl-block-wrapper): Removed.
* cl.el ('cl-block-throw): Removed.
These aren't needed in code generated by this XEmacs. They
shouldn't be needed in code generated by XEmacs 21.4, but if it
turns out the packages do need them, we can put them back.
2011-01-30 Mike Sperber <mike@xemacs.org>
* font-lock.el (font-lock-fontify-pending-extents): Don't fail if
`font-lock-mode' is unset, which can happen in the middle of
`revert-buffer'.
2011-01-23 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (delete):
* cl-macs.el (delq):
* cl-macs.el (remove):
* cl-macs.el (remq):
Don't use the compiler macro if these functions were given the
wrong number of arguments, as happens in lisp-tests.el.
* cl-seq.el (remove, remq): Removed.
I added these to subr.el, and forgot to remove them from here.
2011-01-22 Aidan Kehoe <kehoea@parhasard.net>
* bytecomp.el (byte-compile-setq, byte-compile-set):
Remove kludge allowing keywords' values to be set, all the code
that does that is gone.
* cl-compat.el (elt-satisfies-test-p):
* faces.el (set-face-parent):
* faces.el (face-doc-string):
* gtk-font-menu.el:
* gtk-font-menu.el (gtk-reset-device-font-menus):
* msw-font-menu.el:
* msw-font-menu.el (mswindows-reset-device-font-menus):
* package-get.el (package-get-installedp):
* select.el (select-convert-from-image-data):
* sound.el:
* sound.el (load-sound-file):
* x-font-menu.el (x-reset-device-font-menus-core):
Don't quote keywords, they're self-quoting, and the
win from backward-compatibility is sufficiently small now that the
style problem overrides it.
2011-01-22 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (block, return-from): Require that NAME be a symbol
in these macros, as always documented in the #'block docstring and
as required by Common Lisp.
* descr-text.el (unidata-initialize-unihan-database):
Correct the use of non-symbols in #'block and #'return-from in
this function.
2011-01-15 Aidan Kehoe <kehoea@parhasard.net>
* cl-extra.el (concatenate): Accept more complicated TYPEs in this
function, handing the sequences over to #'coerce if we don't
understand them here.
* cl-macs.el (inline): Don't proclaim #'concatenate as inline, its
compiler macro is more useful than doing that.
2011-01-11 Aidan Kehoe <kehoea@parhasard.net>
* subr.el (delete, delq, remove, remq): Move #'remove, #'remq
here, they don't belong in cl-seq.el; move #'delete, #'delq here
from fns.c, implement them in terms of #'delete*, allowing support
for sequences generally.
* update-elc.el (do-autoload-commands): Use #'delete*, not #'delq
here, now the latter's no longer dumped.
* cl-macs.el (delete, delq): Add compiler macros transforming
#'delete and #'delq to #'delete* calls.
2011-01-10 Aidan Kehoe <kehoea@parhasard.net>
* dialog.el (make-dialog-box): Correct a misplaced parenthesis
here, thank you Mats Lidell in 87zkr9gqrh.fsf@mail.contactor.se !
2011-01-02 Aidan Kehoe <kehoea@parhasard.net>
* dialog.el (make-dialog-box):
* list-mode.el (display-completion-list):
These functions used to use cl-parsing-keywords; change them to
use defun* instead, fixing the build. (Not sure what led to me
not including this change in d1b17a33450b!)
2011-01-02 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (define-star-compiler-macros):
Make sure the form has ITEM and LIST specified before attempting
to change to calls with explicit tests; necessary for some tests
in lisp-tests.el to compile correctly.
(stable-union, stable-intersection): Add compiler macros for these
functions, in the same way we do for most of the other functions
in cl-seq.el.
2011-01-01 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (dolist, dotimes, do-symbols, macrolet)
(symbol-macrolet):
Define these macros with defmacro* instead of parsing the argument
list by hand, for the sake of style and readability; use backquote
where appropriate, instead of calling #'list and and friends, for
the same reason.
2010-12-30 Aidan Kehoe <kehoea@parhasard.net>
* x-misc.el (device-x-display):
Provide this function, documented in the Lispref for years, but
not existing previously. Thank you Julian Bradfield, thank you
Jeff Mincy.
2010-12-30 Aidan Kehoe <kehoea@parhasard.net>
* cl-seq.el:
Move the heavy lifting from this file to C. Dump the
cl-parsing-keywords macro, but don't use defun* for the functions
we define that do take keywords, dynamic scope lossage makes that
not practical.
* subr.el (sort, fillarray): Move these aliases here.
(map-plist): #'nsublis is now built-in, but at this point #'eql
isn't necessarily available as a test; use #'eq.
* obsolete.el (cl-delete-duplicates): Make this available for old
compiler macros and old code.
(memql): Document that this is equivalent to #'member*, and worse.
* cl.el (adjoin, subst): Removed. These are in C.
2010-12-30 Aidan Kehoe <kehoea@parhasard.net>
* simple.el (assoc-ignore-case): Remove a duplicate definition of
this function (it's already in subr.el).
* iso8859-1.el (char-width):
On non-Mule, make this function equivalent to that produced by
(constantly 1), but preserve its docstring.
* subr.el (subst-char-in-string): Define this in terms of
#'substitute, #'nsubstitute.
(string-width): Define this using #'reduce and #'char-width.
(char-width): Give this a simpler definition, it makes far more
sense to check for mule at load time and redefine, as we do in
iso8859-1.el.
(store-substring): Implement this in terms of #'replace, now
#'replace is cheap.
2010-12-30 Aidan Kehoe <kehoea@parhasard.net>
* update-elc.el (lisp-files-needed-for-byte-compilation)
(lisp-files-needing-early-byte-compilation):
cl-macs belongs in the former, not the latter, it is as
fundamental as bytecomp.el.
2010-12-30 Aidan Kehoe <kehoea@parhasard.net>
* cl.el:
Provde the Common Lisp program-error, type-error as error
symbols. This doesn't nearly go far enough for anyone using the
Common Lisp errors.
2010-12-29 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (delete-duplicates):
If the form has an incorrect number of arguments, don't attempt a
compiler macroexpansion.
2010-12-29 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (cl-safe-expr-p):
Forms that start with the symbol lambda are also safe.
2010-12-29 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (= < > <= >=):
For these functions' compiler macros, the optimisation is safe
even if the first and the last arguments have side effects, since
they're only used the once.
2010-12-29 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (inline-side-effect-free-compiler-macros):
Unroll a loop here at macro-expansion time, so these compiler
macros are compiled. Use #'eql instead of #'eq in a couple of
places for better style.
2010-12-29 Aidan Kehoe <kehoea@parhasard.net>
* cl-extra.el (notany, notevery): Avoid some dynamic scope
stupidity with local variable names in these functions, when they
weren't prefixed with cl-; go into some more detail in the doc
strings.
2010-12-29 Aidan Kehoe <kehoea@parhasard.net>
* byte-optimize.el (side-effect-free-fns): #'remove, #'remq are
free of side-effects.
(side-effect-and-error-free-fns):
Drop dot, dot-marker from the list.
2010-11-17 Aidan Kehoe <kehoea@parhasard.net>
* cl-extra.el (coerce):
In the argument list, name the first argument OBJECT, not X; the
former name was always used in the doc string and is clearer.
Handle vector type specifications which include the length of the
target sequence, error if there's a mismatch.
* cl-macs.el (cl-make-type-test): Handle type specifications
starting with the symbol 'eql.
2010-11-14 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (eql): Don't remove the byte-compile property of this
symbol. That was necessary to override a bug in bytecomp.el where
#'eql was confused with #'eq, which bug we no longer have.
If neither expression is constant, don't attempt to handle the
expression in this compiler macro, leave it to byte-compile-eql,
which produces better code anyway.
* bytecomp.el (eq): #'eql is not the function associated with the
byte-eq byte code.
(byte-compile-eql): Add an explicit compile method for this
function, for cases where the cl-macs compiler macro hasn't
reduced it to #'eq or #'equal.
2010-10-25 Aidan Kehoe <kehoea@parhasard.net>
Add compiler macros and compilation sanity-checking for various
functions that take keywords.
* byte-optimize.el (side-effect-free-fns): #'symbol-value is
side-effect free and not error free.
* bytecomp.el (byte-compile-normal-call): Check keyword argument
lists for sanity; store information about the positions where
keyword arguments start using the new byte-compile-keyword-start
property.
* cl-macs.el (cl-const-expr-val): Take a new optional argument,
cl-not-constant, defaulting to nil, in this function; return it if
the expression is not constant.
(cl-non-fixnum-number-p): Make this into a separate function, we
want to pass it to #'every.
(eql): Use it.
(define-star-compiler-macros): Use the same code to generate the
member*, assoc* and rassoc* compiler macros; special-case some
code in #'add-to-list in subr.el.
(remove, remq): Add compiler macros for these two functions, in
preparation for #'remove being in C.
(define-foo-if-compiler-macros): Transform (remove-if-not ...) calls to
(remove ... :if-not) at compile time, which will be a real win
once the latter is in C.
(define-substitute-if-compiler-macros)
(define-subst-if-compiler-macros): Similarly for these functions.
(delete-duplicates): Change this compiler macro to use
#'plists-equal; if we don't have information about the type of
SEQUENCE at compile time, don't bother attempting to inline the
call, the function will be in C soon enough.
(equalp): Remove an old commented-out compiler macro for this, if
we want to see it it's in version control.
(subst-char-in-string): Transform this to a call to nsubstitute or
nsubstitute, if that is appropriate.
* cl.el (ldiff): Don't call setf here, this makes for a load-time
dependency problem in cl-macs.el
2010-06-14 Stephen J. Turnbull <stephen@xemacs.org>
* term/vt100.el:
Refer to XEmacs, not GNU Emacs, in permissions.
* term/bg-mouse.el:
* term/sup-mouse.el:
Put copyright notice in canonical "Copyright DATE AUTHOR" form.
Refer to XEmacs, not GNU Emacs, in permissions.
* site-load.el:
Add permission boilerplate.
* mule/canna-leim.el:
* alist.el:
Refer to XEmacs, not APEL/this program, in permissions.
* mule/canna-leim.el:
Remove my copyright, I've assigned it to the FSF.
2010-06-14 Stephen J. Turnbull <stephen@xemacs.org>
* gtk.el:
* gtk-widget-accessors.el:
* gtk-package.el:
* gtk-marshal.el:
* gtk-compose.el:
* gnome.el:
Add copyright notice based on internal evidence.
2010-06-14 Stephen J. Turnbull <stephen@xemacs.org>
* easymenu.el: Add reference to COPYING to permission notice.
* gutter.el:
* gutter-items.el:
* menubar-items.el:
Fix typo "Xmacs" in permissions notice.
2010-06-14 Stephen J. Turnbull <stephen@xemacs.org>
* auto-save.el:
* font.el:
* fontconfig.el:
* mule/kinsoku.el:
Add "part of XEmacs" text to permission notice.
2010-10-14 Aidan Kehoe <kehoea@parhasard.net>
* byte-optimize.el (side-effect-free-fns):
* cl-macs.el (remf, getf):
* cl-extra.el (tailp, cl-set-getf, cl-do-remf):
* cl.el (ldiff, endp):
Tighten up Common Lisp compatibility for #'ldiff, #'endp, #'tailp;
add circularity checking for the first two.
#'cl-set-getf and #'cl-do-remf were Lisp implementations of
#'plist-put and #'plist-remprop; change the names to aliases,
changes the macros that use them to using #'plist-put and
#'plist-remprop directly.
2010-10-12 Aidan Kehoe <kehoea@parhasard.net>
* abbrev.el (fundamental-mode-abbrev-table, global-abbrev-table):
Create both these abbrev tables using the usual
#'define-abbrev-table calls, rather than attempting to
special-case them.
* cl-extra.el: Force cl-macs to be loaded here, if cl-extra.el is
being loaded interpreted. Previously other, later files would
redundantly call (load "cl-macs") when interpreted, it's more
reasonable to do it here, once.
* cmdloop.el (read-quoted-char-radix): Use defcustom here, we
don't have any dump-order dependencies that would prevent that.
* custom.el (eval-when-compile): Don't load cl-macs when
interpreted or when byte-compiling, rely on cl-extra.el in the
former case and the appropriate entry in bytecomp-load-hook in the
latter. Get rid of custom-declare-variable-list, we have no
dump-time dependencies that would require it.
* faces.el (eval-when-compile): Don't load cl-macs when
interpreted or when byte-compiling.
* packages.el: Remove some inaccurate comments.
* post-gc.el (cleanup-simple-finalizers): Use #'delete-if-not
here, now the order of preloaded-file-list has been changed to
make it available.
* subr.el (custom-declare-variable-list): Remove. No need for it.
Also remove a stub define-abbrev-table from this file, given the
current order of preloaded-file-list there's no need for it.
2010-10-10 Aidan Kehoe <kehoea@parhasard.net>
* bytecomp.el (byte-compile-constp) Forms quoted with FUNCTION are
also constant.
(byte-compile-initial-macro-environment): In #'the, if FORM is
constant and does not match TYPE, warn at byte-compile time.
2010-10-10 Aidan Kehoe <kehoea@parhasard.net>
* backquote.el (bq-vector-contents, bq-list*): Remove; the former
is equivalent to (append VECTOR nil), the latter to (list* ...).
(bq-process-2): Use (append VECTOR nil) instead of using
#'bq-vector-contents to convert to a list.
(bq-process-1): Now we use list* instead of bq-list
* subr.el (list*): Moved from cl.el, since it is now required to
be available the first time a backquoted form is encountered.
* cl.el (list*): Move to subr.el.
2010-09-16 Aidan Kehoe <kehoea@parhasard.net>
* test-harness.el (Check-Message):
Add an omitted comma here, thank you the buildbot.
2010-09-16 Aidan Kehoe <kehoea@parhasard.net>
* hash-table.el (hash-table-key-list, hash-table-value-list)
(hash-table-key-value-alist, hash-table-key-value-plist):
Remove some useless #'nreverse calls in these files; our hash
tables have no order, it's not helpful to pretend they do.
* behavior.el (read-behavior):
Do the same in this file, in some code evidently copied from
hash-table.el.
2010-09-16 Aidan Kehoe <kehoea@parhasard.net>
* info.el (Info-insert-dir):
* format.el (format-deannotate-region):
* files.el (cd, save-buffers-kill-emacs):
Use #'some, #'every and related functions for applying boolean
operations to lists, instead of rolling our own ones that cons and
don't short-circuit.
2010-09-16 Aidan Kehoe <kehoea@parhasard.net>
* bytecomp.el (byte-compile-initial-macro-environment):
* cl-macs.el (the):
Rephrase the docstring, make its implementation when compiling
files a little nicer.
2010-09-16 Aidan Kehoe <kehoea@parhasard.net>
* descr-text.el (unidata-initialize-unicodedata-database)
(unidata-initialize-unihan-database, describe-char-unicode-data)
(describe-char-unicode-data):
Wrap calls to the database functions with (with-fboundp ...),
avoiding byte compile warnings on builds without support for the
database functions.
(describe-char): (reduce #'max ...), not (apply #'max ...), no
need to cons needlessly.
(describe-char): Remove a redundant lambda wrapping
#'extent-properties.
(describe-char-unicode-data): Call #'nsubst when replacing "" with
nil in the result of #'split-string, instead of consing inside
mapcar.
2010-09-16 Aidan Kehoe <kehoea@parhasard.net>
* x-faces.el (x-available-font-sizes):
* specifier.el (let-specifier):
* package-ui.el (pui-add-required-packages):
* msw-faces.el (mswindows-available-font-sizes):
* modeline.el (modeline-minor-mode-menu):
* minibuf.el (minibuf-directory-files):
Replace the O2N (delq nil (mapcar (lambda (W) (and X Y)) Z)) with
the ON (mapcan (lambda (W) (and X (list Y))) Z) in these files.
2010-09-16 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (= < > <= >=):
When these functions are handed more than two arguments, and those
arguments have no side effects, transform to a series of two
argument calls, avoiding funcall in the byte-compiled code.
* mule/mule-cmds.el (finish-set-language-environment):
Take advantage of this change in a function called 256 times at
startup.
2010-09-16 Aidan Kehoe <kehoea@parhasard.net>
* bytecomp.el (byte-compile-function-form, byte-compile-quote)
(byte-compile-quote-form):
Warn at compile time, and error at runtime, if a (quote ...) or a
(function ...) form attempts to quote more than one object.
2010-09-16 Aidan Kehoe <kehoea@parhasard.net>
* byte-optimize.el (byte-optimize-apply): Transform (apply 'nconc
(mapcar ...)) to (mapcan ...); warn about use of the first idiom.
* update-elc.el (do-autoload-commands):
* packages.el (packages-find-package-library-path):
* frame.el (frame-list):
* extents.el (extent-descendants):
* etags.el (buffer-tag-table-files):
* dumped-lisp.el (preloaded-file-list):
* device.el (device-list):
* bytecomp-runtime.el (proclaim-inline, proclaim-notinline)
Use #'mapcan, not (apply #'nconc (mapcar ...) in all these files.
* bytecomp-runtime.el (eval-when-compile, eval-and-compile):
In passing, mention that these macros also evaluate the body when
interpreted.
tests/ChangeLog addition:
2011-02-07 Aidan Kehoe <kehoea@parhasard.net>
* automated/lisp-tests.el:
Test lexical scope for `block', `return-from'; add a
Known-Bug-Expect-Failure for a contorted example that fails when
byte-compiled.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Mon, 07 Feb 2011 12:01:24 +0000 |
parents | e6508b64ee08 |
children | b9167d522a9a |
rev | line source |
---|---|
428 | 1 /* -*-C-*- |
2 Server code for handling requests from clients and forwarding them | |
613 | 3 on to the XEmacs process. |
428 | 4 |
5290
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
5 Copyright (C) 1989 Free Software Foundation, Inc. |
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
6 |
613 | 7 This file is part of XEmacs. |
428 | 8 |
5290
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
9 XEmacs is free software; you can redistribute it and/or modify it |
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
10 under the terms of the GNU General Public License as published by |
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
11 the Free Software Foundation; either version 2, or (at your option) |
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
12 any later version. |
428 | 13 |
5290
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
14 XEmacs is distributed in the hope that it will be useful, but |
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
15 WITHOUT ANY WARRANTY; without even the implied warranty of |
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
17 General Public License for more details. |
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
18 |
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
19 You should have received a copy of the GNU General Public License |
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
20 along with XEmacs; see the file COPYING. If not, write to the Free |
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
21 Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
e6508b64ee08
More permission consistency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
2286
diff
changeset
|
22 Boston, MA 02110-1301, USA. |
428 | 23 |
24 Author: Andy Norman (ange@hplb.hpl.hp.com), based on 'etc/server.c' | |
25 from the 18.52 GNU Emacs distribution. | |
26 | |
27 Please mail bugs and suggestions to the author at the above address. | |
28 */ | |
29 | |
442 | 30 /* HISTORY |
31 * 11-Nov-1990 bristor@simba | |
428 | 32 * Added EOT stuff. |
33 */ | |
34 | |
35 /* | |
36 * This file incorporates new features added by Bob Weiner <weiner@mot.com>, | |
37 * Darrell Kindred <dkindred@cmu.edu> and Arup Mukherjee <arup@cmu.edu>. | |
38 * Please see the note at the end of the README file for details. | |
39 * | |
40 * (If gnuserv came bundled with your emacs, the README file is probably | |
41 * ../etc/gnuserv.README relative to the directory containing this file) | |
42 */ | |
43 | |
456 | 44 #include "gnuserv.h" |
428 | 45 |
456 | 46 char gnuserv_version[] = "gnuserv version" GNUSERV_VERSION; |
47 | |
428 | 48 |
49 #ifdef USE_LITOUT | |
50 #ifdef linux | |
51 #include <bsd/sgtty.h> | |
52 #else | |
53 #include <sgtty.h> | |
54 #endif | |
55 #endif | |
56 | |
57 #ifdef AIX | |
58 #include <sys/select.h> | |
59 #endif | |
60 | |
61 #include <stdlib.h> | |
62 #include <stdio.h> | |
63 #include <sys/types.h> | |
64 #include <sys/stat.h> | |
65 | |
66 #ifdef HAVE_UNISTD_H | |
67 #include <unistd.h> | |
68 #endif /* HAVE_UNISTD_H */ | |
69 | |
70 #ifdef HAVE_STRING_H | |
71 #include <string.h> | |
72 #endif /* HAVE_STRING_H */ | |
73 | |
2286 | 74 #include "compiler.h" |
75 | |
428 | 76 #if !defined(SYSV_IPC) && !defined(UNIX_DOMAIN_SOCKETS) && \ |
77 !defined(INTERNET_DOMAIN_SOCKETS) | |
2286 | 78 int main () |
428 | 79 { |
80 fprintf (stderr,"Sorry, the Emacs server is only supported on systems that have\n"); | |
81 fprintf (stderr,"Unix Domain sockets, Internet Domain sockets or System V IPC\n"); | |
82 exit (1); | |
83 } /* main */ | |
84 #else /* SYSV_IPC || UNIX_DOMAIN_SOCKETS || INTERNET_DOMAIN_SOCKETS */ | |
85 | |
86 #ifdef SYSV_IPC | |
87 | |
88 int ipc_qid = 0; /* ipc message queue id */ | |
89 pid_t ipc_wpid = 0; /* watchdog task pid */ | |
90 | |
91 | |
92 /* | |
93 ipc_exit -- clean up the queue id and queue, then kill the watchdog task | |
94 if it exists. exit with the given status. | |
95 */ | |
96 void | |
97 ipc_exit (int stat) | |
98 { | |
99 msgctl (ipc_qid,IPC_RMID,0); | |
442 | 100 |
428 | 101 if (ipc_wpid != 0) |
102 kill (ipc_wpid, SIGKILL); | |
103 | |
104 exit (stat); | |
105 } /* ipc_exit */ | |
106 | |
107 | |
108 /* | |
109 ipc_handle_signal -- catch the signal given and clean up. | |
110 */ | |
111 void | |
112 ipc_handle_signal(int sig) | |
113 { | |
114 ipc_exit (0); | |
115 } /* ipc_handle_signal */ | |
116 | |
117 | |
442 | 118 /* |
428 | 119 ipc_spawn_watchdog -- spawn a watchdog task to clean up the message queue should the |
120 server process die. | |
121 */ | |
122 void | |
123 ipc_spawn_watchdog (void) | |
124 { | |
125 if ((ipc_wpid = fork ()) == 0) | |
126 { /* child process */ | |
127 pid_t ppid = getppid (); /* parent's process id */ | |
128 | |
129 setpgrp(); /* gnu kills process group on exit */ | |
130 | |
131 while (1) | |
132 { | |
133 if (kill (ppid, 0) < 0) /* ppid is no longer valid, parent | |
134 may have died */ | |
135 { | |
136 ipc_exit (0); | |
137 } /* if */ | |
138 | |
139 sleep(10); /* have another go later */ | |
140 } /* while */ | |
141 } /* if */ | |
142 | |
143 } /* ipc_spawn_watchdog */ | |
144 | |
145 | |
146 /* | |
147 ipc_init -- initialize server, setting the global msqid that can be listened on. | |
148 */ | |
149 void | |
150 ipc_init (struct msgbuf **msgpp) | |
151 { | |
152 key_t key; /* messge key */ | |
153 char buf[GSERV_BUFSZ]; /* pathname for key */ | |
154 | |
155 sprintf (buf,"%s/gsrv%d",tmpdir,(int)geteuid ()); | |
156 creat (buf,0600); | |
157 key = ftok (buf,1); | |
158 | |
159 if ((ipc_qid = msgget (key,0600|IPC_CREAT)) == -1) | |
160 { | |
161 perror (progname); | |
162 fprintf (stderr, "%s: unable to create msg queue\n", progname); | |
163 ipc_exit (1); | |
164 } /* if */ | |
165 | |
166 ipc_spawn_watchdog (); | |
167 | |
168 signal (SIGTERM,ipc_handle_signal); | |
169 signal (SIGINT,ipc_handle_signal); | |
170 | |
171 if ((*msgpp = (struct msgbuf *) | |
172 malloc (sizeof **msgpp + GSERV_BUFSZ)) == NULL) | |
173 { | |
174 fprintf (stderr, | |
175 "%s: unable to allocate space for message buffer\n", progname); | |
176 ipc_exit(1); | |
177 } /* if */ | |
178 } /* ipc_init */ | |
179 | |
180 | |
181 /* | |
182 handle_ipc_request -- accept a request from a client, pass the request on | |
613 | 183 to the XEmacs process, then wait for its reply and |
428 | 184 pass that on to the client. |
185 */ | |
186 void | |
187 handle_ipc_request (struct msgbuf *msgp) | |
188 { | |
189 struct msqid_ds msg_st; /* message status */ | |
190 char buf[GSERV_BUFSZ]; | |
191 int len; /* length of message / read */ | |
192 int s, result_len; /* tag fields on the response from emacs */ | |
193 int offset = 0; | |
194 int total = 1; /* # bytes that will actually be sent off */ | |
195 | |
196 if ((len = msgrcv (ipc_qid, msgp, GSERV_BUFSZ - 1, 1, 0)) < 0) | |
197 { | |
198 perror (progname); | |
199 fprintf (stderr, "%s: unable to receive\n", progname); | |
200 ipc_exit (1); | |
201 } /* if */ | |
202 | |
203 msgctl (ipc_qid, IPC_STAT, &msg_st); | |
204 strncpy (buf, msgp->mtext, len); | |
205 buf[len] = '\0'; /* terminate */ | |
442 | 206 |
428 | 207 printf ("%d %s", ipc_qid, buf); |
208 fflush (stdout); | |
209 | |
210 /* now for the response from gnu */ | |
211 msgp->mtext[0] = '\0'; | |
212 | |
213 #if 0 | |
214 if ((len = read(0,buf,GSERV_BUFSZ-1)) < 0) | |
215 { | |
216 perror (progname); | |
217 fprintf (stderr, "%s: unable to read\n", progname); | |
218 ipc_exit (1); | |
219 } /* if */ | |
220 | |
221 sscanf (buf, "%d:%[^\n]\n", &junk, msgp->mtext); | |
222 #else | |
223 | |
224 /* read in "n/m:" (n=client fd, m=message length) */ | |
225 | |
442 | 226 while (offset < (GSERV_BUFSZ-1) && |
428 | 227 ((len = read (0, buf + offset, 1)) > 0) && |
228 buf[offset] != ':') | |
229 { | |
230 offset += len; | |
231 } | |
232 | |
233 if (len < 0) | |
234 { | |
235 perror (progname); | |
236 fprintf (stderr, "%s: unable to read\n", progname); | |
237 exit(1); | |
238 } | |
239 | |
240 /* parse the response from emacs, getting client fd & result length */ | |
241 buf[offset] = '\0'; | |
242 sscanf (buf, "%d/%d", &s, &result_len); | |
243 | |
244 while (result_len > 0) | |
245 { | |
246 if ((len = read(0, buf, min2 (result_len, GSERV_BUFSZ - 1))) < 0) | |
247 { | |
248 perror (progname); | |
249 fprintf (stderr, "%s: unable to read\n", progname); | |
250 exit (1); | |
251 } | |
252 | |
442 | 253 /* Send this string off, but only if we have enough space */ |
428 | 254 |
255 if (GSERV_BUFSZ > total) | |
256 { | |
257 if (total + len <= GSERV_BUFSZ) | |
258 buf[len] = 0; | |
259 else | |
260 buf[GSERV_BUFSZ - total] = 0; | |
261 | |
262 send_string(s,buf); | |
263 total += strlen(buf); | |
264 } | |
265 | |
266 result_len -= len; | |
267 } | |
268 | |
269 /* eat the newline */ | |
270 while ((len = read (0,buf,1)) == 0) | |
271 ; | |
272 if (len < 0) | |
273 { | |
274 perror(progname); | |
275 fprintf (stderr,"%s: unable to read\n", progname); | |
276 exit (1); | |
277 } | |
278 if (buf[0] != '\n') | |
279 { | |
280 fprintf (stderr,"%s: garbage after result [%c]\n", progname, buf[0]); | |
281 exit (1); | |
282 } | |
283 #endif | |
284 | |
285 /* Send a response back to the client. */ | |
286 | |
287 msgp->mtype = msg_st.msg_lspid; | |
288 if (msgsnd (ipc_qid,msgp,strlen(msgp->mtext)+1,0) < 0) | |
289 perror ("msgsend(gnuserv)"); | |
290 | |
291 } /* handle_ipc_request */ | |
292 #endif /* SYSV_IPC */ | |
293 | |
294 | |
295 #if defined(INTERNET_DOMAIN_SOCKETS) || defined(UNIX_DOMAIN_SOCKETS) | |
296 /* | |
297 echo_request -- read request from a given socket descriptor, and send the information | |
298 to stdout (the gnu process). | |
299 */ | |
300 static void | |
301 echo_request (int s) | |
302 { | |
303 char buf[GSERV_BUFSZ]; | |
304 int len; | |
305 | |
306 printf("%d ",s); | |
442 | 307 |
428 | 308 /* read until we get a newline or no characters */ |
309 while ((len = recv(s,buf,GSERV_BUFSZ-1,0)) > 0) { | |
310 buf[len] = '\0'; | |
311 printf("%s",buf); | |
312 | |
313 if (buf[len-1] == EOT_CHR) { | |
314 fflush(stdout); | |
315 break; /* end of message */ | |
316 } | |
317 | |
318 } /* while */ | |
319 | |
320 if (len < 0) { | |
321 perror(progname); | |
322 fprintf(stderr,"%s: unable to recv\n",progname); | |
323 exit(1); | |
324 } /* if */ | |
442 | 325 |
428 | 326 } /* echo_request */ |
327 | |
328 | |
329 /* | |
330 handle_response -- accept a response from stdin (the gnu process) and pass the | |
331 information on to the relevant client. | |
332 */ | |
333 static void | |
334 handle_response (void) | |
335 { | |
336 char buf[GSERV_BUFSZ+1]; | |
337 int offset=0; | |
338 int s; | |
339 int len = 0; | |
340 int result_len; | |
341 | |
342 /* read in "n/m:" (n=client fd, m=message length) */ | |
442 | 343 while (offset < GSERV_BUFSZ && |
428 | 344 ((len = read(0,buf+offset,1)) > 0) && |
345 buf[offset] != ':') { | |
346 offset += len; | |
347 } | |
348 | |
349 if (len < 0) { | |
350 perror(progname); | |
351 fprintf(stderr,"%s: unable to read\n",progname); | |
352 exit(1); | |
353 } | |
442 | 354 |
428 | 355 /* parse the response from emacs, getting client fd & result length */ |
356 buf[offset] = '\0'; | |
357 sscanf(buf,"%d/%d", &s, &result_len); | |
358 | |
359 while (result_len > 0) { | |
360 if ((len = read(0,buf,min2(result_len,GSERV_BUFSZ))) < 0) { | |
361 perror(progname); | |
362 fprintf(stderr,"%s: unable to read\n",progname); | |
363 exit(1); | |
364 } | |
365 buf[len] = '\0'; | |
366 send_string(s,buf); | |
367 result_len -= len; | |
368 } | |
369 | |
370 /* eat the newline */ | |
371 while ((len = read(0,buf,1)) == 0) | |
372 ; | |
373 if (len < 0) | |
374 { | |
375 perror(progname); | |
376 fprintf(stderr,"%s: unable to read\n",progname); | |
377 exit(1); | |
378 } | |
379 if (buf[0] != '\n') | |
380 { | |
381 fprintf(stderr,"%s: garbage after result\n",progname); | |
382 exit(1); | |
383 } | |
384 /* send the newline */ | |
385 buf[1] = '\0'; | |
386 send_string(s,buf); | |
442 | 387 close(s); |
428 | 388 |
389 } /* handle_response */ | |
390 #endif /* INTERNET_DOMAIN_SOCKETS || UNIX_DOMAIN_SOCKETS */ | |
391 | |
392 | |
393 #ifdef INTERNET_DOMAIN_SOCKETS | |
394 struct entry { | |
458 | 395 unsigned long host_addr; |
428 | 396 struct entry *next; |
397 }; | |
398 | |
399 struct entry *permitted_hosts[TABLE_SIZE]; | |
400 | |
401 #ifdef AUTH_MAGIC_COOKIE | |
402 # include <X11/X.h> | |
403 # include <X11/Xauth.h> | |
404 | |
405 static Xauth *server_xauth = NULL; | |
442 | 406 #endif |
428 | 407 |
442 | 408 static int |
428 | 409 timed_read (int fd, char *buf, int max, int timeout, int one_line) |
410 { | |
411 fd_set rmask; | |
412 struct timeval tv; /* = {timeout, 0}; */ | |
413 char c = 0; | |
414 int nbytes = 0; | |
415 int r; | |
442 | 416 |
428 | 417 tv.tv_sec = timeout; |
418 tv.tv_usec = 0; | |
419 | |
420 FD_ZERO(&rmask); | |
421 FD_SET(fd, &rmask); | |
442 | 422 |
428 | 423 do |
424 { | |
425 r = select(fd + 1, &rmask, NULL, NULL, &tv); | |
426 | |
427 if (r > 0) | |
428 { | |
429 if (read (fd, &c, 1) == 1 ) | |
430 { | |
431 *buf++ = c; | |
432 ++nbytes; | |
433 } | |
434 else | |
435 { | |
436 printf ("read error on socket\004\n"); | |
437 return -1; | |
438 } | |
439 } | |
440 else if (r == 0) | |
441 { | |
442 printf ("read timed out\004\n"); | |
443 return -1; | |
444 } | |
445 else | |
446 { | |
447 printf ("error in select\004\n"); | |
448 return -1; | |
449 } | |
450 } while ((nbytes < max) && !(one_line && (c == '\n'))); | |
451 | |
452 --buf; | |
453 if (one_line && *buf == '\n') | |
454 { | |
455 *buf = 0; | |
456 } | |
457 | |
458 return nbytes; | |
459 } | |
442 | 460 |
461 | |
428 | 462 |
463 /* | |
464 permitted -- return whether a given host is allowed to connect to the server. | |
465 */ | |
466 static int | |
458 | 467 permitted (unsigned long host_addr, int fd) |
428 | 468 { |
469 int key; | |
470 struct entry *entry; | |
471 | |
442 | 472 char auth_protocol[128]; |
428 | 473 char buf[1024]; |
474 int auth_data_len; | |
475 | |
476 if (fd > 0) | |
477 { | |
478 /* we are checking permission on a real connection */ | |
479 | |
480 /* Read auth protocol name */ | |
442 | 481 |
428 | 482 if (timed_read(fd, auth_protocol, AUTH_NAMESZ, AUTH_TIMEOUT, 1) <= 0) |
483 return FALSE; | |
484 | |
485 if (strcmp (auth_protocol, DEFAUTH_NAME) && | |
486 strcmp (auth_protocol, MCOOKIE_NAME)) | |
487 { | |
442 | 488 printf ("authentication protocol (%s) from client is invalid...\n", |
428 | 489 auth_protocol); |
490 printf ("... Was the client an old version of gnuclient/gnudoit?\004\n"); | |
442 | 491 |
428 | 492 return FALSE; |
493 } | |
494 | |
495 if (!strcmp(auth_protocol, MCOOKIE_NAME)) | |
496 { | |
497 | |
498 /* | |
499 * doing magic cookie auth | |
500 */ | |
501 | |
647 | 502 if (timed_read (fd, buf, 10, AUTH_TIMEOUT, 1) <= 0) |
428 | 503 return FALSE; |
504 | |
647 | 505 auth_data_len = atoi (buf); |
428 | 506 |
647 | 507 if (auth_data_len <= 0 || auth_data_len > (int) sizeof (buf)) |
456 | 508 { |
509 return FALSE; | |
510 } | |
511 | |
647 | 512 if (timed_read (fd, buf, auth_data_len, AUTH_TIMEOUT, 0) != |
513 auth_data_len) | |
428 | 514 return FALSE; |
442 | 515 |
428 | 516 #ifdef AUTH_MAGIC_COOKIE |
456 | 517 if (server_xauth && server_xauth->data) |
462 | 518 { |
456 | 519 /* Do a compare without comprising info about |
520 the size of the cookie */ | |
460 | 521 int auth_data_pos; |
522 int auth_mismatches = | |
456 | 523 ( auth_data_len ^ |
524 server_xauth->data_length ); | |
525 | |
647 | 526 for(auth_data_pos = 0; auth_data_pos < auth_data_len; |
527 ++auth_data_pos) | |
456 | 528 auth_mismatches |= |
529 ( buf[auth_data_pos] ^ | |
647 | 530 server_xauth->data[auth_data_pos % |
531 server_xauth->data_length]); | |
456 | 532 |
533 if (auth_mismatches == 0) | |
428 | 534 return TRUE; |
456 | 535 |
536 for(;rand() % 1000;); | |
462 | 537 } |
456 | 538 |
442 | 539 #else |
428 | 540 printf ("client tried Xauth, but server is not compiled with Xauth\n"); |
541 #endif | |
442 | 542 |
428 | 543 /* |
544 * auth failed, but allow this to fall through to the GNU_SECURE | |
545 * protocol.... | |
546 */ | |
547 | |
548 printf ("Xauth authentication failed, trying GNU_SECURE auth...\004\n"); | |
549 | |
550 } | |
442 | 551 |
428 | 552 /* Other auth protocols go here, and should execute only if the |
553 * auth_protocol name matches. | |
554 */ | |
555 | |
556 } | |
557 | |
558 | |
559 /* Now, try the old GNU_SECURE stuff... */ | |
442 | 560 |
428 | 561 /* First find the hash key */ |
562 key = HASH(host_addr) % TABLE_SIZE; | |
442 | 563 |
428 | 564 /* Now check the chain for that hash key */ |
565 for(entry=permitted_hosts[key]; entry != NULL; entry=entry->next) | |
442 | 566 if (host_addr == entry->host_addr) |
428 | 567 return(TRUE); |
442 | 568 |
428 | 569 return(FALSE); |
570 | |
571 } /* permitted */ | |
572 | |
573 | |
442 | 574 /* |
428 | 575 add_host -- add the given host to the list of permitted hosts, provided it isn't |
576 already there. | |
442 | 577 */ |
428 | 578 static void |
458 | 579 add_host (unsigned long host_addr) |
428 | 580 { |
581 int key; | |
582 struct entry *new_entry; | |
442 | 583 |
428 | 584 if (!permitted(host_addr, -1)) |
585 { | |
586 if ((new_entry = (struct entry *) malloc(sizeof(struct entry))) == NULL) { | |
587 fprintf(stderr,"%s: unable to malloc space for permitted host entry\n", | |
588 progname); | |
589 exit(1); | |
590 } /* if */ | |
591 | |
592 new_entry->host_addr = host_addr; | |
593 key = HASH(host_addr) % TABLE_SIZE; | |
594 new_entry->next = permitted_hosts[key]; | |
595 permitted_hosts[key] = new_entry; | |
596 } /* if */ | |
597 | |
598 } /* add_host */ | |
599 | |
600 | |
601 /* | |
602 setup_table -- initialize the table of hosts allowed to contact the server, | |
603 by reading from the file specified by the GNU_SECURE | |
604 environment variable | |
605 Put in the local machine, and, if a security file is specifed, | |
606 add each host that is named in the file. | |
607 Return the number of hosts added. | |
608 */ | |
609 static int | |
610 setup_table (void) | |
611 { | |
612 FILE *host_file; | |
613 char *file_name; | |
614 char hostname[HOSTNAMSZ]; | |
458 | 615 unsigned int host_addr; |
428 | 616 int i, hosts=0; |
442 | 617 |
428 | 618 /* Make sure every entry is null */ |
619 for (i=0; i<TABLE_SIZE; i++) | |
620 permitted_hosts[i] = NULL; | |
621 | |
622 gethostname(hostname,HOSTNAMSZ); | |
623 | |
647 | 624 if ((host_addr = internet_addr (hostname)) == (unsigned int) -1) |
428 | 625 { |
442 | 626 fprintf(stderr,"%s: unable to find %s in /etc/hosts or from YP", |
428 | 627 progname,hostname); |
628 exit(1); | |
629 } /* if */ | |
630 | |
631 #ifdef AUTH_MAGIC_COOKIE | |
442 | 632 |
633 server_xauth = XauGetAuthByAddr (FamilyInternet, | |
428 | 634 sizeof(host_addr), (char *)&host_addr, |
442 | 635 strlen(MCOOKIE_SCREEN), MCOOKIE_SCREEN, |
428 | 636 strlen(MCOOKIE_X_NAME), MCOOKIE_X_NAME); |
637 hosts++; | |
638 | |
639 #endif /* AUTH_MAGIC_COOKIE */ | |
442 | 640 |
428 | 641 |
642 #if 0 /* Don't even want to allow access from the local host by default */ | |
643 add_host(host_addr); /* add local host */ | |
442 | 644 #endif |
428 | 645 |
646 if (((file_name = getenv("GNU_SECURE")) != NULL && /* security file */ | |
647 (host_file = fopen(file_name,"r")) != NULL)) /* opened ok */ | |
648 { | |
649 while ((fscanf(host_file,"%s",hostname) != EOF)) /* find a host */ | |
647 | 650 if ((host_addr = internet_addr(hostname)) != (unsigned int) -1) |
651 /* get its addr */ | |
428 | 652 { |
647 | 653 add_host(host_addr); /* add the addr */ |
428 | 654 hosts++; |
655 } | |
656 fclose(host_file); | |
657 } /* if */ | |
658 | |
659 return hosts; | |
660 } /* setup_table */ | |
661 | |
662 | |
663 /* | |
664 internet_init -- initialize server, returning an internet socket that can | |
665 be listened on. | |
666 */ | |
667 static int | |
668 internet_init (void) | |
669 { | |
670 int ls; /* socket descriptor */ | |
671 struct servent *sp; /* pointer to service information */ | |
672 struct sockaddr_in server; /* for local socket address */ | |
673 char *ptr; /* ptr to return from getenv */ | |
674 | |
442 | 675 if (setup_table() == 0) |
428 | 676 return -1; |
677 | |
678 /* clear out address structure */ | |
442 | 679 memset (&server, '\0', sizeof (server)); |
680 | |
428 | 681 /* Set up address structure for the listen socket. */ |
682 server.sin_family = AF_INET; | |
683 server.sin_addr.s_addr = INADDR_ANY; | |
684 | |
685 /* Find the information for the gnu server | |
686 * in order to get the needed port number. | |
687 */ | |
688 if ((ptr=getenv("GNU_PORT")) != NULL) | |
689 server.sin_port = htons(atoi(ptr)); | |
690 else if ((sp = getservbyname ("gnuserv", "tcp")) == NULL) | |
691 server.sin_port = htons(DEFAULT_PORT+getuid()); | |
692 else | |
693 server.sin_port = sp->s_port; | |
442 | 694 |
428 | 695 /* Create the listen socket. */ |
696 if ((ls = socket (AF_INET,SOCK_STREAM, 0)) == -1) | |
697 { | |
698 perror(progname); | |
699 fprintf(stderr,"%s: unable to create socket\n",progname); | |
700 exit(1); | |
701 } /* if */ | |
442 | 702 |
428 | 703 /* Bind the listen address to the socket. */ |
704 if (bind(ls,(struct sockaddr *) &server,sizeof(struct sockaddr_in)) == -1) | |
705 { | |
706 perror(progname); | |
707 fprintf(stderr,"%s: unable to bind socket\n",progname); | |
708 exit(1); | |
709 } /* if */ | |
710 | |
711 /* Initiate the listen on the socket so remote users | |
442 | 712 * can connect. |
428 | 713 */ |
714 if (listen(ls,20) == -1) | |
715 { | |
716 perror(progname); | |
717 fprintf(stderr,"%s: unable to listen\n",progname); | |
718 exit(1); | |
719 } /* if */ | |
720 | |
721 return(ls); | |
722 | |
723 } /* internet_init */ | |
724 | |
725 | |
726 /* | |
727 handle_internet_request -- accept a request from a client and send the information | |
728 to stdout (the gnu process). | |
729 */ | |
730 static void | |
731 handle_internet_request (int ls) | |
732 { | |
733 int s; | |
442 | 734 socklen_t addrlen = sizeof (struct sockaddr_in); |
428 | 735 struct sockaddr_in peer; /* for peer socket address */ |
736 | |
442 | 737 memset (&peer, '\0', sizeof (peer)); |
428 | 738 |
440 | 739 if ((s = accept(ls,(struct sockaddr *)&peer, &addrlen)) == -1) |
428 | 740 { |
741 perror(progname); | |
742 fprintf(stderr,"%s: unable to accept\n",progname); | |
743 exit(1); | |
744 } /* if */ | |
442 | 745 |
428 | 746 /* Check that access is allowed - if not return crud to the client */ |
747 if (!permitted(peer.sin_addr.s_addr, s)) | |
748 { | |
749 send_string(s,"gnudoit: Connection refused\ngnudoit: unable to connect to remote"); | |
750 close(s); | |
751 | |
752 printf("Refused connection from %s\004\n", inet_ntoa(peer.sin_addr)); | |
753 return; | |
754 } /* if */ | |
755 | |
756 echo_request(s); | |
442 | 757 |
428 | 758 } /* handle_internet_request */ |
759 #endif /* INTERNET_DOMAIN_SOCKETS */ | |
760 | |
761 | |
762 #ifdef UNIX_DOMAIN_SOCKETS | |
763 /* | |
764 unix_init -- initialize server, returning an unix-domain socket that can | |
765 be listened on. | |
766 */ | |
767 static int | |
768 unix_init (void) | |
769 { | |
770 int ls; /* socket descriptor */ | |
771 struct sockaddr_un server; /* unix socket address */ | |
442 | 772 socklen_t bindlen; |
428 | 773 |
774 if ((ls = socket(AF_UNIX,SOCK_STREAM, 0)) < 0) | |
775 { | |
776 perror(progname); | |
777 fprintf(stderr,"%s: unable to create socket\n",progname); | |
778 exit(1); | |
779 } /* if */ | |
780 | |
781 /* Set up address structure for the listen socket. */ | |
782 #ifdef HIDE_UNIX_SOCKET | |
783 sprintf(server.sun_path,"%s/gsrvdir%d",tmpdir,(int)geteuid()); | |
784 if (mkdir(server.sun_path, 0700) < 0) | |
785 { | |
786 /* assume it already exists, and try to set perms */ | |
787 if (chmod(server.sun_path, 0700) < 0) | |
788 { | |
789 perror(progname); | |
790 fprintf(stderr,"%s: can't set permissions on %s\n", | |
791 progname, server.sun_path); | |
792 exit(1); | |
793 } | |
794 } | |
795 strcat(server.sun_path,"/gsrv"); | |
796 unlink(server.sun_path); /* remove old file if it exists */ | |
797 #else /* HIDE_UNIX_SOCKET */ | |
798 sprintf(server.sun_path,"%s/gsrv%d",tmpdir,(int)geteuid()); | |
799 unlink(server.sun_path); /* remove old file if it exists */ | |
800 #endif /* HIDE_UNIX_SOCKET */ | |
801 | |
802 server.sun_family = AF_UNIX; | |
803 #ifdef HAVE_SOCKADDR_SUN_LEN | |
804 /* See W. R. Stevens "Advanced Programming in the Unix Environment" | |
805 p. 502 */ | |
806 bindlen = (sizeof (server.sun_len) + sizeof (server.sun_family) | |
807 + strlen (server.sun_path) + 1); | |
808 server.sun_len = bindlen; | |
809 #else | |
810 bindlen = strlen (server.sun_path) + sizeof (server.sun_family); | |
811 #endif | |
442 | 812 |
428 | 813 if (bind(ls,(struct sockaddr *)&server,bindlen) < 0) |
814 { | |
815 perror(progname); | |
816 fprintf(stderr,"%s: unable to bind socket\n",progname); | |
817 exit(1); | |
818 } /* if */ | |
819 | |
820 chmod(server.sun_path,0700); /* only this user can send commands */ | |
821 | |
822 if (listen(ls,20) < 0) { | |
823 perror(progname); | |
824 fprintf(stderr,"%s: unable to listen\n",progname); | |
825 exit(1); | |
826 } /* if */ | |
827 | |
828 /* #### there are also better ways of dealing with this when | |
829 sigvec() is present. */ | |
830 #if defined (HAVE_SIGPROCMASK) | |
442 | 831 { |
428 | 832 sigset_t _mask; |
833 sigemptyset (&_mask); | |
834 sigaddset (&_mask, SIGPIPE); | |
835 sigprocmask (SIG_BLOCK, &_mask, NULL); | |
836 } | |
837 #else | |
838 signal(SIGPIPE,SIG_IGN); /* in case user kills client */ | |
839 #endif | |
840 | |
841 return(ls); | |
842 | |
843 } /* unix_init */ | |
844 | |
845 | |
846 /* | |
847 handle_unix_request -- accept a request from a client and send the information | |
848 to stdout (the gnu process). | |
849 */ | |
850 static void | |
851 handle_unix_request (int ls) | |
852 { | |
853 int s; | |
442 | 854 socklen_t len = sizeof (struct sockaddr_un); |
428 | 855 struct sockaddr_un server; /* for unix socket address */ |
856 | |
857 server.sun_family = AF_UNIX; | |
858 | |
440 | 859 if ((s = accept(ls,(struct sockaddr *)&server, &len)) < 0) |
428 | 860 { |
861 perror(progname); | |
862 fprintf(stderr,"%s: unable to accept\n",progname); | |
863 } /* if */ | |
864 | |
865 echo_request(s); | |
442 | 866 |
428 | 867 } /* handle_unix_request */ |
868 #endif /* UNIX_DOMAIN_SOCKETS */ | |
869 | |
870 | |
871 int | |
2286 | 872 main (int UNUSED (argc), char *argv[]) |
428 | 873 { |
874 int chan; /* temporary channel number */ | |
875 #ifdef SYSV_IPC | |
876 struct msgbuf *msgp; /* message buffer */ | |
877 #else | |
878 int ils = -1; /* internet domain listen socket */ | |
879 int uls = -1; /* unix domain listen socket */ | |
880 #endif /* SYSV_IPC */ | |
881 | |
882 progname = argv[0]; | |
883 | |
884 for(chan=3; chan < _NFILE; close(chan++)) /* close unwanted channels */ | |
885 ; | |
886 | |
771 | 887 |
888 #ifdef WIN32_NATIVE | |
889 tmpdir = getenv ("TEMP"); | |
890 if (!tmpdir) | |
891 tmpdir = getenv ("TMP"); | |
892 if (!tmpdir) | |
893 tmpdir = "c:\\"; | |
894 #else | |
428 | 895 #ifdef USE_TMPDIR |
771 | 896 tmpdir = getenv ("TMPDIR"); |
428 | 897 #endif |
898 if (!tmpdir) | |
899 tmpdir = "/tmp"; | |
771 | 900 #endif /* WIN32_NATIVE */ |
428 | 901 #ifdef USE_LITOUT |
902 { | |
903 /* this is to allow ^D to pass to emacs */ | |
904 int d = LLITOUT; | |
905 (void) ioctl(fileno(stdout), TIOCLBIS, &d); | |
906 } | |
907 #endif | |
908 | |
909 #ifdef SYSV_IPC | |
910 ipc_init(&msgp); /* get a msqid to listen on, and a message buffer */ | |
911 #endif /* SYSV_IPC */ | |
912 | |
913 #ifdef INTERNET_DOMAIN_SOCKETS | |
914 ils = internet_init(); /* get an internet domain socket to listen on */ | |
915 #endif /* INTERNET_DOMAIN_SOCKETS */ | |
916 | |
917 #ifdef UNIX_DOMAIN_SOCKETS | |
918 uls = unix_init(); /* get a unix domain socket to listen on */ | |
919 #endif /* UNIX_DOMAIN_SOCKETS */ | |
920 | |
921 while (1) { | |
922 #ifdef SYSV_IPC | |
923 handle_ipc_request(msgp); | |
924 #else /* NOT SYSV_IPC */ | |
925 fd_set rmask; | |
926 FD_ZERO(&rmask); | |
927 FD_SET(fileno(stdin), &rmask); | |
928 if (uls >= 0) | |
929 FD_SET(uls, &rmask); | |
930 if (ils >= 0) | |
931 FD_SET(ils, &rmask); | |
442 | 932 |
933 if (select(max2(fileno(stdin),max2(uls,ils)) + 1, &rmask, | |
428 | 934 (fd_set *)NULL, (fd_set *)NULL, (struct timeval *)NULL) < 0) |
935 { | |
936 perror(progname); | |
937 fprintf(stderr,"%s: unable to select\n",progname); | |
442 | 938 return 1; |
428 | 939 } /* if */ |
940 | |
941 #ifdef UNIX_DOMAIN_SOCKETS | |
942 if (uls > 0 && FD_ISSET(uls, &rmask)) | |
943 handle_unix_request(uls); | |
944 #endif | |
945 | |
946 #ifdef INTERNET_DOMAIN_SOCKETS | |
947 if (ils > 0 && FD_ISSET(ils, &rmask)) | |
948 handle_internet_request(ils); | |
949 #endif /* INTERNET_DOMAIN_SOCKETS */ | |
950 | |
951 if (FD_ISSET(fileno(stdin), &rmask)) /* from stdin (gnu process) */ | |
952 handle_response(); | |
953 #endif /* NOT SYSV_IPC */ | |
442 | 954 } /* while (1) */ |
428 | 955 } /* main */ |
956 | |
957 #endif /* SYSV_IPC || UNIX_DOMAIN_SOCKETS || INTERNET_DOMAIN_SOCKETS */ |