1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
// See https://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler
/* async-signal-safe implementation of integer to string conversion.
*
* Null terminates the output string.
*
* The input buffer size must be large enough to contain the output,
* the caller must calculate it properly.
*
* @param[out] value Input integer value to convert.
* @param[out] result Buffer to output to.
* @param[in] base Base to convert to.
* @return Pointer to the end of the written string.
*/
char *itoa_safe(intmax_t value, char *result, int base) {
intmax_t tmp_value;
char *ptr, *ptr2, tmp_char;
if (base < 2 || base > 36) {
return NULL;
}
ptr = result;
do {
tmp_value = value;
value /= base;
*ptr++ = "ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210"
"123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[35 + (tmp_value - value * base)];
} while (value);
if (tmp_value < 0)
*ptr++ = '-';
ptr2 = result;
result = ptr;
*ptr-- = '\0';
while (ptr2 < ptr) {
tmp_char = *ptr;
*ptr--= *ptr2;
*ptr2++ = tmp_char;
}
return result;
}
long int prime;
unsigned int interval;
// See http://man7.org/linux/man-pages/man7/signal-safety.7.html
// There is a restrictive list of functions that can be called
// in signal handers, and printf() isn't one of them.
// http://man7.org/linux/man-pages/man2/sigaction.2.html is preferred over signal()
void writeString(int fd, const char *buff) {
write(fd,buff,strlen(buff));
}
void ALARMhandler(int sig) {
if (sig == SIGALRM) {
char buff[200];
writeString(1,"The most recent prime ");
itoa_safe(prime,buff,10);
writeString(1,buff);
writeString(1,"\n");
signal(SIGALRM, ALARMhandler);
alarm(interval);
}
}
int isPrime(int n) {
int limit = (int)ceil(sqrt(n));
int result = 1;
if ( n == 2 ) return result;
if ( n % 2 == 0 ) return !result;
for ( int i = 3 ; i <= limit ; i += 2 ) {
if ( n % i == 0 ) {
result = 0;
break;
}
}
return result;
}
long int computeNthPrime(int n) {
long int p = 3;
for ( int i = 1 ; i <= n ; i++, p += 2 ) {
while ( !isPrime(p) ) p += 2;
}
return p;
}
int main(int argc, const char *argv[])
{
if (argc < 2) {
printf("Usage: %s filename integer\n", argv[0]);
exit(1);
}
FILE *file = fopen(argv[1], "w");
if (file == 0) {
printf("Failed to open\n");
exit(1);
}
interval = atoi(argv[2]);
signal(SIGALRM, ALARMhandler);
alarm(interval);
for ( int i = 1 ; i < 10000 ; i++ ) {
prime = computeNthPrime(i);
fprintf(file, " %ld\n", prime);
fflush(file);
}
fclose(file);
return 0;
}
| |