summaryrefslogtreecommitdiff
path: root/packages/sccd/files/scc-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'packages/sccd/files/scc-utils.c')
-rw-r--r--packages/sccd/files/scc-utils.c376
1 files changed, 376 insertions, 0 deletions
diff --git a/packages/sccd/files/scc-utils.c b/packages/sccd/files/scc-utils.c
new file mode 100644
index 0000000000..ab48ecb677
--- /dev/null
+++ b/packages/sccd/files/scc-utils.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2006
+ * Protium Computing, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Protium Computing, Inc.
+ * 4. The name of Protium Computing, Inc. may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PROTIUM COMPUTING ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PROTIUM COMPUTING BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/syslog.h>
+#include <sys/resource.h>
+#include <termios.h>
+
+#include "scc.h"
+
+int scc_die = 0;
+
+char
+scc_cksum(int *i, int *j)
+{
+ unsigned char s;
+ unsigned char *b;
+
+ b = (unsigned char *)i;
+ s = b[0] + b[1] + b[2] + b[3];
+ b = (unsigned char *)j;
+ s = s + b[0] + b[1] + b[2];
+ s = (s & 0x7f);
+
+ return((char)s);
+}
+
+int
+scc_validate(int *i, int *j, int verbose)
+{
+ int r, s;
+
+ /* if (verbose) printf("Packet: [0x%08x 0x%08x]\n", *i, *j); */
+
+ switch (*i & SCC_POWERMASK) {
+ case SCC_RUN:
+ if (verbose) printf("\tPower: run\n");
+ break;
+ case SCC_STOP:
+ if (verbose) printf("\tPower: stop\n");
+ break;
+ case SCC_ADVISESTOP:
+ if (verbose) printf("\tPower: advise stop\n");
+ break;
+ case SCC_RESTART:
+ if (verbose) printf("\tPower: restart\n");
+ break;
+ case SCC_ADVISERESTART:
+ if (verbose) printf("\tPower: advise restart\n");
+ break;
+ case SCC_RESET:
+ if (verbose) printf("\tPower: reset\n");
+ break;
+ case SCC_ADVISERESET:
+ if (verbose) printf("\tPower: advise reset\n");
+ break;
+ default:
+ if (verbose) printf("validate: bad power 0x%08x\n", *i);
+ return(-1);
+ }
+
+ switch (*i & SCC_LEDMASK) {
+ case SCC_LEDOFF:
+ if (verbose) printf("\tLed: off\n");
+ break;
+ case SCC_LEDBLUE:
+ if (verbose) printf("\tLed: blue\n");
+ break;
+ case SCC_LEDRED:
+ if (verbose) printf("\tLed: red\n");
+ break;
+ case SCC_LEDBLUEFLASH:
+ if (verbose) printf("\tLed: blue flash\n");
+ break;
+ case SCC_LEDREDFLASH:
+ if (verbose) printf("\tLed: red flash\n");
+ break;
+ case SCC_LEDALTERNATE1:
+ if (verbose) printf("\tLed: alternate1\n");
+ break;
+ case SCC_LEDALTERNATE3:
+ if (verbose) printf("\tLed: alternate3\n");
+ break;
+ default:
+ if (verbose) printf("validate: bad led value 0x%08x\n", *i);
+ return(-1);
+ }
+
+ r = ((*i & SCC_LEDRATEMASK) >> SCC_LEDRATESHIFT);
+
+ if (verbose) {
+ printf("\tLed Flash Rate: %d\n", r);
+ }
+
+ if (r >= SCC_LEDRATEHI)
+ printf("warning: led rate too high - led on (%d)\n", r);
+ if (r <= SCC_LEDRATELO)
+ printf("warning: led rate too low - led off (%d)\n", r);
+
+
+ switch (*i & SCC_FANMASK) {
+ case SCC_FANAUTO:
+ if (verbose) printf("\tFan: auto\n");
+ break;
+ case SCC_FANON:
+ if (verbose) printf("\tFan: on\n");
+ break;
+ default:
+ if (verbose) printf("validate: bad fan value 0x%08x\n", *i);
+ return(-1);
+ }
+
+ r = ((*j & SCC_FANTEMPONMASK) >> SCC_FANTEMPONSHIFT);
+ s = ((*j & SCC_FANTEMPOFFMASK) >> SCC_FANTEMPOFFSHIFT);
+
+ if (verbose) {
+ printf("\tFan On Temprature: %dC\n", r);
+ printf("\tFan Off Temprature: %dC\n", s);
+ }
+
+ if (r >= SCC_FANTEMPONHI)
+ printf("warning: fan on temp too high - fan off (%dC)\n", r);
+ if (s <= SCC_FANTEMPONLO)
+ printf("warning: fan on temp too low - fan on (%dC)\n", s);
+ if ((r - s) < SCC_FANTEMPDIFF) {
+ printf("warning: fan on/off temp too close or on < off \n");
+ printf("warning:\tfan on (%dC) fan off (%dC) \n", r, s);
+ }
+
+ r = *j & SCC_IDMASK;
+ if ((r != SCC_HOST) &&
+ (r != SCC_CTLR00) &&
+ (r != SCC_CTLR12)) {
+ printf("warning: bad id %08x\n", r);
+ }
+
+ r = *j & SCC_CKSUMMASK;
+ if (r != scc_cksum(i, j)) {
+ printf("warning: checksum incorrect (%02x != %02x)\n",
+ r, scc_cksum(i, j));
+ }
+ return(0);
+}
+
+int
+scc_setval(int *i, int mask, int val)
+{
+ /* clear the field */
+ *i = (*i & (mask ^ 0xffffffff));
+
+ /* insert the field */
+ *i = (*i ^ val);
+ return(0);
+}
+
+int
+scc_setrate(int *i, int mask, int shift, int val)
+{
+ /* Assumption: val is < field width */
+
+ /* clear the field */
+ *i = (*i & (mask ^ 0xffffffff));
+
+ /* insert the field */
+ *i = (*i ^ (val << shift));
+ return(0);
+}
+
+int
+scc_defaults(int *i, int *j)
+{
+ scc_setval(i, SCC_POWERMASK, SCC_POWERDEFAULT);
+ scc_setval(i, SCC_LEDMASK, SCC_LEDDEFAULT);
+ scc_setrate(i, SCC_LEDRATEMASK, SCC_LEDRATESHIFT, SCC_LEDRATEDEFAULT);
+ scc_setval(i, SCC_FANMASK, SCC_FANDEFAULT);
+
+ scc_setrate(j, SCC_FANTEMPONMASK,
+ SCC_FANTEMPONSHIFT, SCC_FANTEMPONDEFAULT);
+ scc_setrate(j, SCC_FANTEMPOFFMASK,
+ SCC_FANTEMPOFFSHIFT, SCC_FANTEMPOFFDEFAULT);
+ return(0);
+}
+
+void
+scc_sighandler(int sig)
+{
+ /*
+ * Just catch quit and term and set die
+ */
+ switch(sig) {
+ case SIGQUIT:
+ case SIGTERM:
+ syslog(LOG_INFO, "Terminating");
+ scc_die=1;
+ break;
+ }
+}
+
+int
+scc_daemonize(int cores)
+{
+ int fd, i;
+ char pidstr[20];
+ pid_t pid;
+
+ struct rlimit limit[1] = {{ 0, 0 }};
+
+
+ if (!cores) {
+ /*
+ * No corefiles please
+ */
+ if (getrlimit(RLIMIT_CORE, limit) == -1) {
+ perror("getrlimit");
+ return -1;
+ }
+
+ limit->rlim_cur = 0;
+
+ if (setrlimit(RLIMIT_CORE, limit) != 0) {
+ perror("setrlimit");
+ return -1;
+ }
+ }
+
+ /*
+ * Must be root
+ */
+ if (getuid() != 0) {
+ fprintf(stderr, "Must be root\n");
+ return -1;
+ }
+
+ /*
+ * If parent isn't init, make it init.
+ */
+ if (getppid() != 1) {
+
+ pid = fork();
+ if (pid == -1) {
+ return -1;
+ }
+ if (pid != 0) {
+ exit(EXIT_SUCCESS);
+ }
+
+ setsid();
+
+ /*
+ * ignore sig hup so that when our new padre exits
+ * the kinder won't exit
+ */
+ signal(SIGHUP, SIG_IGN);
+
+ pid = fork();
+ if (pid == -1) {
+ return -1;
+ }
+ if (pid != 0) {
+ exit(EXIT_SUCCESS);
+ }
+ }
+
+ /*
+ * Set working dir to root
+ */
+ chdir("/");
+
+ /*
+ * Make sure file creations are created with explicit perms
+ */
+ umask(0);
+
+ /*
+ * Close all FDs
+ */
+ for (i = 0; i < sysconf(_SC_OPEN_MAX); i++) {
+ close(i);
+ }
+
+ /*
+ * set std in, out, err to /dev/null
+ */
+ for (i = 0; i < 3; i++) {
+
+ if ((fd = open("/dev/null", (i==0?O_RDONLY:O_WRONLY))) == -1) {
+ perror("setting up stdin, stdout, stderr");
+ return -1;
+ }
+
+ if (i != fd) {
+ if (dup2(fd, i) == -1) {
+ perror("setting up stdin, stdout, stderr");
+ return -1;
+ }
+ close(fd);
+ }
+ }
+
+ /*
+ * Open and lock the pid file. Ensures only one daemon
+ * Write our pid into the file
+ */
+ fd = open(SCC_PIDFILE, O_RDWR|O_CREAT, 0640);
+ if (fd < 0) {
+ return(-1);
+
+ }
+
+ if (lockf(fd, F_TLOCK, 0) < 0) {
+ /* we are not alone */
+ close(fd);
+ return(-1);
+ }
+
+ sprintf(pidstr,"%-6d\n", getpid());
+ write(fd, pidstr, strlen(pidstr));
+
+ /*
+ * Open syslog
+ */
+ openlog("sccd", LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "Starting");
+
+ /*
+ * Ignore some signals and handle others
+ */
+ signal(SIGCHLD, SIG_IGN);
+ signal(SIGTSTP, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+ signal(SIGQUIT, scc_sighandler);
+ signal(SIGTERM, scc_sighandler);
+
+ return(0);
+}
+
+