sscanf linux kernel differs from sscanf glibc - c

Running the following code (make runtest) on my machine (4.6.4-1-ARCH)
/* scanf userland & kernelspace test */
#if __KERNEL__
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
MODULE_AUTHOR("Enteee (duckpond.ch) ");
MODULE_DESCRIPTION("scanf test");
MODULE_LICENSE("GPL");
MODULE_ALIAS("scanf_test");
#else
#include <stdio.h>
#include <string.h>
#define printk printf
#endif
void test(void){
int ret = 0;
char fp[20] = { 0 };
memset(fp, 0xaa, sizeof(fp));
printk("init, ret = %d fp = "
"%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
"%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
"%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
"%2.2hhx%2.2hhx, "
// overflow prints (hacky)
"after fp = "
"%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx, "
"before fp = "
"%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
"\n",
ret,
(fp)[0], (fp)[1], (fp)[2], (fp)[3], (fp)[4], (fp)[5],
(fp)[6], (fp)[7], (fp)[8], (fp)[9], (fp)[10], (fp)[11],
(fp)[12], (fp)[13], (fp)[14], (fp)[15], (fp)[16], (fp)[17],
(fp)[18], (fp)[19],
// overflow
(fp)[20], (fp)[21], (fp)[22], (fp)[23], (fp)[24], (fp)[25],
(fp)[-1], (fp)[-2], (fp)[-3], (fp)[-4], (fp)[-5], (fp)[-6]
);
ret = sscanf("aabb", "%2hhx%2hhx", &fp[0], &fp[1]);
printk("ret = %d fp = %2.2hhx%2.2hhx\n", ret, fp[0], fp[1]);
ret = sscanf(
"ffffffffffffffffffffffffffffffffffffffff",
"%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx"
"%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx"
"%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx"
"%2hhx%2hhx",
&(fp)[0], &(fp)[1], &(fp)[2], &(fp)[3], &(fp)[4], &(fp)[5],
&(fp)[6], &(fp)[7], &(fp)[8], &(fp)[9], &(fp)[10], &(fp)[11],
&(fp)[12], &(fp)[13], &(fp)[14], &(fp)[15], &(fp)[16], &(fp)[17],
&(fp)[18], &(fp)[19]
);
printk("ret = %d fp = "
"%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
"%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
"%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
"%2.2hhx%2.2hhx, "
// overflow prints (hacky)
"after fp = "
"%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx, "
"before fp = "
"%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
"\n",
ret,
(fp)[0], (fp)[1], (fp)[2], (fp)[3], (fp)[4], (fp)[5],
(fp)[6], (fp)[7], (fp)[8], (fp)[9], (fp)[10], (fp)[11],
(fp)[12], (fp)[13], (fp)[14], (fp)[15], (fp)[16], (fp)[17],
(fp)[18], (fp)[19],
(fp)[20], (fp)[21], (fp)[22], (fp)[23], (fp)[24], (fp)[25],
(fp)[-1], (fp)[-2], (fp)[-3], (fp)[-4], (fp)[-5], (fp)[-6]
);
}
#ifndef __KERNEL__
int main(void){
test();
return 0;
}
#else
static int __init test_init(void) {
test();
return 0;
}
static void __exit test_exit(void) {
}
module_init(test_init);
module_exit(test_exit);
#endif
yields:
=== user space ===
init, ret = 0 fp = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, after fp = 65005f5f7664, before fp = 000000000000
ret = 2 fp = aabb
ret = 20 fp = ffffffffffffffffffffffffffffffffffffffff, after fp = 65005f5f7664, before fp = 000000000000
=== kernel space ===
[386177.161037] init, ret = 0 fp = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, after fp = baae0dbc0000, before fp = bc0daebaffff
[386177.161044] ret = 2 fp = aabb
[386177.161061] ret = 20 fp = 000000000000000000000000ffffffffffffffff, after fp = baae0dbc0000, before fp = bc0daebaffff
The test.c basically reads ffffffffffffffffffffffffffffffffffffffff to fp using sscanf with a sequence of %2hhx format specifiers. After that, it prints fp using printf / printk with a sequence of %2.2hhx format specifiers.
Can somebody explain me why fp is no the same when read with glibc sscanf and linux sscanf. In addition, why is the aabb-test working just fine?
I already checked the linux sscanf impelmentation and from what I can see it should be similar to the glibc sscanf.
I do think I'm missing the obvious here..
Notes:
the gist containing the Makefile can be found here
this is just an example, please don't tell me that this is an ugly implementation. There are even 24 invalid reads! thx, I'm aware of that.

Related

C language how to make a timeout function using in gethostname()?

This program reads the domain from a file to a string, truncates the string with "\n" as a key, and then executes the getostbyname() function for each domain to enter the resulting information into the file.
When I use gethostbyname, I want to create a function to enter fail if there is no response for a certain period of time. I tried to implement and process the timeout function, but the function did not work.
The logic that I thought of is calling gethostbyname() and entering fail in the file if there is no response for two seconds, then proceed to the next string and call gethostbyname().
The amount of files is about 150 million domains, so I took only a part of them and made them an example.
Please help me create the functions I want.
This is input.txt
www.naver.com
kbphonemall.com
kbplant.com
k-bplus.com
kbpointreestore.com
kbprint.com
kbprism.com
kbprivatebanking.com
kbpstore.com
kbr9rtudaf5ppy.com
kbrafting.com
kbraille.com
kbrainbank.com
kbrainbow.com
kbrainc.com
kbrainglocal.com
kbrandexpo.com
kbrandingschool.com
kbrandmall.com
kbrandmuseum.com
kbranking.com
k-bread.com
k-breadshop.com
kbreaknews.com
kbreasy.com
kbr-easy.com
kb-rent.com
kbrentacar.com
kb-rentcar.com
kbreport.com
k-brew.com
kbrewtec.com
kbrick.com
kbridge21.com
kbrno.com
k-broad.com
kbrockstar.com
kbrosbeauty.com
kbrosis.com
kbrworks.com
kbs1004.com
kbs123.com
kbs20.com
kbs220.com
kbs3.com
kbs31.com
kbs336.com
kbs358.com
kbs40.com
kbs556.com
kbs5678.com
kbs69.com
kbs7.com
kbs700.com
kbs79.com
kbs87.com
kbs9003.com
kbs911.com
kbs97.com
kbsarchive.com
kbsavers.com
kbsavings.com
kbsavingstar.com
kbsba.com
kbsbaechoo.com
kbsbook.com
kbsc1.com
kbscarf.com
kbsccoding.com
kbscert.com
kbschoolbanking.com
kbscyerrutb.com
kbsec.com
kbsec-greeting.com
kbsecuritynews.com
kbseschool.com
kbsestudy.com
kbsfn.com
kbsgmp.com
kbsgreen.com
kbsgulbee.com
kbs-hip.com
kbsholdings.com
kbshsg.com
kbsisa.com
kbsjeju.com
kbskadt.com
kbskiotmall.com
kbsklt.com
kbskorea.com
kbskorean.com
kbskovo.com
kbsktw.com
kbsktwidea.com
kbslogos.com
kbslove.com
kbs-lse.com
kbsmc-ibd.com
kbsmcob.com
kbsmedi.com
kbsmetal.com
kbsmol.com
kbs-mt.com
kbsmt-academy.com
kbsnd.com
kbsnews.com
kbsnnews.com
kbsonbocns.com
kbsonbodirect.com
kbsonsa.com
kbspetdoc.com
kbsplus.com
kbspro.com
kbsq.com
kbssky.com
kbssomgr.com
kbssports.com
kbsstudy.com
kbstar.com
kbstar2020.com
kbstar21.com
kbstar24.com
kbstarb.com
kbstarcard.com
kbstarclub.com
kbstardirect.com
kbstarebank.com
kbstarfg.com
kbstarfinance.com
kbstarflower.com
kbstarfx.com
kbstarg.com
kbstarir.com
kbstarland.com
kbstarmail.com
kbstarmall.com
kbstarmbank.com
kbstarmoney.com
kbstarpb.com
kbstarsvc.com
kbstarworld.com
kbstarzone.com
kbstbt.com
kbsteel.com
kbstock1.com
kbstock5.com
kbs-travel.com
kbstructure.com
kbstv.com
kbstve.com
kbsuf.com
kbsupercard.com
kbsupporters.com
kbsv.com
kbsvoice.com
kbtac.com
kbtchain.com
kbtechgate.com
kbtechone.com
kbtechpos.com
kbtechshop.com
kbtilbo.com
kb-truck.com
kbtups.com
kbtva.com
kbubi.com
kbuddhism.com
k-buddhism.com
k-buddy.com
kbujejucall.com
kbulgyonews.com
k-bulls.com
kbumall.com
kbund.com
kb-uniform.com
kbusinessnews.com
kbusinfo.com
kbusking.com
kbuvd.com
kbvalve.com
kbvipstock.com
kbweb.com
kbweddingfair.com
kbwel.com
kbwith.com
kbwlab.com
kbwnet.com
kb-world.com
kbworldwide.com
kb-world-wide.com
kby8992.com
kbynews.com
kc005.com
kc04.com
kc0522.com
kc1004.com
kc114.com
kc1357.com
kc1895.com
kc1904.com
kc22.com
kc25.com
kc712.com
kc9479.com
kc97bkyg3tvzgdws.com
kca2009.com
kca21.com
kca7.com
kcaa1.com
kcaa12.com
kcaa21.com
kca-academy.com
kcaawelfare.com
kcabiz.com
kca-charcoal.com
kcadcom.com
k-caddie.com
k-cae.com
kcafrp.com
kcagcf.com
kcagolf.com
kcagym.com
kcahub.com
kcairfiltertech.com
kcakca.com
kcakn.com
kcakorea.com
kcakyrgyz.com
kcallica.com
kcaltrip.com
kcangle.com
kcar.com
k-car.com
kcar2.com
kcaratpay.com
kcarauction.com
kcaraudio.com
kcarb2b.com
kcarcapital.com
kcar-capital.com
kcard.com
kcardirect.com
kcar-direct.com
k-cardirect.com
k-careeraptitude.com
kcarfriends.com
kcarlogis.com
kcarmall.com
kcarnet.com
kcarschool.com
kcarz.com
k-cata.com
kcateam.com
kcatfree.com
kca-therapy.com
kcb4u.com
kcb5.com
kcbc-acc.com
kcbcard.com
kcbec.com
kcbend.com
kcbetrade.com
kcbexchange.com
kcbiea.com
kc-biz.com
kcboltec.com
kcbs119.com
kcbtec.com
kcbtv.com
kcbunion.com
kcc000.com
kcc001.com
kcc002.com
kcc003.com
kcc007.com
kcc1004.com
kcc1122.com
kcc114.com
kcc2.com
kcc21.com
kcc258.com
kcc339.com
kcc5858.com
kcc775.com
kcc7777.com
kcc7979.com
kcc8282.com
kccaedu.com
kccardpos.com
kccarr.com
kccaster.com
kccasters.com
kccauto.com
kccce.com
kccchem.com
kccckorea.com
kcccolorndesign.com
kcccontainer.com
kccdeco.com
kccdepot.com
kccea.com
kccegis.com
kccei.com
kcceleader.com
kccenc.com
kccepost.com
kcceramice.com
kcceye.com
kccf2012.com
kccfilm.com
kccflooring.com
kccgift.com
kccglass.com
kccgroup.com
kcchain.com
kccheavyduty.com
kccholdings.com
kcchomecc.com
kcchomeccinterior.com
kcchwarang.com
kccia.com
kccichem.com
kccinsight.com
kccinterior.com
kccjewelry.com
kcckdong.com
kccks.com
kccmarine.com
kccmaul.com
kccnara.com
kccofficial.com
kccold.com
kccomang.com
kccond.com
kcconveyor.com
kc-coop.com
kc-cottrell.com
kccpaint114.com
kccpaintmall.com
kccplant.com
kccplus.com
kccpr.com
kccrefinish.com
kccrose.com
kccsa.com
kccscleaning.com
kccseoul.com
kccsilicon.com
kccsilicone.com
kccsmms.com
kccssafe.com
kccswitzen-patio.com
kcctm.com
kcctour.com
kccultural.com
kccview.com
kccvma.com
kccwelltztower.com
kccwindow.com
kccwindows.com
kccworld.com
kccycasters.com
kccyes.com
kcdc2020.com
kcdc21.com
kcdcode.com
kcdeaf.com
kcdfarm.com
kcdic.com
kcdkorea.com
kcdoll.com
kcdoor.com
k-cea.com
kcea98.com
kceasw.com
kceautodoor.com
kceccenter.com
kcecctv.com
kcecoin.com
kcecrs.com
and this is code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#define IPATH "example.txt"
#define OPATH "result/output.txt"
struct hostent *host;
int whatthe = 0;
void sig_handler(int signum){
host = NULL;
}
void dnslookup(char temp1[]){
host = gethostbyname(temp1);
}
int main(int argc, char *argv[]){
struct timeval tv;
double begin, end;
gettimeofday(&tv, NULL);
begin = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ;
char *ListBuffer;
int ListSize;
FILE *InputFile = fopen(IPATH, "r");
FILE *OutputFile = fopen(OPATH, "w");
fseek(InputFile, 0, SEEK_END);
ListSize = ftell(InputFile); //길이를 재고
ListSize ++; //NULL 문자가 들어갈 자리까지 해줌. 문자열의 끝을 알기 위해서
ListBuffer = malloc(ListSize); //잰 길이만큼 동적할당
memset(ListBuffer, 0, ListSize); //할당한 메모리 초기화
ListBuffer[ListSize] = '\0';
fseek(InputFile, 0, SEEK_SET);
fread(ListBuffer, ListSize, 1, InputFile); //읽어와서 동적할당한 배열에 넣기
char temp[] = {0, };
char *temp2;
int count = 0;
int h_count = 0;
char *str1 = NULL;
char *temp1 = strtok_r(ListBuffer, "\n", &str1);
while (temp1 != NULL){
dnslookup(temp1);
signal(SIGALRM,sig_handler);
alarm(2);
if (host != NULL){
fprintf(OutputFile, "%s / %s\n", temp1, inet_ntoa(*(struct in_addr *)host->h_addr_list[0]));
}
else{
fprintf(OutputFile, "%s / %s\n",temp1, "FAIL");
}
temp1 = strtok_r(NULL, "\n", &str1);
}
fclose(InputFile); //파일 포인터 닫기
fclose(OutputFile); //파일 포인터 닫기
free(ListBuffer); // 동적 메모리 해제
ListBuffer = NULL;
gettimeofday(&tv, NULL);
end = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ;
// 출력
printf("Execution time %f\n", (end - begin) / 1000);
}
what is problem?
If you need more explanation, I'll answer it quickly.
Thank you for reading my question. Have a nice day.
Use setjmp() & longjmp() pair with alarm().
#include <setjmp.h>
#define DNS_TIMEOUT 2 // timeout you need
static jmp_buf env;
void sig_handler (int signum) {
//host = NULL;
longjmp (env, 1); // jump to setjmp() location with value 1
}
int dnslookup (const char* domain) {
#define STATUS_TIMEOUT 128 // custom: timeout occurred
int status = 0;
signal (SIGALRM, sig_handler);
if (0 == setjmp(env)) { // to return here after timeout with return value 1
alarm (DNS_TIMEOUT); // setting timeout
host = gethostbyname (domain);
signal (SIGALRM, SIG_DFL);
alarm (0); // cancel alarm
} else { // after timeout-alarm we're here
// you may want to record TIMEOUT instead of FAIL
status = STATUS_TIMEOUT;
host = NULL;
//printf ("\nTimeout for %s", domain);
}
return status;
}
Also:
ListBuffer = malloc(ListSize); //잰 길이만큼 동적할당
memset(ListBuffer, 0, ListSize); //할당한 메모리 초기화 // not necessary
//ListBuffer[ListSize] = '\0'; // BUFFER-OVERFLOW
...
char *rmdList = NULL;
char *domain = strtok_r (ListBuffer, "\n", &rmdList);
while (domain != NULL) {
int status = dnslookup (domain);
// signal (SIGALRM, sig_handler);
// alarm (2);
if (host)
fprintf (OutputFile, "%s / %s\n", domain, inet_ntoa (* (struct in_addr *) host->h_addr_list[0]));
else if (STATUS_TIMEOUT == status)
fprintf (OutputFile, "%s / %s\n", domain, "TIMEOUT");
else
fprintf (OutputFile, "%s / %s\n", domain, "FAIL");
domain = strtok_r (NULL, "\n", &rmdList);
}
That said :
The gethostbyname*(), gethostbyaddr*(), herror(), and hstrerror()
functions are obsolete. Applications should use getaddrinfo(3),
getnameinfo(3), and gai_strerror(3) instead.

How can I generation sine function faster in c

Is there anyway in which i can compute sine function faster in c.When i generate a sine waveform with 16,384 samples it is taking me 3.96 seconds and I want it less than 1 sec.
Give below is the logic i used for sine wave and it is taking almost 4 seconds to compute.I also tried optimization of the code but its of no help.
Someone please help me out
int i;
float f,temp = (2 * M_PI) /16384
for(i=0;i<16384;i++)
{
f = sin(temp * i);
}
There's no reason that you have to compute f more than once, ever. If performance is so critical, hardcode the array of values into the source.
Floating point can be very slow in embedded implementations, but I don't believe it can be slower to index an array. This will create a C source file to #include in the project. I presume OP wanted an unsigned integer table, modify if not what was wanted. If you want to save on code space, code only the first quadrant and do a simple runtime adjustment of the lookup index and value for the other quadrants.
#define _USE_MATH_DEFINES 1
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define TRIGPOINTS 16384
#define AMPLITUDE 8192.0
//#define M_PI 3.14159265358979323846
int main(int argc, char **argv)
{
FILE *fout;
char *filename = "sinetable.c";
int i;
double d;
if( (fout = fopen( filename, "w" )) == NULL ) {
printf( "The file '%s' was not opened\n", filename );
exit (1);
}
fprintf (fout, "#define TRIGPOINTS %u\n", TRIGPOINTS);
fprintf (fout, "#define AMPLITUDE %f\n", AMPLITUDE);
fprintf (fout, "\unsigned sintab [%u] = { ", TRIGPOINTS);
for (i=0; i<TRIGPOINTS; i++)
{
if (i)
fprintf (fout, ", ");
if ((i % 10) == 0)
fprintf (fout, "\n ");
d = AMPLITUDE + AMPLITUDE * sin(2.0 * M_PI * (double)i / TRIGPOINTS);
fprintf (fout, "%u", (unsigned)d);
}
fprintf (fout, " };\n");
fclose (fout);
return (0);
}
The C source generated looks like this:
#define TRIGPOINTS 16384
#define AMPLITUDE 8192.000000
unsigned sintab [16384] = {
8192, 8195, 8198, 8201, 8204, 8207, 8210, 8213, 8217, 8220,
8223, 8226, 8229, 8232, 8235, 8239, 8242, 8245, 8248, 8251,
...

How to use fgetpwent()?

I am trying to get a list of all the users in the system (linux, fedora).
and i've heard that the function:fgetpwent is the one that i need to that mission.
the sad part is that i didnt find any documentation or example of how to use this function.
if someone would give me an example, that would be great, thanks in advance.
No idea why I ever could have used it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crypt.h>
#include <pwd.h>
#include <sys/types.h>
char *testentry = "testread";
static void read_etc_passwd (void) {
struct passwd *pwd_entry = NULL;
int found = 0;
setpwent(); // go to the top of /etc/passwd
while (!found && (pwd_entry = getpwent())){
if (0 == strcmp (testentry, pwd_entry->pw_name)){
found = 1;
}
}
if (found) {
printf ("name = %s\nhome = %s\n", pwd_entry->pw_name,
pwd_entry->pw_dir);
} else {
puts("could not find the entry you were looking for, or"
"some error occurred");
}
}
void change_etc_passwd (void){
struct passwd *pwd = NULL;
FILE *pwd_fd = NULL;
FILE *pwd_new = NULL;
int result = 0;
pwd_fd = fopen ("/etc/passwd", "r");
pwd_new = fopen ("/tmp/passwd.neu", "a");
// assuming everthing went fine (bad idea)
while (pwd = fgetpwent (pwd_fd)){
if (0 == strcmp (pwd->pw_name, testentry)){
pwd->pw_passwd = crypt ("new_pwd", "aa");
}
result = putpwent(pwd, pwd_new);
if (result < 0){
fprintf (stderr, "Failed to write entry, giving up\n");
exit (EXIT_FAILURE);
}
}
}
int main (void) {
/* handling of /etc/passwd */
read_etc_passwd ();
change_etc_passwd();
return 0;
}
Add error handling and it may even work without breaking ;-)

File operation in C giving bizzare output

I'm running a piece of C code that takes information from 10 Dynamixel servo motors ( ID, position, angle , load-torque ) and prints them to the screen as well as writes it to a log file ( watchdog_log.txt).
#include <stdio.h>
#include <stdlib.h>
#include <termio.h>
#include <unistd.h>
#include <string.h>
#include <dynamixel.h>
#include <math.h>
#include <dynamixelAX.h>
#include "utils_v2.h"
#include "low_level_v2AX.h"
#include "low_level_v2.h"
// Control table address
#define P_GOAL_POSITION_L 30
#define P_GOAL_POSITION_H 31
#define P_PRESENT_POSITION_L 36
#define P_PRESENT_POSITION_H 37
#define P_MOVING 46
// Defulat setting
#define DEFAULT_BAUDNUM 34 // 1Mbps
#define DEFAULT_BAUDNUM_AX 1
#define DEFAULT_ID 1
int main()
{
FILE *fp;
/* Get actuator ID from command line argument */
int baudnum = 34;
int baudnum_AX = 1;
int deviceIndex = 0;
int deviceIndex_AX = 1;
int current;
float load, angle;
int i=0;
int MOTOR_CHAIN[13]={-1,1,1,0,0,0,-1,1,1,0,0,0,-1};
int MOTOR_CHAIN_AX[18]={2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};
int MOTOR_HOME[13]={404,444,3216,2037,2289,512,860,661,879,3474,1747,512}; //0, 6 and 12 are dummy
int MOTOR_HOME_AX[18]={512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,};
char report[1000];
char buffer[50];
strcpy(report,"***********\n");
/* Initialise Open USB2Dynamixel */
if( dxl_initialize(deviceIndex, baudnum) == 0 )
{
printf( "Failed to open USB2Dynamixel!-chain'0'\n" );
printf( "Press Enter key to terminate...\n" );
}
else
printf( "Successfully opened USB2Dynamixel 0!\n" );
if( dxl_initializeAX(deviceIndex_AX, baudnum_AX) == 0 )
{
printf( "Failed to open USB2Dynamixel!-chain'1'\n" );
printf( "Press Enter key to terminate...\n" );
}
else
printf( "Successfully opened USB2Dynamixel 1!\n" );
/* Ping all devices */
printf("Pinging devices...");
for( i=0; i<=12; i++)
{
dxl_ping(i);
if (dxl_get_result() == COMM_RXSUCCESS)
{
current = (fabs(dxl_read_word(i, 0x34)-512)*10);
load = dxl_read_word(i, 0x28);
if (load>=1024)
load=(load-1024)*0.1;
else load=load*0.1;
int theta = dxl_read_word(i, 36);
angle = counttoangle(MOTOR_CHAIN[i], MOTOR_HOME[i], theta);
printf("ID: %d success, Load: %3.1f, Count = %d, Angle = %3.2f\n", i, load, theta, angle) ;
sprintf(buffer,"ID: %d success, Load: %3.1f, Count = %d, Angle = %3.2f\n",i, load, theta, angle);
strcat(report,buffer);
}
else printf("ID: %d failure\n",i);
}
//File operations
strcat(report,"***********\n\n\n");
fp = fopen("watchdog_log.txt","w"); /* append file (add text to a file or create a file if it does not exist.*/
fprintf(fp,"%s",report); /*writes to file*/
fclose(fp); /*done!*/**
/* Close device */
dxl_terminateAX();
return 0;
}
I am running the code every one second using 'watch' command on Ubuntu to constantly monitor the output of the code on the screen.
watch -n 1 ./watchdog
The output on the terminal is normal when file operations are not done. But when file writing is done, the terminal gives bizzare outputs:
Normal Output
Bizzare Output
Any help on the above problem will be appreciated.
At first glance probles is in your variables:
char report[1000];
char buffer[50];
they are overflowed whe you are working with them.
for example
sprintf(buffer,"ID: %d success, Load: %3.1f, Count = %d, Angle = %3.2f\n",i, load, theta, angle);
The minimum size of the string is greater than 50 bytes!
So you can try increase the size of your string vars or calc needed size and allocate them in heap ...

Getting the OS version in Mac OS X using standard C

I'm trying to get the version of Mac OS X programmatically in C. After searching for a while I tried this code:
#include <CoreServices/CoreServices.h>
int GetOS()
{
SInt32 majorVersion,minorVersion,bugFixVersion;
Gestalt(gestaltSystemVersionMajor, &majorVersion);
Gestalt(gestaltSystemVersionMinor, &minorVersion);
Gestalt(gestaltSystemVersionBugFix, &bugFixVersion);
printf("Running on Mac OS X %d.%d.%d\n",majorVersion,minorVersion,bugFixVersion);
return 0;
}
XCode returns an LD error:
Undefined symbols for architecture x86_64:
"_Gestalt", referenced from:
_GetOS in main.o
What am I missing? How do you do this?
I found also this snippet
[[NSProcessInfo processInfo] operatingSystemVersionString]
But I have no idea how to write that in C.
Did you pass the appropriate framework to GCC in order to enable CoreServices?
% gcc -framework CoreServices -o getos main.c
The code below should work in the foreseeable future for figuring out the current version of Mac Os X.
/* McUsr put this together, and into public domain,
without any guarrantees about anything,
but the statement that it works for me.
*/
#if 1 == 1
#define TESTING
#endif
#include <sys/param.h>
#include <sys/sysctl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct osver {
int minor;
int sub;
} ;
typedef struct osver osxver ;
void macosx_ver(char *darwinversion, osxver *osxversion ) ;
char *osversionString(void) ;
#ifdef TESTING
int main( int argc, char *argv[] )
{
osxver foundver;
char *osverstr= NULL ;
osverstr=osversionString() ;
macosx_ver(osverstr, &foundver ) ;
printf("Mac os x version = 10.%d.%d\n",foundver.minor,foundver.sub );
free(osverstr);
return 0;
}
#endif
char *osversionString(void) {
int mib[2];
size_t len;
char *kernelVersion=NULL;
mib[0] = CTL_KERN;
mib[1] = KERN_OSRELEASE;
if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0 ) {
fprintf(stderr,"%s: Error during sysctl probe call!\n",__PRETTY_FUNCTION__ );
fflush(stdout);
exit(4) ;
}
kernelVersion = malloc(len );
if (kernelVersion == NULL ) {
fprintf(stderr,"%s: Error during malloc!\n",__PRETTY_FUNCTION__ );
fflush(stdout);
exit(4) ;
}
if (sysctl(mib, 2, kernelVersion, &len, NULL, 0) < 0 ) {
fprintf(stderr,"%s: Error during sysctl get verstring call!\n",__PRETTY_FUNCTION__ );
fflush(stdout);
exit(4) ;
}
return kernelVersion ;
}
void macosx_ver(char *darwinversion, osxver *osxversion ) {
/*
From the book Mac Os X and IOS Internals:
In version 10.1.1, Darwin (the core OS) was renumbered from v1.4.1 to 5.1,
and since then has followed the OS X numbers consistently by being four
numbers ahead of the minor version, and aligning its own minor with the
sub-version.
*/
char firstelm[2]= {0,0},secElm[2]={0,0};
if (strlen(darwinversion) < 5 ) {
fprintf(stderr,"%s: %s Can't possibly be a version string. Exiting\n",__PRETTY_FUNCTION__,darwinversion);
fflush(stdout);
exit(2);
}
char *s=darwinversion,*t=firstelm,*curdot=strchr(darwinversion,'.' );
while ( s != curdot )
*t++ = *s++;
t=secElm ;
curdot=strchr(++s,'.' );
while ( s != curdot )
*t++ = *s++;
int maj=0, min=0;
maj= (int)strtol(firstelm, (char **)NULL, 10);
if ( maj == 0 && errno == EINVAL ) {
fprintf(stderr,"%s Error during conversion of version string\n",__PRETTY_FUNCTION__);
fflush(stdout);
exit(4);
}
min=(int)strtol(secElm, (char **)NULL, 10);
if ( min == 0 && errno == EINVAL ) {
fprintf(stderr,"%s: Error during conversion of version string\n",__PRETTY_FUNCTION__);
fflush(stdout);
exit(4);
}
osxversion->minor=maj-4;
osxversion->sub=min;
}
Here is one with "less work", good enough for home projects (statically allocated buffers, ignoring errors). Works for me in OS X 10.11.1.
#include <stdio.h>
/*!
#brief Returns one component of the OS version
#param component 1=major, 2=minor, 3=bugfix
*/
int GetOSVersionComponent(int component) {
char cmd[64] ;
sprintf(
cmd,
"sw_vers -productVersion | awk -F '.' '{print $%d}'",
component
) ;
FILE* stdoutFile = popen(cmd, "r") ;
int answer = 0 ;
if (stdoutFile) {
char buff[16] ;
char *stdout = fgets(buff, sizeof(buff), stdoutFile) ;
pclose(stdoutFile) ;
sscanf(stdout, "%d", &answer) ;
}
return answer ;
}
int main(int argc, const char * argv[]) {
printf(
"Your OS version is: %d.%d.%d\n",
GetOSVersionComponent(1),
GetOSVersionComponent(2),
GetOSVersionComponent(3)
) ;
return 0 ;
}
Using the hint from #uchuugaka in the comment on the answer by #McUsr, I wrote a function that seems to work. I'm not saying it's better than any other answer.
/*
* Structure for MacOS version number
*/
typedef struct macos_version_str
{
ushort major;
ushort minor;
ushort point;
} macos_type;
/****************************************************************************
*
* Determine the MacOS version.
*
* Parameters:
* version_struct: (pointer to) macos_version structure to be filled in.
*
* Return value:
* 0: no error.
*
****************************************************************************/
static int get_macos_version ( macos_type *version_struct )
{
char os_temp [20] = "";
char *os_temp_ptr = os_temp;
size_t os_temp_len = sizeof(os_temp);
size_t os_temp_left = 0;
int rslt = 0;
version_struct->major = 0;
version_struct->minor = 0;
version_struct->point = 0;
rslt = sysctlbyname ( "kern.osproductversion", os_temp, &os_temp_len, NULL, 0 );
if ( rslt != 0 )
{
fprintf ( stderr,
"sysctlbyname() returned %d error (%d): %s",
rslt, errno, strerror(errno));
return ( rslt );
}
os_temp_left = os_temp_len; /* length of string returned */
int temp = atoi ( os_temp_ptr );
version_struct->major = temp;
version_struct->major = atoi ( os_temp_ptr );
while ( os_temp_left > 0 && *os_temp_ptr != '.' )
{
os_temp_left--;
os_temp_ptr++;
}
os_temp_left--;
os_temp_ptr++;
version_struct->minor = atoi ( os_temp_ptr );
while ( os_temp_left > 0 && *os_temp_ptr != '.' )
{
os_temp_left--;
os_temp_ptr++;
}
os_temp_left--;
os_temp_ptr++;
version_struct->point = atoi ( os_temp_ptr );
fprintf ( stderr, "Calculated OS Version: %d.%d.%d", version_struct->major, version_struct->minor, version_struct->point );
if ( version_struct->major == 0 ||
version_struct->minor == 0 ||
version_struct->point == 0 )
{
fprintf ( stderr, "Unable to parse MacOS version string %s", os_temp );
return ( -2 );
}
return 0;
}
If for whatever reason you want to avoid the Gestalt API (which still works fine, but is deprecated), the macosx_deployment_target.c in cctools contains a code snippet that uses the CTL_KERN + KERN_OSRELEASE sysctl(), similar to other answers here.
Here's a small program adapted from that code and taking macOS 11 and newer (tested and verified with up to macOS 12.6, which was at time of updating this post the latest stable release) into account:
#include <stdio.h>
#include <sys/sysctl.h>
int main()
{
char osversion[32];
size_t osversion_len = sizeof(osversion) - 1;
int osversion_name[] = { CTL_KERN, KERN_OSRELEASE };
if (sysctl(osversion_name, 2, osversion, &osversion_len, NULL, 0) == -1) {
printf("sysctl() failed\n");
return 1;
}
uint32_t major, minor;
if (sscanf(osversion, "%u.%u", &major, &minor) != 2) {
printf("sscanf() failed\n");
return 1;
}
if (major >= 20) {
major -= 9;
// macOS 11 and newer
printf("%u.%u\n", major, minor);
} else {
major -= 4;
// macOS 10.1.1 and newer
printf("10.%u.%u\n", major, minor);
}
return 0;
}

Resources