Merge pull request #35 from DevManu-de/dev-redirect-handle
[psh.git] / lib / util.c
blob2d305a83bfa31bbf46bf404462b168dd30088920
1 /*
2 libpsh/util.c - libpsh utilities for everyone
3 Copyright 2018-2020 Zhang Maiyun
5 This file is part of Psh, P shell.
7 Psh is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Psh is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
25 #include <stdio.h>
26 #include <string.h>
27 #ifdef HAVE_READLINE_READLINE_H
28 #include <readline/readline.h>
29 #elif defined(HAVE_READLINE)
30 /* Have libreadline but no header */
31 char *readline(char *);
32 #endif
34 #include "libpsh/util.h"
35 #include "libpsh/xmalloc.h"
37 /* Get a line from file FP with prompt PROMPT.
38 * The memory is allocated automatically.
39 * Returns the content when an EOF or \n is read,
40 * not including the trailing EOF or \n. */
41 char *psh_fgets(const char *prompt, FILE *fp)
43 #ifdef HAVE_READLINE
44 if (fp == stdin)
45 return readline(prompt);
46 #endif
47 if (fp == NULL)
48 return NULL;
49 if (fp == stdin)
51 printf("%s", prompt);
52 fflush(stdout);
55 size_t charcount = 0, nowhave = 256;
56 int ch;
57 char *result = xmalloc(P_CS * nowhave);
58 char *ptr = result;
59 if (result == NULL)
60 return NULL;
61 while (1)
63 ch = fgetc(fp);
64 if (ch == EOF)
66 if (ptr == result) /* nothing read */
68 xfree(result);
69 return NULL;
71 break;
73 if (ch == '\n')
74 break;
75 *ptr++ = ch;
76 if ((++charcount) == nowhave)
77 result = xrealloc(result, P_CS * (nowhave <<= 1));
79 *ptr = 0; /* Replace EOF or \n with NUL */
80 result = xrealloc(result, P_CS * (strlen(result) +
81 1)); /* Resize the array to minimum */
82 return result;
86 char *psh_gets(const char *prompt) { return psh_fgets(prompt, stdin); }
88 /* Copy string of length SIZE from SRC to DST */
89 size_t psh_strncpy(char *dst, const char *src, size_t size)
91 strncpy(dst, src, size);
92 dst[size] = '\0';
93 return size;
96 /* Compare the string str1 to a string as were produced by strcat(str2_1,
97 * str2_2). */
98 int strdblcmp(const char *str1, const char *str2_1, const char *str2_2)
100 int diff;
101 /* End loop if str2_1 is empty */
102 while (*str2_1)
104 printf("%d %d\n", *str1, *str2_1);
105 diff = *(str1++) - *(str2_1++);
106 if (diff)
107 return diff;
111 printf("%d %d\n", *str1, *str2_2);
112 diff = *str1 - *str2_2;
113 if (diff)
114 return diff;
115 } while (*(str2_2++) && *(str1++));
116 return 0;
119 char *psh_strdup(const char *str)
121 size_t length = strlen(str) + 1;
122 char *dest = xmalloc(P_CS * length);
123 memmove(dest, str, length);
124 return dest;
127 /* Get a string from FUNC, where the first argument is a string pointer,
128 * while the second one is the length of the buffer.
129 * Original function's return value is copied into *RESULT.
130 * If that doesn't matter, use NULL, and RESULT will be left untouched.
131 * returned pointer needs to be free()d
133 char *psh_getstring(void *(*func)(char *, size_t), void **result)
135 size_t len = 256;
136 char *oldtry = NULL, *newtry = NULL;
137 for (;;)
139 newtry = xmalloc(P_CS * len);
140 if (result)
141 *result = (*func)(newtry, len);
142 else
143 (*func)(newtry, len);
144 if (oldtry && strcmp(oldtry, newtry) == 0) /* Identical */
145 break;
146 xfree(oldtry);
147 oldtry = newtry;
148 len *= 2;
150 xfree(oldtry);
151 newtry = xrealloc(newtry, strlen(newtry) + 1);
152 return newtry;