/* //- // ========================================================================== // Copyright (C) 1995 - 2005 Alias Systems Corp. and/or its licensors. All // rights reserved. // // The coded instructions, statements, computer programs, and/or related // material (collectively the "Data") in these files are provided by Alias // Systems Corp. ("Alias") and/or its licensors for the exclusive use of the // Customer (as defined in the Alias Software License Agreement that // accompanies this Alias software). Such Customer has the right to use, // modify, and incorporate the Data into other products and to distribute such // products for use by end-users. // // THE DATA IS PROVIDED "AS IS". ALIAS HEREBY DISCLAIMS ALL WARRANTIES // RELATING TO THE DATA, INCLUDING, WITHOUT LIMITATION, ANY AND ALL EXPRESS OR // IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. IN NO EVENT SHALL ALIAS BE LIABLE FOR ANY DAMAGES // WHATSOEVER, WHETHER DIRECT, INDIRECT, SPECIAL, OR PUNITIVE, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, OR IN EQUITY, // ARISING OUT OF ACCESS TO, USE OF, OR RELIANCE UPON THE DATA. // ========================================================================== //+ */ #include #include #include #include #include #include #include #ifndef _WIN32 # include # include # include # include #else # include # include # include #endif //wIN32 #ifdef LINUX #define GETOPTHUH '?' #endif /* LINUX */ #ifdef _WIN32 char * optarg = NULL; int optind = 1; int opterr = 0; int optlast = 0; #define GETOPTHUH 0 int getopt(int argc, char **argv, char *pargs) { if (optind >= argc) return EOF; if (optarg==NULL || optlast==':') { optarg = argv[optind]; if (*optarg!='-' && *optarg!='/') return EOF; } if (*optarg=='-' || *optarg=='/') optarg++; pargs = strchr(pargs, *optarg); if (*optarg) optarg++; if (*optarg=='\0') { optind++; optarg = NULL; } if (pargs == NULL) return 0; //error if (*(pargs+1)==':') { if (optarg==NULL) { if (optind >= argc) return EOF; // we want a second paramter optarg = argv[optind]; } optind++; } optlast = *(pargs+1); return *pargs; } #else #define closesocket close #endif /* * Missing prototypes */ #ifndef _WIN32 #include #include #else #define bzero ZeroMemory #include #include #endif #ifndef lengthof #define lengthof(array) (sizeof(array) / sizeof(array[0])) #endif /* lengthof */ static int daemon_mode = 0; static int inetd_mode = 0; static int show_usage = 0; static int verbose = 0; static int debug_mode = 0; static char program[80]; static char *server_name = program; static CapChannel hours, minutes, seconds; static int handle_client(int client_fd); static void get_data(int client_fd); static int create_channels(int client_fd); int main(int argc, char **argv) { int opt; #ifndef _WIN32 char *cptr; #endif int status; int client_fd = -1; /* * Grab a copy of the program name */ #ifdef _WIN32 _splitpath (argv[0], NULL, NULL, program, NULL); #else cptr = strrchr(argv[0], '/'); if (cptr) { strcpy(program, (cptr + 1)); } else { strcpy(program, argv[0]); } #endif //WIN32 /* * Parse the options */ #ifdef DEVEL while ((opt = getopt(argc, argv, "hdvDin:")) != -1) #else /* DEVEL */ while ((opt = getopt(argc, argv, "hdn:")) != -1) #endif /* DEVEL */ { switch (opt) { case 'h': show_usage++; break; case 'd': daemon_mode++; break; case 'D': debug_mode++; break; case 'i': inetd_mode++; break; case 'n': server_name = optarg; break; case 'v': verbose++; break; case GETOPTHUH: show_usage++; } } /* * Check for errors */ if (daemon_mode && inetd_mode) show_usage++; if (optind < argc) show_usage++; if (show_usage) { fprintf(stderr, "Usage:\n"); #ifdef DEVEL fprintf(stderr, " %s [-hdvDi] [-n name]\n", program); #else /* DEVEL */ fprintf(stderr, " %s [-hd] [-n name]\n", program); #endif /* DEVEL */ fprintf(stderr, "\n"); fprintf(stderr, " -h Print this help message\n"); fprintf(stderr, " -d Run as a daemon in the background\n"); #ifdef DEVEL fprintf(stderr, " -i Run from inetd\n"); fprintf(stderr, " -D Set the debug flag\n"); fprintf(stderr, " -v Set the vebose flag\n"); #endif /* DEVEL */ fprintf(stderr, " -n name Set the UNIX socket name to name\n"); fprintf(stderr, "\n"); fprintf(stderr, "Defaults:\n"); fprintf(stderr, " %s -n %s\n", program, program); fprintf(stderr, "\n"); exit(1); } if (inetd_mode) { /* * The socket to the client is open on file descriptor 0. * Handle one client and then exit. */ client_fd = 0; } if (daemon_mode) { /* * Convert this process into a standard unix type daemon process. * It will be running in the background with no controlling terminal * and using syslog to report error messages. */ status = CapDaemonize(); if (status < 0) { CapError(-1, CAP_SEV_FATAL, program, NULL); exit(1); } } if (inetd_mode) { /* * The socket to the client is already open on file descriptor 0. * Handle one client and then exit. */ status = handle_client(client_fd); exit(status); } else { while (1) { /* * Set up the server socket and wait for a connection. */ client_fd = CapServe(server_name); if (client_fd < 0) { CapError(-1, CAP_SEV_FATAL, program, NULL); exit(1); } /* Handle client requests */ status = handle_client(client_fd); if (status < 0) { CapError(-1, CAP_SEV_FATAL, program, NULL); } /* Shutdown the client */ closesocket(client_fd); client_fd = -1; /* Go back and wait for another connection request */ continue; } } return 0; } static int handle_client(int client_fd) { int status; CapCommand cmd; char ruser[64], rhost[64], realhost[64]; fd_set rd_fds; struct timeval base_timeout, timeout; int recording = 0; static int channels_created = 0; base_timeout.tv_sec = 1; base_timeout.tv_usec = 0; while (1) { FD_ZERO(&rd_fds); FD_SET((unsigned int)client_fd, &rd_fds); timeout.tv_sec = base_timeout.tv_sec; timeout.tv_usec = base_timeout.tv_usec; status = select(FD_SETSIZE, &rd_fds, NULL, NULL, &timeout); if (status < 0) { #ifndef _WIN32 if (errno == EINTR) { /* Ignore signals and try again */ continue; } #endif /*WIN32*/ /* Otherwise, give a fatal error message */ CapError(client_fd, CAP_SEV_FATAL, program, "select failed"); CapError(client_fd, CAP_SEV_FATAL, "select", NULL); exit(1); } else if (status == 0) { /* We got a timeout */ if (recording) get_data(client_fd); /* Try again */ continue; } else { /* There is data on the client file descriptor */ cmd = CapGetCommand(client_fd); switch (cmd) { case CAP_CMD_QUIT: return 0; #ifdef _WIN32 case CAP_CMD_ERROR: return -1; #endif case CAP_CMD_AUTHORIZE: status = CapGetAuthInfo(client_fd, ruser, rhost, realhost); if (status < 0) { return -1; } /* * If user@host is not authorized to use this server then: * * status = CapAuthorize(client_fd, 0); */ status = CapAuthorize(client_fd, 1); break; case CAP_CMD_INIT: /* Initial client/server handshake */ status = CapInitialize(client_fd, program); break; case CAP_CMD_VERSION: /* Send version information */ status = CapVersion(client_fd, program, "1.0", "Clock capture server - v1.0"); break; case CAP_CMD_INFO: if (!channels_created) { /* Only create the channel data once */ status = create_channels(client_fd); if (status < 0) { break; } channels_created = 1; } #ifdef SERVER_SIDE_RECORDING /* The server side recording returns incorrect time in * the current version */ status = CapInfo(client_fd, 1.0, 100.0, 10.0, 512 * 1024, 1); #else status = CapInfo(client_fd, 0.0, 0.0, 0.0, 512 * 1024, 1); #endif break; case CAP_CMD_DATA: /* Send frame data */ get_data(client_fd); status = CapData(client_fd); break; #ifdef SERVER_SIDE_RECORDING /* The server side recording returns incorrect time in * the current version */ case CAP_CMD_START_RECORD: /* Start recording */ { int size = 0; float rate = 0.0f, time = 0.0f; rate = CapGetRequestedRecordRate(client_fd); size = CapGetRequestedRecordSize(client_fd); /* Convert rate in Hz to a timeout value in a timeval structure */ if (rate < 1.0) rate = 1.0; if (rate > 100.0) rate = 100.0; time = 1.0 / rate; base_timeout.tv_sec = time; base_timeout.tv_usec = (time - base_timeout.tv_sec) * 1000000; status = CapStartRecord(client_fd, rate, size); if (status != -1) { recording = 1; } break; } case CAP_CMD_STOP_RECORD: /* Stop recording */ status = CapStopRecord(client_fd); recording = 0; base_timeout.tv_sec = 1; base_timeout.tv_usec = 0; break; #endif /* server side recording */ default: /* Ignore unknown commands */ status = CapError(client_fd, CAP_SEV_ERROR, program, "Unknown server command."); break; } if (status < 0) { return -1; } } } /* return 0; */ } #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #define ANGLE(t, a) (((t) % (a)) * 2 * M_PI / (a)) static void get_data(int client_fd) { time_t now, midnight; struct tm *local; time_t elapsed; float hangle, mangle, sangle; now = time(0); local = localtime(&now); local->tm_hour = 0; local->tm_min = 0; local->tm_sec = 0; midnight = mktime(local); elapsed = now - midnight; hangle = (float) -ANGLE(elapsed, 12 * 60 * 60); mangle = (float) -ANGLE(elapsed, 60 * 60); sangle = (float) -ANGLE(elapsed, 60); CapSetData(hours, &hangle); CapSetData(minutes, &mangle); CapSetData(seconds, &sangle); return; } static int create_channels(int client_fd) { hours = CapCreateChannel("hours", CAP_USAGE_ZROT, 1); minutes = CapCreateChannel("minutes", CAP_USAGE_ZROT, 1); seconds = CapCreateChannel("seconds", CAP_USAGE_ZROT, 1); return 0; }