mirror of
https://github.com/eddyem/eddys_snippets.git
synced 2025-12-06 18:55:16 +03:00
add FITS.
This commit is contained in:
parent
04960e8f20
commit
cb9c37fbd1
22
FITS/Makefile
Normal file
22
FITS/Makefile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
PROGRAM = fitsread
|
||||||
|
LDFLAGS = -lcfitsio
|
||||||
|
SRCS = $(wildcard *.c)
|
||||||
|
CC = gcc
|
||||||
|
DEFINES = -D_XOPEN_SOURCE=1111 -DEBUG
|
||||||
|
CXX = gcc
|
||||||
|
CFLAGS = -Wall -Werror -Wextra $(DEFINES)
|
||||||
|
OBJS = $(SRCS:.c=.o)
|
||||||
|
all : $(PROGRAM)
|
||||||
|
$(PROGRAM) : $(OBJS)
|
||||||
|
$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $(PROGRAM)
|
||||||
|
|
||||||
|
# some addition dependencies
|
||||||
|
# %.o: %.c
|
||||||
|
# $(CC) $(LDFLAGS) $(CFLAGS) $< -o $@
|
||||||
|
#$(SRCS) : %.c : %.h $(INDEPENDENT_HEADERS)
|
||||||
|
# @touch $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
/bin/rm -f *.o *~
|
||||||
|
depend:
|
||||||
|
$(CXX) -MM $(CXX.SRCS)
|
||||||
1
FITS/README
Normal file
1
FITS/README
Normal file
@ -0,0 +1 @@
|
|||||||
|
Simple routines for FITS reading/writing
|
||||||
161
FITS/fits.c
Normal file
161
FITS/fits.c
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* fits.c - cfitsio routines
|
||||||
|
*
|
||||||
|
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program 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 program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fitsio.h>
|
||||||
|
|
||||||
|
#include "fits.h"
|
||||||
|
#include "usefull_macros.h"
|
||||||
|
|
||||||
|
static int fitsstatus = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros for error processing when working with cfitsio functions
|
||||||
|
*/
|
||||||
|
#define TRYFITS(f, ...) \
|
||||||
|
do{ fitsstatus = 0; \
|
||||||
|
f(__VA_ARGS__, &fitsstatus); \
|
||||||
|
if(fitsstatus){ \
|
||||||
|
fits_report_error(stderr, fitsstatus); \
|
||||||
|
return FALSE;} \
|
||||||
|
}while(0)
|
||||||
|
#define FITSFUN(f, ...) \
|
||||||
|
do{ fitsstatus = 0; \
|
||||||
|
int ret = f(__VA_ARGS__, &fitsstatus); \
|
||||||
|
if(ret || fitsstatus) \
|
||||||
|
fits_report_error(stderr, fitsstatus); \
|
||||||
|
}while(0)
|
||||||
|
#define WRITEKEY(...) \
|
||||||
|
do{ fitsstatus = 0; \
|
||||||
|
fits_write_key(__VA_ARGS__, &fitsstatus); \
|
||||||
|
if(status) fits_report_error(stderr, status);\
|
||||||
|
}while(0)
|
||||||
|
|
||||||
|
void imfree(IMAGE **img){
|
||||||
|
size_t i, sz = (*img)->keynum;
|
||||||
|
char **list = (*img)->keylist;
|
||||||
|
for(i = 0; i < sz; ++i) FREE(list[i]);
|
||||||
|
FREE((*img)->keylist);
|
||||||
|
FREE((*img)->data);
|
||||||
|
FREE(*img);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readFITS(char *filename, IMAGE **fits){
|
||||||
|
FNAME();
|
||||||
|
bool ret = TRUE;
|
||||||
|
fitsfile *fp;
|
||||||
|
// float nullval = 0., imBits, bZero = 0., bScale = 1.;
|
||||||
|
int i, j, hdunum, hdutype, nkeys, keypos;
|
||||||
|
int naxis;
|
||||||
|
long naxes[2];
|
||||||
|
char card[FLEN_CARD];
|
||||||
|
IMAGE *img = MALLOC(IMAGE, 1);
|
||||||
|
|
||||||
|
TRYFITS(fits_open_file, &fp, filename, READONLY);
|
||||||
|
FITSFUN(fits_get_num_hdus, fp, &hdunum);
|
||||||
|
if(hdunum < 1){
|
||||||
|
WARNX(_("Can't read HDU"));
|
||||||
|
ret = FALSE;
|
||||||
|
goto returning;
|
||||||
|
}
|
||||||
|
// get image dimensions
|
||||||
|
TRYFITS(fits_get_img_param, fp, 2, &img->dtype, &naxis, naxes);
|
||||||
|
if(naxis > 2){
|
||||||
|
WARNX(_("Images with > 2 dimensions are not supported"));
|
||||||
|
ret = FALSE;
|
||||||
|
goto returning;
|
||||||
|
}
|
||||||
|
img->width = naxes[0];
|
||||||
|
img->height = naxes[1];
|
||||||
|
DBG("got image %ldx%ld pix, bitpix=%d", naxes[0], naxes[1], img->dtype);
|
||||||
|
// loop through all HDUs
|
||||||
|
for(i = 1; !(fits_movabs_hdu(fp, i, &hdutype, &fitsstatus)); ++i){
|
||||||
|
TRYFITS(fits_get_hdrpos, fp, &nkeys, &keypos);
|
||||||
|
int oldnkeys = img->keynum;
|
||||||
|
img->keynum += nkeys;
|
||||||
|
if(!(img->keylist = realloc(img->keylist, sizeof(char*) * img->keynum))){
|
||||||
|
ERR(_("Can't realloc"));
|
||||||
|
}
|
||||||
|
char **currec = &(img->keylist[oldnkeys]);
|
||||||
|
DBG("HDU # %d of %d keys", i, nkeys);
|
||||||
|
for(j = 1; j <= nkeys; ++j){
|
||||||
|
FITSFUN(fits_read_record, fp, j, card);
|
||||||
|
if(!fitsstatus){
|
||||||
|
*currec = MALLOC(char, FLEN_CARD);
|
||||||
|
memcpy(*currec, card, FLEN_CARD);
|
||||||
|
DBG("key %d: %s", oldnkeys + j, *currec);
|
||||||
|
++currec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(fitsstatus == END_OF_FILE){
|
||||||
|
fitsstatus = 0;
|
||||||
|
}else{
|
||||||
|
fits_report_error(stderr, fitsstatus);
|
||||||
|
ret = FALSE;
|
||||||
|
goto returning;
|
||||||
|
}
|
||||||
|
size_t sz = naxes[0] * naxes[1];
|
||||||
|
img->data = MALLOC(double, sz);
|
||||||
|
int stat = 0;
|
||||||
|
TRYFITS(fits_read_img, fp, TDOUBLE, 1, sz, NULL, img->data, &stat);
|
||||||
|
if(stat) WARNX(_("Found %d pixels with undefined value"), stat);
|
||||||
|
DBG("ready");
|
||||||
|
|
||||||
|
returning:
|
||||||
|
FITSFUN(fits_close_file, fp);
|
||||||
|
if(!ret){
|
||||||
|
imfree(&img);
|
||||||
|
}
|
||||||
|
if(fits) *fits = img;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool writeFITS(char *filename, IMAGE *fits){
|
||||||
|
int w = fits->width, h = fits->height;
|
||||||
|
long naxes[2] = {w, h};
|
||||||
|
size_t sz = w * h, keys = fits->keynum;
|
||||||
|
fitsfile *fp;
|
||||||
|
|
||||||
|
TRYFITS(fits_create_file, &fp, filename);
|
||||||
|
TRYFITS(fits_create_img, fp, fits->dtype, 2, naxes);
|
||||||
|
|
||||||
|
if(keys){ // there's keys
|
||||||
|
size_t i;
|
||||||
|
char **records = fits->keylist;
|
||||||
|
for(i = 0; i < keys; ++i){
|
||||||
|
char *rec = records[i];
|
||||||
|
if(strncmp(rec, "SIMPLE", 6) == 0 || strncmp(rec, "EXTEND", 6) == 0) // key "file does conform ..."
|
||||||
|
continue;
|
||||||
|
else if(strncmp(rec, "COMMENT", 7) == 0) // comment of obligatory key in FITS head
|
||||||
|
continue;
|
||||||
|
else if(strncmp(rec, "NAXIS", 5) == 0 || strncmp(rec, "BITPIX", 6) == 0) // NAXIS, NAXISxxx, BITPIX
|
||||||
|
continue;
|
||||||
|
FITSFUN(fits_write_record, fp, rec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FITSFUN(fits_write_record, fp, "COMMENT modified by simple test routine");
|
||||||
|
|
||||||
|
TRYFITS(fits_write_img, fp, TDOUBLE, 1, sz, fits->data);
|
||||||
|
TRYFITS(fits_close_file, fp);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
42
FITS/fits.h
Normal file
42
FITS/fits.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* fits.h
|
||||||
|
*
|
||||||
|
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program 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 program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#ifndef __FITS_H__
|
||||||
|
#define __FITS_H__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
int width; // width
|
||||||
|
int height; // height
|
||||||
|
int dtype; // data type
|
||||||
|
double *data; // picture data
|
||||||
|
char **keylist; // list of options for each key
|
||||||
|
size_t keynum; // full number of keys (size of *keylist)
|
||||||
|
} IMAGE;
|
||||||
|
|
||||||
|
void imfree(IMAGE **ima);
|
||||||
|
bool readFITS(char *filename, IMAGE **fits);
|
||||||
|
bool writeFITS(char *filename, IMAGE *fits);
|
||||||
|
|
||||||
|
#endif // __FITS_H__
|
||||||
44
FITS/main.c
Normal file
44
FITS/main.c
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* main.c
|
||||||
|
*
|
||||||
|
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program 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 program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "usefull_macros.h"
|
||||||
|
#include "fits.h"
|
||||||
|
|
||||||
|
void signals(int signo){
|
||||||
|
exit(signo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv){
|
||||||
|
IMAGE *fits;
|
||||||
|
//size_t i, s;
|
||||||
|
initial_setup();
|
||||||
|
if(argc != 3) ERRX("Usage: %s infile outfile", argv[0]);
|
||||||
|
readFITS(argv[1], &fits);
|
||||||
|
DBG("ima: %dx%d", fits->width, fits->height);
|
||||||
|
//s = fits->width * fits->height;
|
||||||
|
//double *img = fits->data;
|
||||||
|
//for(i = 0; i < s; ++i) *img++ /= 2.;
|
||||||
|
unlink(argv[2]);
|
||||||
|
writeFITS(argv[2], fits);
|
||||||
|
imfree(&fits);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
327
FITS/usefull_macros.c
Normal file
327
FITS/usefull_macros.c
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
/*
|
||||||
|
* usefull_macros.h - a set of usefull functions: memory, color etc
|
||||||
|
*
|
||||||
|
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
||||||
|
*
|
||||||
|
* This program 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 program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "usefull_macros.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* function for different purposes that need to know time intervals
|
||||||
|
* @return double value: time in seconds
|
||||||
|
*/
|
||||||
|
double dtime(){
|
||||||
|
double t;
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
t = tv.tv_sec + ((double)tv.tv_usec)/1e6;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************\
|
||||||
|
* Coloured terminal
|
||||||
|
\******************************************************************************/
|
||||||
|
int globErr = 0; // errno for WARN/ERR
|
||||||
|
|
||||||
|
// pointers to coloured output printf
|
||||||
|
int (*red)(const char *fmt, ...);
|
||||||
|
int (*green)(const char *fmt, ...);
|
||||||
|
int (*_WARN)(const char *fmt, ...);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* format red / green messages
|
||||||
|
* name: r_pr_, g_pr_
|
||||||
|
* @param fmt ... - printf-like format
|
||||||
|
* @return number of printed symbols
|
||||||
|
*/
|
||||||
|
int r_pr_(const char *fmt, ...){
|
||||||
|
va_list ar; int i;
|
||||||
|
printf(RED);
|
||||||
|
va_start(ar, fmt);
|
||||||
|
i = vprintf(fmt, ar);
|
||||||
|
va_end(ar);
|
||||||
|
printf(OLDCOLOR);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
int g_pr_(const char *fmt, ...){
|
||||||
|
va_list ar; int i;
|
||||||
|
printf(GREEN);
|
||||||
|
va_start(ar, fmt);
|
||||||
|
i = vprintf(fmt, ar);
|
||||||
|
va_end(ar);
|
||||||
|
printf(OLDCOLOR);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* print red error/warning messages (if output is a tty)
|
||||||
|
* @param fmt ... - printf-like format
|
||||||
|
* @return number of printed symbols
|
||||||
|
*/
|
||||||
|
int r_WARN(const char *fmt, ...){
|
||||||
|
va_list ar; int i = 1;
|
||||||
|
fprintf(stderr, RED);
|
||||||
|
va_start(ar, fmt);
|
||||||
|
if(globErr){
|
||||||
|
errno = globErr;
|
||||||
|
vwarn(fmt, ar);
|
||||||
|
errno = 0;
|
||||||
|
globErr = 0;
|
||||||
|
}else
|
||||||
|
i = vfprintf(stderr, fmt, ar);
|
||||||
|
va_end(ar);
|
||||||
|
i++;
|
||||||
|
fprintf(stderr, OLDCOLOR "\n");
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char stars[] = "****************************************";
|
||||||
|
/*
|
||||||
|
* notty variants of coloured printf
|
||||||
|
* name: s_WARN, r_pr_notty
|
||||||
|
* @param fmt ... - printf-like format
|
||||||
|
* @return number of printed symbols
|
||||||
|
*/
|
||||||
|
int s_WARN(const char *fmt, ...){
|
||||||
|
va_list ar; int i;
|
||||||
|
i = fprintf(stderr, "\n%s\n", stars);
|
||||||
|
va_start(ar, fmt);
|
||||||
|
if(globErr){
|
||||||
|
errno = globErr;
|
||||||
|
vwarn(fmt, ar);
|
||||||
|
errno = 0;
|
||||||
|
globErr = 0;
|
||||||
|
}else
|
||||||
|
i = +vfprintf(stderr, fmt, ar);
|
||||||
|
va_end(ar);
|
||||||
|
i += fprintf(stderr, "\n%s\n", stars);
|
||||||
|
i += fprintf(stderr, "\n");
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
int r_pr_notty(const char *fmt, ...){
|
||||||
|
va_list ar; int i;
|
||||||
|
i = printf("\n%s\n", stars);
|
||||||
|
va_start(ar, fmt);
|
||||||
|
i += vprintf(fmt, ar);
|
||||||
|
va_end(ar);
|
||||||
|
i += printf("\n%s\n", stars);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run this function in the beginning of main() to setup locale & coloured output
|
||||||
|
*/
|
||||||
|
void initial_setup(){
|
||||||
|
// setup coloured output
|
||||||
|
if(isatty(STDOUT_FILENO)){ // make color output in tty
|
||||||
|
red = r_pr_; green = g_pr_;
|
||||||
|
}else{ // no colors in case of pipe
|
||||||
|
red = r_pr_notty; green = printf;
|
||||||
|
}
|
||||||
|
if(isatty(STDERR_FILENO)) _WARN = r_WARN;
|
||||||
|
else _WARN = s_WARN;
|
||||||
|
// Setup locale
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
setlocale(LC_NUMERIC, "C");
|
||||||
|
#if defined GETTEXT_PACKAGE && defined LOCALEDIR
|
||||||
|
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
|
||||||
|
textdomain(GETTEXT_PACKAGE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************\
|
||||||
|
* Memory
|
||||||
|
\******************************************************************************/
|
||||||
|
/*
|
||||||
|
* safe memory allocation for macro ALLOC
|
||||||
|
* @param N - number of elements to allocate
|
||||||
|
* @param S - size of single element (typically sizeof)
|
||||||
|
* @return pointer to allocated memory area
|
||||||
|
*/
|
||||||
|
void *my_alloc(size_t N, size_t S){
|
||||||
|
void *p = calloc(N, S);
|
||||||
|
if(!p) ERR("malloc");
|
||||||
|
//assert(p);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mmap file to a memory area
|
||||||
|
*
|
||||||
|
* @param filename (i) - name of file to mmap
|
||||||
|
* @return stuct with mmap'ed file or die
|
||||||
|
*/
|
||||||
|
mmapbuf *My_mmap(char *filename){
|
||||||
|
int fd;
|
||||||
|
char *ptr;
|
||||||
|
size_t Mlen;
|
||||||
|
struct stat statbuf;
|
||||||
|
if(!filename) ERRX(_("No filename given!"));
|
||||||
|
if((fd = open(filename, O_RDONLY)) < 0)
|
||||||
|
ERR(_("Can't open %s for reading"), filename);
|
||||||
|
if(fstat (fd, &statbuf) < 0)
|
||||||
|
ERR(_("Can't stat %s"), filename);
|
||||||
|
Mlen = statbuf.st_size;
|
||||||
|
if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
|
||||||
|
ERR(_("Mmap error for input"));
|
||||||
|
if(close(fd)) ERR(_("Can't close mmap'ed file"));
|
||||||
|
mmapbuf *ret = MALLOC(mmapbuf, 1);
|
||||||
|
ret->data = ptr;
|
||||||
|
ret->len = Mlen;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void My_munmap(mmapbuf *b){
|
||||||
|
if(munmap(b->data, b->len))
|
||||||
|
ERR(_("Can't munmap"));
|
||||||
|
FREE(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************\
|
||||||
|
* Terminal in no-echo mode
|
||||||
|
\******************************************************************************/
|
||||||
|
static struct termios oldt, newt; // terminal flags
|
||||||
|
static int console_changed = 0;
|
||||||
|
// run on exit:
|
||||||
|
void restore_console(){
|
||||||
|
if(console_changed)
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state
|
||||||
|
console_changed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initial setup:
|
||||||
|
void setup_con(){
|
||||||
|
if(console_changed) return;
|
||||||
|
tcgetattr(STDIN_FILENO, &oldt);
|
||||||
|
newt = oldt;
|
||||||
|
newt.c_lflag &= ~(ICANON | ECHO);
|
||||||
|
if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){
|
||||||
|
WARN(_("Can't setup console"));
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||||
|
signals(0); //quit?
|
||||||
|
}
|
||||||
|
console_changed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read character from console without echo
|
||||||
|
* @return char readed
|
||||||
|
*/
|
||||||
|
int read_console(){
|
||||||
|
int rb;
|
||||||
|
struct timeval tv;
|
||||||
|
int retval;
|
||||||
|
fd_set rfds;
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(STDIN_FILENO, &rfds);
|
||||||
|
tv.tv_sec = 0; tv.tv_usec = 10000;
|
||||||
|
retval = select(1, &rfds, NULL, NULL, &tv);
|
||||||
|
if(!retval) rb = 0;
|
||||||
|
else {
|
||||||
|
if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar();
|
||||||
|
else rb = 0;
|
||||||
|
}
|
||||||
|
return rb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getchar() without echo
|
||||||
|
* wait until at least one character pressed
|
||||||
|
* @return character readed
|
||||||
|
*/
|
||||||
|
int mygetchar(){ // getchar() without need of pressing ENTER
|
||||||
|
int ret;
|
||||||
|
do ret = read_console();
|
||||||
|
while(ret == 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************\
|
||||||
|
* TTY with select()
|
||||||
|
\******************************************************************************/
|
||||||
|
static struct termio oldtty, tty; // TTY flags
|
||||||
|
static int comfd = -1; // TTY fd
|
||||||
|
|
||||||
|
// run on exit:
|
||||||
|
void restore_tty(){
|
||||||
|
if(comfd == -1) return;
|
||||||
|
ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state
|
||||||
|
close(comfd);
|
||||||
|
comfd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BAUD_RATE
|
||||||
|
#define BAUD_RATE B9600
|
||||||
|
#endif
|
||||||
|
// init:
|
||||||
|
void tty_init(char *comdev){
|
||||||
|
DBG("\nOpen port...\n");
|
||||||
|
if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){
|
||||||
|
WARN("Can't use port %s\n",comdev);
|
||||||
|
ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state
|
||||||
|
close(comfd);
|
||||||
|
signals(0); // quit?
|
||||||
|
}
|
||||||
|
DBG(" OK\nGet current settings... ");
|
||||||
|
if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings
|
||||||
|
WARN(_("Can't get settings"));
|
||||||
|
signals(0);
|
||||||
|
}
|
||||||
|
tty = oldtty;
|
||||||
|
tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG)
|
||||||
|
tty.c_oflag = 0;
|
||||||
|
tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl
|
||||||
|
tty.c_cc[VMIN] = 0; // non-canonical mode
|
||||||
|
tty.c_cc[VTIME] = 5;
|
||||||
|
if(ioctl(comfd,TCSETA,&tty) < 0){
|
||||||
|
WARN(_("Can't set settings"));
|
||||||
|
signals(0);
|
||||||
|
}
|
||||||
|
DBG(" OK\n");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Read data from TTY
|
||||||
|
* @param buff (o) - buffer for data read
|
||||||
|
* @param length - buffer len
|
||||||
|
* @return amount of readed bytes
|
||||||
|
*/
|
||||||
|
size_t read_tty(uint8_t *buff, size_t length){
|
||||||
|
ssize_t L = 0;
|
||||||
|
fd_set rfds;
|
||||||
|
struct timeval tv;
|
||||||
|
int retval;
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(comfd, &rfds);
|
||||||
|
tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms
|
||||||
|
retval = select(comfd + 1, &rfds, NULL, NULL, &tv);
|
||||||
|
if (!retval) return 0;
|
||||||
|
if(FD_ISSET(comfd, &rfds)){
|
||||||
|
if((L = read(comfd, buff, length)) < 1) return 0;
|
||||||
|
}
|
||||||
|
return (size_t)L;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_tty(uint8_t *buff, size_t length){
|
||||||
|
ssize_t L = write(comfd, buff, length);
|
||||||
|
if((size_t)L != length){
|
||||||
|
WARN("Write error!");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
124
FITS/usefull_macros.h
Normal file
124
FITS/usefull_macros.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* usefull_macros.h - a set of usefull macros: memory, color etc
|
||||||
|
*
|
||||||
|
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
||||||
|
*
|
||||||
|
* This program 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 program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef __USEFULL_MACROS_H__
|
||||||
|
#define __USEFULL_MACROS_H__
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#if defined GETTEXT_PACKAGE && defined LOCALEDIR
|
||||||
|
/*
|
||||||
|
* GETTEXT
|
||||||
|
*/
|
||||||
|
#include <libintl.h>
|
||||||
|
#define _(String) gettext(String)
|
||||||
|
#define gettext_noop(String) String
|
||||||
|
#define N_(String) gettext_noop(String)
|
||||||
|
#else
|
||||||
|
#define _(String) (String)
|
||||||
|
#define N_(String) (String)
|
||||||
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <termio.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
// unused arguments with -Wall -Werror
|
||||||
|
#define _U_ __attribute__((__unused__))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Coloured messages output
|
||||||
|
*/
|
||||||
|
#define RED "\033[1;31;40m"
|
||||||
|
#define GREEN "\033[1;32;40m"
|
||||||
|
#define OLDCOLOR "\033[0;0;0m"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ERROR/WARNING messages
|
||||||
|
*/
|
||||||
|
extern int globErr;
|
||||||
|
extern void signals(int sig);
|
||||||
|
#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); signals(0);}while(0)
|
||||||
|
#define ERRX(...) do{globErr=0; _WARN(__VA_ARGS__); signals(0);}while(0)
|
||||||
|
#define WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0)
|
||||||
|
#define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print function name, debug messages
|
||||||
|
* debug mode, -DEBUG
|
||||||
|
*/
|
||||||
|
#ifdef EBUG
|
||||||
|
#define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__)
|
||||||
|
#define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \
|
||||||
|
fprintf(stderr, __VA_ARGS__); \
|
||||||
|
fprintf(stderr, "\n");} while(0)
|
||||||
|
#else
|
||||||
|
#define FNAME() do{}while(0)
|
||||||
|
#define DBG(...) do{}while(0)
|
||||||
|
#endif //EBUG
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Memory allocation
|
||||||
|
*/
|
||||||
|
#define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type)))
|
||||||
|
#define MALLOC(type, size) ((type *)my_alloc(size, sizeof(type)))
|
||||||
|
#define FREE(ptr) do{free(ptr); ptr = NULL;}while(0)
|
||||||
|
|
||||||
|
double dtime();
|
||||||
|
|
||||||
|
// functions for color output in tty & no-color in pipes
|
||||||
|
extern int (*red)(const char *fmt, ...);
|
||||||
|
extern int (*_WARN)(const char *fmt, ...);
|
||||||
|
extern int (*green)(const char *fmt, ...);
|
||||||
|
void * my_alloc(size_t N, size_t S);
|
||||||
|
void initial_setup();
|
||||||
|
|
||||||
|
// mmap file
|
||||||
|
typedef struct{
|
||||||
|
char *data;
|
||||||
|
size_t len;
|
||||||
|
} mmapbuf;
|
||||||
|
mmapbuf *My_mmap(char *filename);
|
||||||
|
void My_munmap(mmapbuf *b);
|
||||||
|
|
||||||
|
void restore_console();
|
||||||
|
void setup_con();
|
||||||
|
int read_console();
|
||||||
|
int mygetchar();
|
||||||
|
|
||||||
|
void restore_tty();
|
||||||
|
void tty_init(char *comdev);
|
||||||
|
size_t read_tty(uint8_t *buff, size_t length);
|
||||||
|
int write_tty(uint8_t *buff, size_t length);
|
||||||
|
|
||||||
|
#endif // __USEFULL_MACROS_H__
|
||||||
69
guard.c
Normal file
69
guard.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int child_killed = 0;
|
||||||
|
pthread_t athread;
|
||||||
|
|
||||||
|
void sighndlr(int sig){
|
||||||
|
printf("got signal %d\n", sig);
|
||||||
|
if(sig == SIGCHLD){
|
||||||
|
printf("Child was killed\n");
|
||||||
|
child_killed = 1;
|
||||||
|
}else if(sig == SIGSEGV){
|
||||||
|
printf("suicide\n");
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}else
|
||||||
|
exit(sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dummy(){
|
||||||
|
int i;
|
||||||
|
char *ptr = malloc(10000);
|
||||||
|
for(i = 0; i < 256; ++i, ptr += 1024){
|
||||||
|
*ptr += i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t create_child(){
|
||||||
|
child_killed = 0;
|
||||||
|
pid_t p = fork();
|
||||||
|
if(p == 0){
|
||||||
|
printf("child\n");
|
||||||
|
dummy();
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *thrfnctn(void *buf){
|
||||||
|
dummy();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
int i;
|
||||||
|
//for(i = 0; i < 255; ++i)
|
||||||
|
// signal(i, sighndlr);
|
||||||
|
signal(SIGCHLD, sighndlr);
|
||||||
|
signal(SIGSEGV, sighndlr);
|
||||||
|
for(i = 0; i < 10; ++i){
|
||||||
|
pid_t p = create_child();
|
||||||
|
if(p){
|
||||||
|
printf("child #%d with PID %d\n", i, p);
|
||||||
|
while(!child_killed)
|
||||||
|
usleep(10000);
|
||||||
|
}else return 0;
|
||||||
|
}
|
||||||
|
for(i = 0; i < 10; ++i){
|
||||||
|
if(pthread_create(&athread, NULL, thrfnctn, NULL))
|
||||||
|
return -1;
|
||||||
|
printf("thread #%d\n", i);
|
||||||
|
while(pthread_kill(athread, 0) != ESRCH)
|
||||||
|
usleep(1000);
|
||||||
|
pthread_join(athread, NULL);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
45
sigtest.c
Normal file
45
sigtest.c
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
volatile pid_t childpid = 0;
|
||||||
|
|
||||||
|
void signal_handler(int sig){
|
||||||
|
printf("PID %zd got signal %d, die\n", getpid(), sig);
|
||||||
|
if(childpid)
|
||||||
|
kill(childpid, SIGTERM);
|
||||||
|
exit(sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t create_child(){
|
||||||
|
int i;
|
||||||
|
pid_t p = fork();
|
||||||
|
if(p == 0){
|
||||||
|
prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies
|
||||||
|
printf("child\n");
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
int i = 0;
|
||||||
|
signal(SIGTERM, signal_handler); // kill (-15)
|
||||||
|
signal(SIGINT, signal_handler); // ctrl+C
|
||||||
|
signal(SIGQUIT, signal_handler); // ctrl+\ .
|
||||||
|
signal(SIGTSTP, SIG_IGN); // ctrl+Z
|
||||||
|
signal(SIGSEGV, signal_handler);
|
||||||
|
printf("my PID: %zd\n", getpid());
|
||||||
|
while(1){
|
||||||
|
childpid = create_child();
|
||||||
|
if(childpid){
|
||||||
|
printf("child #%d with PID %d\n", ++i, childpid);
|
||||||
|
wait(NULL);
|
||||||
|
printf("died\n");
|
||||||
|
}else return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user