This is msqld.c in view mode; [Download] [Up]
/* ** msqld.c - ** ** ** Copyright (c) 1993-95 David J. Hughes ** Copyright (c) 1995 Hughes Technologies Pty Ltd ** ** Permission to use, copy, and distribute for non-commercial purposes, ** is hereby granted without fee, providing that the above copyright ** notice appear in all copies and that both the copyright notice and this ** permission notice appear in supporting documentation. ** ** This software is provided "as is" without any expressed or implied warranty. ** ** ID = "$Id:" ** */ #include <stdio.h> #include <fcntl.h> #include <limits.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdlib.h> #include <varargs.h> #include "version.h" #include "common/portability.h" #ifdef HAVE_SYS_UN_H # include <sys/un.h> #endif #include <signal.h> #include <netdb.h> #ifdef HAVE_SELECT_H # include <select.h> #endif #ifdef HAVE_SYS_SELECT_H # include <sys/select.h> #endif #include "common/site.h" #include "common/debug.h" #include "msql_priv.h" #include "errmsg.h" extern char *yytext; extern int yylineno; extern int yydebug; extern char errMsg[]; int curSock, IPsock, UNIXsock, numCons; char *unixPort; #define MAX_SOCK_NUM 100 cinfo_t conArray[MAX_SOCK_NUM]; extern char *packet; char PROGNAME[] = "msqld", BLANK_ARGV[] = " "; #define safeFree(x) { if(x){ (void)free(x); x = NULL; } } void sigTrap(sig) int sig; { int clientSock; signal(sig,SIG_IGN); fprintf(stderr,"\nHit by a sig %d\n\n",sig); clientSock = 3; printf("\n\nForced server shutdown due to bad signal!\n\n"); while(clientSock < MAX_SOCK_NUM) { if (conArray[clientSock].db) { printf("Forcing close on Socket %d\n",clientSock); shutdown(clientSock,2); close(clientSock); } clientSock++; } shutdown(IPsock,2); close(IPsock); #ifdef HAVE_SYS_UN_H shutdown(UNIXsock,2); close(UNIXsock); unlink(unixPort); #endif printf("\n"); abort(); } sendError(fd,err) char *err; { # ifdef DEBUG printf("Send error called\n"); # endif if (err) sprintf(packet,"-1:%s\n",err); else sprintf(packet,"-1:%s\n",errMsg); writePkt(fd); } sendOK(fd) { # ifdef DEBUG printf("Send OK called\n"); # endif sprintf(packet,"1:\n"); writePkt(fd); } /**************************************************************************** ** _initServer ** ** Purpose : ** Args : ** Returns : ** Notes : */ initServer() { int sock, tcpPort, addrLen; struct sockaddr_in IPaddr; struct servent *serv_ptr; char *envVar; #ifdef HAVE_SYS_UN_H struct sockaddr_un UNIXaddr; #endif /* ** Create an IP socket */ tcpPort = MSQL_PORT; if ((serv_ptr = getservbyname("msql", "tcp"))) { tcpPort = serv_ptr->s_port; } if ((envVar = getenv("MSQL_TCP_PORT"))) { tcpPort = atoi(envVar); } msqlDebug(MOD_GENERAL,"IP Socket is %d\n",tcpPort); IPsock = socket(AF_INET, SOCK_STREAM, 0); if (IPsock < 0) { perror("Can't start server : IP Socket "); exit(1); } (void)bzero(&IPaddr, sizeof(IPaddr)); IPaddr.sin_family = AF_INET; IPaddr.sin_addr.s_addr = htonl(INADDR_ANY); IPaddr.sin_port = htons(tcpPort); if (bind(IPsock, (struct sockaddr *)&IPaddr, sizeof(IPaddr)) < 0) { perror("Can't start server : IP Bind "); exit(1); } listen(IPsock,5); #ifdef HAVE_SYS_UN_H /* ** Create the UNIX socket */ unixPort = MSQL_UNIX_ADDR; if ((envVar = getenv("MSQL_UNIX_PORT"))) { unixPort = envVar; } msqlDebug(MOD_GENERAL,"UNIX Socket is %s\n",unixPort); UNIXsock = socket(AF_UNIX, SOCK_STREAM, 0); if (UNIXsock < 0) { perror("Can't start server : UNIX Socket "); exit(1); } (void)bzero(&UNIXaddr, sizeof(UNIXaddr)); UNIXaddr.sun_family = AF_UNIX; strcpy(UNIXaddr.sun_path, unixPort); unlink(unixPort); if (bind(UNIXsock, (struct sockaddr *)&UNIXaddr, sizeof(UNIXaddr)) < 0) { perror("Can't start server : UNIX Bind "); exit(1); } listen(UNIXsock,5); #endif } RETSIGTYPE puntServer(sig) int sig; { int clientSock; signal(sig,SIG_IGN); clientSock = 3; if (sig == -1) { printf("\n\nNormal Server shutdown!\n\n"); } else { printf("\n\nServer Aborting!\n\n"); } while(clientSock < MAX_SOCK_NUM) { if (conArray[clientSock].db) { printf("Forcing close on Socket %d\n",clientSock); shutdown(clientSock,2); close(clientSock); } clientSock++; } shutdown(IPsock,2); close(IPsock); #ifdef HAVE_SYS_UN_H shutdown(UNIXsock,2); close(UNIXsock); unlink(unixPort); #endif printf("\n"); dropCache(); if (debugSet(MOD_MALLOC)) { fprintf(stderr,"\n\nmalloc() leak detection .....\n"); checkBlocks(MALLOC_BLK); } if (debugSet(MOD_MMAP)) { fprintf(stderr,"\n\nmmap() leak detection .....\n"); checkBlocks(MMAP_BLK); } printf("\n\nmSQL Daemon Shutdown Complete.\n\n"); if (sig >= 0) { exit(1); } } yyerror(s) char *s; { sprintf(packet,"-1:%s near \"%s\"\n", s, yytext?yytext:""); writePkt(curSock); msqlClean(); } static int curComSock; static fd_set *clientFdSet; static setConnectionState(sock, fds) int sock; fd_set *fds; { curComSock = sock; clientFdSet = fds; } RETSIGTYPE puntClient(sig) int sig; { signal(sig, puntClient); if (clientFdSet) { FD_CLR(curComSock, clientFdSet); shutdown(curComSock,2); close(curComSock); if (conArray[curComSock].db) { safeFree(conArray[curComSock].db); safeFree(conArray[curComSock].host); safeFree(conArray[curComSock].user); } conArray[curComSock].db = NULL; printf("Forced close of client on socket %d due to pipe sig\n", curComSock); numCons--; } } setupSignals() { #ifdef SIGSEGV signal(SIGSEGV,sigTrap); #endif #ifdef SIGBUS signal(SIGBUS,sigTrap); #endif #ifdef SIGINT signal(SIGINT,puntServer); #endif #ifdef SIGQUIT signal(SIGQUIT,puntServer); #endif #ifdef SIGKILL signal(SIGKILL,puntServer); #endif #ifdef SIGPIPE signal(SIGPIPE,puntClient); #endif #ifdef SIGTERM signal(SIGTERM,puntServer); #endif #ifdef SIGHUP signal(SIGHUP,SIG_IGN); #endif } main(argc,argv) int argc; char *argv[]; { fd_set readFDs, clientFDs; int sock, newSock, comSock, command, opt, sig, error; char dbname[30], *uname, *cp, *prog, *arg, path[255]; FILE *pidFile; /* ** We have enough space for fiddling with the argv, continue */ msqlHomeDir = (char *)getenv("MSQL_HOME"); if (!msqlHomeDir) { msqlHomeDir = INST_DIR; } umask(0); numCons=0; chdir(msqlHomeDir); printf("\n\nmSQL Server %s starting ...\n\n",SERVER_VERSION); initDebug(); initNet(); initServer(); initBackend(); (void)sprintf(path,"%s/msqld.pid",PID_DIR); pidFile = fopen(path,"w"); if (!pidFile) { perror("Couldn't open PID file"); } else { fprintf(pidFile,"%d",getpid()); fclose(pidFile); } chmod(path,0644); umask(0); setupSignals(); msqlLoadAcl(1); (void)bzero(&clientFDs,sizeof(fd_set)); msqlDebug(MOD_GENERAL,"miniSQL debug mode. Waiting for connections.\n"); while(1) { (void)bcopy(&clientFDs,&readFDs,sizeof(fd_set)); FD_SET(IPsock,&readFDs); #ifdef HAVE_SYS_UN_H FD_SET(UNIXsock,&readFDs); #endif if(select(MAX_SOCK_NUM+1,&readFDs,0,0,0) < 0) continue; /* ** Is this a new connection request */ sock = 0; if (FD_ISSET(IPsock,&readFDs)) { sock = IPsock; } #ifdef HAVE_SYS_UN_H if (FD_ISSET(UNIXsock,&readFDs)) { sock = UNIXsock; } #endif if (sock) { struct sockaddr_in cAddr; struct sockaddr dummy; int cAddrLen, dummyLen; cAddrLen = sizeof(struct sockaddr_in); newSock = accept(sock, (struct sockaddr *)&cAddr, &cAddrLen); if(newSock < 0) { perror("Error in accept "); continue; } dummyLen = sizeof(struct sockaddr); if (getsockname(newSock,&dummy, &dummyLen) < 0) { perror("Error on new connection socket"); continue; } if (conArray[newSock].db) { safeFree(conArray[newSock].db); safeFree(conArray[newSock].host); safeFree(conArray[newSock].user); conArray[newSock].db = NULL; } /* ** Are we over the connection limit */ numCons++; if (numCons > MAX_CON) { numCons--; sendError(newSock,CON_COUNT_ERROR); shutdown(newSock,2); close(newSock); continue; } /* ** store the connection details */ msqlDebug(MOD_GENERAL,"New connection received on %d\n", newSock); error = 0; if (sock == IPsock) { int addrLen; struct hostent *hp; addrLen = sizeof(struct sockaddr); getpeername(newSock, (struct sockaddr *) &conArray[newSock].remote, &addrLen); addrLen = sizeof(struct sockaddr); getsockname(newSock, (struct sockaddr *) &conArray[newSock].local, &addrLen); hp = (struct hostent *)gethostbyaddr( (char *)&conArray[newSock].remote.sin_addr, sizeof(conArray[newSock].remote.sin_addr), AF_INET); if (!hp) { sendError(newSock, BAD_HOST_ERROR); error = 1; shutdown(newSock,2); close(newSock); } else { conArray[newSock].host = (char *) strdup(hp->h_name); msqlDebug(MOD_GENERAL,"Host = %s\n", hp->h_name); } } else { conArray[newSock].host = NULL; bzero(&conArray[newSock].local, sizeof(struct sockaddr)); bzero(&conArray[newSock]. remote,sizeof(struct sockaddr)); msqlDebug(MOD_GENERAL,"Host = UNIX domain\n"); } setConnectionState(newSock,&clientFDs); if (!error) { opt=1; setsockopt(newSock,SOL_SOCKET,SO_KEEPALIVE, (char *) &opt, sizeof(opt)); sprintf(packet, "0:%d:%s\n", PROTOCOL_VERSION,SERVER_VERSION); writePkt(newSock); if (readPkt(newSock) <=0) { sendError(newSock,HANDSHAKE_ERROR); shutdown(newSock,2); close(newSock); conArray[newSock].host = NULL; bzero(&conArray[newSock].local, sizeof(struct sockaddr)); bzero(&conArray[newSock]. remote,sizeof(struct sockaddr)); } else { FD_SET(newSock,&clientFDs); uname = (char *)strtok(packet,"\n"); msqlDebug(MOD_GENERAL,"User = %s\n",uname); conArray[newSock].user = (char *) strdup(uname); sprintf(packet,"-100:\n"); writePkt(newSock); } } continue; } /* ** This must be a command. */ comSock = 3; while(comSock < MAX_SOCK_NUM) { if (FD_ISSET(comSock,&readFDs)) { setConnectionState(comSock,&clientFDs); if (readPkt(comSock) <= 0) { msqlDebug(MOD_GENERAL, "Command read on sock %d failed!\n", comSock); command = QUIT; } else { command = atoi(packet); } msqlDebug(MOD_GENERAL,"Command on sock %d = %d (%s)\n", comSock, command, comTable[command]); switch(command) { case INIT_DB: cp=(char *)strtok(packet+2,"\n\r"); strcpy(dbname,cp); msqlDebug(MOD_GENERAL,"DBName = %s\n", dbname); conArray[comSock].access = msqlCheckAccess( dbname, conArray + comSock); if(conArray[comSock].access == NO_ACCESS) { sendError(comSock, ACCESS_DENIED_ERROR); break; } if (msqlInit(dbname) < 0) { sendError(comSock,NULL); } else { sendOK(comSock); conArray[comSock].db = (char *)strdup(dbname); msqlSetDB(dbname); } break; case QUERY: if (!conArray[comSock].db) { sendError(comSock,NO_DB_ERROR); break; } curSock = comSock; cp=(char *)(packet+2); arg = (char *)strdup(cp); if (debugSet(MOD_QUERY)) fprintf(stderr,"\n"); msqlDebug(MOD_QUERY,"Query = %s",arg); msqlSetDB(conArray[comSock].db); msqlSetPerms(conArray[comSock].access); msqlParseQuery(arg,comSock); safeFree(arg); break; case DB_LIST: curSock = comSock; msqlListDBs(comSock); break; case TABLE_LIST: if (!conArray[comSock].db) { sendError(comSock, NO_DB_ERROR); break; } curSock = comSock; msqlListTables(comSock,conArray[comSock].db); break; case FIELD_LIST: if (!conArray[comSock].db) { sendError(comSock,NO_DB_ERROR); break; } cp=(char *)strtok(packet+2, "\n\r"); arg = (char *)strdup(cp); curSock = comSock; msqlListFields(comSock, arg,conArray[comSock].db); break; case QUIT: msqlDebug(MOD_GENERAL,"DB QUIT!\n"); FD_CLR(comSock,&clientFDs); shutdown(comSock,2); close(comSock); if (conArray[comSock].db) { safeFree(conArray[comSock].db); safeFree(conArray[comSock].host); safeFree(conArray[comSock].user); } conArray[comSock].db = NULL; numCons--; break; case CREATE_DB: if (!msqlCheckLocal(conArray + comSock)) { sendError(comSock,PERM_DENIED_ERROR); break; } cp=(char *)strtok(packet+2, "\n\r"); arg = (char *)strdup(cp); msqlCreateDB(comSock,arg); break; case DROP_DB: if (!msqlCheckLocal(conArray + comSock)) { sendError(comSock,PERM_DENIED_ERROR); break; } cp=(char *)strtok(packet+2, "\n\r"); arg = (char *)strdup(cp); msqlDropDB(comSock,arg); break; case RELOAD_ACL: if (!msqlCheckLocal(conArray + comSock)) { sendError(comSock,PERM_DENIED_ERROR); break; } (void)sprintf(packet,"-100:\n"); reloadAcls(comSock); writePkt(comSock); break; case SHUTDOWN: if (!msqlCheckLocal(conArray + comSock)) { sendError(comSock,PERM_DENIED_ERROR); break; } sprintf(packet,"-100:\n"); writePkt(comSock); puntServer(-1); exit(0); break; default: sendError(comSock, UNKNOWN_COM_ERROR); break; } msqlDebug(MOD_GENERAL,"Command Processed!\n"); } comSock++; } } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.