Does anyone know of a library which will assist in decoding cron style timings, i.e.
30 7 * * 1-5
Which is 7:30am every Monday, Tuesday, Wednesday, Thursday, Friday.
M.
There is a library for PHP, Perl but I never saw one for C++.
The good thing is that Cron's source is freely available and you can reuse its code to parse entries in the cron format.
The entry data structure is defined in "cron.h" file:
typedef struct _entry {
struct _entry *next;
uid_t uid;
gid_t gid;
char **envp;
char *cmd;
bitstr_t bit_decl(minute, MINUTE_COUNT);
bitstr_t bit_decl(hour, HOUR_COUNT);
bitstr_t bit_decl(dom, DOM_COUNT);
bitstr_t bit_decl(month, MONTH_COUNT);
bitstr_t bit_decl(dow, DOW_COUNT);
int flags;
#define DOM_STAR 0x01
#define DOW_STAR 0x02
#define WHEN_REBOOT 0x04
#define MIN_STAR 0x08
#define HR_STAR 0x10
} entry;
And there are two functions you need from "entry.c" file (too large to post code here):
void free_entry (e);
entry *load_entry (file, error_func, pw, envp);
You can compile those files into a shared library or object files and use directly in your project.
This is an example of getting cron source code in Debian (Ubuntu):
apt-get source cron
You can also download it from http://cron.sourcearchive.com/
For those that wish to achieve the same goal as #ScaryAardvark
Dependency:
http://cron.sourcearchive.com/downloads/3.0pl1/cron_3.0pl1.orig.tar.gz
Build:
gcc -o main main.c cron-3.0pl1.orig/entry.c cron-3.0pl1.orig/env.c
cron-3.0pl1.orig/misc.c -I cron-3.0pl1.orig
Source:
#include <pwd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <uuid/uuid.h>
#define MAIN_PROGRAM 1
#include "cron-3.0pl1.orig/cron.h"
void error_handler( char* message )
{
fprintf( stderr, "Error: %s\n", message );
}
void print_entry( const entry* e )
{
fprintf( stdout, "uid: %i\n", e->uid );
fprintf( stdout, "gid: %i\n", e->gid );
fprintf( stdout, "command: %s\n", e->cmd);
//etc...
}
int main( int argc, char** argv, char** envp )
{
const char* filename = "crontab";
const char* username = "bcrowhurst";
//Retreive Crontab File
FILE *file = fopen( filename, "r" );
if ( file == NULL )
{
error_handler( strerror( errno ) );
return EXIT_FAILURE;
}
//Retreive Password Entry
struct passwd *pw = getpwnam( username );
if ( pw == NULL )
{
error_handler( strerror( errno ) );
return EXIT_FAILURE;
}
//Read Entry
entry *e = load_entry( file, &error_handler, pw, envp );
if ( e == NULL )
{
error_handler( "No entry found!" );
return EXIT_FAILURE;
}
print_entry( e );
//Clean-up
fclose( file );
free_entry( e );
return EXIT_SUCCESS;
}
Example Crontab
#yearly /home/bcrowhurst/annual-process
*/10 * * * * /home/bcrowhurst/fschk
Related
I'm working on adding some restrictions to my build process - to detect cycles, specifically. To achieve this I've been experimenting with user namespaces.
Here's my 'hello world' program:
#include <sched.h>
#include <unistd.h>
int main()
{
if( unshare(CLONE_NEWUSER) != 0)
{
return -1;
}
execl("/bin/sh", "/bin/sh", "-e", "-c", "make", NULL);
return 0;
}
Here is the makefile being run by make, namespace_test.cpp is the name of the file above:
namespace_test: namespace_test.cpp
g++ namespace_test.cpp -o ./namespace_test
When everything is up to date (as determined by make) the exec'd program works as expected:
make: 'namespace_test' is up to date.
But if make actually runs the g++ invocation I get an opaque error:
g++ namespace_test.cpp -o ./namespace_test
make: g++: Invalid argument
make: *** [Makefile:2: namespace_test] Error 127
What is the reason for this behavior?
This error was due to my failure to set up the uid_map and gid_map. I have not produced a satisfactory, explicit, minimal example of the error, but I have written a working minimal solution, that I will share here. Notice that int main() is identical, except before exec'ing the target command we first set up the uid_map and then the gid_map (granting ourselves permission via setgroups).
On my terminal $ id informs me that my real uid and gid are both 1000, so I have hardcoded that in the maps. It is more correct to query for the original id at the start of the process, see this excellent blog post. Also instrumental in this solution is this man page.
#include <cstdio>
#include <cstring>
#include <fcntl.h>
#include <sched.h>
#include <stdlib.h>
#include <unistd.h>
#define fatal_error(...) \
do { \
fprintf(stderr, "namespace_test \033[1;31merror:\033[0m "); \
fprintf(stderr, __VA_ARGS__ ); \
fprintf(stderr, "\n"); \
exit(EXIT_FAILURE); \
} while(0)
void write_string_to_file(const char* filename, const char* str, size_t str_len)
{
int fd = open(filename, O_RDWR);
if(fd == -1)
{
fatal_error("Failed to open %s: %m", filename);
}
if( write(fd, str, str_len) != str_len )
{
fatal_error("Failed to write %s: %m", filename);
}
close(fd);
}
void write_uid_mapping()
{
const char* mapping = "0 1000 1";
write_string_to_file("/proc/self/uid_map", mapping, strlen(mapping));
}
void write_set_groups()
{
const char* deny = "deny\n";
write_string_to_file("/proc/self/setgroups", deny, strlen(deny));
}
void write_gid_mapping()
{
write_set_groups();
const char* mapping = "0 1000 1";
write_string_to_file("/proc/self/gid_map", mapping, strlen(mapping));
}
int main()
{
if(unshare(CLONE_NEWUSER) != 0)
{
fatal_error("Failed to move into new user namespace");
}
write_uid_mapping();
write_gid_mapping();
execl("/bin/sh", "/bin/sh", "-e", "-c", "make", NULL);
return 0;
}
I'm trying to search all files that follow this pattern "console-*" and move them to another path on my machine if they exist. (For example from: /documents/fs/pstore to /sdk/sys/kernel_dump/).
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int dirExists(const char *pathname)
{
struct stat info;
if( stat( pathname, &info ) != 0 )
return 0; // printf( "cannot access %s\n", pathname );
else if( info.st_mode & S_IFDIR ) // S_ISDIR() doesn't exist on my windows
return 1; // printf( "%s is a directory\n", pathname );
else
return 0; // printf( "%s is no directory\n", pathname );
}
int main()
{
const char *path = "/documents/fs/pstore";
if(dirExists(path))
system("mv /documents/fs/pstore/console-* /sdk/sys/kernel_dump/ ");
else
printf( "error" );
return 0;
}
I've experienced with the code above, but it does not seem to work properly, should I try another approach, maybe with the rename() function? (I'm working on Linux)
Any advice would be greatly appreciated, thank you in advance.
You can call glob() and rename() C functions in Linux if C++17's std::filesystem is not an option for you. glob() gives you the list of files that matches globbing pattern like *, ? and []. However, rename() may fail if the mount position of from and to path are not identical. In this case, you should create your own copy and remove file function.
I wrote a C++ code which I am converting to a mex file so that I can run from Matlab. My original C++ code displays output of some function declared in third party library. However, when I convert it into mex file, the output seems to be suppressed.
NOTE: output of following command get suppressed
int systemRet = std::system("./genb_test");
Original code:
#include <stdio.h> /* defines FILENAME_MAX */
#include <cstdlib>
#include <iostream>
#ifdef _MSC_VER
#include "direct.h"
#define GetCurrentDir _getcwd // window ??
#else
#include "unistd.h"
#define GetCurrentDir getcwd
#endif
int main()
{
const char *ParentFolder = "/home/dkumar/libtsnnls-2.3.3/tsnnls/";
int res3 = chdir(ParentFolder);
if (res3 == -1){
// The system method failed
std::cout<< "the chdir method has failed \n";
}
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
{
printf("Could not find current directory " );
// return errno;
}
cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */
printf ("The current working directory is %s", cCurrentPath);
printf ("\n");
printf("Now running genb test " );
int systemRet = std::system("./genb_test");
if(systemRet == -1){
// The system method failed
}else{
printf("System command execuated successfully " );
}
return 0;
}
Output from original code:
The current working directory is /home/dkumar/libtsnnls-2.3.3/tsnnls
genb_tests
Creating 100 random test 121 x 89 problems using
the genb algorithm of PJV. Each problem will be given
to the tsnnls method, and the error printed below.
We require an error less than 1e-8 to pass the test.
# M N Error (PJV error) (Spiv error) Result
-----------------------------------------------------------------
1 121 89 1.375271e-15 1.375271e-15 0.000000e+00 pass
2 121 89 1.953126e-15 1.953126e-15 0.000000e+00 pass
3 121 89 4.272569e-15 4.272569e-15 0.000000e+00 pass
4 121 89 1.440234e-15 1.440234e-15 0.000000e+00 pass
5 121 89 2.392671e-15 2.392671e-15 0.000000e+00 pass
.......
.......
98 121 89 4.696796e-15 4.696796e-15 0.000000e+00 pass
99 121 89 1.820247e-15 1.820247e-15 0.000000e+00 pass
100 121 89 1.520109e-15 1.520109e-15 0.000000e+00 pass
100 (of 100) tests passed.
Now running genb test System command execuated successfully
Translated original code to mex file: various input and output (LHS) are left as it is, since I would start using that soon.
#include <matrix.h> // mex
#include <mex.h> // mex
#include <iostream> // Basic I/O
using namespace std; // Basic I/O
/* Definitions to keep compatibility with earlier versions of ML */
#ifndef MWSIZE_MAX
typedef int mwSize;
typedef int mwIndex;
typedef int mwSignedIndex;
#if (defined(_LP64) || defined(_WIN64)) && !defined(MX_COMPAT_32)
/* Currently 2^48 based on hardware limitations */
# define MWSIZE_MAX 281474976710655UL
# define MWINDEX_MAX 281474976710655UL
# define MWSINDEX_MAX 281474976710655L
# define MWSINDEX_MIN -281474976710655L
#else
# define MWSIZE_MAX 2147483647UL
# define MWINDEX_MAX 2147483647UL
# define MWSINDEX_MAX 2147483647L
# define MWSINDEX_MIN -2147483647L
#endif
#define MWSIZE_MIN 0UL
#define MWINDEX_MIN 0UL
#endif
// 'Hello World!' program
#include <stdio.h> /* defines FILENAME_MAX */
#include <cstdlib>
#include <iostream>
#ifdef _MSC_VER
#include "direct.h"
#define GetCurrentDir _getcwd // window ??
#else
#include "unistd.h"
#define GetCurrentDir getcwd
#endif
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
//const char *ParentFolder = "/home/dkumar/All_Matlab_Codes_DKU/";
const char *ParentFolder = "/home/dkumar/libtsnnls-2.3.3/tsnnls/";
//declare variables
mxArray *a_in_m, *b_in_m, *c_out_m, *d_out_m;
const mwSize *dims;
double *a, *b, *c, *d;
int dimx, dimy, numdims;
int i,j;
//associate inputs
a_in_m = mxDuplicateArray(prhs[0]);
b_in_m = mxDuplicateArray(prhs[1]);
//figure out dimensions
dims = mxGetDimensions(prhs[0]);
numdims = mxGetNumberOfDimensions(prhs[0]);
dimy = (int)dims[0]; dimx = (int)dims[1];
//associate outputs
c_out_m = plhs[0] = mxCreateDoubleMatrix(dimy,dimx,mxREAL);
d_out_m = plhs[1] = mxCreateDoubleMatrix(dimy,dimx,mxREAL);
//associate pointers
a = mxGetPr(a_in_m);
b = mxGetPr(b_in_m);
c = mxGetPr(c_out_m);
d = mxGetPr(d_out_m);
std::cout<< "Trying to change the directory "<< "\n";
// COPIED FROM ORIGINAL C++
int res3 = chdir(ParentFolder);
if (res3 == -1){
// The system method failed
std::cout<< "the chdir method has failed \n";
}
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
{
printf("Could not find current directory " );
// return errno;
}
cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */
printf ("The current working directory is %s", cCurrentPath);
printf ("\n");
printf("Now running genb test " );
int systemRet = std::system("./genb_test");
if(systemRet == -1){
// The system method failed
}else{
printf("System command execuated successfully " );
}
// ADDED THIS PART at the suggestion of king_nak
//Capturing the output terminal
FILE * f = popen( "ls -al", "r" );
if ( f == 0 ) {
fprintf( stderr, "Could not execute\n" );
return;
}
const int BUFSIZE = 1000;
char buf[ BUFSIZE ];
while( fgets( buf, BUFSIZE, f ) ) {
fprintf( stdout, "%s", buf );
}
pclose( f );
return;
}
The output is:
>> [c d]=test_snnls_mex(a,b)
Trying to change the directory
The current working directory is /home/dkumar/libtsnnls-2.3.3/tsnnls
Now running genb test
c =
6 7 8
9 10 11
12 13 14
d =
1 4 9
16 25 36
49 64 81
Some help would be appreciated.
Regards,
Dushyant
std::system will start the system's command processor to execute the command. If you have a console app, this will print the output to the current console. This is why you see it in your test program. The output is not passed to the calling program!
In your case, Matlab seems to start the process in the background, where the output is discarded. Try instead opening the process and reading out its output into your program/MEX.
In POSIX, you can use popen (see for example this answer), in Windows you can use ReadPipe (cf. this article)
UPDATE
You have to adjust the code I have linked to. The original code calls ls -al and prints its output to the screen. You have to call your process genb_test!
Use this code to get the output in matlab, instead of your std::system call:
FILE * f = popen( "genb_test", "r" ); // <- call genb_test
if ( f == 0 ) {
fprintf( stderr, "Could not execute\n" );
return;
}
const int BUFSIZE = 1000;
char buf[ BUFSIZE ];
while( fgets( buf, BUFSIZE, f ) ) {
mexPrintf(buf); // <- use mexPrintf to print to matlab
}
pclose( f );
Have you tried the mex-command mexPrintf ?
However, the output won't be printed before the whole mex-program has been executed. Two work-arounds for this are to either use
mexEvalString("disp('Bla')")
or
mexPrintf("Bla")
mexEvalString("drawnow;");
I want to copy the framebuffer to an LCD display on my raspberry pi running raspbian. To do so I am using the following code:
#include <stdio.h>
#include <stdlib.h>
#include "RAIO8870.h"
#include <bcm_host.h>
int main(int argc, char **argv)
{
DISPMANX_DISPLAY_HANDLE_T main_display_handle;
DISPMANX_RESOURCE_HANDLE_T screen_resource_handle;
VC_RECT_T rectangle;
int ret;
uint32_t image_prt;
uint16_t image[ PICTURE_PIXELS ];
bcm_host_init();
if ( !bcm2835_init() )
return ( -1 );
TFT_init_board();
TFT_hard_reset();
RAIO_init();
RAIO_SetBacklightPWMValue( 255 );
uint32_t screen=0;
printf("Open display[%i]...\n", screen );
// open main framebuffer device
main_display_handle = vc_dispmanx_display_open( screen );
if ( !main_display_handle )
{
printf("\n Unable to open display %i Handle: %i",screen,main_display_handle);
return( -1 );
}
The program always exits in the if condition, as vc_dispmanx_display_open does return 0. I was not able to find any documentation about this function.
So why does it return an invalid handle and how to avoid this?
I would like to load image to my application, but I have an error:
http://img510.imageshack.us/img510/5814/blad07864.png
This is a code of this application:
#include <stdio.h>
#include <stdlib.h>
#undef _UNICODE
#include "il.h"
#pragma comment( lib, "DevIL.lib" )
// Wow. DevIL is amazing.
// From http://gpwiki.org/index.php/DevIL:Tutorials:Basics
// The library consists of three sub-libraries:
// * IL - main DevIL library. It allows you to load and save images to files. Every function in this library have 'il' prefixed to their name.
// * ILU - this library contains functions for altering images. Every function in this library have 'ilu' prefixed to their name.
// * ILUT - this library connects DevIL with OpenGL. Every function in this library have 'ilut' prefixed to their name.
int main()
{
ilInit();
printf("DevIL has been initialized\n");
// Loading an image
ILboolean result = ilLoadImage( "tex1.png" ) ;
if( result == true )
{
printf("the image loaded successfully\n");
}
else
{
printf("The image failed to load\n" ) ;
ILenum err = ilGetError() ;
printf( "the error %d\n", err );
printf( "string is %s\n", ilGetString( err ) );
}
int size = ilGetInteger( IL_IMAGE_SIZE_OF_DATA ) ;
printf("Data size: %d\n", size );
ILubyte * bytes = ilGetData() ;
for( int i = 0 ; i < size; i++ )
{
// see we should see the byte data of the image now.
printf( "%d\n", bytes[ i ] );
}
}
I found code from this site: http://bobobobo.wordpress.com/2009/03/02/how-to-load-a-png-image-in-c/
Can you help me?
According to this post, 1290 means the image path wasn't found. Try using an absolute file path and see if it can load then.