📄 main.c
字号:
MemTrace_Init (argv[0], MEMTRACE_REPORT_ON_EXIT);#endif /* ** Turn off IO buffering so that stdlib doesn't ** eat 64k blocks of memory */ setbuf(stdout, NULL); setbuf(stdin, NULL); bzero(&server, sizeof(server)); globalServer = &server; serverStartTime = time(NULL); printf("\n\nMini SQL Version %s\n",SERVER_VERSION); printf("Copyright (c) 1993-94 David J. Hughes\n"); printf("Copyright (c) 1995-2004 Hughes Technologies Pty Ltd.\n"); printf("All rights reserved.\n\n"); /* Try to set the locale but don't bail if it fails (freeBSD) */ setlocale(LC_ALL, ""); /* ** Handle the command line args */ *confFile = 0; while((c=getopt(argc,argv,"f:"))!= -1) { switch(c) { case 'f': if (*confFile) errFlag++; else strcpy(confFile,optarg); break; case '?': errFlag++; break; } } if (errFlag) { usage(); exit(1); } if (*confFile == 0) { snprintf(confFile,sizeof(confFile),"%s/msql.conf", INST_DIR); } printf("\tLoading configuration from '%s'.\n",confFile); configLoadFile(confFile); server.config.instDir=strdup(configGetCharEntry("general","inst_dir")); server.config.dbDir = strdup(configGetCharEntry("general", "db_dir")); server.config.readOnly = configGetIntEntry("system", "read_only"); server.config.msyncTimer = configGetIntEntry("system", "msync_timer"); server.config.sortMaxMem = configGetIntEntry("system","sort_max_mem"); server.config.tableCache = configGetIntEntry("system","table_cache"); server.config.cacheDescriptors = server.config.tableCache * (NUM_INDEX + 2); server.config.needFileLock = 0; server.config.hasBroker = 0; /* ** Check out the file descriptor limit ** ** Some boxes have broken getrlimit() implementations (or ** missing RLIMIT_NOFILE) so we try to use sysconf first ** ** Watch out for broken BSDI here. It looks like BSDI returns ** the kernel MAX_FILES not the per process MAX_FILE in ** getrlimit() which kinda sucks if you want to use select()! */# ifdef HAVE_RLIMIT_NOFILE getrlimit(RLIMIT_NOFILE,&limit); limit.rlim_cur = (limit.rlim_max > 256)? 256 : limit.rlim_max; setrlimit(RLIMIT_NOFILE,&limit); getrlimit(RLIMIT_NOFILE,&limit); maxCons = limit.rlim_cur - server.config.cacheDescriptors; printf("\tServer process reconfigured to accept %d ",maxCons); printf("connections.\n");# else# ifdef HAVE_SYSCONF maxCons = sysconf(_SC_OPEN_MAX)-server.config.cacheDescriptors; printf("\tServer process reconfigured to accept %d ",maxCons); printf("connections.\n");# else maxCons = 64 - server.config.cacheDescriptors; printf("\tDynamic server config failed!\n"); printf("\tServer can accept %d connections.\n", maxCons);# endif# endif cacheSize = configGetIntEntry("system", "table_cache"); if (cacheSize >= 2) printf("\tServer table cache holds %d entries.\n", cacheSize); else printf("\tServer table cache config too small. Using 2.\n"); if (maxCons > 254) maxCons = 254; /* ** Set up query logging if required */ server.logFP = NULL; if (configGetIntEntry("system","query_log")) { server.logFP = fopen(configGetCharEntry("system", "query_log_file"),"a"); if (server.logFP) { printf("\tQuery logging enabled.\n"); setbuf(server.logFP, NULL); } else { printf("\tERROR : Open of query log failed!\n"); } } server.updateFP = NULL; if (configGetIntEntry("system","update_log")) { server.updateFP = fopen(configGetCharEntry("system", "update_log_file"),"a"); if (server.updateFP) { printf("\tUpdate logging enabled.\n"); setbuf(server.updateFP, NULL); } else { printf("\tERROR : Open of update log failed!\n"); } } /* ** We have to do this now. If msql is configured to run as nobody ** then nobody would have to have write perms for the INST_DIR ** This way we can start as root and then run as the MSQL_USER when ** we're setup properly */ initDebug(1); netInitialise(); initServer(&server); (void)snprintf(path, MSQL_PATH_LEN, "%s", (char *)configGetCharEntry("general","pid_file")); pidFD = open(path, O_CREAT|O_TRUNC|O_RDWR, 0700); if (pidFD < 0) { perror("Error : Couldn't open PID file"); exit(1); } else { if (lockNonBlockingLock(pidFD) < 0) { printf("\nError : Cannot lock PID file!\n\n"); exit(1); } sprintf(pidBuf,"%d", (int)getpid()); write(pidFD, pidBuf, strlen(pidBuf) + 1); } /* ** Are we running as the right user? */ pwd = getpwuid(getuid()); if (!pwd) { printf("\nError! No username for our UID (%d)\n\n", (int)getuid()); exit(1); } uname = (char *)configGetCharEntry("general","msql_user"); if (strcmp(uname,pwd->pw_name) != 0) { pwd = getpwnam(uname); if (!pwd) { printf("\nError! Unknown username (%s)\n\n", uname); exit(1); } chown(path,pwd->pw_uid, pwd->pw_gid); chown("/proc/self/fd",pwd->pw_uid,pwd->pw_gid); if (setuid(pwd->pw_uid) < 0) { printf("\nError! Can't run as user '%s'\n\n",uname); exit(1); } } printf("\tServer running as user '%s'.\n",uname); printf("\tServer mode is %s.\n", configGetIntEntry("system", "read_only")?"Read-Only":"Read/Write"); /* ** Ensure that the correct user owns the database files */ snprintf(path,MSQL_PATH_LEN, "%s/msqldb", (char *)configGetCharEntry("general","inst_dir")); if (stat(path,&sbuf) < 0) { printf("\nError! Can't stat '%s'\n\n",path); exit(1); } if (sbuf.st_uid != getuid()) { printf("\nError! '%s' is not owned by '%s'\n\n",path, pwd->pw_name); exit(1); } /* Ensure there's no wierd FD's open */ for ( count = server.unixSock + 1; count<= 255; count++) { close(count); } /* Try to set the locale but don't bail if it fails (freeBSD) */ setlocale(LC_ALL, ""); /* ** Initialise the connection array */ count = 0; while (count < 255) { server.conArray[count].sock = -1; server.conArray[count].db = NULL; count++; } /* ** OK, on with the show */ umask(0); numCons=0; maxSock = 0; /* chdir(msqlHomeDir); */ tableCleanTmpDir(&server);# ifdef BETA_RELEASE timeRemain = (863060000 + 60*24*60*60) - time(NULL); if (timeRemain < 0) { printf("\nThis Beta test release has expired!\n"); printf("Check out www.Hughes.com.au for a new release!\n\n"); exit(1); } else { printf("\n\tThis Beta test release expires in %d days.\n\n", (int)(timeRemain / (24*60*60))); }# endif chmod(path,0700); umask(0077); setupSignals(); (void)bzero(&server.conArray,sizeof(&server.conArray)); aclLoadFile(1); msqlDebug0(MOD_GENERAL, "miniSQL debug mode. Waiting for connections.\n"); FD_ZERO(&server.clientFDs); while(1) { bcopy(&server.clientFDs, &readFDs, sizeof(readFDs)); if (server.unixSock >= 0) FD_SET(server.unixSock,&readFDs); if (server.ipSock >= 0) FD_SET(server.ipSock,&readFDs); if(select(255,&readFDs,0,0,0) < 0) { if (errno == EINTR) { eintrCount++; if(eintrCount > 100) { printf(SELECT_EINTR_ERRORS); puntServer(0); } continue; } puntServer(0); } eintrCount = 0; /* ** How about a new connection? Grab the lock so we ** can ensure the broker notification gets out before ** the new connection becomes active */ sock = 0; if (server.unixSock >= 0 && FD_ISSET(server.unixSock,&readFDs)) sock = server.unixSock; if (server.ipSock >= 0 && FD_ISSET(server.ipSock,&readFDs)) sock = server.ipSock; if (sock != 0) { struct sockaddr_un cAddr; size_t cAddrLen; if (FD_ISSET(server.unixSock,&readFDs)) sock = server.unixSock; else sock = server.ipSock; bzero(&cAddr, sizeof(cAddr)); cAddrLen = sizeof(struct sockaddr_un); newSock = accept(sock, (struct sockaddr *)&cAddr, &cAddrLen); if(newSock < 0) { perror("Error in accept "); puntServer(-1); exit(1); } if (newSock > maxSock) maxSock = newSock; if (server.conArray[newSock].db) { if(server.conArray[newSock].db) { free(server.conArray[newSock].db); server.conArray[newSock].db = NULL; } if(server.conArray[newSock].host) { free(server.conArray[newSock].host); server.conArray[newSock].host = NULL; } if(server.conArray[newSock].user) { free(server.conArray[newSock].user); server.conArray[newSock].user = NULL; } } /* ** Are we over the connection limit */ numCons++; if (numCons > maxCons) { numCons--; netError(newSock,CON_COUNT_ERROR); shutdown(newSock,2); close(newSock); continue; } /* ** store the connection details */ msqlDebug1(MOD_GENERAL, "New connection received on %d\n", newSock); error = 0; if (sock == server.ipSock) { size_t addrLen; struct hostent *hp; struct sockaddr_in remote; char *ipAddr; addrLen = sizeof(struct sockaddr); getpeername(newSock, (struct sockaddr *) &remote, &addrLen); ipAddr = inet_ntoa(remote.sin_addr); if (ipAddr) { server.conArray[newSock].clientIP = strdup(ipAddr); } if (configGetIntEntry("system","host_lookup") == 1) { /* ** Validate remote host */ if(auth_hostname(&remote)) { netError(newSock, BAD_HOST_ERROR); error = 1; numCons--; shutdown(newSock,2); close(newSock); } /* ** Grab the hostname for later */ hp = (struct hostent *)gethostbyaddr( (char *)&remote.sin_addr, sizeof(remote.sin_addr), AF_INET); } else { hp = NULL; } if (!hp) { server.conArray[newSock].host=(char *) strdup("UNKNOWN_HOST"); msqlDebug0(MOD_GENERAL, "Host=UNKNOWN_HOST\n"); } else { server.conArray[newSock].host=(char *) strdup((char *)hp->h_name); msqlDebug1(MOD_GENERAL,"Host = %s\n", hp->h_name); } } else { server.conArray[newSock].host = NULL; server.conArray[newSock].clientIP = NULL; msqlDebug0(MOD_GENERAL,"Host = UNIX domain\n"); } server.conArray[newSock].connectTime = 0; server.conArray[newSock].numQueries = 0; if (!error) { opt=1; setsockopt(newSock,SOL_SOCKET,SO_KEEPALIVE, (char *) &opt, sizeof(opt)); /* fcntl(newSock, F_SETFL, O_NONBLOCK);*/ snprintf(packet, PKT_LEN, "0:%d:%s\n", PROTOCOL_VERSION,SERVER_VERSION); netWritePacket(newSock); if (netReadPacket(newSock) <=0) { netError(newSock,HANDSHAKE_ERROR); shutdown(newSock,2); close(newSock); server.conArray[newSock].host=NULL; server.conArray[newSock].clientIP=NULL; } else { FD_SET(newSock, &server.clientFDs); uname = (char *)strtok(packet,"\n"); msqlDebug1(MOD_GENERAL, "User = %s\n",uname); if(server.conArray[newSock].user) free(server.conArray[newSock].user); server.conArray[newSock].user = (char *) strdup(uname); server.conArray[newSock].sock = newSock; netEndOfList(newSock); } } continue; } /* ** Looks like a request from an existing client */ count = 0; while(count <= maxSock) { if (server.conArray[count].sock == -1) { count++; continue; } if (!FD_ISSET(server.conArray[count].sock,&readFDs)) { count++; continue; } processClientRequest(&server, count); count++; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -