static muroar_t muroar_open_socket (const char * server) { #if MUROAR_HDLTYPE == MUROAR_HDLTYPE_YIFF_VIO yiff_identifier_t fh = -1; #else int fh = muroar_open_socket_bsd(server); #endif muroar_t ret; if ( fh == -1 ) return MUROAR_HANDLE_INVALID; #if MUROAR_HDLTYPE == MUROAR_HDLTYPE_POSIX_SYSIO || MUROAR_HDLTYPE == MUROAR_HDLTYPE_WIN32_SOCKET ret = fh; #elif MUROAR_HDLTYPE == MUROAR_HDLTYPE_POSIX_STDIO ret = fdopen(fh, "a+"); #else #error Unsupported value for MUROAR_HDLTYPE #endif if ( ret == MUROAR_HANDLE_INVALID ) { __CLOSE(fh); return MUROAR_HANDLE_INVALID; } return ret; }
// Open Socket to server. static int muroar_open_socket_bsd (const char * server) { struct hostent * he; struct sockaddr_in in; #ifdef HAVE_AF_UNIX struct sockaddr_un un; #endif int fh = -1; char * buf = NULL; char * object; #ifdef HAVE_LIB_DNET char * node; static char localnode[16] = {0}; struct dn_naddr *binaddr; struct nodeent *dp; #endif #ifdef __WIN32 muroar_init_win32(); #endif if ( !strcmp(server, MUROAR_ABSTRACT) || (strstr(server, "/") != NULL && strstr(server, "::") == NULL) ) { // Handle AF_UNIX Sockets, // do not build on broken systems like win32 not // supporting the AF_UNIX sockets. #ifdef HAVE_AF_UNIX if ( (fh = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) return -1; un.sun_family = AF_UNIX; if ( !strcmp(server, MUROAR_ABSTRACT) ) { memset(un.sun_path, 0, sizeof(un.sun_path)); strncpy(un.sun_path + 1, "RoarAudio/UNIX/Abstract/1", sizeof(un.sun_path) - 2); } else { strncpy(un.sun_path, server, sizeof(un.sun_path) - 1); } if ( connect(fh, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) == -1 ) { __CLOSE(fh); return -1; } return fh; #else return -1; #endif } else if ( strstr(server, "::") != NULL ) { #ifdef HAVE_LIB_DNET // alloc a temp buffer so we can change the string at will: buf = strdup(server); // cut node::object into buf and object object = strstr(buf, "::"); *object = 0; object += 2; // use default if we have a zero-size node name: if ( *buf == 0 ) { if ( !localnode[0] ) { if ( (binaddr=getnodeadd()) == NULL) { free(buf); return -1; } if ( (dp = getnodebyaddr((char*)binaddr->a_addr, binaddr->a_len, AF_DECnet)) == NULL ) { free(buf); return -1; } strncpy(localnode, dp->n_name, sizeof(localnode)-1); localnode[sizeof(localnode)-1] = 0; } node = localnode; } else { node = buf; } // use default if we have a zero size object name: if ( *object == 0 ) { object = MUROAR_OBJECT; } fh = dnet_conn(node, object, SOCK_STREAM, NULL, 0, NULL, 0); // free buffer when we are done. free(buf); return fh; #else return -1; #endif } if ( strstr(server, ":") != NULL ) { buf = strdup(server); server = buf; object = strstr(buf, ":"); *object = 0; object++; if ( !*object ) /* finnaly check if this is just a tailing :, in that case we assume the default port */ object = NULL; } else { object = NULL; } if ( (he = gethostbyname(server)) == NULL ) { if ( buf != NULL ) free(buf); return -1; } memcpy((struct in_addr *)&(in.sin_addr), he->h_addr, sizeof(struct in_addr)); in.sin_family = AF_INET; if ( object != NULL ) { in.sin_port = htons(atoi(object)); } else { in.sin_port = htons(MUROAR_PORT); } if ( buf != NULL ) free(buf); if ( (fh = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) return -1; if ( connect(fh, (const struct sockaddr *)&in, sizeof(in)) == -1 ) { __CLOSE(fh); return -1; } return fh; }
/* We assume here that we are the only remaining thread. */ void attribute_hidden _stdio_term(void) { #if defined(__STDIO_BUFFERS) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) register FILE *ptr; #ifdef __UCLIBC_HAS_THREADS__ /* First, make sure the open file list is unlocked. If it was * locked, then I suppose there is a chance that a pointer in the * chain might be corrupt due to a partial store. */ __stdio_init_mutex(&_stdio_openlist_add_lock); #warning check #ifdef __STDIO_BUFFERS __stdio_init_mutex(&_stdio_openlist_del_lock); #endif /* Next we need to worry about the streams themselves. If a stream * is currently locked, then it may be in an invalid state. So we * 'disable' it in case a custom stream is stacked on top of it. * Then we reinitialize the locks. */ for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) { if (__STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(ptr)) { /* The stream is already locked, so we don't want to touch it. * However, if we have custom streams, we can't just close it * or leave it locked since a custom stream may be stacked * on top of it. So we do unlock it, while also disabling it. */ ptr->__modeflags = (__FLAG_READONLY|__FLAG_WRITEONLY); __STDIO_STREAM_DISABLE_GETC(ptr); __STDIO_STREAM_DISABLE_PUTC(ptr); __STDIO_STREAM_INIT_BUFREAD_BUFPOS(ptr); } ptr->__user_locking = 1; /* Set locking mode to "by caller". */ __stdio_init_mutex(&ptr->__lock); /* Shouldn't be necessary, but... */ } #endif /* Finally, flush all writing streams and shut down all custom streams. * NOTE: We assume that any stacking by custom streams is done on top * of streams previously allocated, and hence further down the * list. Otherwise we have no way of knowing the order in which * to shut them down. * Remember that freopen() counts as a new allocation here, even * though the stream is reused. That's because it moves the * stream to the head of the list. */ for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) { #ifdef __STDIO_BUFFERS /* Write any pending buffered chars. */ if (__STDIO_STREAM_IS_WRITING(ptr)) { __STDIO_COMMIT_WRITE_BUFFER(ptr); } #endif #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ /* Actually close all custom streams to perform any special cleanup. */ if (ptr->__cookie != &ptr->__filedes) { __CLOSE(ptr); } #endif } #endif }
int fclose(register FILE *stream) { int rv = 0; __STDIO_AUTO_THREADLOCK_VAR; #ifdef __STDIO_HAS_OPENLIST #if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS) /* First, remove the file from the open file list. */ { FILE *ptr; __STDIO_THREADLOCK_OPENLIST_DEL; __STDIO_THREADLOCK_OPENLIST_ADD; ptr = _stdio_openlist; if ((ptr = _stdio_openlist) == stream) { _stdio_openlist = stream->__nextopen; } else { while (ptr) { if (ptr->__nextopen == stream) { ptr->__nextopen = stream->__nextopen; break; } ptr = ptr->__nextopen; } } __STDIO_THREADUNLOCK_OPENLIST_ADD; __STDIO_THREADUNLOCK_OPENLIST_DEL; } #endif #endif __STDIO_AUTO_THREADLOCK(stream); __STDIO_STREAM_VALIDATE(stream); #ifdef __STDIO_BUFFERS /* Write any pending buffered chars. */ if (__STDIO_STREAM_IS_WRITING(stream)) { rv = fflush_unlocked(stream); } #endif if (__CLOSE(stream) < 0) { /* Must close even if fflush failed. */ rv = EOF; } stream->__filedes = -1; /* We need a way for freopen to know that a file has been closed. * Since a file can't be both readonly and writeonly, that makes * an effective signal. It also has the benefit of disabling * transitions to either reading or writing. */ #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) /* Before we mark the file as closed, make sure we increment the openlist use count * so it isn't freed under us while still cleaning up. */ __STDIO_OPENLIST_INC_USE; #endif stream->__modeflags &= (__FLAG_FREEBUF|__FLAG_FREEFILE); stream->__modeflags |= (__FLAG_READONLY|__FLAG_WRITEONLY); #ifndef NDEBUG __STDIO_STREAM_RESET_GCS(stream); /* Reinitialize everything (including putc since fflush could fail). */ __STDIO_STREAM_DISABLE_GETC(stream); __STDIO_STREAM_DISABLE_PUTC(stream); __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); # ifdef __UCLIBC_HAS_WCHAR__ stream->__ungot_width[0] = 0; # endif # ifdef __STDIO_MBSTATE __INIT_MBSTATE(&(stream->__state)); # endif #endif __STDIO_AUTO_THREADUNLOCK(stream); __STDIO_STREAM_FREE_BUFFER(stream); #ifdef __UCLIBC_MJN3_ONLY__ #warning REMINDER: inefficient - locks and unlocks twice and walks whole list #endif #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) /* inefficient - locks/unlocks twice and walks whole list */ __STDIO_OPENLIST_INC_DEL_CNT; __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */ #else __STDIO_STREAM_FREE_FILE(stream); #endif return rv; }