Alessandro Mauri 3 years ago
parent 7414651893
commit 01d4457763
  1. 55
      err.c
  2. 16
      err.h
  3. 15
      fstr.c
  4. 1
      fstr.h
  5. 4
      makefile
  6. BIN
      msh
  7. 42
      msh.c

55
err.c

@ -0,0 +1,55 @@
#define _POSIX_C_SOURCE 200809l
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include "err.h"
void die(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
if (fmt[0] && fmt[strlen(fmt) - 1] == ':')
fprintf(stderr, " %s", strerror(errno));
else
fputc('\n', stderr);
va_end(ap);
exit(errno ? errno : EXIT_FAILURE);
}
void *emalloc(size_t s)
{
if (!s || s == (size_t)-1)
die("bad malloc: invalid size");
void *p = malloc(s);
if (!p)
die("bad malloc:");
return p;
}
void *erealloc(void *p, size_t s)
{
if (!s || s == (size_t)-1)
die("bad realloc: invalid size");
void *r = realloc(p, s);
if (!r)
die("bad realloc:");
return r;
}
char *estrdup(const char *s)
{
if (!s)
die("bad strdup: cannot duplicate NULL pointer");
char *r = strdup(s);
if (!r)
die("bad strdup:");
return r;
}

16
err.h

@ -0,0 +1,16 @@
#ifndef _ACRON_ERR_H
#define _ACRON_ERR_H
/* Helper error/error-ing functions, like die() and dying versions of memory
* allocating functions */
#include <stdlib.h>
void die(const char *, ...);
/* Erroring functions */
void *emalloc(size_t);
void *erealloc(void *, size_t);
char *estrdup(const char *);
#endif

@ -3,11 +3,12 @@
#include <stdlib.h>
#include "fstr.h"
#include "err.h"
#include "config.h"
void fstr_add_space(fstr_t *fs)
{
erealloc(fs->s, fs->len + fs->space + DEF_CHUNKSIZE + 1);
fs->s = erealloc(fs->s, fs->len + fs->space + DEF_CHUNKSIZE + 1);
fs->space += DEF_CHUNKSIZE;
}
@ -17,7 +18,15 @@ void fstr_append_char(fstr_t *fs, char c)
return;
if (fs->space < 1)
fstr_add_space(fs);
fs->s[fs->len++] = c;
fs->s[fs->len] = '\0';
// I don't know if this is faster
if (fs->s[fs->len] != c)
fs->s[fs->len] = c;
fs->s[++fs->len] = '\0';
fs->space--;
}
void fstr_clear(fstr_t *fs)
{
fs->space += fs->len;
fs->len = 0;
}

@ -10,5 +10,6 @@ typedef struct _fstr {
} fstr_t;
void fstr_append_char(fstr_t *, char);
void fstr_clear(fstr_t *);
#endif

@ -1,8 +1,8 @@
.POSIX:
CFLAGS = -Wall -Werror -pedantic -Wextra -std=c11
CFLAGS = -Wall -Werror -pedantic -Wextra -std=c11 -O0 -g
msh: msh.c fstr.c
msh: msh.c fstr.c err.c
clean:
rm -f msh *.o

BIN
msh

Binary file not shown.

42
msh.c

@ -2,13 +2,15 @@
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
#include <termios.h>
#include "config.h"
#include "fstr.h"
#include "err.h"
fstr_t PS1 = {0};
unsigned int histsize = DEF_HISTSIZE;
@ -26,6 +28,12 @@ struct {
char tag;
} shinfo;
struct {
struct termios tio;
struct termios tio_before;
} terminfo;
void sh_setup_terminal(void);
void sh_update_uinfo(void);
void sh_update_shinfo(void);
void sh_update_ps1(void);
@ -35,19 +43,40 @@ int main(int argc, char **argv)
{
(void)argc;
(void)argv;
char i;
sh_setup_terminal();
for (;;) {
sh_update_uinfo();
sh_update_shinfo();
sh_update_ps1();
sh_print_ps1();
for(;;);
fflush(stdout);
while (1) {
read(STDIN_FILENO, &i, 1); // This blocks
fputc(i, stdout);
fflush(stdout);
if (i == '\n')
break;
}
}
return EXIT_SUCCESS;
}
void sh_fill_uinfo(void)
void sh_setup_terminal(void)
{
if (tcgetattr(STDOUT_FILENO, &terminfo.tio_before) == -1)
die("tcgetattr:");
terminfo.tio = terminfo.tio_before;
/* Do not echo and input is available immediately */
terminfo.tio.c_lflag &= ~ECHO;
terminfo.tio.c_lflag &= ~ICANON;
if (tcsetattr(STDOUT_FILENO, TCSANOW, &terminfo.tio) == -1)
die("tcsetattr:");
}
void sh_update_uinfo(void)
{
struct passwd *pw;
uid_t nuid;
@ -58,7 +87,7 @@ void sh_fill_uinfo(void)
pw = getpwuid(uinfo.uid);
// User not found
if (!pw)
exit(EXIT_FAILURE);
die("getpwuid:");
uinfo.gid = pw->pw_gid;
uinfo.name = estrdup(pw->pw_name);
uinfo.home = estrdup(pw->pw_dir);
@ -69,13 +98,14 @@ void sh_update_shinfo(void)
shinfo.tag = uinfo.uid ? '$' : '#';
}
inline void sh_print_ps1(void)
void sh_print_ps1(void)
{
puts(PS1.s);
fputs(PS1.s, stdout);
}
void sh_update_ps1(void)
{
fstr_clear(&PS1);
fstr_append_char(&PS1, shinfo.tag);
fstr_append_char(&PS1, ' ');
}