Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * \file
- * \author Vladar <[email protected]>
- * \version 1.1
- * \brief *nix ls command implementation.
- *
- * \copyright \parblock
- * Copyright (c) 2014 Vladar <[email protected]>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- * \endparblock
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <dirent.h> /* For dir listing */
- #include <sys/ioctl.h> /* For terminal width */
- #include <unistd.h> /* For STDOUT_FILENO, getcwd */
- typedef struct SList List;
- struct SList
- {
- List *next;
- size_t len; /**< Name length */
- char name[NAME_MAX];
- };
- /**
- * \brief Add new list node.
- * \param prev Previous node.
- * \returns new list node on success.
- * \returns NULL on failure.
- */
- static List*
- list_add (List *prev)
- {
- static const size_t size = sizeof (List);
- List *result = (List*) malloc (size);
- if (result)
- {
- memset (result, '\0', size);
- if (prev)
- prev->next = result;
- }
- return result;
- }
- /**
- * \brief Free list structure.
- * \param head First node.
- */
- static void
- list_free (List *head)
- {
- List *target, *iterator = head;
- while (iterator)
- {
- target = iterator;
- iterator = iterator->next;
- free (target);
- target = NULL;
- }
- }
- /**
- * \brief Wrap long output lines.
- * \param width Output column width.
- * \param str String.
- * \param cols Columns count.
- * \returns Remained string.
- */
- void
- wrap (int width, const char *str, int cols)
- {
- if (str)
- {
- if (cols > 1)
- {
- printf ("%-*s", width, str);
- } /* if (cols > 1) */
- else
- { /* cols = 1 */
- if (strlen (str) >= width)
- {
- char str_a[width];
- strncpy (str_a, str, width-1);
- str_a[width-1] = '\0';
- printf ("%s\n", str_a);
- wrap (width, str+width-1, cols);
- }
- else
- {
- printf ("%s", str);
- }
- } /* else : if (cols > 1) */
- } /* if (str) */
- }
- /**
- * \brief Output directory listing.
- * \param dirpath Directory path.
- */
- void
- listdir (char *dirpath)
- {
- DIR *dp;
- struct dirent *entry;
- List *list_head = NULL, *list_tail = NULL;
- int count = 1, maxlen;
- /* Try to open dirpath */
- if (! (dp = opendir (dirpath)))
- {
- perror("Error");
- return;
- }
- /* Init head */
- entry = readdir (dp);
- list_head = list_add (NULL);
- strcpy (list_head->name, entry->d_name);
- maxlen = list_head->len = strlen (list_head->name);
- list_tail = list_head;
- /* Fill dir listing */
- while ( (entry = readdir (dp)))
- {
- count++;
- list_tail = list_add (list_tail);
- strcpy (list_tail->name, entry->d_name);
- list_tail->len = strlen (list_tail->name);
- if (list_tail->len > maxlen)
- maxlen = list_tail->len;
- }
- /* Fill quick access array */
- List *listdir[count], *iterator;
- int i;
- for (i = 0, iterator = list_head;
- iterator;
- i++, iterator = iterator->next)
- {
- listdir[i] = iterator;
- }
- /* Get terminal params */
- struct winsize ws;
- ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws);
- /* Calculating columns */
- const maxcolw = ws.ws_col / 2; /* Minimal width of column is 2 */
- int colw[maxcolw], next_colw[maxcolw];
- int maxtotalw, totalw;
- int col_count, row_count;
- int next_col_count = 1, next_row_count = count;
- for (i = 0; (i < maxcolw) && (i < count); i++)
- next_colw[i] = maxlen + 1;
- do
- {
- /* assign prev iteration to final vars */
- col_count = next_col_count;
- row_count = next_row_count;
- int i;
- for (i = 0; i < col_count; i++)
- {
- colw[i] = next_colw[i];
- }
- /* trying next iteration */
- next_col_count++;
- next_row_count = count / next_col_count;
- int row, col, idx;
- maxtotalw = 0;
- /*for (col = 0; col < next_col_count; col++)
- next_colw[col] = 2;*/
- for (row = 0; row < next_row_count; row++)
- {
- totalw = 0;
- for (col = 0; col < next_col_count; col++)
- {
- if (count <= (idx = row + col * next_row_count))
- continue;
- if (next_colw[col] < (listdir[idx]->len + 1))
- next_colw[col] = listdir[idx]->len + 1;
- totalw += next_colw[col];
- } /* for col */
- if (maxtotalw < totalw)
- maxtotalw = totalw;
- } /* for row */
- } while ((maxtotalw < ws.ws_col) && (col_count < count));
- /* Output */
- int row, col, idx;
- for (row = 0; row < row_count; row++)
- {
- for (col = 0; col < col_count; col++)
- {
- if (count <= (idx = row + col * row_count))
- continue; /* check for overflow */
- wrap(colw[col], listdir[idx]->name, col_count);
- } /* for col */
- printf("\n");
- } /* for row */
- /* Clean up */
- list_free (list_head);
- closedir (dp);
- }
- int
- main (int argc, char *argv[])
- {
- if (argc < 2) /* No directories specified */
- {
- char *cwd = NULL; /* Current Working Directory */
- cwd = getcwd(NULL, 0);
- printf ("%s\n", cwd);
- listdir (cwd);
- free (cwd);
- printf ("\n");
- } /* if */
- else
- {
- int i;
- for (i = 1; i < argc; i++)
- {
- printf ("%s\n", argv[i]);
- listdir (argv[i]);
- printf ("\n");
- } /* for */
- } /* else */
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment