# SO Lista 3 Nielokalne skoki i terminal

## Zadanie 1 Kornelia

:::info
- proces osierocony - proces, który dalej żyje; jego rodzic już umarł
- zadanie drugoplanowe - działa w tle, nie blokuje okna terminala; z jednego terminala możemy uruchomić wiele zadań w tle; (zadanie drugoplanowe wywołujemy dodając znak '&' na końcu polecenia)
- sesja - zbiór jednej lub więcej grup procesów; członkowie tej samej grupy należą do jednej sesji
- lider sesji - proces, którego PID = ID sesji
- terminal sterujący- jest przypisany do sesji powłoki, możemy za jego pośrednictwem kontrolować grupę procesów pierwszoplanowych (może być tylko jedna) dla tego terminala (wysyłać / odbierać sygnały)
:::
:::spoiler Terminal

:::
Polecenia :
``xterm -e ’bash -i’ &``
``sleep 1000 & <- w nowej powłoce``
``ps -o pid,ppid,cmd <- w nowej powłoce``
``ps -eo pid,ppid,cmd | grep [sleep PPID]``
``kill -SIGKILL [bash PID]``
``ps -eo pid,ppid,cmd | grep sleep``
``cat /proc/[sleep PPID]/cmdline``
Rodzicem `sleep 1000` jest bash. Po zabicu powłoki nowym rodzicem staje się systemd.
---
:::warning
???
:::
Kiedy procesy tracą terminal sterujący, jądro wysyła im sygnał SIGHUP. Domyślną akcją jest zabicie procesów.
ps -eo pid,ppid,cmd | grep terminal
kill -SIGKILL [terminal PID]
## Zadanie 2 Kuba (pls tym razem nie odręczne notatki xD)

## Zadanie 3 Olek


Sygnały związane z **zarządzaniem zadaniami**:
`*` oznacza ustawienia nie ze standardu POSIX
Sygnały związane z **zarządzaniem zadaniami**:
- `intr` wysyła sygnał przerwania
- `quit` wysyła sygnał zamknięcia
- `* swtch` włącza inną warstwę powłoki
- `start`/`stop` wznawia/wstrzymuje wyświetlanie
- `susp` wysyła sygnał SIGSTP
Sygnały związane z **edycją wiersza** (do zaprezentowania z `cat`):
- `erase` kasuje ostatni wprowadzony znak,
- `kill` kasuje obecną linie
- `eof` wysyła znak końca pliku (końca wejścia)
- `eol`/`* eol2` wysyła znak końca wiersza
- `* werase` kasuje ostatnie wprowadzone słowo
- `* rprnt` powtarza bieżący wiersz
- `* lnext` wprowadza kolejny znak w cudzysłowie
Program może zostać poinformowany zmianie **rozmiaru okna** terminala. W tym celu musi zainstalować procedurę obsługi sygnału `SIGWINCH`.
`man ioctl_tty` (input/output control)
Procedury `TIOCGWINSZ`, `TIOCSWINSZ` służą kolejno do odczytywania i wczytywania rozmiaru okna.
```c=
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
int main(void) {
struct winsize ws;
ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);
printf ("lines %d\n", ws.ws_row);
printf ("columns %d\n", ws.ws_col);
return (0);
}
```
## Zadanie 4

## Zadanie 5 kasia

Za pomocą ``stty -a`` wyświetlamy bieżącą konfigurację termianala.

1. Używamy ``CTRL+Z`` \(sygnał ``SIGTSTP``\)

2. ``CTRL+S`` i ``CTRL+Q`` służą do sterowania przepływem, ``XOFF`` (^S) powiadamia proces/urządzenie wysyłające dane, że bufor wejścia jest pełny i nie powinny być już wysyłane żadne dane. Terminal odpowiada za obsługę tych wywołań i jest odpowiedzialny za ich obsługę - może umożliwić dalsze działanie i wysyłanie danych, odrzucenie danych, czy wznowienie po otrzymaniu ``XON`` (^Q).
3. ``-`` to standardowe wejście, ``&`` znaczy, że chcemy wysłać polecenie w background \(do tła?\) i odzyskujemy kontrolę nad wejściem terminala niezależnie od wykonywanego programu. Widać, że nie można ich wywołać naraz, więc gdy próbujemy, program zostaje wstrzymany sygnałem ``SIGSTOP``. ***(wydaje mi się że raczej SIGTTIN ~ Olek)***

4. przed:

po:

``cat /etc/shells &`` wypisuje dany plik w tle.
``stty tostop`` wysyła ``SIGTTOU`` do grupy procesu, procesu który próbuje pisać do terminala.
``SIGTTOU`` domyślnie zatrzymuje proces.
5. Przed ``echoctl`` pojawił się dash (ostatnia linjka)

Wyłączyliśmy wypisywanie naszych ``CTRL + <litera>``

> echo control characters in hat notation ('^c')
---

## Zadanie 6 Marcin

W C nie można użyć ``goto`` znajdującego się w innej funkcji, dlatego musimy skorzystać z ``setjmp`` oraz ``longjmp``. Funkcję ``setjmp`` wywołujemy w miejscu, do którego chcemy wrócić (i tam powinna zwrócić ``0``, jako że wywołaliśmy ją bezpośrednio). W argumencie przekazujemy środowisko *env*, a więc np. ``jmpbuffer`` (typu ``jmp_buf``, zadeklarowanego globalnie). Funkcja ``longjmp`` używa danych z *env* do przekazania kontroli w miejsce, w którym ``setjmp`` zostało wywołane i przywraca stos do stanu w czasie wywołania ``setjmp``. Gdy ``longjmp`` się powiedzie, program będzie działał dalej i ``setjmp`` zwróci wartość drugi raz - będzie to wartość przekazana w argumencie ``val``, a gdy programista przekaże ``0`` do ``val``, to zwrócone zostanie ``1``.
``Jmpbuf`` nie przechowuje wszystkich rejestrów procesora, gdyż jest to funkcja taka jak każda inna, dlatego może odrzucić rejestry *caller-saved*, które przechowują wartości tymczasowe. Dzięki temu nie trzeba ich zapisywać i przywracać.
``Longjmp`` zapisuje na stos wartość ``%r11``, do której wcześniej przypisany był ``%rip``, dzięki temu wiadomo, którą instrukcję należy wykonać po powrocie.
``` =C
/* Setjmp & longjmp implementation without sigprocmask */
typedef struct {
long rbx;
long rbp;
long r12;
long r13;
long r14;
long r15;
void *rsp;
void *rip;
} Jmpbuf[1];
int Setjmp(Jmpbuf env);
noreturn void Longjmp(Jmpbuf env, int val);
```
``` =C
_JB_RBX = 0
_JB_RBP = 1 # poczatek stosu
_JB_R12 = 2
_JB_R13 = 3
_JB_R14 = 4
_JB_R15 = 5
_JB_RSP = 6 # biezaca lokalizacja na stosie
_JB_RIP = 7 # wskaznik instrukcji
.text
.globl Setjmp
.type Setjmp,@function
Setjmp: # int Setjmp(Jmpbuf env (%rdi)):
movq (%rsp),%r11 # przenosimy adres powrotu do r11 (kopia zapasowa)
movq %rbx,(_JB_RBX * 8)(%rdi) # przenosimy rejestry do jmp_buf
movq %rbp,(_JB_RBP * 8)(%rdi)
movq %r12,(_JB_R12 * 8)(%rdi)
movq %r13,(_JB_R13 * 8)(%rdi)
movq %r14,(_JB_R14 * 8)(%rdi)
movq %r15,(_JB_R15 * 8)(%rdi)
movq %rsp,(_JB_RSP * 8)(%rdi)
movq %r11,(_JB_RIP * 8)(%rdi)
xorl %eax,%eax
ret
.size Setjmp, . - Setjmp
.globl Longjmp
.type Longjmp,@function
Longjmp: # noreturn void Longjmp(Jmpbuf env (%rdi), int val (%esi)):
movq (_JB_RBX * 8)(%rdi),%rbx # przywracamy rejestry z jmp_buf
movq (_JB_RBP * 8)(%rdi),%rbp
movq (_JB_R12 * 8)(%rdi),%r12
movq (_JB_R13 * 8)(%rdi),%r13
movq (_JB_R14 * 8)(%rdi),%r14
movq (_JB_R15 * 8)(%rdi),%r15
movq (_JB_RSP * 8)(%rdi),%rsp
movq (_JB_RIP * 8)(%rdi),%r11
movl %esi,%eax # przenosimy drugi argument do %rax, jesli jest rowny
# 0, to zmieniamy go na 1
testl %eax,%eax
jnz 1f # if (!eax) eax = 1; else goto 1;
incl %eax
1: movq %r11,(%rsp) # umieszczenie starego %rip (z %r11) na stos
ret
.size Longjmp, . - Longjmp
```
::::: spoiler ``Setjmp.s``
``` =C
_JB_RBX = 0
_JB_RBP = 1
_JB_R12 = 2
_JB_R13 = 3
_JB_R14 = 4
_JB_R15 = 5
_JB_RSP = 6
_JB_RIP = 7
.text
.globl Setjmp
.type Setjmp,@function
Setjmp:
movq (%rsp),%r11
movq %rbx,(_JB_RBX * 8)(%rdi)
movq %rbp,(_JB_RBP * 8)(%rdi)
movq %r12,(_JB_R12 * 8)(%rdi)
movq %r13,(_JB_R13 * 8)(%rdi)
movq %r14,(_JB_R14 * 8)(%rdi)
movq %r15,(_JB_R15 * 8)(%rdi)
movq %rsp,(_JB_RSP * 8)(%rdi)
movq %r11,(_JB_RIP * 8)(%rdi)
xorl %eax,%eax
ret
.size Setjmp, . - Setjmp
.globl Longjmp
.type Longjmp,@function
Longjmp:
movq (_JB_RBX * 8)(%rdi),%rbx
movq (_JB_RBP * 8)(%rdi),%rbp
movq (_JB_R12 * 8)(%rdi),%r12
movq (_JB_R13 * 8)(%rdi),%r13
movq (_JB_R14 * 8)(%rdi),%r14
movq (_JB_R15 * 8)(%rdi),%r15
movq (_JB_RSP * 8)(%rdi),%rsp
movq (_JB_RIP * 8)(%rdi),%r11
movl %esi,%eax
testl %eax,%eax
jnz 1f
incl %eax
1: movq %r11,(%rsp)
ret
.size Longjmp, . - Longjmp
```
:::::
::::: spoiler ``csapp.h``
``` =C
#ifndef __CSAPP_H__
#define __CSAPP_H__
#include <sys/types.h>
#include <sys/mman.h>
#ifdef LINUX
#include <sys/sysmacros.h>
#include <sys/prctl.h>
#endif
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <limits.h>
#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
#include <pthread.h>
#include <pwd.h>
#include <semaphore.h>
#include <setjmp.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdnoreturn.h>
#include <string.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#define _CONCAT(x, y) x##y
#define CONCAT(x, y) _CONCAT(x, y)
#define min(a, b) \
({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
_a < _b ? _a : _b; \
})
#define max(a, b) \
({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
_a > _b ? _a : _b; \
})
#ifndef powerof2
#define powerof2(x) (((x) & ((x)-1)) == 0)
#endif
#ifndef __unused
#define __unused __attribute__((unused))
#endif
extern char **environ;
/* Useful constants. */
#define MAXLINE 4096
/* Our own error-handling functions */
noreturn void unix_error(const char *fmt, ...)
__attribute__((format(printf, 1, 2)));
noreturn void posix_error(int code, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
noreturn void app_error(const char *fmt, ...)
__attribute__((format(printf, 1, 2)));
noreturn void gai_error(int code, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
/* Signal safe I/O functions */
void safe_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
void safe_error(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
/* Decent hashing function. */
#define HASHINIT 5381
uint32_t jenkins_hash(const void *key, size_t length, uint32_t initval);
/* Memory allocation wrappers */
void *Malloc(size_t size);
void *Realloc(void *ptr, size_t size);
void *Calloc(size_t nmemb, size_t size);
/* Process control wrappers */
pid_t Fork(void);
pid_t Waitpid(pid_t pid, int *iptr, int options);
#define Wait(iptr) Waitpid(-1, iptr, 0)
void Prctl(int option, long arg);
/* Process environment */
char *Getcwd(char *buf, size_t buflen);
/* Signal control wrappers */
void (*Signal(int sig, void (*func)(int)))(int);
void Kill(pid_t pid, int sig);
void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
void Sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
void Sigsuspend(const sigset_t *mask);
/* Process group control wrappers */
void Setpgid(pid_t pid, pid_t pgid);
/* Stdio wrappers */
char *Fgets(char *ptr, int n, FILE *stream);
void Fputs(const char *ptr, FILE *stream);
/* Unix I/O wrappers */
int Open(const char *pathname, int flags, mode_t mode);
size_t Read(int fd, void *buf, size_t count);
size_t Write(int fd, const void *buf, size_t count);
size_t Writev(int fd, const struct iovec *iov, int iovcnt);
off_t Lseek(int fildes, off_t offset, int whence);
void Close(int fd);
void Ftruncate(int fd, off_t length);
int Dup(int fd);
int Dup2(int oldfd, int newfd);
void Pipe(int fds[2]);
void Socketpair(int domain, int type, int protocol, int sv[2]);
int Select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout);
int Poll(struct pollfd *fds, nfds_t nfds, int timeout);
/* Directory access (Linux specific) */
struct linux_dirent {
unsigned long d_ino; /* Inode number */
unsigned long d_off; /* Offset to next linux_dirent */
unsigned short d_reclen; /* Length of this linux_dirent */
char d_name[]; /* Filename (null-terminated) */
};
int Getdents(int fd, struct linux_dirent *dirp, unsigned count);
/* Directory operations */
void Rename(const char *oldpath, const char *newpath);
void Unlink(const char *pathname);
/* File metadata access wrapper */
void Fstat(int fd, struct stat *statbuf);
void Fstatat(int dirfd, const char *pathname, struct stat *statbuf, int flags);
size_t Readlink(const char *pathname, char *buf, size_t bufsiz);
size_t Readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz);
/* Memory mapped files & anonymous memory */
void *Mmap(void *addr, size_t length, int prot, int flags, int fd,
off_t offset);
void Mprotect(void *addr, size_t len, int prot);
void Munmap(void *addr, size_t len);
void Madvise(void *addr, size_t length, int advice);
/* Terminal control */
void Tcsetpgrp(int fd, pid_t pgrp);
pid_t Tcgetpgrp(int fd);
void Tcsetattr(int fd, int action, const struct termios *termios_p);
void Tcgetattr(int fd, struct termios *termios_p);
/* Setjmp & longjmp implementation without sigprocmask */
typedef struct {
long rbx;
long rbp;
long r12;
long r13;
long r14;
long r15;
void *rsp;
void *rip;
} Jmpbuf[1];
int Setjmp(Jmpbuf env);
noreturn void Longjmp(Jmpbuf env, int val);
/* Socket interface wrappers. */
typedef struct sockaddr SA;
int Socket(int domain, int type, int protocol);
void Setsockopt(int s, int level, int optname, const void *optval, int optlen);
void Bind(int sockfd, struct sockaddr *my_addr, int addrlen);
void Listen(int s, int backlog);
int Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
/* Protocol-independent wrappers. */
void Getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res);
void Getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
size_t hostlen, char *serv, size_t servlen, int flags);
int open_clientfd(char *hostname, char *port);
int Open_clientfd(char *hostname, char *port);
int open_listenfd(char *port, int backlog);
int Open_listenfd(char *port, int backlog);
/* POSIX thread control wrappers. */
void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
void *(*routine)(void *), void *argp);
void Pthread_cancel(pthread_t tid);
void Pthread_join(pthread_t tid, void **thread_return);
void Pthread_detach(pthread_t tid);
/* POSIX semaphore wrappers. */
void Sem_init(sem_t *sem, int pshared, unsigned value);
void Sem_destroy(sem_t *sem);
void Sem_wait(sem_t *sem);
void Sem_getvalue(sem_t *sem, int *sval);
void Sem_post(sem_t *sem);
/* POSIX mutex wrappers. */
void Pthread_mutex_init(pthread_mutex_t *mutex,
const pthread_mutexattr_t *mutexattr);
void Pthread_mutex_destroy(pthread_mutex_t *mutex);
void Pthread_mutex_lock(pthread_mutex_t *mutex);
void Pthread_mutex_unlock(pthread_mutex_t *mutex);
/* POSIX conditional variable wrappers. */
void Pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
void Pthread_cond_destroy(pthread_cond_t *cond);
void Pthread_cond_signal(pthread_cond_t *cond);
void Pthread_cond_broadcast(pthread_cond_t *cond);
void Pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
/* POSIX reader-writer lock wrappers. */
void Pthread_rwlock_init(pthread_rwlock_t *rwlock,
const pthread_rwlockattr_t *rwlockattr);
void Pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
void Pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
void Pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
void Pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
#endif /* __CSAPP_H__ */
```
:::::
## Zadanie 7

## Zadanie 8
