📄 baytech.c
字号:
SEND(unum); /* Expect "RPC->x "... or "(Y/N)" (if confirmation turned on) */ if (RPCLookFor(bt, RPC, 10) == 1) { /* They've turned on that annoying command confirmation :-( */ SEND("Y\r"); EXPECT(RPC, 10); } EXPECT(GTSign, 10); /* All Right! Command done. Life is Good! */ syslog(LOG_NOTICE, _("Power to host %s turned %s."), unitid, onoff); /* Pop back to main menu */ SEND("MENU\r"); return(S_OK);}#endif /* defined(ST_POWERON) && defined(ST_POWEROFF) *//* * Map the given host name into an (AC) Outlet number on the power strip */static intRPCNametoOutlet(struct BayTech* bt, const char * name){ char NameMapping[128]; int sockno; char sockname[32]; int ret = -1; /* Verify that we're in the top-level menu */ SEND("\r"); /* Expect "RPC-x Menu" */ EXPECT(RPC, 5); EXPECT(Menu, 5); /* OK. Request sub-menu 1 (Outlet Control) */ SEND("1\r"); /* Verify that we're in the sub-menu */ /* Expect: "RPC-x>" */ EXPECT(RPC, 5); EXPECT(GTSign, 5); /* The status command output contains mapping of hosts to outlets */ SEND("STATUS\r"); /* Expect: "emperature:" so we can skip over it... */ EXPECT(bt->modelinfo->expect, 5); EXPECT(CRNL, 5); /* Looks Good! Parse the status output */ do { char * last; NameMapping[0] = EOS; SNARF(NameMapping, 5); if (!parse_socket_line(bt, NameMapping, &sockno, sockname)) { continue; } last = sockname+bt->modelinfo->socklen; *last = EOS; --last; /* Strip off trailing blanks */ for(; last > sockname; --last) { if (*last == ' ') { *last = EOS; }else{ break; } } g_strdown(sockname); if (strcmp(name, sockname) == 0) { ret = sockno; } } while (strlen(NameMapping) > 2 && ret < 0); /* Pop back out to the top level menu */ SEND("MENU\r"); return(ret);}static intbaytech_status(Stonith *s){ struct BayTech* bt; int rc; if (!ISBAYTECH(s)) { syslog(LOG_ERR, "invalid argument to RPC_status"); return(S_OOPS); } if (!ISCONFIGED(s)) { syslog(LOG_ERR , "unconfigured stonith object in RPC_status"); return(S_OOPS); } bt = (struct BayTech*) s->pinfo; if ((rc = RPCRobustLogin(bt) != S_OK)) { syslog(LOG_ERR, _("Cannot log into " DEVICE ".")); return(rc); } /* Verify that we're in the top-level menu */ SEND("\r"); /* Expect "RPC-x Menu" */ EXPECT(RPC, 5); EXPECT(Menu, 5); return(RPCLogout(bt));}/* * Return the list of hosts (outlet names) for the devices on this BayTech unit */static char **baytech_hostlist(Stonith *s){ char NameMapping[128]; char* NameList[64]; unsigned int numnames = 0; char ** ret = NULL; struct BayTech* bt; if (!ISBAYTECH(s)) { syslog(LOG_ERR, "invalid argument to baytech_hostlist"); return(NULL); } if (!ISCONFIGED(s)) { syslog(LOG_ERR , "unconfigured stonith object in baytech_hostlist"); return(NULL); } bt = (struct BayTech*) s->pinfo; if (RPCRobustLogin(bt) != S_OK) { syslog(LOG_ERR, _("Cannot log into " DEVICE ".")); return(NULL); } /* Verify that we're in the top-level menu */ SEND("\r"); /* Expect "RPC-x Menu" */ NULLEXPECT(RPC, 5); NULLEXPECT(Menu, 5); /* OK. Request sub-menu 1 (Outlet Control) */ SEND("1\r"); /* Verify that we're in the sub-menu */ /* Expect: "RPC-x>" */ NULLEXPECT(RPC, 5); NULLEXPECT(GTSign, 5); /* The status command output contains mapping of hosts to outlets */ SEND("STATUS\r"); /* Expect: "emperature:" so we can skip over it... */ NULLEXPECT(bt->modelinfo->expect, 5); NULLEXPECT(CRNL, 5); /* Looks Good! Parse the status output */ do { int sockno; char sockname[64]; char * last; char * nm; NameMapping[0] = EOS; NULLSNARF(NameMapping, 5); if (!parse_socket_line(bt, NameMapping, &sockno, sockname)) { continue; } last = sockname+bt->modelinfo->socklen; *last = EOS; --last; /* Strip off trailing blanks */ for(; last > sockname; --last) { if (*last == ' ') { *last = EOS; }else{ break; } } if (numnames >= DIMOF(NameList)-1) { break; } if ((nm = (char*)STRDUP(sockname)) == NULL) { syslog(LOG_ERR, "out of memory"); return(NULL); } g_strdown(nm); NameList[numnames] = nm; ++numnames; NameList[numnames] = NULL; } while (strlen(NameMapping) > 2); /* Pop back out to the top level menu */ SEND("MENU\r"); if (numnames >= 1) { ret = (char **)MALLOC((numnames+1)*sizeof(char*)); if (ret == NULL) { syslog(LOG_ERR, "out of memory"); }else{ memcpy(ret, NameList, (numnames+1)*sizeof(char*)); } } (void)RPCLogout(bt); return(ret);}static voidbaytech_free_hostlist (char ** hlist){ char ** hl = hlist; if (hl == NULL) { return; } while (*hl) { FREE(*hl); *hl = NULL; ++hl; } FREE(hlist);}/* * Parse the given configuration information, and stash it away... */static intRPC_parse_config_info(struct BayTech* bt, const char * info){ static char dev[1024]; static char user[1024]; static char passwd[1024]; if (bt->config) { return(S_OOPS); } if (sscanf(info, "%s %s %[^\n\r\t]", dev, user, passwd) == 3 && strlen(passwd) > 1) { if ((bt->device = STRDUP(dev)) == NULL) { syslog(LOG_ERR, "out of memory"); return(S_OOPS); } if ((bt->user = STRDUP(user)) == NULL) { FREE(bt->device); bt->device=NULL; syslog(LOG_ERR, "out of memory"); return(S_OOPS); } if ((bt->passwd = STRDUP(passwd)) == NULL) { FREE(bt->user); bt->user=NULL; FREE(bt->device); bt->device=NULL; syslog(LOG_ERR, "out of memory"); return(S_OOPS); } bt->config = 1; return(S_OK); } return(S_BADCONFIG);}/* * Connect to the given BayTech device. We should add serial support here * eventually... */static intRPC_connect_device(struct BayTech * bt){ char TelnetCommand[256]; snprintf(TelnetCommand, sizeof(TelnetCommand) , "exec telnet %s 2>/dev/null", bt->device); bt->pid=STARTPROC(TelnetCommand, &bt->rdfd, &bt->wrfd); if (bt->pid <= 0) { return(S_OOPS); } return(S_OK);}/* * Reset the given host on this Stonith device. */static intbaytech_reset_req(Stonith * s, int request, const char * host){ int rc = 0; int lorc = 0; struct BayTech* bt; if (!ISBAYTECH(s)) { syslog(LOG_ERR, "invalid argument to baytech_reset"); return(S_OOPS); } if (!ISCONFIGED(s)) { syslog(LOG_ERR , "unconfigured stonith object in baytech_reset"); return(S_OOPS); } bt = (struct BayTech*) s->pinfo; if ((rc = RPCRobustLogin(bt)) != S_OK) { syslog(LOG_ERR, _("Cannot log into " DEVICE ".")); }else{ int noutlet; noutlet = RPCNametoOutlet(bt, host); if (noutlet < 1) { syslog(LOG_WARNING, _("%s %s " "doesn't control host [%s]."), bt->idinfo , bt->unitid, host); RPCkillcomm(bt); return(S_BADHOST); } switch(request) {#if defined(ST_POWERON) && defined(ST_POWEROFF) case ST_POWERON: case ST_POWEROFF: rc = RPC_onoff(bt, noutlet, host, request); break;#endif case ST_GENERIC_RESET: rc = RPCReset(bt, noutlet, host); break; default: rc = S_INVAL; break; } } lorc = RPCLogout(bt); RPCkillcomm(bt); return(rc != S_OK ? rc : lorc);}/* * Parse the information in the given configuration file, * and stash it away... */static intbaytech_set_config_file(Stonith* s, const char * configname){ FILE * cfgfile; char RPCid[256]; struct BayTech* bt; if (!ISBAYTECH(s)) { syslog(LOG_ERR, "invalid argument to baytech_set"); return(S_OOPS); } bt = (struct BayTech*) s->pinfo; if ((cfgfile = fopen(configname, "r")) == NULL) { syslog(LOG_ERR, _("Cannot open %s"), configname); return(S_BADCONFIG); } while (fgets(RPCid, sizeof(RPCid), cfgfile) != NULL){ if (*RPCid == '#' || *RPCid == '\n' || *RPCid == EOS) { continue; } return(RPC_parse_config_info(bt, RPCid)); } return(S_BADCONFIG);}/* * Parse the config information in the given string, and stash it away... */static intbaytech_set_config_info(Stonith* s, const char * info){ struct BayTech* bt; if (!ISBAYTECH(s)) { syslog(LOG_ERR, "baytech_set_config_info: invalid argument"); return(S_OOPS); } bt = (struct BayTech *)s->pinfo; return(RPC_parse_config_info(bt, info));}static const char *baytech_getinfo(Stonith * s, int reqtype){ struct BayTech* bt; const char * ret; if (!ISBAYTECH(s)) { syslog(LOG_ERR, "RPC_idinfo: invalid argument"); return NULL; } /* * We look in the ST_TEXTDOMAIN catalog for our messages */ bt = (struct BayTech *)s->pinfo; switch (reqtype) { case ST_DEVICEID: /* Exactly what type of device? */ ret = bt->idinfo; break; case ST_DEVICENAME: /* Which particular individual device? */ ret = bt->device; break; case ST_CONF_INFO_SYNTAX: ret = _("IP-address login password\n" "The IP-address and login are white-space delimited."); break; case ST_CONF_FILE_SYNTAX: ret = _("IP-address login password\n" "The IP-address and login are white-space delimited. " "All three items must be on one line. " "Blank lines and lines beginning with # are ignored"); break; case ST_DEVICEDESCR: /* Description of device type */ ret = _("Bay Technical Associates (Baytech) RPC " "series power switches (via telnet).\n" "The RPC-5, RPC-3 and RPC-3A switches are well tested."); break; case ST_DEVICEURL: /* Manufacturer's web site */ ret = "http://www.baytech.net/"; break; default: ret = NULL; break; } return ret;}/* * Baytech Stonith destructor... */static voidbaytech_destroy(Stonith *s){ struct BayTech* bt; if (!ISBAYTECH(s)) { syslog(LOG_ERR, "baytech_del: invalid argument"); return; } bt = (struct BayTech *)s->pinfo; bt->BTid = NOTbtid; RPCkillcomm(bt); if (bt->rdfd >= 0) { close(bt->rdfd); bt->rdfd = -1; } if (bt->wrfd >= 0) { close(bt->wrfd); bt->wrfd = -1; } if (bt->device != NULL) { FREE(bt->device); bt->device = NULL; } if (bt->user != NULL) { FREE(bt->user); bt->user = NULL; } if (bt->passwd != NULL) { FREE(bt->passwd); bt->passwd = NULL; } if (bt->idinfo != NULL) { FREE(bt->idinfo); bt->idinfo = NULL; } if (bt->unitid != NULL) { FREE(bt->unitid); bt->unitid = NULL; }}/* Create a new BayTech Stonith device. */static void *baytech_new(void){ struct BayTech* bt = MALLOCT(struct BayTech); if (bt == NULL) { syslog(LOG_ERR, "out of memory"); return(NULL); } memset(bt, 0, sizeof(*bt)); bt->BTid = BTid; bt->pid = -1; bt->rdfd = -1; bt->wrfd = -1; bt->config = 0; bt->user = NULL; bt->device = NULL; bt->passwd = NULL; bt->idinfo = NULL; bt->unitid = NULL; REPLSTR(bt->idinfo, DEVICE); bt->modelinfo = &ModelInfo[0]; return((void *)bt);}static intparse_socket_line(struct BayTech * bt, const char *NameMapping, int *sockno, char *sockname){#if 0 char format[64]; snprintf(format, sizeof(format), "%%7d %%%dc" , bt->modelinfo->socklen); /* 7 digits, 7 blanks, then 'socklen' characters */ /* [0-6]: digits, NameMapping[13] begins the sockname */ /* NameMapping strlen must be >= socklen + 14 */ if (sscanf(NameMapping, format, sockno, sockname) != 2) { return FALSE; }#else# define OFFSET 14 if (sscanf(NameMapping, "%7d", sockno) != 1 || strlen(NameMapping) < OFFSET+bt->modelinfo->socklen) { return FALSE; } strncpy(sockname, NameMapping+OFFSET, bt->modelinfo->socklen); sockname[bt->modelinfo->socklen] = EOS;#endif return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -