static void pipe_intrin (void) { int fds[2]; SLFile_FD_Type *f0; SLFile_FD_Type *f1; while (-1 == pipe (fds)) { if (errno == EINTR) { if (-1 != SLang_handle_interrupt ()) continue; } SLerrno_set_errno (errno); SLang_verror (SL_OS_Error, "pipe failed: %s", SLerrno_strerror(errno)); return; } f0 = SLfile_create_fd ("*pipe*", fds[0]); f1 = SLfile_create_fd ("*pipe*", fds[1]); if ((NULL != f0) && (NULL != f1)) { /* Ignore errors and allow the free_fd routines to clean up */ (void) SLfile_push_fd (f0); (void) SLfile_push_fd (f1); } SLfile_free_fd (f1); SLfile_free_fd (f0); }
static void accept_intrin (void) { SLFile_FD_Type *f; Socket_Type *s, *s1; Domain_Methods_Type *methods; int nargs = SLang_Num_Function_Args; SLang_Ref_Type *refs[MAX_ACCEPT_REF_ARGS]; int i; if (nargs <= 0) { SLang_verror (SL_Usage_Error, "s1 = accept (s [,&v...])"); return; } if (-1 == SLroll_stack (-nargs)) return; if (NULL == (s = pop_socket (&f))) return; nargs--; if (nargs > MAX_ACCEPT_REF_ARGS) { SLang_verror (SL_NumArgs_Error, "accept: too many reference args"); SLfile_free_fd (f); } memset ((char *)refs, 0, sizeof (refs)); i = nargs; while (i != 0) { i--; if (-1 == SLang_pop_ref (refs+i)) goto free_return; } methods = s->methods; if (NULL != (s1 = (*methods->accept)(s, nargs, refs))) (void) push_socket (s1); /* frees it upon error */ /* drop */ free_return: for (i = 0; i < nargs; i++) { if (refs[i] != NULL) SLang_free_ref (refs[i]); } SLfile_free_fd (f); }
static int fdtype_datatype_deref (SLtype type) { SLFile_FD_Type *f; int status; int fd; (void) type; if (-1 == SLang_pop_int (&fd)) return -1; #ifdef F_GETFL while (-1 == fcntl (fd, F_GETFL)) { if (is_interrupt (errno, 1)) continue; return SLang_push_null (); } #endif f = find_chained_fd (fd); if (f != NULL) return SLfile_push_fd (f); /* The descriptor is valid, but we have no record of what it is. So make sure * it is not automatically closed. */ if (NULL == (f = SLfile_create_fd (NULL, fd))) return -1; f->flags |= _SLFD_NO_AUTO_CLOSE; status = SLfile_push_fd (f); SLfile_free_fd (f); return status; }
static void posix_fileno (void) { FILE *fp; SLang_MMT_Type *mmt; int fd; SLFile_FD_Type *f; SLFUTURE_CONST char *name; if (-1 == SLang_pop_fileptr (&mmt, &fp)) { SLang_push_null (); return; } name = SLang_get_name_from_fileptr (mmt); fd = fileno (fp); f = SLfile_create_fd (name, fd); if (f != NULL) { /* prevent fd from being closed when it goes out of scope */ f->flags |= _SLFD_NO_AUTO_CLOSE; f->close = dummy_close; } SLang_free_mmt (mmt); if (-1 == SLfile_push_fd (f)) SLang_push_null (); SLfile_free_fd (f); }
static int posix_fileno_int (void) { int fd; SLFile_FD_Type *f; if (SLang_peek_at_stack () == SLANG_FILE_PTR_TYPE) { SLang_MMT_Type *mmt; FILE *fp; if (-1 == SLang_pop_fileptr (&mmt, &fp)) return -1; fd = fileno (fp); SLang_free_mmt (mmt); return fd; } if (-1 == SLfile_pop_fd (&f)) return -1; if (-1 == get_fd (f, &fd)) fd = -1; SLfile_free_fd (f); return fd; }
static void posix_ttyname (void) { SLFile_FD_Type *f; SLang_MMT_Type *mmt; int fd; char buf[512]; int e; if (SLang_Num_Function_Args == 0) { fd = 0; f = NULL; mmt = NULL; } else if (-1 == pop_fd (&fd, &f, &mmt)) return; if (0 != (e = TTYNAME_R (fd, buf, sizeof(buf)))) { _pSLerrno_errno = e; SLang_push_null (); } else (void) SLang_push_string (buf); if (mmt != NULL) SLang_free_mmt (mmt); if (f != NULL) SLfile_free_fd (f); }
static void posix_open (void) { char *file; int mode, flags; SLFile_FD_Type *f; switch (SLang_Num_Function_Args) { case 3: if (-1 == pop_string_int_int (&file, &flags, &mode)) { SLang_push_null (); return; } break; case 2: default: if (-1 == pop_string_int (&file, &flags)) return; mode = 0777; break; } f = SLfile_create_fd (file, -1); if (f == NULL) { SLang_free_slstring (file); SLang_push_null (); return; } SLang_free_slstring (file); while (-1 == (f->fd = open (f->name, flags, mode))) { if (is_interrupt (errno, 1)) continue; SLfile_free_fd (f); SLang_push_null (); return; } if (-1 == SLfile_push_fd (f)) SLang_push_null (); SLfile_free_fd (f); }
static void posix_dup (SLFile_FD_Type *f) { if ((NULL == (f = SLfile_dup_fd (f))) || (-1 == SLfile_push_fd (f))) SLang_push_null (); SLfile_free_fd (f); }
static void destroy_fd_type (SLtype type, VOID_STAR ptr) { /* Avoid setting errno when a variable goes out of scope */ int e = _pSLerrno_errno; (void) type; SLfile_free_fd (*(SLFile_FD_Type **) ptr); e = _pSLerrno_errno; }
static int pop_fd (int *fdp) { SLFile_FD_Type *f; int status; if (SLang_peek_at_stack () == SLANG_INT_TYPE) return SLang_pop_int (fdp); if (-1 == SLfile_pop_fd (&f)) return -1; status = SLfile_get_fd (f, fdp); SLfile_free_fd (f); return status; }
static void bind_intrin (void) { Socket_Type *s; SLFile_FD_Type *f; int nargs = SLang_Num_Function_Args; Domain_Methods_Type *methods; if (-1 == SLroll_stack (-nargs)) return; if (NULL == (s = pop_socket (&f))) return; nargs--; methods = s->methods; (void)(*methods->bind)(s, nargs); SLfile_free_fd (f); }
static Socket_Type *pop_socket (SLFile_FD_Type **fp) { SLFile_FD_Type *f; Socket_Type *s; if (-1 == SLfile_pop_fd (&f)) { *fp = NULL; return NULL; } if (NULL == (s = socket_from_fd (f))) { SLfile_free_fd (f); return NULL; } *fp = f; return s; }
/* This function frees the socket before returning */ static int push_socket (Socket_Type *s) { SLFile_FD_Type *f; int status; if (s == NULL) return SLang_push_null (); if (NULL == (f = socket_to_fd (s))) { free_socket (s); return -1; } status = SLfile_push_fd (f); SLfile_free_fd (f); return status; }
static int posix_isatty (void) { int ret; SLFile_FD_Type *f; SLang_MMT_Type *mmt; int fd; if (-1 == pop_fd (&fd, &f, &mmt)) return 0; /* invalid descriptor */ if (0 == (ret = isatty (fd))) _pSLerrno_errno = errno; if (mmt != NULL) SLang_free_mmt (mmt); if (f != NULL) SLfile_free_fd (f); return ret; }
static int pop_fd (int *fdp, SLFile_FD_Type **fp, SLang_MMT_Type **mmtp) { int fd; *fp = NULL; *mmtp = NULL; switch (SLang_peek_at_stack ()) { case SLANG_FILE_PTR_TYPE: { SLang_MMT_Type *mmt; FILE *p; if (-1 == SLang_pop_fileptr (&mmt, &p)) return -1; fd = fileno (p); *mmtp = mmt; } break; case SLANG_FILE_FD_TYPE: { SLFile_FD_Type *f; if (-1 == SLfile_pop_fd (&f)) return -1; if (-1 == get_fd (f, &fd)) { SLfile_free_fd (f); return -1; } } break; default: if (-1 == SLang_pop_int (&fd)) return -1; } *fdp = fd; return 0; }
static void sl_ssl_connect (void){ int fd; SLFile_FD_Type *slfd; SLsslctx_Type *ctx; SLssl_Type *slssl; SSL *ssl; SLang_MMT_Type *sslmmt; SLang_MMT_Type *sslmmto; if (SLfile_pop_fd(&slfd) == -1) return; if (NULL==(sslmmt=SLang_pop_mmt(SLsslctx_Type_Id))) return; SLfile_get_fd(slfd,&fd); SLfile_free_fd(slfd); ctx = (SLsslctx_Type *)SLang_object_from_mmt(sslmmt); // create the ssl object ssl = SSL_new((SSL_CTX *)ctx->ctx); // set the file descriptor for input/output if (0==SSL_set_fd(ssl,fd)){ return; } // fprintf(stderr,"Set client socket fd to %d\n",fd); slssl = (SLssl_Type *)malloc(sizeof(SLssl_Type)); slssl->ssl = (void *) ssl; slssl->is_server = ctx->is_server; sslmmt = SLang_create_mmt(SLssl_Type_Id, (VOID_STAR) slssl); if (0==SLang_push_mmt(sslmmt)) return; SLang_free_mmt(sslmmt); }
/* Usage: get/setsockopt (socket, level, optname, value) */ static void getset_sockopt (int set) { Socket_Type *s; SLFile_FD_Type *f; int level, optname; SockOpt_Type *table; if (-1 == SLreverse_stack (SLang_Num_Function_Args)) return; if (NULL == (s = pop_socket (&f))) return; if ((-1 == SLang_pop_int (&level)) || (-1 == SLang_pop_int (&optname))) { SLfile_free_fd (f); return; } switch (level) { #ifdef SOL_SOCKET case SOL_SOCKET: table = SO_Option_Table; break; #endif #ifdef SOL_IP case SOL_IP: table = IP_Option_Table; break; #endif default: SLang_verror (SL_NotImplemented_Error, "get/setsockopt level %d is not supported", level); goto free_return; } while (1) { if (table->optname == optname) { int (*func)(Socket_Type *, int, int); if (set) func = table->setopt; else func = table->getopt; if (func == NULL) goto not_implemented_error; (void)(*func)(s, level, optname); break; } if (table->optname == -1) goto free_return; table++; } /* drop */ free_return: SLfile_free_fd (f); return; not_implemented_error: SLang_verror (SL_NotImplemented_Error, "get/setsockopt option %d is not supported at level %d", optname, level); SLfile_free_fd (f); }