⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sysdep.c

📁 支持网络和单机的麻将游戏
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Header: /home/jcb/newmj/RCS/sysdep.c,v 11.16 2003/10/08 19:35:42 jcb Rel $ * sysdep.c * By intention, this file contains all functions that might need * fiddling with to cope with different variants of Unix. * In particular, all the networking code is in here. * Some parts of the other code assume POSIXish functions for file * descriptors and the like; this file is responsible for providing them * if they're not native. All such cases that occurred to me as I was * writing them can be found by searching for sysdep.c in the other * files. *//****************** COPYRIGHT STATEMENT ********************** * This file is Copyright (c) 2000 by J. C. Bradfield.       * * Distribution and use is governed by the LICENCE file that * * accompanies this file.                                    * * The moral rights of the author are asserted.              * *                                                           * ***************** DISCLAIMER OF WARRANTY ******************** * This code is not warranted fit for any purpose. See the   * * LICENCE file for further information.                     * *                                                           * *************************************************************/static const char rcs_id[] = "$Header: /home/jcb/newmj/RCS/sysdep.c,v 11.16 2003/10/08 19:35:42 jcb Rel $";#include "sysdep.h"#include <string.h>#include <fcntl.h>#ifndef WIN32#include <sys/socket.h>#include <netinet/in.h>/* needed for HP-UX 11 with _XOPEN_SOURCE_EXTENDED */#include <arpa/inet.h>#include <sys/un.h>/* this is modern, I think. */#include <netdb.h>#include <pwd.h>#endif /* not WIN32 */#include <stdlib.h>#include <stdarg.h>#include <time.h>#include <signal.h>#ifdef WIN32#include <io.h>#include <fcntl.h>#endif/* warn: = fprintf(stderr,...), with automatic new line *//* log_msg is a generalized version with a syslog like warning   level. Currently only two levels are defined by the   LogLevel enum, LogWarning and LogInfo. */int (*log_msg_hook)(LogLevel l,char *);static char *log_prefixes[] = { "" , "-I- ", "+W+ " };/* internal function */static int vlog_msg(LogLevel l, char *format,va_list args) {  char buf[1024];  int ret;  int n;  strcpy(buf,log_prefixes[l]);  n = strlen(log_prefixes[l]);  /* My Windows/Mingw installation doesn't have vsnprintf!     Oh well, we'll just hope it doesn't overflow. */#ifdef WIN32  ret = vsprintf(buf+n,format,args);#else  /* reserve 1 char for extra '\n' */  ret = vsnprintf(buf+n,sizeof(buf)-n-1,format,args);#endif  buf[1023] = 0;  n = strlen(buf);  /* do quick check for terminators */#ifdef WIN32  if ( buf[n-2] == '\r' ) {    /* OK */    ;  } else if ( buf[n-1] == '\n' ) {    /* already have unix terminator */    buf[n-1] = '\r' ; buf[n] = '\n' ; buf[n+1] = 0 ;  } else {    /* no terminator */    strcat(buf,"\r\n");  }#else  if ( buf[n-1] != '\n' ) strcat(buf,"\n");#endif  /* call the hook */  if ( log_msg_hook == NULL || log_msg_hook(l,buf) == 0 ) {    fprintf(stderr,"%s",buf);  }  return ret;}int log_msg(LogLevel l,char *format,...) {  va_list args;  va_start(args,format);  return vlog_msg(l,format,args);}int warn(char *format,...) {  va_list args;  va_start(args,format);  return vlog_msg(LogWarning,format,args);}int info(char *format,...) {  va_list args;  va_start(args,format);  return vlog_msg(LogInfo,format,args);}/* ignore the SIGPIPE signal. Return 0 on success, -1 on error */int ignore_sigpipe(void) {#ifdef WIN32  return 0;#else  /* this is just posix at present */  struct sigaction act;  act.sa_handler = SIG_IGN;  sigemptyset(&act.sa_mask);  act.sa_flags = 0;  return sigaction(SIGPIPE,&act,NULL);#endif /* WIN32 */}/* functions to be applied by the socket routines */static void *(*skt_open_transform)(SOCKET) = NULL;static int (*skt_closer)(void *) = NULL;static int (*skt_reader)(void *, void *, size_t) = NULL;static int (*skt_writer)(void *, const void *,size_t) = NULL;static int sockets_initialized = 0;#ifdef WIN32static void shutdown_sockets(void) {  WSACleanup();  /* I don't care what it returns */}#endif /* WIN32 *//* initialize sockets */int initialize_sockets(void *(*open_transform)(SOCKET),		       int (*closer)(void *),		       int (*reader)(void *, void *, size_t),		       int (*writer)(void *, const void *,size_t)) {  skt_open_transform = open_transform;  skt_closer = closer;  skt_reader = reader;  skt_writer = writer;#ifdef WIN32  if ( ! sockets_initialized ) {    WORD version;    WSADATA data;    int err;        version = MAKEWORD( 2, 2 );        err = WSAStartup( version, &data );    if (err != 0) {      return 0;    }    if ((LOBYTE( data.wVersion ) != 2) || (HIBYTE( data.wVersion ) != 2)) {      WSACleanup();      return 0;    }    if ( atexit(shutdown_sockets) != 0 ) {      warn("couldn't register socket shutdown routine");    }  }#endif /* WIN32 */  sockets_initialized = 1;  return 1;}/* this function takes a string and parses it as an address.   It returns 0 for an Internet address, 1 for a Unix address.   For Internet addresses, the host name and port are placed   in the given variables (the string had better be long enough);   for Unix, the file name is copied to the given variable.*/static int parse_address(const char *address,			 char *ret_host,			 unsigned short *ret_port,			 char *ret_file) {  if ( strchr(address,':') ) {    /* grrr */    if ( address[0] == ':' ) {      strcpy(ret_host,"localhost");      sscanf(address,":%hu",ret_port);    } else {      sscanf(address,"%[^:]:%hu",ret_host,ret_port);    }    return 0;  } else {    if ( ret_file) strcpy(ret_file,address);    return 1;  }}/* set_up_listening_socket:   Set up a socket listening on the given address.   Return its fd.*/SOCKET set_up_listening_socket(const char *address) {  SOCKET sfd;  struct protoent *prstruc = NULL;  struct sockaddr_in inaddr;#ifndef WIN32  struct sockaddr_un unaddr;#endif  int unixsockets;  unsigned short port;  char name[256];  int sockopt;  if ( ! sockets_initialized ) initialize_sockets(NULL,NULL,NULL,NULL);  unixsockets = #ifdef WIN32    parse_address(address,name,&port,NULL);#else    parse_address(address,name,&port,unaddr.sun_path);#endif /* WIN32 */#ifdef WIN32  if ( unixsockets ) {    warn("unix sockets not available on Windows");    return INVALID_SOCKET;  }#endif /* WINDOWS */  if ( !unixsockets ) {    prstruc = getprotobyname("tcp");    if ( prstruc == NULL ) {      perror("getprotobyname failed");      return INVALID_SOCKET;    }  }  sfd = socket(unixsockets ? AF_UNIX : AF_INET,	       SOCK_STREAM,	       unixsockets ? 0 : prstruc->p_proto);  if ( sfd == INVALID_SOCKET ) {    perror("socket failed");    return INVALID_SOCKET;  }  sockopt=1;  setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,(void *)&sockopt,sizeof(int));#ifndef WIN32  if ( unixsockets ) {    unaddr.sun_family = AF_UNIX;    unlink(unaddr.sun_path); /* need to check success FIXME */    if ( bind(sfd,(struct sockaddr *)&unaddr,sizeof(struct sockaddr_un)) < 0 ) {      perror("bind failed");      return INVALID_SOCKET;    }  } else {#else  if ( 1 ) {#endif /* WIN32 */    inaddr.sin_family = AF_INET;    inaddr.sin_port = htons(port);    inaddr.sin_addr.s_addr = INADDR_ANY;    if ( bind(sfd,(struct sockaddr *)&inaddr,sizeof(struct sockaddr_in)) < 0 ) {      perror("bind failed");      return INVALID_SOCKET;    }  }  if ( listen(sfd,5) < 0 ) {    perror("listen failed");    return INVALID_SOCKET;  }    if ( skt_open_transform ) {    return (SOCKET) skt_open_transform(sfd);  } else {    return sfd;  }}    /* accept_new_connection:   A connection has arrived on the socket fd.   Accept the connection, and return the new fd,   or INVALID_SOCKET on error.*/SOCKET accept_new_connection(SOCKET fd) {  SOCKET newfd;  struct sockaddr saddr;  struct linger l = { 1, 1000 } ; /* linger on close for 10 seconds */  socklen_t saddrlen = sizeof(saddr);  if ( ! sockets_initialized ) initialize_sockets(NULL,NULL,NULL,NULL);  newfd = accept(fd,&saddr,&saddrlen);  if ( newfd == INVALID_SOCKET ) { perror("accept failed"); }  /* we should make sure that data is sent when this socket is closed */  if ( setsockopt(newfd,SOL_SOCKET,SO_LINGER,(void *)&l,sizeof(l)) < 0 ) {    warn("setsockopt failed");  }  if ( skt_open_transform ) {    return (SOCKET) skt_open_transform(newfd);  } else {    return newfd;  }}/* connect_to_host:   Establish a connection to the given address.   Return the file descriptor or INVALID_SOCKET on error.   If unixsockets, only the port number is used in making the name   The returned socket is marked close-on-exec .*/SOCKET connect_to_host(const char *address) {  SOCKET fd;  struct sockaddr_in inaddr;#ifndef WIN32  struct sockaddr_un unaddr;#endif  char name[512];  int unixsockets;  unsigned short port;  struct hostent *hent = NULL;  struct protoent *prstruc = NULL;  if ( ! sockets_initialized ) initialize_sockets(NULL,NULL,NULL,NULL);#ifdef WIN32  unixsockets = parse_address(address,name,&port,NULL);  if ( unixsockets ) {    warn("Unix sockets not supported on Windows");    return INVALID_SOCKET;  }#else  unixsockets = parse_address(address,name,&port,unaddr.sun_path);#endif /* WIN32 */  if ( !unixsockets ) {    hent = gethostbyname(name);        if ( ! hent ) {      perror("connect_to_host: gethostbyname failed");      return INVALID_SOCKET;    }        prstruc = getprotobyname("tcp");    if ( prstruc == NULL ) {      perror("connect_to_host: getprotobyname failed");      return INVALID_SOCKET;    }  }  fd = socket(unixsockets ? AF_UNIX : AF_INET,	      SOCK_STREAM,	      unixsockets ? 0 : prstruc->p_proto);  if ( fd == INVALID_SOCKET ) {    perror("connect_to_host: socket failed");    return INVALID_SOCKET;  }#ifndef WIN32  if ( unixsockets ) {    unaddr.sun_family = AF_UNIX;    if ( connect(fd,(struct sockaddr *)&unaddr,sizeof(struct sockaddr_un)) < 0 ) {      perror("connect_to_host: connect failed");      return INVALID_SOCKET;    }  } else {#else  if ( 1 ) {#endif /* WIN32 */    inaddr.sin_family = AF_INET;    inaddr.sin_port = htons(port);    inaddr.sin_addr = *((struct in_addr *)hent->h_addr);    if ( connect(fd,(struct sockaddr *)&inaddr,sizeof(struct sockaddr_in)) < 0 ) {      perror("connect_to_host: connect failed");      return INVALID_SOCKET;    }  }  #ifndef WIN32  /* mark close on exec */  fcntl(fd,F_SETFD,1);#endif /* WIN32 */  if ( skt_open_transform ) {    return (SOCKET) skt_open_transform(fd);  } else {    return fd;  }}/* close a network connection */int close_socket(SOCKET s) {  if ( skt_closer ) {    return skt_closer((void *)s);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -