aboutsummaryrefslogtreecommitdiff
path: root/src/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/output.c')
-rw-r--r--src/output.c173
1 files changed, 139 insertions, 34 deletions
diff --git a/src/output.c b/src/output.c
index 53a0ff3..254d73f 100644
--- a/src/output.c
+++ b/src/output.c
@@ -5,6 +5,7 @@
* vim:ts=4:sw=4:expandtab
*/
+#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
@@ -16,6 +17,20 @@
+/* === DEFINITIONS === */
+
+#define out_vsep fputc('|', stdout)
+
+#define out_print_newline() fputc('\n', stdout)
+#define out_print_fname(x) printf(" %s ", x->fname)
+
+void out_print_size(struct list_node *ptr);
+void out_print_time(time_t tv);
+void out_print_time_by_option(struct list_node *ptr);
+
+
+/* === IMPLEMENTATION === */
+
inline int fputc_all_cols(char c, FILE *fdout) {
struct winsize terminal;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &terminal);
@@ -45,13 +60,57 @@ inline int fputc_width_x(char c, size_t x, FILE *fdout) {
}
+
+/* === FORMATTING RELATED FUNCTIONS === */
+inline void out_print_size(struct list_node *ptr) {
+ printf(" %8ld %2s ", ((ptr->ln_stat.st_size>=1024) ? (ptr->ln_stat.st_size/1024) : ptr->ln_stat.st_size),
+ ((ptr->ln_stat.st_size >= 1024) ? "kB" : ""));
+}
+
+inline void out_print_time(time_t tv) {
+ struct tm *tm = NULL;
+ char timestamp[128];
+
+ tm = localtime(&tv);
+ if (option_timestamp_long) {
+ strftime(timestamp, sizeof(timestamp), "%Y%m%d %H:%M:%S %Z", tm);
+ printf(" %20s ", timestamp);
+ } else {
+ strftime(timestamp, sizeof(timestamp), "%H:%M:%S", tm);
+ printf(" %8s ", timestamp);
+ }
+}
+
+inline void out_print_time_by_option(struct list_node *ptr) {
+ time_t time_value = 0;
+
+ switch (option_time_field) {
+ case 'm':
+ time_value = ptr->ln_stat.st_mtim.tv_sec;
+ break;
+ case 'a':
+ time_value = ptr->ln_stat.st_atim.tv_sec;
+ break;
+ case 'c':
+ time_value = ptr->ln_stat.st_ctim.tv_sec;
+ break;
+ default:
+ LOGERR("WARNING: option_time_field has invalid value %c 0x%02X - going by default m\n",
+ option_time_field, option_time_field);
+ option_time_field = 'm';
+ time_value = ptr->ln_stat.st_mtim.tv_sec;
+ break;
+ };
+ out_print_time(time_value);
+}
+/* === END OF FORMATTING FUNCTIONS === */
+
+
+
/* The most simple default output, formatted output is planned */
void print_list(struct list_head *list) {
struct list_head *lh = list;
struct list_node *ptr;
- struct tm *tm = NULL;
- time_t time_value = 0;
- char timestamp[128];
size_t total_size = 0;
if (list == NULL) return;
@@ -65,38 +124,11 @@ void print_list(struct list_head *list) {
ptr = lh->first;
while (ptr != NULL) {
- time_value = 0;
-
- switch (option_time_field) {
- case 'm':
- time_value = ptr->ln_stat.st_mtim.tv_sec;
- break;
- case 'a':
- time_value = ptr->ln_stat.st_atim.tv_sec;
- break;
- case 'c':
- time_value = ptr->ln_stat.st_ctim.tv_sec;
- break;
- default:
- LOGERR("WARNING: option_time_field has invalid value %c 0x%02X - going by default m\n",
- option_time_field, option_time_field);
- option_time_field = 'm';
- time_value = ptr->ln_stat.st_mtim.tv_sec;
- break;
- };
-
- printf(" %8ld %2s ", ((ptr->ln_stat.st_size>=1024) ? (ptr->ln_stat.st_size/1024) : ptr->ln_stat.st_size),
- ((ptr->ln_stat.st_size >= 1024) ? "kB" : ""));
+ out_print_size(ptr);
+ out_print_time_by_option(ptr);
+ out_print_fname(ptr);
+ out_print_newline();
- tm = localtime(&time_value);
- if (option_timestamp_long) {
- strftime(timestamp, sizeof(timestamp), "%Y%m%d %H:%M:%S %Z", tm);
- printf(" %20s ", timestamp);
- } else {
- strftime(timestamp, sizeof(timestamp), "%H:%M:%S", tm);
- printf(" %8s ", timestamp);
- }
- printf(" %s\n", ptr->fname);
/* Linux: Neither man stat(2) nor stat(3type) declare why struct stat field st_size
* would get a negative value assigned. The type off_t masks __off_t or __off64_t
* which themselves mask bits/types.h __SLONGWORD_TYPE on x86_64 that's long int.
@@ -113,3 +145,76 @@ void print_list(struct list_head *list) {
if (lh != list) destroy_list(lh);
}
+
+/* For now with a large walk around common format strings and prevention of attack vectors.
+ * n - name
+ * s - file size
+ *
+ * Time related
+ * t - timestamp set by option_time_field
+ * A - timestamp from atim.tv_sec
+ * C - timestamp from ctim.tv_sec
+ * M - timestamp from mtim.tv_sec
+ */
+void print_list_formatted(const char *format, struct list_head *list) {
+ struct list_head *lh = list;
+ struct list_node *ptr;
+ size_t format_len = 0, i = 0;
+
+ if (format == NULL || format[0] == '\0') {
+ LOGERR("ERROR: No format string given");
+ return;
+ }
+
+ if (list == NULL || list->first == NULL) {
+ LOGERR("ERROR: No data to print.\n");
+ return;
+ }
+
+ if (option_sort_reverse_order) {
+ lh = create_list_sort_reversed(list);
+ /* be tolerant */
+ if (lh == NULL) {
+ lh = list;
+ }
+ }
+
+ /* Note: the maximum length needs to be adjusted if the strings
+ * shall contain more complicated settings */
+ format_len = strnlen(format, 80);
+
+ ptr = lh->first;
+ while (ptr != NULL) {
+ for (i=0; i < format_len; i++) {
+ switch (format[i]) {
+ case 'n':
+ out_print_fname(ptr);
+ break;
+ case 's':
+ out_print_size(ptr);
+ break;
+ case 't':
+ out_print_time_by_option(ptr);
+ break;
+ case 'A':
+ out_print_time(ptr->ln_stat.st_atim.tv_sec);
+ break;
+ case 'C':
+ out_print_time(ptr->ln_stat.st_ctim.tv_sec);
+ break;
+ case 'M':
+ out_print_time(ptr->ln_stat.st_mtim.tv_sec);
+ break;
+ case ' ': /* just ignore this without warning */
+ break;
+ default:
+ LOGERR("WARNING: Invalid character 0x%02X ignoring it\n", format[i]);
+ break;
+ };
+ }
+ out_print_newline();
+ ptr = ptr->next;
+ }
+ if (lh != list) destroy_list(lh);
+}
+