summaryrefslogtreecommitdiffstats
path: root/src/b_h.c
blob: f6e1d59c90b300b637591f1706679d7226a5f927 (plain)
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   b_h.c                                              :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: rbousset <marvin@42.fr>                    +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2020/02/14 17:19:27 by rbousset          #+#    #+#             */
/*   Updated: 2020/02/14 17:19:29 by rbousset         ###   ########lyon.fr   */
/*                                                                            */
/* ************************************************************************** */

#include <libft.h>
#include <stddef.h>
#include <unistd.h>

#include "d_define.h"
#include "f_fail.h"
#include "s_struct.h"
#include "u_utils.h"

static unsigned long	b_get_total_hist(t_msh *msh)
{
	unsigned long	total;
	char			*ptr;

	total = 0;
	if (msh->prev_hist != NULL)
	{
		ptr = msh->prev_hist;
		while (*ptr != C_NUL)
		{
			if (*ptr == C_LF)
				total += 1;
			ptr++;
		}
	}
	ptr = msh->curr_hist_ptr;
	while (*ptr != C_NUL)
	{
		if (*ptr == C_LF)
			total += 1;
		ptr++;
	}
	return (total);
}

static unsigned int		b_print_prev_history(unsigned long asked,
										unsigned long total,
										t_msh *msh)
{
	char	*hist;
	char	*tok;
	long	to_print;
	long	i;

	to_print = total - asked;
	to_print = (to_print < 0) ? (0) : (to_print);
	i = 1;
	if (msh->prev_hist != NULL)
	{
		if ((hist = ft_strdup(msh->prev_hist)) == NULL)
			return (i);
		tok = ft_strtok(hist, "\n");
		while (tok != NULL)
		{
			if (i > to_print)
				ft_printf("%5lu  %s\n", i, tok);
			i++;
			tok = ft_strtok(NULL, "\n");
		}
		ft_memdel((void*)&hist);
	}
	return (i);
}

static void				b_print_history(unsigned long asked,
										unsigned long total,
										t_msh *msh)
{
	char	*hist;
	char	*tok;
	long	to_print;
	long	i;

	to_print = total - asked;
	to_print = (to_print < 0) ? (0) : (to_print);
	i = b_print_prev_history(asked, total, msh);
	if ((hist = ft_strdup(msh->curr_hist_ptr)) == NULL)
		return ;
	tok = ft_strtok(hist, "\n");
	while (tok != NULL)
	{
		if (i > to_print)
			ft_printf("%5lu  %s\n", i, tok);
		i++;
		tok = ft_strtok(NULL, "\n");
	}
	ft_memdel((void*)&hist);
}

static t_bool			b_check_numeric(const char arg[])
{
	char	*ptr;

	ptr = (char*)arg;
	while (*ptr != C_NUL)
	{
		if (ft_isdigit(*ptr) == FALSE)
		{
			return (FALSE);
		}
		ptr++;
	}
	return (TRUE);
}

unsigned char			b_h(char *args[], t_msh *msh)
{
	const unsigned long	argc = u_builtins_get_argc((const char **)args);

	if (argc > 1)
	{
		f_fail_too_many_args("h", msh);
		return (127);
	}
	if (argc == 1 && b_check_numeric(*args) == FALSE)
	{
		ft_dprintf(STDERR_FILENO,
			"minishell: history: %s: numeric argument required\n",
			*args);
		return (1);
	}
	else
	{
		if (argc == 1)
			b_print_history(ft_atoi(*args), b_get_total_hist(msh), msh);
		else
			b_print_history(0, 0, msh);
	}
	return (0);
}