Dan Sugalski ([EMAIL PROTECTED]) writes:
> At 09:52 AM 4/26/00 -0400, Charles Lane wrote:
> >When Perl opens the socket, it also does (paraphrasing):
>>     fp_read = fdopen(socket,"r");
>>     fp_write= fdopen(socket,"w");
> >so that you can use stdio routines to read or write from the socket.

> You can't do stdio to sockets on VMS. This bit me a year or so ago. I
> exchanged mail with the C RTL folks, and the net result was "You can't
> fdopen socket file descriptors." It's not in any POSIX standard, so it
> wasn't high on their list of things to fix. (I put in a fix request, but
> this was when they were working on getting the 7.2 changes into the C RTL)

Yeah, I figured that it might come down to that; the tantalizing bit is
that it *almost* works....in fact, were it not for the too-frequent
buffer flushes, it would work in this one case.  But for sockets if you
don't flush frequently, you get deadlocks.

If we could make my_fwrite use a "write" call for sockets instead of
"fputs" then we'd be okay, this much is clear.

> >Everything going INTO the fputs routine is fine.  But the extra NULs
> >come out the other end.

> That's OK--if you were reading from that socket you'd find that you get
> back what you wrote. Bleah. One ought not print and <> from sockets.
> sysread/syswrite is the way to go.

You read the socket and get back stuff left in the buffer from
previous "accept/fputs/fflush/close" cycles, or NULs or other trash.
That's what the test program demonstrates.  Check it out.

I agree that sysread/syswrite are the way to go; but there's a huge
amount of inertia behind using "print", and for good reason.

> >I can see how to do it, but it's really painful....in my_fwrite:
> >
>>     if (fstat(fileno(dest),&s) == 0 &&  S_ISSOCK(s.st_mode)) {
>>         write(fileno(dest),src,nitm*itmsz);
>>     } else {
>>         ...the code currently in my_fwrite...
>>     }
> >
> >This works, but that damn "fstat" has to be done for *every* *single*
> >print...that's a performance hit we don't really need.  (my_fwrite
> >doesn't know when the FILE * has been closed and reopened, and yes they
> >do get reused).

> Nope. Perl tags each filehandle with a type. We can wedge our own type in
> there for sockets and test for it instead of using fstat. I'll see about
> throwing something together.

If that "nope" was to the reuse, I suggest you run the code in the
debugger.  You'll find the same file#'s and FILE* pointers being
reused after closing and reopening a new connection.

As for checking socket/nonsocket, by the time you get down to
"do_print" and "my_fwrite" you're operating on a stdio FILE *, and
have no idea whether the original filehandle was a socket type.

Rewriting most of Perl's i/o code to pass filehandles down to lower
levels didn't seem like a good way to solve a VMS-specific problem.

Other ideas:

1. Subvert FILE:

    struct _subvert {
        FILE ptr;
        int is_a_socket;
    };
    typedef struct _subvert myFILE;

    FILE *fp = fopen(...);    or   FILE *fp = fdopen(socket,...);

    myFILE *fp2 = malloc(sizeof myFILE);

    fp2->ptr = *fp;
    fp2->is_a_socket = ...;

    fp = (FILE *) fp2;

    ...
(I think this is a *bad* *idea*, and do not advocate it...even IF it works
[big IF])

2.  some sort of global file# "is_a_socket" array:

    open socket:
        int fd = accept(...);
        global_isasock[fd] = 1;     (dimensioned 256 or the like...)
        fp = fdopen(fd...)         /* not used for i/o */
        ...

    open file:
        FILE * fp = fopen(...);
        global_isasock[fileno(fp)] = 0;

    close:
        global_isasock[fileno(fp)] = 0;

(I suspect this may be as good as we can do...)
--
 Drexel University       \V                     --Chuck Lane
----------------->--------*------------<[EMAIL PROTECTED]
     (215) 895-1545      / \  Particle Physics  [EMAIL PROTECTED]
FAX: (215) 895-5934        /~~~~~~~~~~~         [EMAIL PROTECTED]

Reply via email to