diff --git a/src/utils.c b/src/utils.c index 222a6e1..d63901f 100644 --- a/src/utils.c +++ b/src/utils.c @@ -10,7 +10,7 @@ $Id$ This file, utils.c, contains the implementation of various utility - function for Star Traders. + functions used in Star Traders. This program is free software: you can redistribute it and/or modify it @@ -28,9 +28,15 @@ */ -#include "system.h" -#include "utils.h" -#include "intf.h" +#include "trader.h" + + +/************************************************************************ +* Module-specific constants * +************************************************************************/ + +#define GAME_FILENAME_PROTO "game%d" +#define GAME_FILENAME_BUFSIZE 16 /************************************************************************ @@ -43,28 +49,21 @@ static char *data_directory_str = NULL; // Writable data dir pathname /************************************************************************ -* Utility function definitions * +* Initialisation and environment function definitions * ************************************************************************/ -/*----------------------------------------------------------------------- - Function: init_program_name - Make the program name "canonical" - Arguments: argv - Same as passed to main() - Returns: (nothing) +// These functions are documented in the file "utils.h" - This function modifies the argv[0] pointer to eliminate the leading - path name from the program name. In other words, it strips any leading - directories and leaves just the base name of the program. It also - assigns the module variable "program_name_str". -*/ +/***********************************************************************/ void init_program_name (char *argv[]) { - if ((argv == NULL) || (argv[0] == NULL) || (*(argv[0]) == '\0')) { + if (argv == NULL || argv[0] == NULL || *argv[0] == '\0') { program_name_str = PACKAGE; } else { char *p = strrchr(argv[0], '/'); - if ((p != NULL) && (*++p != '\0')) { + if (p != NULL && *++p != '\0') { argv[0] = p; } @@ -73,16 +72,7 @@ void init_program_name (char *argv[]) } -/*----------------------------------------------------------------------- - Function: program_name - Return the canonical program name - Arguments: (none) - Returns: const char * - Pointer to program name - - This function returns the canonical program name (the program name as - invoked on the command line, without any leading pathname). NULL - should never be returned. -*/ - +/***********************************************************************/ const char *program_name (void) { if (program_name_str == NULL) { @@ -93,24 +83,15 @@ const char *program_name (void) } -/*----------------------------------------------------------------------- - Function: home_directory - Return home directory pathname - Arguments: (none) - Returns: const char * - Pointer to home directory - - This function returns the full pathname to the user's home directory, - using the HOME environment variable. Note that the existance or - writability of this pathname is NOT checked by this function. NULL is - returned if the home directory cannot be determined. -*/ - +/***********************************************************************/ const char *home_directory (void) { if (home_directory_str == NULL) { // Use the HOME environment variable where possible - char *p = getenv("HOME"); - if ((p != NULL) && (*p != '\0')) { - home_directory_str = strdup(p); + char *home = getenv("HOME"); + + if (home != NULL && *home != '\0') { + home_directory_str = strdup(home); } } @@ -118,24 +99,18 @@ const char *home_directory (void) } -/*----------------------------------------------------------------------- - Function: data_directory - Return writable data directory pathname - Arguments: (none) - Returns: const char * - Pointer to data directory - - This function returns the full pathname to a writable subdirectory - within the user's home directory. Essentially, home_directory() + "/." - + program_name() is returned. Note that this path is NOT created by - this function, nor is the writability of this path checked. NULL is - returned if this path cannot be determined. -*/ - +/***********************************************************************/ const char *data_directory (void) { + /* This implementation assumes a POSIX environment by using "/" as + the directory separator. It also assumes a dot-starting directory + name is permissible (again, true on POSIX systems) */ + if (data_directory_str == NULL) { const char *name = program_name(); const char *home = home_directory(); - if ((name != NULL) && (home != NULL)) { + + if (name != NULL && home != NULL) { char *p = malloc(strlen(home) + strlen(name) + 3); if (p != NULL) { strcpy(p, home); @@ -150,38 +125,33 @@ const char *data_directory (void) } -/*----------------------------------------------------------------------- - Function: game_filename - Convert an integer to a game filename - Arguments: game_num - Game number (1-9) as an integer - Returns: char * - Pointer to game filename string - - This function returns the full game filename as a malloc()ed string. - If game_num is between 1 and 9 inclusive, the string returned is in the - form data_directory() + "/" + GAME_FILENAME(game_num). If game_num is - any other integer, NULL is returned. -*/ - -char *game_filename (const int game_num) +/***********************************************************************/ +char *game_filename (int gamenum) { - char buf[GAME_FILENAME_BUFSIZE]; // Buffer for part of filename - const char *dd; // Data directory + /* This implementation assumes a POSIX environment by using "/" as + the directory separator */ + + char buf[GAME_FILENAME_BUFSIZE]; // Buffer for part of filename + const char *dd; // Data directory - if ((game_num < 1) || (game_num > 9)) { + if (gamenum < 1 || gamenum > 9) { return NULL; } dd = data_directory(); - snprintf(buf, GAME_FILENAME_BUFSIZE, GAME_FILENAME_PROTO, game_num); + snprintf(buf, GAME_FILENAME_BUFSIZE, GAME_FILENAME_PROTO, gamenum); if (dd == NULL) { char *p = malloc(strlen(buf) + 1); + if (p != NULL) { strcpy(p, buf); } return p; } else { char *p = malloc(strlen(dd) + strlen(buf) + 2); + if (p != NULL) { strcpy(p, dd); strcat(p, "/"); @@ -192,22 +162,14 @@ char *game_filename (const int game_num) } -/*----------------------------------------------------------------------- - Function: err_exit - Print an error and exit - Arguments: format - printf()-like format of error message - ... - printf()-like arguments - Returns: (does not return) +/************************************************************************ +* Error-reporting function definitions * +************************************************************************/ - This function closes all curses windows, prints the name of the program - and the error message to stderr (using format and following arguments - as if passed to printf()) and exits with error code EXIT_FAILURE. The - format supplied does NOT need to supply the program name nor the - trailing end-line character. The format should not be NULL; user- - supplied strings should ALWAYS be printed using "%s" as the format (and - with the user string as a second argument), NOT passed in as the format - itself. -*/ +// These functions are documented in the file "utils.h" + +/***********************************************************************/ void err_exit (const char *format, ...) { va_list args; @@ -225,21 +187,7 @@ void err_exit (const char *format, ...) } -/*----------------------------------------------------------------------- - Function: errno_exit - Print an error (using errno) and exit - Arguments: format - printf()-like format of error message - ... - printf()-like arguments - Returns: (does not return) - - This function closes all curses windows, prints the name of the - program, the error message (using format and following arguments as if - passed to printf()) and the string corresponding to errno to stderr, - then exits with error code EXIT_FAILURE. The format supplied does NOT - need to supply the program name, any colons nor the trailing end-line - character. The format may be NULL if no intermediate message is - needed. -*/ - +/***********************************************************************/ void errno_exit (const char *format, ...) { va_list args; @@ -261,93 +209,68 @@ void errno_exit (const char *format, ...) } -/*----------------------------------------------------------------------- - Function: err_exit_nomem - Print an "out of memory" error and exit - Arguments: (none) - Returns: (does not return) - - This function calls err_exit with an "out of memory" error message. -*/ - +/***********************************************************************/ void err_exit_nomem (void) { err_exit("out of memory"); } -/*----------------------------------------------------------------------- - Function: init_rand - Initialise the random number generator - Arguments: (none) - Returns: (nothing) +/************************************************************************ +* Random-number function definitions * +************************************************************************/ - This function initialises the pseudo-random number generator. -*/ +// These functions are documented in the file "utils.h" + +/***********************************************************************/ void init_rand (void) { + /* Ideally, initialisation of the random number generator should be + made using seed48() and lcong48(). However, we can only be + assured of no more than 32 bits of "randomness" by using time(), + available on all POSIX systems. If time_t is larger than long + int, we throw away the top bits. */ + time_t curtime = time(NULL); // NB: time_t may be larger than long int srand48((long int) curtime); } -/*----------------------------------------------------------------------- - Function: randf - Return a random number between 0.0 and 1.0 - Arguments: (none) - Returns: double - The random number - - This function returns a pseudo-random number between 0.0 (inclusive) - and 1.0 (not inclusive) as a floating-point number. -*/ - +/***********************************************************************/ extern double randf (void) { return drand48(); } -/*----------------------------------------------------------------------- - Function: randi - Return a random number between 0 and limit - Arguments: limit - Upper limit of random number - Returns: int - The random number - - This function returns a pseudo-random number between 0 (inclusive) and - limit (not inclusive) as an integer. -*/ - +/***********************************************************************/ extern int randi (int limit) { - return randf() * (double) limit; + return drand48() * (double) limit; } -/*----------------------------------------------------------------------- - Function: scramble - Scramble (encrypt) the buffer - Arguments: key - Encryption/decryption key - buf - Pointer to buffer to encrypt - bufsize - Size of buffer - Returns: char * - Pointer to buffer - - This function scrambles (encrypts) the buffer pointed to by buf using a - trivial in-place encryption algorithm. If key is zero, no encryption - takes place. The buffer buf must contain a string terminated by '\0'. - The characters '\r', '\n' and '\0' are guaranteed to remain the same - after encryption. At most bufsize characters are encrypted; buf is - returned as the result. -*/ - +/***********************************************************************/ char *scramble (int key, char *buf, int bufsize) { - if ((buf != NULL) && (key != 0)) { + /* The algorithm used here is reversable: scramble(scramble(...)) + will (or, at least, should!) return the same as the original + buffer. Problematic characters are ignored; however, this + function assumes all other characters are permitted in files. + This is true on all POSIX systems. */ + + if (buf != NULL && key != 0) { char *p = buf; unsigned char k = ~key; int i; - for (i = 0; (i < bufsize) && (*p != '\0'); i++, k++, p++) { + for (i = 0; i < bufsize && *p != '\0'; i++, k++, p++) { char c = *p; char r = c ^ k; // Simple encryption: XOR on a moving key - if ((c != '\r') && (c != '\n') && - (r != '\r') && (r != '\n') && (r != '\0')) { + if (c != '\r' && c != '\n' + && r != '\r' && r != '\n' && r != '\0') { *p = r; } } @@ -357,22 +280,12 @@ char *scramble (int key, char *buf, int bufsize) } -/*----------------------------------------------------------------------- - Function: unscramble - Unscramble (decrypt) the buffer - Arguments: key - Encryption/decryption key - buf - Pointer to buffer to decrypt - bufsize - Size of buffer - Returns: char * - Pointer to buffer - - This function unscrambles (decrypts) the buffer pointed to by buf using - a trivial in-place decryption algorithm. If key is zero, no decryption - takes place. The buffer buf must contain a string terminated by '\0'. - The characters '\r', '\n' and '\0' are guaranteed to remain the same - after decryption. At most bufsize characters are decrypted; buf is - returned as the result. -*/ - +/***********************************************************************/ char *unscramble (int key, char *buf, int bufsize) { return scramble(key, buf, bufsize); } + + +/***********************************************************************/ +// End of file diff --git a/src/utils.h b/src/utils.h index cd5e19f..91f9f03 100644 --- a/src/utils.h +++ b/src/utils.h @@ -9,8 +9,8 @@ Author: John Zaitseff $Id$ - This file, utils.h, contains various utility function declarations for - Star Traders. + This file, utils.h, contains declarations for various utility functions + used in Star Traders. This program is free software: you can redistribute it and/or modify it @@ -32,14 +32,6 @@ #define included_UTILS_H 1 -/************************************************************************ -* Constants and type declarations * -************************************************************************/ - -#define GAME_FILENAME_PROTO "game%d" -#define GAME_FILENAME_BUFSIZE 16 - - /************************************************************************ * Utility macro definitions * ************************************************************************/ @@ -51,37 +43,216 @@ /************************************************************************ -* Utility function prototypes * +* Initialisation and environment function prototypes * ************************************************************************/ -// Initialisation and environment functions +/* + Function: init_program_name - Make the program name "canonical" + Parameters: argv - Same as passed to main() + Returns: (nothing) + This function modifies the argv[0] pointer to eliminate any leading + pathname (directory) components from the program name, leaving just the + basename of the program. It also saves a copy that can be accessed via + the program_name() function. +*/ extern void init_program_name (char *argv[]); + + +/* + Function: program_name - Return the canonical program name + Parameters: (none) + Returns: const char * - Pointer to program name + + This function returns the canonical program name (the program name as + invoked on the command line, without any leading pathname components). + NULL should never be returned; however, init_program_name() SHOULD be + called before using this function. +*/ extern const char *program_name (void); + +/* + Function: home_directory - Return home directory pathname + Parameters: (none) + Returns: const char * - Pointer to home directory + + This function returns the full pathname to the user's home directory, + using the HOME environment variable. Note that the existance or + writability of this pathname is NOT checked by this function. NULL is + returned if the home directory cannot be determined. +*/ extern const char *home_directory (void); + + +/* + Function: data_directory - Return writable data directory pathname + Parameters: (none) + Returns: const char * - Pointer to data directory + + This function returns the full pathname to a potentially-writable + subdirectory within the user's home directory. Essentially, this + function returns home_directory() + "/." + program_name(). Note that + this path is NOT created by this function, nor is the writability of + this path checked. NULL is returned if this path cannot be determined. +*/ extern const char *data_directory (void); -extern char *game_filename (const int game_num); -// Error-reporting functions +/* + Function: game_filename - Convert an integer to a game filename + Parameters: gamenum - Game number (1-9) as an integer + Returns: char * - Pointer to game filename string -extern void err_exit (const char *format, ...) + This function returns the full game filename as a malloc()ed string + (ie, a string that must be freed at a later time by calling free()). + + If gamenum is between 1 and 9 inclusive, the string returned is in the + form data_directory() + "/" + GAME_FILENAME(gamenum). If gamenum is + any other integer, NULL is returned. +*/ +extern char *game_filename (int gamenum); + + +/************************************************************************ +* Error-reporting function prototypes * +************************************************************************/ + +/* + Function: err_exit - Print an error and exit + Parameters: format - printf()-like format of error message + ... - printf()-like arguments + Returns: (does not return) + + This function closes all Curses windows, prints the name of the program + and the error message to stderr (using format and following arguments + as if passed to printf()) and exits with error code EXIT_FAILURE. + + The format supplied does NOT need to supply the program name nor the + trailing end-line character. The format should not be NULL; user- + supplied strings should ALWAYS be printed using "%s" as the format (and + with the user string as a second argument), NOT passed in as the format + itself. +*/ +extern void err_exit (const char *format, ...) __attribute__((noreturn, format (printf, 1, 2))); + + +/* + Function: errno_exit - Print an error message (using errno) and exit + Parameters: format - printf()-like format of error message + ... - printf()-like arguments + Returns: (does not return) + + This function closes all Curses windows, prints the name of the + program, the supplied error message (using format and following + arguments as if passed to printf()), then the string corresponding to + errno to stderr. It then exits with error code EXIT_FAILURE. + + The format supplied does NOT need to supply the program name, any + colons nor the trailing end-line character. The format may be NULL if + no intermediate message is needed. +*/ extern void errno_exit (const char *format, ...) __attribute__((noreturn, format (printf, 1, 2))); + + +/* + Function: err_exit_nomem - Print an "out of memory" error and exit + Parameters: (none) + Returns: (does not return) + + This function calls err_exit() with an "out of memory" error message. + It simply ensures all memory exhaustion error messages are consistent. +*/ extern void err_exit_nomem (void) __attribute__((noreturn)); -// Random number functions +/************************************************************************ +* Random-number function prototypes * +************************************************************************/ + +/* + Function: init_rand - Initialise the random number generator + Parameters: (none) + Returns: (nothing) + + This function initialises the pseudo-random number generator. It + should be called before any random-number functions declared in this + header are called. +*/ extern void init_rand (void); + + +/* + Function: randf - Return a random number between 0.0 and 1.0 + Parameters: (none) + Returns: double - The random number + + This function returns a pseudo-random number between 0.0 (inclusive) + and 1.0 (not inclusive) as a floating-point number. By default, a + linear congruential algorithm is used to generate the random number. +*/ extern double randf (void); + + +/* + Function: randi - Return a random number between 0 and limit + Parameters: limit - Upper limit of random number + Returns: int - The random number + + This function returns a pseudo-random number between 0 (inclusive) and + limit (not inclusive) as an integer. It uses the same algorithm as + randf() to generate the random number. +*/ extern int randi (int limit); -// Encryption and decryption functions to stop casual cheating! +/************************************************************************ +* Encryption function prototypes * +************************************************************************/ + +/* + The functions described here are simple in the extreme: they are only + designed to stop casual cheating! +*/ + +/* + Function: scramble - Scramble (encrypt) the buffer + Parameters: key - Encryption key + buf - Pointer to buffer to encrypt + bufsize - Size of buffer + Returns: char * - Pointer to buffer + + This function scrambles (encrypts) the buffer *buf using a trivial + in-place encryption algorithm. If key is zero, or buf is NULL or + bufsize is less than 1, no encryption takes place. + + The buffer should contain a C-style string terminated by '\0'. The + characters '\r', '\n' and '\0' are guaranteed to remain the same before + and after encryption. At most bufsize bytes are encrypted; buf is + returned as the result. +*/ extern char *scramble (int key, char *buf, int bufsize); + + +/* + Function: unscramble - Unscramble (decrypt) the buffer + Parameters: key - Encryption/decryption key + buf - Pointer to buffer to decrypt + bufsize - Size of buffer + Returns: char * - Pointer to buffer + + This function does the reverse of scramble(): it unscrambles (decrypts) + the buffer *buf using an in-place algorithm. If key is zero, or buf is + NULL or bufsize is less than 1, no decryption takes place. + + The buffer should contain a C-style string terminated by '\0'. As for + scramble(), the characters '\r', '\n' and '\0' will not be changed (nor + will any encrypted character map back to these values). At most + bufsize bytes are decrypted; buf is returned as the result. +*/ extern char *unscramble (int key, char *buf, int bufsize);