void cmdRx(uint8_t c) { // read out the data in the buffer and echo it back to the host. switch (c) { case '\r': case '\n': // terminate the msg and reset the msg ptr. then send // it to the handler for processing. *msg_ptr = '\0'; #if CFG_INTERFACE_SILENTMODE == 0 printf("%s", CFG_PRINTF_NEWLINE); #endif cmdParse((char *)msg); msg_ptr = msg; break; case '\b': #if CFG_INTERFACE_SILENTMODE == 0 printf("%c",c); #endif if (msg_ptr > msg) { msg_ptr--; } break; default: #if CFG_INTERFACE_SILENTMODE == 0 printf("%c",c); #endif *msg_ptr++ = c; break; } }
int main(int argc, char *argv[]) { synTables_t synTables; char versionString[VERSION_STRING_MAX_LEN]; int ret; int funcRet; void *subcommandArgs = NULL; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); /* set global command name */ cmdName = getExecBasename(argv[0]); (void) snprintf(versionString, VERSION_STRING_MAX_LEN, "%s.%s", VERSION_STRING_MAJOR, VERSION_STRING_MINOR); synTables.versionString = versionString; synTables.longOptionTbl = options; synTables.subCommandPropsTbl = subCommands; ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet); if (ret != 0) { return (ret); } return (funcRet); } /* end main */
void cmdRx(uint8_t c) { // read out the data in the buffer and echo it back to the host. switch (c) { case '\r': case '\n': // terminate the msg and reset the msg ptr. then send // it to the handler for processing. *msg_ptr = '\0'; printf("%s", "\n"); cmdParse((char *)msg); msg_ptr = msg; break; case '\b': printf("%c", c); if (msg_ptr > msg) { msg_ptr--; } break; default: printf("%c", c); *msg_ptr++ = c; break; } }
void cmdRx(uint8_t c) { // read out the data in the buffer and echo it back to the host. switch (c) { case '\r': case '\n': // terminate the msg and reset the msg ptr. then send // it to the handler for processing. *msg_ptr = '\0'; printf("%s", CFG_PRINTF_NEWLINE); cmdParse((char *)msg); msg_ptr = msg; break; case '\b': printf("%c", c); if (msg_ptr == msg) { // Send bell alert and space (to maintain position) printf("\a "); } else if (msg_ptr > msg) { msg_ptr--; } break; default: printf("%c", c); *msg_ptr++ = c; break; } }
/*============================================================================= * INTERPRETE */ cmdC* cmdInterprete(char* s, char* fe) { // clear args for(int i = 0; cmd_args[i]; i++) memset(cmd_args[i], 0, sizeof(argT)); // convert '=' and ',' to spaces for(char* c = s; *c; c++) if(*c == '=' || *c == ',') *c = ' '; // process command or recognize environment variables cmdC* c = cmdParse(s); if(c == NULL) { // check if an env var with this name is present char *w = cmd_copy_word(arg1.s, s); if(envGet(arg1.s)) { // fallback to 'set' command // strcpy(arg0.s, "set"); strncpy(arg2.s, cmd_skip_spaces(w), CMD_ARGSTRING_BF-1); arg1.s[CMD_ARGSTRING_BF-1] = '\0'; return cmdParse("set"); } cmd_copy_word(arg0.s, s); pe("%sunknown command '%s'.\n", fe, arg0.s); return NULL; } // save command arg_cmd = c; // process arguments s = cmd_syntax_re(s, c->Syntax); if(s) { pe("%ssyntax error, %s.\n", fe, s); return 0; } // return gracefully return c; }
/* * main calls a parser that checks syntax of the input command against * various rules tables. * * The return value from the function is placed in funcRet */ int main(int argc, char *argv[]) { synTables_t synTables; char versionString[VERSION_STRING_MAX_LEN]; int ret; int funcRet; void *subcommandArgs = NULL; /* to support locale */ (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ #endif (void) textdomain(TEXT_DOMAIN); /* set global command name */ cmdName = getExecBasename(argv[0]); /* check if is global zone */ if (getzoneid() != GLOBAL_ZONEID) { (void *) fprintf(stdout, "%s %s\n", cmdName, gettext("does not support non-global zone.")); return (1); } (void *) snprintf(versionString, sizeof (versionString), "%s.%s", VERSION_STRING_MAJOR, VERSION_STRING_MINOR); synTables.versionString = versionString; synTables.longOptionTbl = &sasinfolongOptions[0]; synTables.subCommandPropsTbl = &sasinfosubcommands[0]; /* call the CLI parser */ ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet); if (ret == 1) { (void *) fprintf(stdout, "%s %s(1M)\n", gettext("For more information, please see"), cmdName); return (1); } else if (ret == -1) { (void *) fprintf(stderr, "%s %s\n", cmdName, strerror(errno)); return (1); } if (funcRet != 0) { return (1); } return (0); }
/*============================================================================= * HELP */ static int cmdEHelp() { if(arg1.miss) { for(cmdC* c = cmdsHook; c; c = c->Next) if(c->Help) pf("%10s: %s\n", c->Name, c->Help); } else { cmdC* c = cmdParse(arg1.s); if(!c) return pf("'%s' is not a command\n", arg1.s); pf("Syntax:\n"); pf("%s %s\n", c->Name, strchr(c->Syntax, ':')+1); if(c->Help) pf("%s\n", c->Help); else pf("(system command)\n"); } }
/* * main calls a parser that checks syntax of the input command against * various rules tables. * * The parser provides usage feedback based upon same tables by calling * two usage functions, usage and subUsage, handling command and subcommand * usage respectively. * * The parser handles all printing of usage syntactical errors * * When syntax is successfully validated, the parser calls the associated * function using the subcommands table functions. * * Syntax is as follows: * command subcommand [options] resource-type [<object>] * * The return value from the function is placed in funcRet */ int main(int argc, char *argv[]) { synTables_t synTables; char versionString[VERSION_STRING_MAX_LEN]; int ret; int funcRet; void *subcommandArgs = NULL; /* set global command name */ cmdName = getExecBasename(argv[0]); if (getzoneid() != GLOBAL_ZONEID) { (void) fprintf(stderr, "%s: this command is only available in the 'global' " "zone\n", cmdName); exit(1); } (void) snprintf(versionString, sizeof (versionString), "%s.%s", VERSION_STRING_MAJOR, VERSION_STRING_MINOR); synTables.versionString = versionString; synTables.longOptionTbl = &longOptions[0]; synTables.subcommandTbl = &subcommands[0]; synTables.objectTbl = &objects[0]; synTables.objectRulesTbl = &objectRules[0]; synTables.optionRulesTbl = &optionRules[0]; /* call the CLI parser */ ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet); if (ret == 1) { (void) printf("%s %s(1M)\n", gettext("For more information, please see"), cmdName); return (1); } else if (ret == -1) { perror(cmdName); return (1); } return (funcRet); }
void readLogger() { int fd; char buf[3] = "0"; fd = open(loggerPipePath, O_RDONLY); unsigned char cmd; unsigned char data; while(1) { read(fd, buf, 3); if (buf[0] != '0') { //int32_t cmd = atoi(buf); //parseCmd(cmd); cmd = buf[0]; data = buf[1]; cmdParse(cmd, data); printf("Received: %c\n", buf[0]); snprintf(buf, 35, "%s", "0"); } } }
void *doSmall(void *arg) { bool runFlag=true; // char *queueName ; mqd_t mq; struct mq_attr attr; ssize_t len; struct cmdMessage buffer; // char *res; struct linuxParser *p; bool ff; struct Small *myTable=arg; // This lock is held by this threads parent. // Once the parent has completed its setup it will release the lock, and // then we can continue. // pthread_mutex_lock(&lock); fprintf(stderr,"Started\n"); queueName = dbLookup(myTable,"QNAME"); if(!queueName) { ff=addRecord(myTable,"QNAME","/atlast"); if(ff) { fprintf(stderr,"db install faulure, fatal error\n"); exit(1); } queueName = dbLookup(myTable,"QNAME"); } attr.mq_flags = 0; attr.mq_maxmsg = 10; printf("size %d\n", sizeof(struct cmdMessage)); attr.mq_msgsize = sizeof(struct cmdMessage); attr.mq_curmsgs = 0; mq = mq_open(queueName, O_CREAT | O_RDONLY, 0644, &attr); if( (mqd_t)-1 == mq) { perror("mq_open"); if(errno == ENOSYS) { fprintf(stderr,"Fatal ERROR\n"); exit(1); } } mq_setattr(mq, &attr,NULL); p=newParser(myTable); setIam(p,queueName); while(runFlag) { len = mq_receive(mq, &buffer, sizeof(buffer), NULL); if( len < 0) { perror("mq_receive"); } else { ff=cmdParse(p,&buffer,NULL); } } }
int cmdParseScript(char *script, cmdScript_t *s, int diags) { int idx, len, b, i, j, tags, resolved; int status; uint32_t p[10]; cmdInstr_t instr; cmdCtlParse_t ctl; char v[CMD_MAX_EXTENSION]; ctl.eaten = 0; status = 0; cmdTagStep_t tag_step[PI_MAX_SCRIPT_TAGS]; len = strlen(script); /* calloc space for PARAMS, VARS, CMDS, and STRINGS */ b = (sizeof(int) * (PI_MAX_SCRIPT_PARAMS + PI_MAX_SCRIPT_VARS)) + (sizeof(cmdInstr_t) * (len + 2) / 2) + len; s->par = calloc(1, b); if (s->par == NULL) return -1; s->var = s->par + PI_MAX_SCRIPT_PARAMS; s->instr = (cmdInstr_t *)(s->var + PI_MAX_SCRIPT_VARS); s->str_area = (char *)(s->instr + ((len + 2) / 2)); s->str_area_len = len; s->str_area_pos = 0; s->instrs = 0; tags = 0; idx = 0; while (ctl.eaten<len) { idx = cmdParse(script, p, CMD_MAX_EXTENSION, v, &ctl); if (idx >= 0) { if (p[3]) { memcpy(s->str_area + s->str_area_pos, v, p[3]); s->str_area[s->str_area_pos + p[3]] = 0; p[4] = (intptr_t) s->str_area + s->str_area_pos; s->str_area_pos += (p[3] + 1); } memcpy(&instr.p, p, sizeof(instr.p)); if (instr.p[0] == PI_CMD_TAG) { if (tags < PI_MAX_SCRIPT_TAGS) { /* check tag not already used */ for (j=0; j<tags; j++) { if (tag_step[j].tag == instr.p[1]) { if (diags) { fprintf(stderr, "Duplicate tag: %d\n", instr.p[1]); } if (!status) status = PI_DUP_TAG; idx = -1; } } tag_step[tags].tag = instr.p[1]; tag_step[tags].step = s->instrs; tags++; } else { if (diags) { fprintf(stderr, "Too many tags: %d\n", instr.p[1]); } if (!status) status = PI_TOO_MANY_TAGS; idx = -1; } } } else { if (diags) { if (idx == CMD_UNKNOWN_CMD) fprintf(stderr, "Unknown command: %s\n", cmdStr()); else fprintf(stderr, "Bad parameter to %s\n", cmdStr()); } if (!status) status = PI_BAD_SCRIPT_CMD; } if (idx >= 0) { if (instr.p[0] != PI_CMD_TAG) { memcpy(instr.opt, &ctl.opt, sizeof(instr.opt)); s->instr[s->instrs++] = instr; } } } for (i=0; i<s->instrs; i++) { instr = s->instr[i]; /* resolve jumps */ if ((instr.p[0] == PI_CMD_JMP) || (instr.p[0] == PI_CMD_CALL) || (instr.p[0] == PI_CMD_JZ) || (instr.p[0] == PI_CMD_JNZ) || (instr.p[0] == PI_CMD_JM) || (instr.p[0] == PI_CMD_JP)) { resolved = 0; for (j=0; j<tags; j++) { if (instr.p[1] == tag_step[j].tag) { s->instr[i].p[1] = tag_step[j].step; resolved = 1; break; } } if (!resolved) { if (diags) { fprintf(stderr, "Can't resolve tag %d\n", instr.p[1]); } if (!status) status = PI_BAD_TAG; } } } return status; }
//************************************************************************************** //*** //*** //*** //************************************************************************************** uchar cmdCheck(uchar exec) { uchar cmd = CMD_NONE; uchar args[RXBUFSIZE]; long li; uchar a[3]; uchar i,j; // ASkr DEBUG uchar tmp[30]; cmd = cmdParse(&args); if( exec != EXEC ) return cmd; switch( cmd ) { //---------------------------------------------------------------------------------- case CMD_NONE: break; // NO ACTION IN HERE! //---------------------------------------------------------------------------------- case CMD_OFF: break; // NO ACTION IN HERE! //---------------------------------------------------------------------------------- case CMD_ERROR: break; // NO ACTION IN HERE! //---------------------------------------------------------------------------------- case CMD_HELP: serUsage(); break; //---------------------------------------------------------------------------------- case CMD_START:break; // NO ACTION IN HERE! //---------------------------------------------------------------------------------- case CMD_STOP:break; // NO ACTION IN HERE! //---------------------------------------------------------------------------------- case CMD_SHOW: serShowParams(); break; //---------------------------------------------------------------------------------- case CMD_LOAD:break; // NO ACTION IN HERE! //---------------------------------------------------------------------------------- case CMD_SAVE:break; // NO ACTION IN HERE! //---------------------------------------------------------------------------------- case CMD_TIMESET: j = 1; for(i=1;i<4;i++) { li = serMatRead((uchar *)&args,i,':'); if( li == NUMERR_LONG ) { j = 0; break; } a[i-1] = (uchar)li; } if(!j) { serSendString("ERROR\r\n"); break; } rtcSetTime(a[0],a[1],a[2]); // continue with next CASE below (TIMEQUERY)... //---------------------------------------------------------------------------------- case CMD_TIMEQUERY: rtcGetTimeString((uchar *)&args); serSendStringDebug((uchar *)&args,NUMERR_LONG,"\r\n"); break; //---------------------------------------------------------------------------------- case CMD_DATESET: j = 1; for(i=1;i<4;i++) { li = serMatRead((uchar *)&args,i,'.'); if( li == NUMERR_LONG ) { j = 0; break; } // quick and more than dirty 4-digit year entry hack if( ( i == 3 ) && ( li > 2000 ) ) li-=2000; a[i-1] = (uchar)li; } if(!j) { serSendString("ERROR\r\n"); break; } // TODO: either error checks in here or return code upon illegal stuff in rtcSetDate() rtcSetDate(a[2],a[1],a[0]); // continue with next CASE below (DATEQUERY)... //---------------------------------------------------------------------------------- case CMD_DATEQUERY: rtcGetDateString((uchar *)&args); serSendStringDebug((uchar *)&args,NUMERR_LONG,"\r\n"); break; //---------------------------------------------------------------------------------- case CMD_SLEEPSET: li = serMatRead((uchar *)&args,1,'X'); if( (li == 0) || (li == 1) ) sCfg.rtcSleep = (uchar)li; else { serSendString("ERROR\r\n"); break; } // continue with next CASE below (SLEEPQUERY)... //---------------------------------------------------------------------------------- case CMD_SLEEPQUERY: if( sCfg.rtcSleep == NOSLEEP ) serSendString("0\r\n"); else serSendString("1\r\n"); break; //---------------------------------------------------------------------------------- case CMD_SRATESET: li = serMatRead((uchar *)&args,1,'X'); if( (li > 0)&&(li < 65536) ) sCfg.rtcSRate = (unsigned)li; else { serSendString("ERROR\r\n"); break; } // continue with next CASE below (SRATEQUERY)... //---------------------------------------------------------------------------------- case CMD_SRATEQUERY: serSendStringDebug(NULL,sCfg.rtcSRate,"\r\n"); break; //---------------------------------------------------------------------------------- case CMD_SMEANSSET: li = serMatRead((uchar *)&args,1,'X'); if( (li > 0)&&(li < 17) ) sCfg.rtcSMeans = (uchar)li; else { serSendString("ERROR\r\n"); break; } // continue with next CASE below (SMEANSQUERY)... //---------------------------------------------------------------------------------- case CMD_SMEANSQUERY: serSendStringDebug(NULL,sCfg.rtcSMeans,"\r\n"); break; //---------------------------------------------------------------------------------- case CMD_SUNITSET: i=0; switch((uchar)args[0]) { case 's': sCfg.rtcSUnit = SECONDS; break; case 'm': sCfg.rtcSUnit = MINUTES; break; // case 'h': sCfg.rtcSUnit = HOURS; break; // BLOCKED (does not make sense...) default: serSendString("ERROR\r\n"); i=1; } if( i ) break; // continue with next CASE below (SUNITQUERY)... //---------------------------------------------------------------------------------- case CMD_SUNITQUERY: switch(sCfg.rtcSUnit) { case SECONDS: serSendString("S\r\n"); break; case MINUTES: serSendString("M\r\n"); break; case HOURS: serSendString("H\r\n"); break; default: serSendString("ERROR\r\n"); } break; //---------------------------------------------------------------------------------- case CMD_SERIALLOGSET: serSendString("NOT IMPLEMENTED\r\n"); break; //---------------------------------------------------------------------------------- case CMD_SERIALLOGQUERY: serSendString("NOT IMPLEMENTED\r\n"); break; //---------------------------------------------------------------------------------- case CMD_SEPSET: i = (uchar)strlen((uchar*)&args); if( i != 1 ) { serSendString("ERROR\r\n"); break; } sCfg.crdSeparator = args[0]; // continue with next CASE below (SEPQUERY)... //---------------------------------------------------------------------------------- case CMD_SEPQUERY: args[0] = '''; args[1] = sCfg.crdSeparator; args[2] = '''; args[3] = 0; serSendStringDebug((uchar *)&args,NUMERR_LONG,"\r\n"); break; //---------------------------------------------------------------------------------- case CMD_LOGDATESET: li = serMatRead((uchar *)&args,1,'X'); if( (li == 0) || (li == 1) ) sCfg.crdLogDate = (uchar)li; else { serSendString("ERROR\r\n"); break; } // continue with next CASE below (LOGDATEQUERY)... //---------------------------------------------------------------------------------- case CMD_LOGDATEQUERY: if( sCfg.crdLogDate == NO ) serSendString("0\r\n"); else serSendString("1\r\n"); break; //---------------------------------------------------------------------------------- case CMD_LOGTIMESET: li = serMatRead((uchar *)&args,1,'X'); if( (li == 0) || (li == 1) ) sCfg.crdLogTime = (uchar)li; else { serSendString("ERROR\r\n"); break; } // continue with next CASE below (LOGDATEQUERY)... //---------------------------------------------------------------------------------- case CMD_LOGTIMEQUERY: if( sCfg.crdLogTime == NO ) serSendString("0\r\n"); else serSendString("1\r\n"); break; //---------------------------------------------------------------------------------- case CMD_FNAMESET: if( !cmdCheckStringAlphaNum( (char *)&args) ) { serSendString("ERROR\r\n"); break; } i = (uchar)strlen((uchar*)&args); if( (i < 1 ) || (i > 8) ) { serSendString("ERROR\r\n"); break; } strcpy( (uchar*)&sCfg.crdFName, (uchar*)&args ); // continue with next CASE below (SUNITQUERY)... //---------------------------------------------------------------------------------- case CMD_FNAMEQUERY: serSendString( (uchar *)&sCfg.crdFName); serSendString("\r\n"); break; //---------------------------------------------------------------------------------- case CMD_USECARDSET: li = serMatRead((uchar *)&args,1,'X'); if( (li == 0) || (li == 1) ) sCfg.crdUseCard = (uchar)li; else { serSendString("ERROR\r\n"); break; } // continue with next CASE below (USECARDQUERY)... //---------------------------------------------------------------------------------- case CMD_USECARDQUERY: if( sCfg.crdUseCard == NO ) serSendString("0\r\n"); else serSendString("1\r\n"); break; //---------------------------------------------------------------------------------- case CMD_BATQUERY: measMeasureAllComplete(); serSendStringDebug(NULL,(long)measGetChannelVoltage(AD_UBEXT),"\r\n"); break; //---------------------------------------------------------------------------------- case CMD_MEASNOW: measMeasureAllComplete(); li = serMatRead((uchar *)&args,1,'X'); if( (li >= 0) && (li < 12) ) serSendStringDebug(NULL,measGetChannelValue((uchar)li),"\r\n"); else serSendString("ERROR\r\n"); break; //---------------------------------------------------------------------------------- case CMD_MEASVOL: measMeasureAllComplete(); li = serMatRead((uchar *)&args,1,'X'); if( (li >= 0) && (li < 12) ) serSendStringDebug(NULL,measGetChannelVoltage((uchar)li),"\r\n"); else serSendString("ERROR\r\n"); break; //---------------------------------------------------------------------------------- case CMD_VERSIONQUERY: serSendStringDebug((uchar*)&sCfg.appVersion,NUMERR_LONG,"\r\n"); break; //---------------------------------------------------------------------------------- case CMD_DATILASTSET: li = serMatRead((uchar *)&args,1,'X'); if( (li == 0) || (li == 1) ) sCfg.crdLogDaTi2nd = (uchar)li; else { serSendString("ERROR\r\n"); break; } // continue with next CASE below (USECARDQUERY)... //---------------------------------------------------------------------------------- case CMD_DATILASTQUERY: if( sCfg.crdLogDaTi2nd == NO ) serSendString("0\r\n"); else serSendString("1\r\n"); break; //---------------------------------------------------------------------------------- case CMD_LOGEXCORESET: li = serMatRead((uchar *)&args,1,'X'); if( (li == 0) || (li == 1) ) sCfg.crdLogExCore = (uchar)li; else { serSendString("ERROR\r\n"); break; } // continue with next CASE below (USECARDQUERY)... //---------------------------------------------------------------------------------- case CMD_LOGEXCOREQUERY: if( sCfg.crdLogExCore == NO ) serSendString("0\r\n"); else serSendString("1\r\n"); break; //---------------------------------------------------------------------------------- case CMD_BGCORRSET: li = serMatRead((uchar *)&args,1,'X'); if( (li < -100) || (li > 100) ) { serSendString("ERROR\r\n"); break; } else sCfg.meaBandCorr = (schar)li; // continue with next CASE below (LOGDATEQUERY)... //---------------------------------------------------------------------------------- case CMD_BGCORRQUERY: serSendStringDebug(NULL,(long)sCfg.meaBandCorr,"\r\n"); break; //---------------------------------------------------------------------------------- default: serSendString("***UNKNOWN***\r\n"); break; }// END switch return cmd; }
int main(int argc , char *argv[]) { int sock, command; int idx, i, pp, l, len; cmdCmd_t cmd; uint32_t p[CMD_P_ARR]; cmdCtlParse_t ctl; cmdScript_t s; char v[CMD_MAX_EXTENSION]; sock = openSocket(); command_buf[0] = 0; l = 0; pp = 0; for (i=1; i<argc; i++) { l += (strlen(argv[i]) + 1); if (l < sizeof(command_buf)) {sprintf(command_buf+pp, "%s ", argv[i]); pp=l;} } if (pp) {command_buf[--pp] = 0;} ctl.eaten = 0; len = strlen(command_buf); idx = 0; while ((idx >= 0) && (ctl.eaten < len)) { if ((idx=cmdParse(command_buf, p, CMD_MAX_EXTENSION, v, &ctl)) >= 0) { command = p[0]; if (command < PI_CMD_SCRIPT) { if (command == PI_CMD_HELP) { printf(cmdUsage); } else if (command == PI_CMD_PARSE) { cmdParseScript(v, &s, 1); if (s.par) free (s.par); } else { cmd.cmd = command; cmd.p1 = p[1]; cmd.p2 = p[2]; cmd.p3 = p[3]; if (sock != SOCKET_OPEN_FAILED) { if (send(sock, &cmd, sizeof(cmdCmd_t), 0) == sizeof(cmdCmd_t)) { if (p[3]) send(sock, v, p[3], 0); /* send extensions */ if (recv(sock, &cmd, sizeof(cmdCmd_t), MSG_WAITALL) == sizeof(cmdCmd_t)) { get_extensions(sock, command, cmd.res); print_result(sock, cmdInfo[idx].rv, cmd); } else fatal("socket receive failed"); } else fatal("socket send failed"); } else fatal("socket connect failed"); } } else fatal("%s only allowed within a script", cmdInfo[idx].name); } else { if (idx == CMD_UNKNOWN_CMD) fatal("%s? unknown command, pigs h for help", cmdStr()); else fatal("%s: bad parameter, pigs h for help", cmdStr()); } } if (sock >= 0) close(sock); return 0; }