PatchworkOS  3984a1d
A non-POSIX operating system.
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1#include <errno.h>
2#include <kernel/ipc/note.h>
3#include <stdio.h>
4#include <string.h>
5#include <sys/io.h>
6#include <sys/proc.h>
7#include <time.h>
8
9#define BUFFER_MAX 0x1000
10
11void note_handler(char* note)
12{
13 UNUSED(note);
14
15 // Do nothing
16 noted();
17}
18
19int main(int argc, char** argv)
20{
21 if (argc < 1)
22 {
23 return EXIT_FAILURE;
24 }
25
26 if (notify(note_handler) == ERR)
27 {
28 printf("boxspawn: failed to register note handler (%s)\n", strerror(errno));
29 return EXIT_FAILURE;
30 }
31
32 char* id = sreadfile("/net/local/seqpacket");
33 if (id == NULL)
34 {
35 printf("boxspawn: failed to open local seqpacket socket (%s)\n", strerror(errno));
36 return EXIT_FAILURE;
37 }
38
39 if (swritefile(F("/net/local/%s/ctl", id), "connect boxspawn") == ERR)
40 {
41 printf("boxspawn: failed to connect to boxspawn (%s)\n", strerror(errno));
42 free(id);
43 return EXIT_FAILURE;
44 }
45
46 char stdio[3][KEY_128BIT];
47 for (uint8_t i = 0; i < 3; i++)
48 {
49 if (share(stdio[i], sizeof(stdio[i]), i, CLOCKS_PER_SEC) == ERR)
50 {
51 printf("boxspawn: failed to share stdio (%s)\n", strerror(errno));
52 free(id);
53 return EXIT_FAILURE;
54 }
55 }
56
57 char group[KEY_128BIT] = {0};
58 char namespace[KEY_128BIT] = {0};
59 if (sharefile(group, sizeof(group), "/proc/self/group", CLOCKS_PER_SEC) == ERR)
60 {
61 if (errno != ENOENT)
62 {
63 printf("boxspawn: failed to share group (%s)\n", strerror(errno));
64 free(id);
65 return EXIT_FAILURE;
66 }
67
68 printf("boxspawn: `/proc` does not appear to be mounted, foreground boxes will not work correctly\n");
69 }
70 else if (sharefile(namespace, sizeof(namespace), "/proc/self/ns", CLOCKS_PER_SEC) == ERR)
71 {
72 printf("boxspawn: failed to share namespace (%s)\n", strerror(errno));
73 free(id);
74 return EXIT_FAILURE;
75 }
76
77 char buffer[BUFFER_MAX];
78 if (group[0] != '\0')
79 {
80 snprintf(buffer, sizeof(buffer), "group=%s namespace=%s stdin=%s stdout=%s stderr=%s -- ", group, namespace,
81 stdio[STDIN_FILENO], stdio[STDOUT_FILENO], stdio[STDERR_FILENO]);
82 }
83 else
84 {
85 snprintf(buffer, sizeof(buffer), "stdin=%s stdout=%s stderr=%s -- ", stdio[STDIN_FILENO], stdio[STDOUT_FILENO],
86 stdio[STDERR_FILENO]);
87 }
88
89 const char* lastSlash = strrchr(argv[0], '/');
90 if (lastSlash == NULL)
91 {
92 strcat(buffer, argv[0]);
93 }
94 else
95 {
97 }
98
99 for (int i = 1; i < argc; i++)
100 {
101 if (strlen(buffer) + 1 + strlen(argv[i]) >= BUFFER_MAX)
102 {
103 printf("boxspawn: arguments too long\n");
104 free(id);
105 return EXIT_FAILURE;
106 }
107 strcat(buffer, " ");
108 strcat(buffer, argv[i]);
109 }
110
111 fd_t data = open(F("/net/local/%s/data", id));
112 if (data == ERR)
113 {
114 printf("boxspawn: failed to open data socket (%s)\n", strerror(errno));
115 free(id);
116 return EXIT_FAILURE;
117 }
118
119 if (swrite(data, buffer) == ERR)
120 {
121 printf("boxspawn: failed to send request (%s)\n", strerror(errno));
122 free(id);
123 close(data);
124 return EXIT_FAILURE;
125 }
126
127 memset(buffer, 0, sizeof(buffer));
128
129 if (read(data, buffer, sizeof(buffer) - 1) == ERR)
130 {
131 printf("boxspawn: failed to read response (%s)\n", strerror(errno));
132 free(id);
133 close(data);
134 return EXIT_FAILURE;
135 }
136 close(data);
137
138 if (wordcmp(buffer, "error") == 0)
139 {
140 printf("boxspawn: %s\n", buffer);
141 free(id);
142 return EXIT_FAILURE;
143 }
144
145 if (wordcmp(buffer, "background") == 0)
146 {
147 free(id);
148 return 0;
149 }
150
151 char waitkey[KEY_MAX];
152 if (sscanf(buffer, "foreground %s", waitkey) != 1)
153 {
154 printf("boxspawn: failed to parse response (%s)\n", strerror(errno));
155 free(id);
156 return EXIT_FAILURE;
157 }
158
159 fd_t wait = claim(waitkey);
160 if (wait == ERR)
161 {
162 printf("boxspawn: failed to claim response (%s)\n", strerror(errno));
163 free(id);
164 return EXIT_FAILURE;
165 }
166
167 char status[NOTE_MAX];
168 if (RETRY_EINTR(read(wait, status, sizeof(status) - 1)) == ERR)
169 {
170 printf("boxspawn: failed to read status (%s)\n", strerror(errno));
171 free(id);
172 close(wait);
173 return EXIT_FAILURE;
174 }
175 close(wait);
176
177 _exit(status);
178}
int main(void)
Definition main.c:5
int64_t y
Definition main.c:153
#define CLOCKS_PER_SEC
Definition clock_t.h:15
static fd_t data
Definition dwm.c:21
#define NOTE_MAX
Maximum size of a notes buffer.
Definition note.h:99
#define ENOENT
No such file or directory.
Definition errno.h:42
#define errno
Error number variable.
Definition errno.h:27
#define UNUSED(x)
Mark a variable as unused.
Definition defs.h:100
#define KEY_128BIT
The size of a buffer needed to hold a 128-bit key.
Definition io.h:509
fd_t open(const char *path)
System call for opening files.
Definition open.c:8
#define KEY_MAX
Maximum size of a key generated by share().
Definition io.h:507
uint64_t close(fd_t fd)
System call for closing files.
Definition close.c:8
#define F(format,...)
Allocates a formatted string on the stack.
Definition io.h:66
size_t read(fd_t fd, void *buffer, size_t count)
System call for reading from files.
Definition read.c:8
size_t swrite(fd_t fd, const char *string)
Wrapper for writing a null-terminated string to a file.
Definition swrite.c:4
size_t swritefile(const char *path, const char *string)
Wrapper for writing a null-terminated string directly to a file using a path.
Definition swritefile.c:4
fd_t claim(const char *key)
System call for claiming a shared file descriptor.
Definition claim.c:6
#define STDOUT_FILENO
Standard output file descriptor.
Definition io.h:35
char * sreadfile(const char *path)
Wrapper for reading an entire file directly into a null-terminated string.
Definition sreadfile.c:3
#define STDERR_FILENO
Standard error file descriptor.
Definition io.h:36
uint64_t share(char *key, uint64_t size, fd_t fd, clock_t timeout)
System call for sharing a file descriptor with another process.
Definition share.c:6
#define RETRY_EINTR(expr)
Macro to automatically retry a function that returns an integer if it errors and errno == EINTR.
Definition io.h:601
uint64_t sharefile(char *key, uint64_t size, const char *path, clock_t timeout)
Helper for sharing a file by its path.
Definition sharefile.c:4
#define STDIN_FILENO
Standard input file descriptor.
Definition io.h:34
int64_t wordcmp(const char *string, const char *word)
Helper for comparing the first word of a string.
Definition wordcmp.c:5
uint64_t notify(note_func_t handler)
System call that sets the handler to be called when a note is received.
Definition notify.c:5
_NORETURN void _exit(const char *status)
System call that handles pending notes for the current thread.
Definition _exit.c:7
_NORETURN void noted(void)
System call that notifies the kernel that the current note has been handled.
Definition noted.c:5
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
__UINT64_TYPE__ fd_t
A file descriptor.
Definition fd_t.h:12
#define BUFFER_MAX
Definition main.c:58
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
void note_handler(char *note)
Definition main.c:11
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
_PUBLIC int sscanf(const char *_RESTRICT s, const char *_RESTRICT format,...)
Definition sscanf.c:4
_PUBLIC int printf(const char *_RESTRICT format,...)
Definition printf.c:3
_PUBLIC int snprintf(char *_RESTRICT s, size_t n, const char *_RESTRICT format,...)
Definition snprintf.c:3
#define EXIT_FAILURE
Definition stdlib.h:47
_PUBLIC void free(void *ptr)
Definition free.c:11
_PUBLIC char * strerror(int errnum)
Definition strerror.c:6
_PUBLIC size_t strlen(const char *s)
Definition strlen.c:3
_PUBLIC char * strcat(char *_RESTRICT s1, const char *_RESTRICT s2)
Definition strcat.c:3
_PUBLIC char * strrchr(const char *s, int c)
Definition strrchr.c:3
_PUBLIC void * memset(void *s, int c, size_t n)
Definition memset.c:4