📄 apcmaster.c
字号:
SEND("\r"); break; case 1: /* Got that annoying command confirmation :-( */ SEND("YES\r"); goto retry; default: return(errno == ETIMEDOUT ? S_RESETFAIL : S_OOPS); } EXPECT(Prompt, 10); /* All Right! Command done. Life is Good! */ syslog(LOG_NOTICE, _("Power to MS outlet(s) %d turned %s."), outletNum, onoff); /* Pop back to main menu */ SEND("\033\033\033\033\033\033\033\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 intMSNametoOutlet(struct APCMS* ms, const char * name){ char NameMapping[128]; int sockno; char sockname[32]; int times = 0; int ret = -1; /* Verify that we're in the top-level menu */ EXPECT(Prompt, 5); SEND("\033"); EXPECT(Prompt, 5); SEND("\033"); EXPECT(Prompt, 5); SEND("\033"); EXPECT(Prompt, 5); SEND("\033"); /* Expect ">" */ EXPECT(Prompt, 5); /* Request menu 1 (Device Control) */ SEND("1\r"); /* Expect: "-----" so we can skip over it... */ EXPECT(Separator, 5); EXPECT(CRNL, 5); EXPECT(CRNL, 5); /* Looks Good! Parse the status output */ do { times++; NameMapping[0] = EOS; SNARF(NameMapping, 5); if (sscanf(NameMapping , "%d- %23c",&sockno, sockname) == 2) { char * last = sockname+23; *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 && times < 8); /* Pop back out to the top level menu */ EXPECT(Prompt, 5); SEND("\033"); EXPECT(Prompt, 5); SEND("\033"); EXPECT(Prompt, 5); SEND("\033"); EXPECT(Prompt, 5); SEND("\033"); return(ret);}static intapcmaster_status(Stonith *s){ struct APCMS* ms; int rc; if (!ISAPCMS(s)) { syslog(LOG_ERR, "invalid argument to apcmaster_status"); return(S_OOPS); } if (!ISCONFIGED(s)) { syslog(LOG_ERR , "unconfigured stonith object in apcmaster_status"); return(S_OOPS); } ms = (struct APCMS*) s->pinfo; if ((rc = MSRobustLogin(ms) != S_OK)) { syslog(LOG_ERR, _("Cannot log into " DEVICE ".")); return(rc); } /* Expect ">" */ SEND("\033\r"); EXPECT(Prompt, 5); return(MSLogout(ms));}/* * Return the list of hosts (outlet names) for the devices on this MS unit */static char **apcmaster_hostlist(Stonith *s){ char NameMapping[128]; char* NameList[64]; unsigned int numnames = 0; char ** ret = NULL; struct APCMS* ms; if (!ISAPCMS(s)) { syslog(LOG_ERR, "invalid argument to apcmaster_list_hosts"); return(NULL); } if (!ISCONFIGED(s)) { syslog(LOG_ERR , "unconfigured stonith object in apcmaster_list_hosts"); return(NULL); } ms = (struct APCMS*) s->pinfo; if (MSRobustLogin(ms) != S_OK) { syslog(LOG_ERR, _("Cannot log into " DEVICE ".")); return(NULL); } /* Expect ">" */ NULLEXPECT(Prompt, 10); /* Request menu 1 (Device Control) */ SEND("1\r"); /* Expect: "-----" so we can skip over it... */ NULLEXPECT(Separator, 5); NULLEXPECT(CRNL, 5); NULLEXPECT(CRNL, 5); /* Looks Good! Parse the status output */ do { int sockno; char sockname[64]; NameMapping[0] = EOS; NULLSNARF(NameMapping, 5); if (sscanf(NameMapping , "%d- %23c",&sockno, sockname) == 2) { char * last = sockname+23; char * nm; *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("\033"); NULLEXPECT(Prompt, 10); SEND("\033"); NULLEXPECT(Prompt, 10); SEND("\033"); NULLEXPECT(Prompt, 10); SEND("\033"); NULLEXPECT(Prompt, 10); 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)MSLogout(ms); return(ret);}static voidapcmaster_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 intapcmaster_parse_config_info(struct APCMS* ms, const char * info){ static char dev[1024]; static char user[1024]; static char passwd[1024]; if (ms->config) { return(S_OOPS); } if (sscanf(info, "%s %s %[^\n\r\t]", dev, user, passwd) == 3 && strlen(passwd) > 1) { if ((ms->device = STRDUP(dev)) == NULL) { syslog(LOG_ERR, "out of memory"); return(S_OOPS); } if ((ms->user = STRDUP(user)) == NULL) { FREE(ms->device); ms->device=NULL; syslog(LOG_ERR, "out of memory"); return(S_OOPS); } if ((ms->passwd = STRDUP(passwd)) == NULL) { FREE(ms->device); ms->device=NULL; FREE(ms->user); ms->user=NULL; syslog(LOG_ERR, "out of memory"); return(S_OOPS); } ms->config = 1; return(S_OK); } return(S_BADCONFIG);}/* * Connect to the given MS device. We should add serial support here * eventually... */static intMS_connect_device(struct APCMS * ms){ char TelnetCommand[256]; snprintf(TelnetCommand, sizeof(TelnetCommand) , "exec telnet %s 2>/dev/null", ms->device); ms->pid=STARTPROC(TelnetCommand, &ms->rdfd, &ms->wrfd); if (ms->pid <= 0) { return(S_OOPS); } return(S_OK);}/* * Reset the given host on this Stonith device. */static intapcmaster_reset_req(Stonith * s, int request, const char * host){ int rc = 0; int lorc = 0; struct APCMS* ms; if (!ISAPCMS(s)) { syslog(LOG_ERR, "invalid argument to apcmaster_reset_req"); return(S_OOPS); } if (!ISCONFIGED(s)) { syslog(LOG_ERR , "unconfigured stonith object in apc_master_reset_req"); return(S_OOPS); } ms = (struct APCMS*) s->pinfo; if ((rc = MSRobustLogin(ms)) != S_OK) { syslog(LOG_ERR, _("Cannot log into " DEVICE ".")); return(rc); }else{ int noutlet; noutlet = MSNametoOutlet(ms, host); if (noutlet < 1) { syslog(LOG_WARNING, _("%s %s " "doesn't control host [%s]."), ms->idinfo , ms->unitid, host); MSkillcomm(ms); return(S_BADHOST); } switch(request) {#if defined(ST_POWERON) && defined(ST_POWEROFF) case ST_POWERON: rc = apcmaster_onoff(ms, noutlet, host, request); break; case ST_POWEROFF: rc = apcmaster_onoff(ms, noutlet, host, request); break;#endif case ST_GENERIC_RESET: rc = MSReset(ms, noutlet, host); break; default: rc = S_INVAL; break; } } lorc = MSLogout(ms); return(rc != S_OK ? rc : lorc);}/* * Parse the information in the given configuration file, * and stash it away... */static intapcmaster_set_config_file(Stonith* s, const char * configname){ FILE * cfgfile; char APCMSid[256]; struct APCMS* ms; if (!ISAPCMS(s)) { syslog(LOG_ERR, "invalid argument to apcmaster_set_config_file"); return(S_OOPS); } ms = (struct APCMS*) s->pinfo; if ((cfgfile = fopen(configname, "r")) == NULL) { syslog(LOG_ERR, _("Cannot open %s"), configname); return(S_BADCONFIG); } while (fgets(APCMSid, sizeof(APCMSid), cfgfile) != NULL){ if (*APCMSid == '#' || *APCMSid == '\n' || *APCMSid == EOS) { continue; } return(apcmaster_parse_config_info(ms, APCMSid)); } return(S_BADCONFIG);}/* * Parse the config information in the given string, and stash it away... */static intapcmaster_set_config_info(Stonith* s, const char * info){ struct APCMS* ms; if (!ISAPCMS(s)) { syslog(LOG_ERR, "apcmaster_set_config_info: invalid argument"); return(S_OOPS); } ms = (struct APCMS *)s->pinfo; return(apcmaster_parse_config_info(ms, info));}static const char *apcmaster_getinfo(Stonith * s, int reqtype){ struct APCMS* ms; const char * ret; if (!ISAPCMS(s)) { syslog(LOG_ERR, "MS_idinfo: invalid argument"); return NULL; } /* * We look in the ST_TEXTDOMAIN catalog for our messages */ ms = (struct APCMS *)s->pinfo; switch (reqtype) { case ST_DEVICEID: ret = ms->idinfo; break; case ST_CONF_INFO_SYNTAX: ret = _("IP-address login password\n" "The IP-address, login and password are white-space delimited."); break; case ST_CONF_FILE_SYNTAX: ret = _("IP-address login password\n" "The IP-address, login and password are white-space delimited. " "All three items must be on one line. " "Blank lines and lines beginning with # are ignored"); break; case ST_DEVICEDESCR: ret = _("APC MasterSwitch (via telnet)\n" "NOTE: The APC MasterSwitch accepts only one (telnet)\n" "connection/session a time. When one session is active,\n" "subsequent attempt to connect to the MasterSwitch" " will fail."); break; case ST_DEVICEURL: ret = "http://www.apc.com/"; break; default: ret = NULL; break; } return ret;}/* * APC MasterSwitch Stonith destructor... */static voidapcmaster_destroy(Stonith *s){ struct APCMS* ms; if (!ISAPCMS(s)) { syslog(LOG_ERR, "apcms_del: invalid argument"); return; } ms = (struct APCMS *)s->pinfo; ms->MSid = NOTmsid; MSkillcomm(ms); if (ms->device != NULL) { FREE(ms->device); ms->device = NULL; } if (ms->user != NULL) { FREE(ms->user); ms->user = NULL; } if (ms->passwd != NULL) { FREE(ms->passwd); ms->passwd = NULL; } if (ms->idinfo != NULL) { FREE(ms->idinfo); ms->idinfo = NULL; } if (ms->unitid != NULL) { FREE(ms->unitid); ms->unitid = NULL; }}/* Create a new APC Master Switch Stonith device. */static void *apcmaster_new(void){ struct APCMS* ms = MALLOCT(struct APCMS); if (ms == NULL) { syslog(LOG_ERR, "out of memory"); return(NULL); } memset(ms, 0, sizeof(*ms)); ms->MSid = MSid; ms->pid = -1; ms->rdfd = -1; ms->wrfd = -1; ms->config = 0; ms->user = NULL; ms->device = NULL; ms->passwd = NULL; ms->idinfo = NULL; ms->unitid = NULL; REPLSTR(ms->idinfo, DEVICE); REPLSTR(ms->unitid, "unknown"); return((void *)ms);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -