// mstun.cpp vers. 0.4 adapted from shm_client.cpp FAC Jan 2011 // Compile: g++ -g -Wall mstun.cpp -o mstun // Usage: mstun // Program mterml_sh must be running or no response will be received. // (You can simulate mterml_sh by starting program "shm_server") // Program attaches a shared memory section and request change/display cmds from user. // Refs: http://www.cs.cf.ac.uk/Dave/C/node27.html#SECTION002700000000000000000 // http://www.go4expert.com/forums/showthread.php?t=8461 // // See file shmemoryMap.txt for list of whats in this shared memory. // // Copyright (C) 2010 F.A. Conle // This file 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 file is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTA- // BILITY 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. Try also their // web site: http://www.gnu.org/copyleft/gpl.html #include #include #include #include #include //used for sleep() in Linux. ? #include //Linux for sleep() #include //Linux req. exit() #include //Linux req. for strtol() #define SHMSZ 1024 //In Linux this is in bytes // Use "ipcs -m" to check if area exists ok int main(int argc, char ** argv ) //argc and argv are not used here. { int shmid; key_t key; long int *shm, *s, *s2; //shared mem address, with s and s2 used as index int i; //loop index long int il_ksaveflag; //=1 save next cycle, =0 use list to save cycles long int iln, iln2, ilcmd; int base; //used by strtol() char line[100]; //used to read in user commands char *endptr; // " long int ilretval; // returned by strtol() long int il_nChecks; //counter for checks for shm write permission // i.e.: check for loc 0 == -1 long int il_binVector; // =0 send bin to sh Mem2, =1 send to disk files bin1, bin2 etc. long int il_workBuff; // buff no. being worked on by loopget long int nl_cycleno; // No. of cycles detected so far float vmaxCh0, vmaxCh1; float vminCh0, vminCh1; float scale2; //multiplier to convert int to +- 10Volts scale2 = 0.000305185; key = 91810; //number just refers to creation date, is a //name for the shared mem segment. printf("#mstun: Finding shared mem...\n"); // Create (find) the segment based on key if ((shmid = shmget(key, SHMSZ, 0666)) < 0) { perror("shmget"); exit(1); } // Attach the segment to our data space. printf("#mstun: Attaching shared mem...\n"); // C++ doesnt like the c line: // if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) { if ((shm = (long int *)shmat(shmid, 0, 0)) == (long int *) -1) { perror("shmat"); exit(1); } // Check to see if shared mem is ok: // Special contents in shm+2, +3, +4.....+9 iln=3; s=shm; while(1) { s=shm+iln; if (*s != iln) { printf("#mstun: Shared memory not attached properly. Content of Loc %li is %li",iln,*s); exit(-1); } iln=iln+1; if(iln == 9) { printf("#mstun: Shared memory looks ok...\n\n"); break; } } DISPLAY: while(1) { //Display the stuff in shared mem now printf(" Loc. Item Contents | CommandSelect \n"); s = shm; i=0; printf(" %3i Smem Read/Write = %12li | 0 = Pause\n",i,*s); s = shm+1; i=1; printf(" %3i Last Command to mblk10 = %12li | 1 = Run\n",i,*s); s = shm+9; i=9; printf(" %3i No. of A/D Chans. = %12li | \n",i,*s); s = shm+10; i=10; printf(" %3i History Rep. no. = %12li | 999 = STOP All\n",i,*s); s = shm+11; i=11; printf(" %3i Blk. no. = %12li | 1000 = RESET DAP\n",i,*s); s = s+12; i=12; printf(" %3i Ramp no. = %12li | 1100 = Kill mblk10\n",i,*s); s = shm+13; i=13; printf(" %3i No. A/D Bufs written = %12li | 1200 = Kill mterml_sh\n",i,*s); s = shm+14; i=14; printf(" %3i Max Ch 0 (int) = %12li | \n",i,*s); vmaxCh0 = (float)(*s) * scale2; s = shm+15; i=15; printf(" %3i Min Ch 0 (int) = %12li | \n",i,*s); vminCh0 = (float)(*s) * scale2; s = shm+16; i=16; printf(" %3i Max Ch 1 (int) = %12li | \n",i,*s); vmaxCh1 = (float)(*s) * scale2; s = shm+17; i=17; printf(" %3i Min Ch 1 (int) = %12li | \n",i,*s); vminCh1 = (float)(*s) * scale2; // locs 18,19,20,21 are for future channels. s = shm+22; i=22; printf(" %3i Next FreeBuff = %12li | \n",i,*s); s = shm+23; i=23; il_binVector = *s; printf(" %3i Bin. Vector = %12li | 1300 = Change Bin Vector\n",i,il_binVector); s = shm+24; i=24; il_workBuff = *s; printf(" %3i Loop workBuff no. = %12li | \n",i,il_workBuff); s = shm+25; i=25; nl_cycleno = *s; printf(" %3i lg: Cycle No. = %12li | \n",i,nl_cycleno); s = shm+26; i=26; il_ksaveflag = *s; printf(" %3i lg: Save Next Loop = %12li | 26 = Get Next Loop \n",i,il_ksaveflag); printf(" \n"); s = shm+101; i=101; printf(" %3i Status of mblk10 = %12li | \n",i,*s); printf(" | 1001 = start mblk10\n"); printf(" Item From_mblk10 To_mblk10 | 200 = Display this again \n"); i=102; s= shm+i; s2=s+100; printf(" PKERROR= %12li %12li | 2 = change PKERROR\n",*s,*s2); i=103; s= shm+i; s2=s+100; printf(" CMDERROR= %12li %12li | 3 = change CMDERROR\n",*s,*s2); i=104; s= shm+i; s2=s+100; printf(" RATE1= %12li %12li | 4 = change RATE1\n",*s,*s2); i=105; s= shm+i; s2=s+100; printf(" RATE2= %12li %12li | 5 = change RATE2\n",*s,*s2); i=106; s= shm+i; s2=s+100; printf(" THRESHOLD= %12li %12li | 6 = change THRESHOLD\n",*s,*s2); i=107; s= shm+i; s2=s+100; printf(" DEPLETE= %12li %12li | 7 = change DEPLETE\n",*s,*s2); i=108; s= shm+i; s2=s+100; printf(" STEPSIZE= %12li %12li | 8 = change STEPSIZE\n",*s,*s2); i=109; s= shm+i; s2=s+100; printf(" MAXREPEATS= %12li %12li | 9 = change MAXREPEATS\n",*s,*s2); printf(" | -1 = exit mstun\n\n"); printf(" Ch_0 Ch_1 Cycle = %li\n", nl_cycleno); printf(" Vmax %7.3f %7.3f \n", vmaxCh0, vmaxCh1 ); printf(" Vmin %7.3f %7.3f \n", vminCh0, vminCh1 ); printf(" \n"); base = 10; //number base used by strtol() below INCOMMAND: printf(" Enter Command No.: "); // Several things have been tried to "catch" bad input. They are // documented here. // When garbage input "scanf" fails badly. Best not used. //iretval=scanf("%li", &ilcmd); // Linux g++ scanf returns a 0 if bad data input(maybe). Check //iretval = sscanf(line, "[+-0123456789]%li", &ilcmd); //printf("ilcmd= %li, iretval= %i\n",ilcmd,iretval); //debug //Using sscanf is also poor. If garbage, it is left in the input buff // and causes endless loop. // atoi works better: except it returns a "0" for bad input. Not good. // Ref.:http://www.eskimo.com/~scs/cclass/krnotes/sx10d.html //fgets(line, sizeof(line), stdin); //ilcmd=atoi(line); //printf("atoi gives: ilcmd= %li\n",ilcmd); //debug //looks like strtol() is best(?): //Ref.: http://linux.die.net/man/3/strtol fgets(line, sizeof(line), stdin); errno =0; //changes to nonzero upon error. (Maybe! not always) //Actually it doesnt get changed upon an error in g++ /*If someone wants to use strot() to verify their input data, they'd be best to follow the advise from the FreeBSD manpage: ``(Thus, if *nptr is not `\0' but **endptr is `\0' on return, the entire string was valid.)'' Ref.: http://lists.freebsd.org/pipermail/freebsd-current/2005-January/045485.html */ // The above comment/philosophy seems to correct. ilretval = strtol(line, &endptr, base); // if bad input ilretval will be set to zero (which is not good // since 0 is also one of our possible commands!) // Code from elsewhere: /* Check for various possible errors */ //we don't need this here. I hope. //if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) // || (errno != 0 && val == 0)) { perror("strtol"); exit(EXIT_FAILURE); } // if (*endptr != '\0') /* Not necessarily an error... */ // printf("Further characters after number: %s\n", endptr); if (endptr == line) //This seems to be the best error check { printf("No digits were found\n"); printf("line = %s endptr= %s ilretval= %li\n",line,endptr,ilretval); goto DISPLAY; } // Input ok. ilcmd=ilretval; printf("#mstun: strtol() returned ilcmd= %ld\n", ilcmd); //debug if(ilcmd == -1) { printf("mstun: exiting...\n"); exit(0); } if(ilcmd == 200) { //redisplay mstun stuff, do not update command mem loc. goto DISPLAY; } // Check to see if server is ready to read // Server will set 1st loc of sh mem to 0 il_nChecks = 0; while(1) { iln2 = *shm; if (iln2 == 0) { // yes, first location is zero, Server has released sh mem printf("#mstun: Detected %li in loc 0...\n",iln2 ); //debug print // Depending on the command no. we have to place stuff in sh mem if(ilcmd == 2) { //change the PKERROR mem loc printf(" Enter PKERROR : "); fgets(line, sizeof(line), stdin); errno =0; ilretval = strtol(line, &endptr, base); if (endptr == line) { printf("No digits were found\n"); printf("line = %s endptr= %s ilretval= %li\n",line,endptr,ilretval); goto INCOMMAND; } // Input ok. iln=ilretval; if(iln < 0 || iln > 32000) //check boundaries { printf("#mstun: PKERROR out of bounds. Try again.\n"); goto INCOMMAND; } s=shm+202; *s=iln; goto SETCMD; } if(ilcmd == 3) { printf(" Enter CMDERROR : "); fgets(line, sizeof(line), stdin); errno =0; ilretval = strtol(line, &endptr, base); if (endptr == line) { printf("No digits were found\n"); printf("line = %s endptr= %s ilretval= %li\n",line,endptr,ilretval); goto INCOMMAND; } // Input ok. iln=ilretval; if(iln < 0 || iln > 32000) //check boundaries { printf("#mstun: CMDERROR out of bounds. Try again.\n"); goto INCOMMAND; } s=shm+203; *s=iln; goto SETCMD; } if(ilcmd == 4) { printf(" Enter RATE1 : "); fgets(line, sizeof(line), stdin); errno =0; ilretval = strtol(line, &endptr, base); if (endptr == line) { printf("No digits were found\n"); printf("line = %s endptr= %s ilretval= %li\n",line,endptr,ilretval); goto INCOMMAND; } iln=ilretval; // Input was ok. if(iln < 0 || iln > 32000) //check boundaries { printf("#mstun: RATE1 out of bounds. Try again.\n"); goto INCOMMAND; } s=shm+204; *s=iln; goto SETCMD; } if(ilcmd == 5) { printf(" Enter RATE2 : "); fgets(line, sizeof(line), stdin); errno =0; ilretval = strtol(line, &endptr, base); if (endptr == line) { printf("No digits were found\n"); printf("line = %s endptr= %s ilretval= %li\n",line,endptr,ilretval); goto INCOMMAND; } iln=ilretval; if(iln < 0 || iln > 32000) //check boundaries { printf("#mstun: RATE2 out of bounds. Try again.\n"); goto INCOMMAND; } s=shm+205; *s=iln; goto SETCMD; } if(ilcmd == 6) { printf(" Enter THRESHOLD : "); fgets(line, sizeof(line), stdin); errno =0; ilretval = strtol(line, &endptr, base); if(errno != 0) { printf("#mstun: input error. Try again.\n"); goto INCOMMAND; } if (endptr == line) //checks for garbage in input { printf("No digits were found\n"); printf("line = %s endptr= %s ilretval= %li\n",line,endptr,ilretval); goto INCOMMAND; } iln=ilretval; if(iln < 0 || iln > 32000) //check boundaries { printf("#mstun: THRESHOLD out of bounds. Try again.\n"); goto INCOMMAND; } s=shm+206; *s=iln; goto SETCMD; } if(ilcmd == 7) { printf(" Enter DEPLETE : "); fgets(line, sizeof(line), stdin); errno =0; ilretval = strtol(line, &endptr, base); if(errno != 0) { printf("#mstun: input error. Try again.\n"); goto INCOMMAND; } if (endptr == line) //checks for garbage in input { printf("No digits were found\n"); printf("line = %s endptr= %s ilretval= %li\n",line,endptr,ilretval); goto INCOMMAND; } iln=ilretval; if(iln < 0 || iln > 2000000) //check boundaries { printf("#mstun: DEPLETE out of bounds. Try again.\n"); goto INCOMMAND; } s=shm+207; *s=iln; goto SETCMD; } if(ilcmd == 8) { printf(" Enter STEPSIZE : "); fgets(line, sizeof(line), stdin); errno =0; ilretval = strtol(line, &endptr, base); if(errno != 0) { printf("#mstun: input error. Try again.\n"); goto INCOMMAND; } if (endptr == line) //checks for garbage in input { printf("No digits were found\n"); printf("line = %s endptr= %s ilretval= %li\n",line,endptr,ilretval); goto INCOMMAND; } iln=ilretval; if(iln < 0 || iln > 32000) //check boundaries { printf("#mstun: STEPSIZE out of bounds. Try again.\n"); goto INCOMMAND; } s=shm+208; *s=iln; goto SETCMD; } if(ilcmd == 9) { printf(" Enter MAXREPEATS : "); fgets(line, sizeof(line), stdin); errno =0; ilretval = strtol(line, &endptr, base); if(errno != 0) { printf("#mstun: input error. Try again.\n"); goto INCOMMAND; } if (endptr == line) //checks for garbage in input { printf("No digits were found\n"); printf("line = %s endptr= %s ilretval= %li\n",line,endptr,ilretval); goto INCOMMAND; } iln=ilretval; if(iln < 0 ) //check boundaries { printf("#mstun: MAXREPEATS out of bounds. Try again.\n"); goto INCOMMAND; } s=shm+209; *s=iln; goto SETCMD; } if(ilcmd == 1300) { printf(" Enter New Bin Vector : "); fgets(line, sizeof(line), stdin); errno =0; ilretval = strtol(line, &endptr, base); if(errno != 0) { printf("#mstun: input error. Try again.\n"); goto INCOMMAND; } if (endptr == line) //checks for garbage in input { printf("No digits were found\n"); printf("line = %s endptr= %s ilretval= %li\n",line,endptr,ilretval); goto INCOMMAND; } iln=ilretval; if(iln < 0 || iln > 1) //check boundaries { printf("#mstun: BinVector out of bounds.Must be 1 or 0 Try again.\n"); goto INCOMMAND; } s=shm+23; *s=iln; goto SETCMD; } if(ilcmd == 26) { printf(" Next Cycle's Loop will be saved.\n"); il_ksaveflag=1; s=shm+26; *s=il_ksaveflag; goto DISPLAY; //this command is only for loopget, thus do not write ilcmd } //if none of the above change stuff commands, then just write the cmd to mem. // Should we check to see if its an allowed command? Nah... SETCMD: // Write the user's command number into loc 1 s=shm+1; *s = ilcmd; //sets 2nd loc. to user input *shm = -1; //tells server we have placed command in shared mem. break; //break out of the wait for write permission loop. // printf("mstun: read loc. %i , ptr= %p, contains= %li\n",i,s,*s); } //end of if loc 0 is = 0 //wait(); //hopefully pause for a while. wait() uses full cpu sleep(3); //sleep for 3 secs (linux). il_nChecks = il_nChecks +1; if(il_nChecks == 3) //check is no access given to sh mem { printf("#mstun: Still no -1 in shm loc. 0 ...\n"); il_nChecks = 0; } } //end of check for write permission } //end of overall while loop. } //end of main()