📄 baytech.c
字号:
RPCNametoOutletList(struct pluginDevice* bt, const char * name, int outletlist[]){ char NameMapping[128]; int sockno; char sockname[32]; int maxfound = 0; /* Verify that we're in the top-level menu */ SEND(bt->wrfd, "\r"); /* Expect "RPC-x Menu" */ EXPECT(bt->rdfd, RPC, 5); EXPECT(bt->rdfd, Menu, 5); /* OK. Request sub-menu 1 (Outlet Control) */ SEND(bt->wrfd, "1\r"); /* Verify that we're in the sub-menu */ /* Expect: "RPC-x>" */ EXPECT(bt->rdfd, RPC, 5); EXPECT(bt->rdfd, GTSign, 5); /* The status command output contains mapping of hosts to outlets */ SEND(bt->wrfd, "STATUS\r"); /* Expect: "emperature:" so we can skip over it... */ EXPECT(bt->rdfd, bt->modelinfo->expect, 5); EXPECT(bt->rdfd, CRNL, 5); /* Looks Good! Parse the status output */ do { char * last; NameMapping[0] = EOS; SNARF(bt->rdfd, 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) { outletlist[maxfound] = sockno; ++maxfound; } } while (strlen(NameMapping) > 2 && maxfound < MAXOUTLET); /* Pop back out to the top level menu */ SEND(bt->wrfd, "MENU\r"); return(maxfound);}static intbaytech_status(StonithPlugin *s){ struct pluginDevice* bt; int rc; ERRIFNOTCONFIGED(s,S_OOPS); bt = (struct pluginDevice*) s; if ((rc = RPCRobustLogin(bt) != S_OK)) { LOG(PIL_CRIT, "%s", "Cannot log into " DEVICE "."); return(rc); } /* Verify that we're in the top-level menu */ SEND(bt->wrfd, "\r"); /* Expect "RPC-x Menu" */ EXPECT(bt->rdfd, RPC, 5); EXPECT(bt->rdfd, Menu, 5); return(RPCLogout(bt));}/* * Return the list of hosts (outlet names) for the devices on this BayTech unit */static char **baytech_hostlist(StonithPlugin *s){ char NameMapping[128]; char* NameList[64]; unsigned int numnames = 0; char ** ret = NULL; struct pluginDevice* bt; ERRIFNOTCONFIGED(s,NULL); bt = (struct pluginDevice*) s; if (RPCRobustLogin(bt) != S_OK) { LOG(PIL_CRIT, "%s", "Cannot log into " DEVICE "."); return(NULL); } /* Verify that we're in the top-level menu */ SEND(bt->wrfd, "\r"); /* Expect "RPC-x Menu" */ NULLEXPECT(bt->rdfd, RPC, 5); NULLEXPECT(bt->rdfd, Menu, 5); /* OK. Request sub-menu 1 (Outlet Control) */ SEND(bt->wrfd, "1\r"); /* Verify that we're in the sub-menu */ /* Expect: "RPC-x>" */ NULLEXPECT(bt->rdfd, RPC, 5); NULLEXPECT(bt->rdfd, GTSign, 5); /* The status command output contains mapping of hosts to outlets */ SEND(bt->wrfd, "STATUS\r"); /* Expect: "emperature:" so we can skip over it... */ NULLEXPECT(bt->rdfd, bt->modelinfo->expect, 5); NULLEXPECT(bt->rdfd, CRNL, 5); /* Looks Good! Parse the status output */ do { int sockno; char sockname[64]; char * last; char * nm; NameMapping[0] = EOS; NULLSNARF(bt->rdfd, 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) { LOG(PIL_CRIT, "%s", "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(bt->wrfd, "MENU\r"); if (numnames >= 1) { ret = (char **)MALLOC((numnames+1)*sizeof(char*)); if (ret == NULL) { LOG(PIL_CRIT, "%s" , "out of memory"); }else{ memcpy(ret, NameList, (numnames+1)*sizeof(char*)); } } (void)RPCLogout(bt); return(ret);}/* * Connect to the given BayTech device. * We should add serial support here eventually... */static intRPC_connect_device(struct pluginDevice * bt){ int fd = OurImports->OpenStreamSocket(bt->device , TELNET_PORT, TELNET_SERVICE); if (fd < 0) { return(S_OOPS); } bt->rdfd = bt->wrfd = fd; return(S_OK);}/* * Reset the given host on this Stonith device. */static intbaytech_reset_req(StonithPlugin * s, int request, const char * host){ int rc = S_OK; int lorc = 0; struct pluginDevice* bt; ERRIFNOTCONFIGED(s,S_OOPS); bt = (struct pluginDevice*) s; if ((rc = RPCRobustLogin(bt)) != S_OK) { LOG(PIL_CRIT, "%s", "Cannot log into " DEVICE "."); }else{ int noutlets; int outlets[MAXOUTLET]; int j; noutlets = RPCNametoOutletList(bt, host, outlets); if (noutlets < 1) { LOG(PIL_CRIT, "%s %s %s [%s]" , bt->idinfo, bt->unitid , "doesn't control host", host); return(S_BADHOST); } switch(request) { case ST_POWERON: case ST_POWEROFF: for (j=0; rc == S_OK && j < noutlets;++j) { rc = RPC_onoff(bt, outlets[j], host, request); } break; case ST_GENERIC_RESET: /* * Our strategy here: * 1. Power off all outlets except the last one * 2. reset the last outlet * 3. power the other outlets back on */ for (j=0; rc == S_OK && j < noutlets-1; ++j) { rc = RPC_onoff(bt,outlets[j],host , ST_POWEROFF); } if (rc == S_OK) { rc = RPCReset(bt, outlets[j], host); } for (j=0; rc == S_OK && j < noutlets-1; ++j) { rc = RPC_onoff(bt, outlets[j], host , ST_POWERON); } break; default: rc = S_INVAL; break; } } lorc = RPCLogout(bt); return(rc != S_OK ? rc : lorc);}static const char **baytech_get_confignames(StonithPlugin * s){ static const char * ret[] = {ST_IPADDR, ST_LOGIN, ST_PASSWD, NULL}; return ret;}/* * Parse the config information in the given string, and stash it away... */static intbaytech_set_config(StonithPlugin* s, StonithNVpair* list){ struct pluginDevice* bt = (struct pluginDevice *)s; int rc; StonithNamesToGet namestoget [] = { {ST_IPADDR, NULL} , {ST_LOGIN, NULL} , {ST_PASSWD, NULL} , {NULL, NULL} }; ERRIFWRONGDEV(s, S_OOPS); if (bt->sp.isconfigured) { return S_OOPS; } if ((rc =OurImports->GetAllValues(namestoget, list)) != S_OK) { return rc; } bt->device = namestoget[0].s_value; bt->user = namestoget[1].s_value; bt->passwd = namestoget[2].s_value; return(S_OK);}static const char *baytech_get_info(StonithPlugin * s, int reqtype){ struct pluginDevice* bt; const char * ret; ERRIFWRONGDEV(s,NULL); bt = (struct pluginDevice *)s; switch (reqtype) { case ST_DEVICEID: /* What type of device? */ ret = bt->idinfo; break; case ST_DEVICENAME: /* Which particular device? */ ret = bt->device; break; case ST_DEVICEDESCR: /* Description of dev 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(StonithPlugin *s){ struct pluginDevice* bt; VOIDERRIFWRONGDEV(s); bt = (struct pluginDevice *)s; bt->pluginid = NOTpluginID; 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 StonithPlugin *baytech_new(void){ struct pluginDevice* bt = MALLOCT(struct pluginDevice); if (bt == NULL) { LOG(PIL_CRIT, "%s", "out of memory"); return(NULL); } memset(bt, 0, sizeof(*bt)); bt->pluginid = pluginid; bt->pid = -1; bt->rdfd = -1; bt->wrfd = -1; REPLSTR(bt->idinfo, DEVICE); bt->modelinfo = &ModelInfo[0]; bt->sp.s_ops = &baytechOps; return &(bt->sp); /* same as "bt" */}static intparse_socket_line(struct pluginDevice * 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 + -