/* * prs.c - Control Pow-R-Switch from BlackBox * * Copyright (C) 2000, 2001 Martin K. Petersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include static char const rcsid[] = "$Id: prs.c,v 1.2 2001/11/19 02:03:36 mkp Exp $"; void usage (void) { fprintf (stderr, "Usage:\n\n"); fprintf (stderr, "prs [-p ] [-u|-d|-t|-s] |all\n\n"); fprintf (stderr, "\t-p \tSerial port to send commands to\n"); fprintf (stderr, "\t-u\tPower Up\n"); fprintf (stderr, "\t-d\tPower Down\n"); fprintf (stderr, "\t-t\tPower Toggle\n"); fprintf (stderr, "\t-s\tPower Status\n\n"); fprintf (stderr, "Where is a number from 0-9 or `all' for all sockets\n\n"); fprintf (stderr, "If PRSPORT is not set, -p must be specified\n\n"); exit (EXIT_FAILURE); } int main (int argc, char *argv[]) { char opt, action = 0, *sockstr, cmdbuf[16], buf[1024], *port = NULL; int fd, socket; struct termios tios; FILE *file; if (argc < 2) usage(); /* Grab default port from environment */ port = getenv ("PRSPORT"); /* Option parsing */ while ((opt = getopt (argc, argv, "udtshp:")) != EOF) { switch (opt) { case 'p': port = optarg; if (port == NULL) usage(); break; case 'u': action = '1'; break; case 'd': action = '0'; break; case 't': action = 'T'; break; case 's': action = '?'; break; case 'h': default: usage(); } } /* No environtment variable, and no -p */ if (port == NULL) usage(); /* I friggin' HATE user input validation */ if (action == 0) action = '?'; sockstr = argv[optind]; /* If nothing or "all" is specified, use that */ if (sockstr == NULL || !strcmp (sockstr, "all")) socket = '*'; /* Else find socket number */ else { if (*sockstr < '0' || *sockstr > '9') usage(); socket = *sockstr; } /* Don't allow powering off, nor toggling all sockets */ if (socket == '*' && (action == '0' || action == 'T')) { fprintf (stderr, "Can't power down/toggle all sockets in one go\n"); exit (EXIT_FAILURE); } /* Do the serial dance */ fd = open (port, O_RDWR|O_SYNC, 0); if (fd < 0) { fprintf (stderr, "Could not open %s for reading and writing\n", port); exit (EXIT_FAILURE); } if (tcgetattr (fd, &tios) < 0) { fprintf (stderr, "Could not get I/O settings for %s\n", port); exit (EXIT_FAILURE); } /* 9600n8 */ tios.c_iflag = IGNBRK; tios.c_oflag = 0; tios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | CRTSCTS; tios.c_lflag = 0; memset ((char *) tios.c_cc, 0, NCCS); if (tcsetattr (fd, TCSANOW, &tios) < 0) { fprintf (stderr, "Could not apply tcsettings for %s\n", port); exit (EXIT_FAILURE); } if (! (file = fdopen (fd, "r+"))) { fprintf (stderr, "Could not open file for %s\n", port); exit (EXIT_FAILURE); } /* Assemble command string */ sprintf (cmdbuf, "\r\n%c%c%c%c%c%c%c%c\r\n", '', '', '', '', '', '', socket, action); /* Kick the PRS into action */ if (write (fd, cmdbuf, 12) < 12) fprintf (stderr, "Error writing command to %s\n", port); /* Can't use select() because we don't know the actual number of * lines the PRS will output. And in the toggle case, we'll have a * huge time gap between Off and On. Sucks! */ sleep (1); /* Read status */ while (fgets (buf, sizeof (buf), file)) if (!strncmp (buf, "Plug", 4)) printf ("%s", buf); if (action == 'T') { sleep (10); while (fgets (buf, sizeof (buf), file)) if (!strncmp (buf, "Plug", 4)) printf ("%s", buf); } exit (EXIT_SUCCESS); } /* EOF */