diff --git a/src/gui.c b/src/gui.c index 5a132b8..16620e8 100644 --- a/src/gui.c +++ b/src/gui.c @@ -4975,7 +4975,22 @@ void nwipe_gui_set_date_time( void ) yy++; mvwprintw( main_window, yy++, tab1, " %s", "Hours" ); mvwprintw( main_window, yy++, tab1, " %s", "Minutes" ); - // mvwprintw( main_window, yy++, tab1, " %s", "System Date/Time" ); + yy++; + mvwprintw( main_window, + yy++, + tab1, + " %s", + "If a Network Time Protocol (NTP) daemon is running date/time may not change" ); + mvwprintw( main_window, + yy++, + tab1, + " %s", + "or may revert back to NTP provided time. Setting time here is for use when" ); + mvwprintw( main_window, + yy++, + tab1, + " %s", + "the host system is not running NTP or not connected to the internet." ); /* Print the cursor. */ mvwaddch( main_window, 4 + focus, tab1, ACS_RARROW ); @@ -5070,7 +5085,7 @@ void nwipe_gui_set_date_time( void ) case 1: /* Set month */ - // NOTE ADD Function + nwipe_gui_set_system_month(); keystroke = 0; break; @@ -5234,24 +5249,173 @@ void nwipe_gui_set_system_year( void ) /* Write year back to system */ status = read_system_datetime( year, month, day, hours, minutes, seconds ); - if( status == 0 ) - { - nwipe_log( NWIPE_LOG_INFO, - "year=%s, month=%s, day=%s, hours=%s, minutes=%s, seconds=%s", - year, - month, - day, - hours, - minutes, - seconds ); - } - else + if( status != 0 ) { nwipe_log( NWIPE_LOG_ERROR, "func:read_system_datetime failed, see previous messages for detail" ); } + strncpy( year, date_buffer, 4 ); + + status = write_system_datetime( year, month, day, hours, minutes, seconds ); + if( status != 0 ) + { + nwipe_log( NWIPE_LOG_ERROR, "func:write_system_datetime failed, see previous messages for detail" ); + } + } /* End of nwipe_gui_set_system_year() */ +void nwipe_gui_set_system_month( void ) +{ + /** + * Allows the user to edit the host systems year + * + * @modifies system month + * @modifies main_window + * + */ + + /* The first tabstop. */ + const int tab1 = 2; + + /* The current working row. */ + int yy = 2; + + /* Input buffer. */ + int keystroke; + + /* Various output from the date command is processed in this buffer */ + char date_buffer[256]; + date_buffer[0] = 0; + + char year[5] = ""; + char month[3] = ""; + char day[3] = ""; + char hours[3] = ""; + char minutes[3] = ""; + char seconds[3] = ""; + + /* buffer index */ + int idx = 0; + + int status = 0; + + FILE* fp; + + extern int terminate_signal; + + /* Update the footer window. */ + werase( footer_window ); + nwipe_gui_title( footer_window, selection_footer_text_entry ); + wrefresh( footer_window ); + + fp = popen( "date +%m", "r" ); + if( fp == NULL ) + { + nwipe_log( NWIPE_LOG_INFO, "popen:Failed to retrieve date +%M %s", date_buffer ); + mvwprintw( main_window, yy + 4, tab1, "popen:date command failed retrieving month" ); + } + + if( fgets( date_buffer, sizeof( date_buffer ), fp ) == NULL ) + { + nwipe_log( NWIPE_LOG_INFO, "fgets:failed to retrieve month %s", date_buffer ); + mvwprintw( main_window, yy + 5, tab1, "fgets:failed retrieving month" ); + } + + /* terminate string after fourth character removing any lf */ + date_buffer[2] = 0; + + pclose( fp ); + + /* Set the buffer index to point to the end of the string, i.e the NULL */ + idx = strlen( date_buffer ); + + do + { + /* Erase the main window. */ + werase( main_window ); + + nwipe_gui_create_all_windows_on_terminal_resize( 0, selection_footer_text_entry ); + + /* Add a border. */ + box( main_window, 0, 0 ); + + /* Add a title. */ + nwipe_gui_title( main_window, " Set System Month " ); + + /* Initialize the working row. */ + yy = 4; + + mvwprintw( + main_window, yy++, tab1, "Enter the current month, two numeric digits, i.e 01, return key to submit" ); + + /* Print this line last so that the cursor is in the right place. */ + mvwprintw( main_window, 2, tab1, ">%s", date_buffer ); + + /* Reveal the cursor. */ + curs_set( 1 ); + + /* Refresh the window. */ + wrefresh( main_window ); + + /* Wait 250ms for input from getch, if nothing getch will then continue, + * This is necessary so that the while loop can be exited by the + * terminate_signal e.g.. the user pressing control-c to exit. + * Do not change this value, a higher value means the keys become + * sluggish, any slower and more time is spent unnecessarily looping + * which wastes CPU cycles. + */ + timeout( 250 ); // block getch() for 250ms. + keystroke = getch(); // Get a keystroke. + timeout( -1 ); // Switch back to blocking mode. + + switch( keystroke ) + { + /* Escape key. */ + case 27: + return; + + case KEY_BACKSPACE: + case KEY_LEFT: + case 127: + + if( idx > 0 ) + { + date_buffer[--idx] = 0; + } + + break; + + } /* switch keystroke */ + + if( ( keystroke >= ' ' && keystroke <= '~' ) && keystroke != '\"' && idx < FIELD_LENGTH && idx < 4 ) + { + date_buffer[idx++] = keystroke; + date_buffer[idx] = 0; + mvwprintw( main_window, 2, tab1, ">%s", date_buffer ); + } + + /* Hide the cursor. */ + curs_set( 0 ); + + } while( keystroke != 10 && terminate_signal != 1 ); + + /* Write year back to system */ + status = read_system_datetime( year, month, day, hours, minutes, seconds ); + if( status != 0 ) + { + nwipe_log( NWIPE_LOG_ERROR, "func:read_system_datetime failed, see previous messages for detail" ); + } + + strncpy( month, date_buffer, 2 ); + + status = write_system_datetime( year, month, day, hours, minutes, seconds ); + if( status != 0 ) + { + nwipe_log( NWIPE_LOG_ERROR, "func:write_system_datetime failed, see previous messages for detail" ); + } + +} /* End of nwipe_gui_set_system_month() */ + void nwipe_gui_load( void ) { /** diff --git a/src/gui.h b/src/gui.h index 84cd7c8..fb01fc1 100644 --- a/src/gui.h +++ b/src/gui.h @@ -69,6 +69,7 @@ void nwipe_gui_add_customer_contact_phone( char* ); // Add new customer contact int nwipe_gui_yes_no_footer( void ); // Change footer to yes no void nwipe_gui_preview_org_customer( void ); // Preview window for wipe organisation and customer void nwipe_gui_set_system_year( void ); // Set the systems current year +void nwipe_gui_set_system_month( void ); /** * Truncate a string based on start position and terminal width diff --git a/src/miscellaneous.c b/src/miscellaneous.c index 0b5c83d..488c8fd 100644 --- a/src/miscellaneous.c +++ b/src/miscellaneous.c @@ -522,3 +522,98 @@ int read_system_datetime( char* year, char* month, char* day, char* hours, char* return status; } + +int write_system_datetime( char* year, char* month, char* day, char* hours, char* minutes, char* seconds ) +{ + /* Writes the system date & time using data from the caller provided strings. + * The calling program must provide the minimum string sizes as shown below + * populated with current date and time data. + * + * year 5 bytes (4 numeric digits plus NULL terminator) + * month 3 bytes (2 numeric digits plus NULL terminator) + * day 3 bytes (2 numeric digits plus NULL terminator) + * hours 3 bytes (2 numeric digits plus NULL terminator) + * minutes 3 bytes (2 numeric digits plus NULL terminator) + * seconds 3 bytes (2 numeric digits plus NULL terminator) + * + * return value: + * 0 = success + * -1 = Failure, see nwipe log for detail. + */ + FILE* fp; + int r; // A result buffer. + int idx; // general index + int strIdx; // Index into each string + int bufferIdx; // Index into the buffer + char buffer[5]; + + /** + * Basic validation that confirms the input strings are numeric and of the correct length, we do this + * by first constructing three arrays. The first are the names of the variables in order + * year, month, day, hours, minutes and seconds. The second array contains the address of + * each of those strings. The third array are the lengths. + * This allows us to create a single loop to validate all fields. + */ + + char* names[] = { "year", "month", "day", "hours", "minutes", "seconds" }; + char* pdata[] = { year, month, day, hours, minutes, seconds }; + int lengths[] = { 4, 2, 2, 2, 2, 2 }; + char cmd_format[] = "date %s%s%s%s%s.%s >/dev/null 2>&1"; + char cmd[256]; + + for( idx = 0; idx < 6; idx++ ) + { + strIdx = 0; // initialise string index + + /* check each characters is numeric */ + while( strIdx < lengths[idx] ) + { + if( pdata[idx][strIdx] >= '0' && pdata[idx][strIdx] <= '9' ) + { + strIdx++; + } + else + { + /* if we haven't reached the correct number of digits due to invalid data, log error, + * but first we read the valid data acquired so far into a buffer, this is done to avoid + * writing to the user provided string because if they did not size the string correctly + * writing a zero at the end could cause a segfault. + */ + + for( bufferIdx = 0; bufferIdx < strIdx + 1; bufferIdx++ ) + { + buffer[bufferIdx] = pdata[idx][bufferIdx]; + } + buffer[bufferIdx] = 0; /* terminate the string, prior to using in nwipe_log */ + + /* A typical error will look like .. + * "User provided year data that appear invalid = 202£" */ + nwipe_log( NWIPE_LOG_ERROR, "User provided %s data that appears invalid = %s", names[idx], buffer ); + return -1; + } + } + } + + /** + * Now using the validated strings construct the date command that we will use to write the system date/time + */ + sprintf( cmd, cmd_format, month, day, hours, minutes, year, seconds ); + + /** + * Run the date command to write the new date/time + */ + + fp = popen( cmd, "w" ); + r = pclose( fp ); + + if( fp == NULL || r != 0 ) + { + nwipe_log( NWIPE_LOG_ERROR, "Failed to write system date/time using command = %s", cmd ); + } + else + { + nwipe_log( NWIPE_LOG_INFO, "Date/time succesfully writen to system using command = %s", cmd ); + } + + return 0; +} diff --git a/src/miscellaneous.h b/src/miscellaneous.h index bf14c08..4292fa5 100644 --- a/src/miscellaneous.h +++ b/src/miscellaneous.h @@ -105,4 +105,19 @@ void convert_double_to_string( char*, double ); */ int read_system_datetime( char*, char*, char*, char*, char*, char* ); +/** + * Writes system date & time from the caller provided strings. + * The calling program must provide the minimum populated string sizes + * as shown below. + * + * @param char* year 5 bytes (4 numeric digits plus NULL terminator) + * @param char* month 3 bytes (2 numeric digits plus NULL terminator) + * @param char* day 3 bytes (2 numeric digits plus NULL terminator) + * @param char* hours 3 bytes (2 numeric digits plus NULL terminator) + * @param char* minutes 3 bytes (2 numeric digits plus NULL terminator) + * @param char* seconds 3 bytes (2 numeric digits plus NULL terminator) + * @return 0 = success, -1 = failure. See nwipe log for detail. + */ +int write_system_datetime( char*, char*, char*, char*, char*, char* ); + #endif /* HPA_DCO_H_ */