1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3
4/*
5 Title: OS Abstraction
6*/
7
8#ifndef BASE_SYSTEM_H
9#define BASE_SYSTEM_H
10
11#include "detect.h"
12#include "fs.h"
13#include "str.h"
14#include "types.h"
15
16#include <chrono>
17#include <cinttypes>
18#include <cstdarg>
19#include <cstdint>
20#include <cstring>
21#include <ctime>
22#include <functional>
23#include <mutex>
24#include <optional>
25#include <string>
26
27#ifdef __MINGW32__
28#undef PRId64
29#undef PRIu64
30#undef PRIX64
31#define PRId64 "I64d"
32#define PRIu64 "I64u"
33#define PRIX64 "I64X"
34#define PRIzu "Iu"
35#else
36#define PRIzu "zu"
37#endif
38
39#ifdef CONF_FAMILY_UNIX
40#include <sys/un.h>
41#endif
42
43#ifdef CONF_PLATFORM_LINUX
44#include <netinet/in.h>
45#include <sys/socket.h>
46#endif
47
48/**
49 * Utilities for debugging.
50 *
51 * @defgroup Debug Debugging
52 */
53
54/**
55 * Breaks into the debugger based on a test.
56 *
57 * @ingroup Debug
58 *
59 * @param test Result of the test.
60 * @param fmt A printf styled format message that should be printed if the test fails.
61 *
62 * @remark Also works in release mode.
63 *
64 * @see dbg_break
65 */
66#define dbg_assert(test, fmt, ...) \
67 do \
68 { \
69 if(!(test)) \
70 { \
71 dbg_assert_imp(__FILE__, __LINE__, fmt, ##__VA_ARGS__); \
72 } \
73 } while(false)
74
75/**
76 * Breaks into the debugger with a message.
77 *
78 * @ingroup Debug
79 * @param fmt A printf styled format message that should be printed in case the
80 * code is reached.
81 *
82 * @remark Also works in release mode.
83 *
84 * @see dbg_break
85 */
86#define dbg_assert_failed(fmt, ...) dbg_assert_imp(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
87
88/**
89 * Use dbg_assert instead!
90 *
91 * @ingroup Debug
92 */
93[[gnu::format(printf, 3, 4)]] [[noreturn]] void
94dbg_assert_imp(const char *filename, int line, const char *fmt, ...);
95
96/**
97 * Checks whether the program is currently shutting down due to a failed
98 * assert.
99 *
100 * @ingroup Debug
101 *
102 * @return indication whether the program is currently shutting down due to a
103 * failed assert.
104 */
105bool dbg_assert_has_failed();
106
107/**
108 * Breaks into the debugger.
109 *
110 * @ingroup Debug
111 *
112 * @remark Also works in release mode.
113 *
114 * @see dbg_assert
115 */
116[[noreturn]] void dbg_break();
117
118typedef std::function<void(const char *message)> DBG_ASSERT_HANDLER;
119void dbg_assert_set_handler(DBG_ASSERT_HANDLER handler);
120
121/**
122 * Prints a debug message.
123 *
124 * @ingroup Debug
125 *
126 * @param sys A string that describes what system the message belongs to.
127 * @param fmt A printf styled format string.
128 *
129 * @remark Also works in release mode.
130 *
131 * @see dbg_assert
132 */
133[[gnu::format(printf, 2, 3)]] void dbg_msg(const char *sys, const char *fmt, ...);
134
135/**
136 * Memory management utilities.
137 *
138 * @defgroup Memory Memory
139 */
140
141/**
142 * Copies a a memory block.
143 *
144 * @ingroup Memory
145 *
146 * @param dest Destination.
147 * @param source Source to copy.
148 * @param size Size of the block to copy.
149 *
150 * @remark This functions DOES NOT handle cases where the source and destination is overlapping.
151 *
152 * @see mem_move
153 */
154void mem_copy(void *dest, const void *source, size_t size);
155
156/**
157 * Copies a a memory block.
158 *
159 * @ingroup Memory
160 *
161 * @param dest Destination.
162 * @param source Source to copy.
163 * @param size Size of the block to copy.
164 *
165 * @remark This functions handles the cases where the source and destination is overlapping.
166 *
167 * @see mem_copy
168 */
169void mem_move(void *dest, const void *source, size_t size);
170
171/**
172 * Sets a complete memory block to 0.
173 *
174 * @ingroup Memory
175 *
176 * @param block Pointer to the block to zero out.
177 * @param size Size of the block.
178 */
179template<typename T>
180inline void mem_zero(T *block, size_t size)
181{
182 static_assert((std::is_trivially_constructible<T>::value && std::is_trivially_destructible<T>::value) || std::is_fundamental<T>::value);
183 memset(block, 0, size);
184}
185
186/**
187 * Compares two blocks of memory
188 *
189 * @ingroup Memory
190 *
191 * @param a First block of data.
192 * @param b Second block of data.
193 * @param size Size of the data to compare.
194 *
195 * @return `< 0` if block a is less than block b.
196 * @return `0` if block a is equal to block b.
197 * @return `> 0` if block a is greater than block b.
198 */
199int mem_comp(const void *a, const void *b, size_t size);
200
201/**
202 * Checks whether a block of memory contains null bytes.
203 *
204 * @ingroup Memory
205 *
206 * @param block Pointer to the block to check for nulls.
207 * @param size Size of the block.
208 *
209 * @return `true` if the block has a null byte, `false` otherwise.
210 */
211bool mem_has_null(const void *block, size_t size);
212
213/**
214 * File I/O related operations.
215 *
216 * @defgroup File-IO File I/O
217 */
218
219/**
220 * @ingroup File-IO
221 */
222enum
223{
224 /**
225 * Open file for reading.
226 *
227 * @see io_open
228 */
229 IOFLAG_READ = 1,
230 /**
231 * Open file for writing.
232 *
233 * @see io_open
234 */
235 IOFLAG_WRITE = 2,
236 /**
237 * Open file for appending at the end.
238 *
239 * @see io_open
240 */
241 IOFLAG_APPEND = 4,
242};
243
244/**
245 * @ingroup File-IO
246 */
247enum ESeekOrigin
248{
249 /**
250 * Start seeking from the beginning of the file.
251 *
252 * @see io_seek
253 */
254 IOSEEK_START = 0,
255 /**
256 * Start seeking from the current position.
257 *
258 * @see io_seek
259 */
260 IOSEEK_CUR = 1,
261 /**
262 * Start seeking from the end of the file.
263 *
264 * @see io_seek
265 */
266 IOSEEK_END = 2,
267};
268
269/**
270 * Opens a file.
271 *
272 * @ingroup File-IO
273 *
274 * @param filename File to open.
275 * @param flags A set of IOFLAG flags.
276 *
277 * @see IOFLAG_READ, IOFLAG_WRITE, IOFLAG_APPEND.
278 *
279 * @return A handle to the file on success, or `nullptr` on failure.
280 */
281IOHANDLE io_open(const char *filename, int flags);
282
283/**
284 * Reads data into a buffer from a file.
285 *
286 * @ingroup File-IO
287 *
288 * @param io Handle to the file to read data from.
289 * @param buffer Pointer to the buffer that will receive the data.
290 * @param size Number of bytes to read from the file.
291 *
292 * @return Number of bytes read.
293 */
294unsigned io_read(IOHANDLE io, void *buffer, unsigned size);
295
296/**
297 * Reads the rest of the file into a buffer.
298 *
299 * @ingroup File-IO
300 *
301 * @param io Handle to the file to read data from.
302 * @param result Receives the file's remaining contents.
303 * @param result_len Receives the file's remaining length.
304 *
305 * @return `true` on success, `false` on failure.
306 *
307 * @remark Does NOT guarantee that there are no internal null bytes.
308 * @remark The result must be freed after it has been used.
309 * @remark The function will fail if more than 1 GiB of memory would
310 * have to be allocated. Large files should not be loaded into memory.
311 */
312bool io_read_all(IOHANDLE io, void **result, unsigned *result_len);
313
314/**
315 * Reads the rest of the file into a null-terminated buffer with
316 * no internal null bytes.
317 *
318 * @ingroup File-IO
319 *
320 * @param io Handle to the file to read data from.
321 *
322 * @return The file's remaining contents, or `nullptr` on failure.
323 *
324 * @remark Guarantees that there are no internal null bytes.
325 * @remark Guarantees that result will contain null-termination.
326 * @remark The result must be freed after it has been used.
327 * @remark The function will fail if more than 1 GiB of memory would
328 * have to be allocated. Large files should not be loaded into memory.
329 */
330char *io_read_all_str(IOHANDLE io);
331
332/**
333 * Skips data in a file.
334 *
335 * @ingroup File-IO
336 *
337 * @param io Handle to the file.
338 * @param size Number of bytes to skip.
339 *
340 * @return `0` on success.
341 */
342int io_skip(IOHANDLE io, int64_t size);
343
344/**
345 * Seeks to a specified offset in the file.
346 *
347 * @ingroup File-IO
348 *
349 * @param io Handle to the file.
350 * @param offset Offset from position to search.
351 * @param origin Position to start searching from.
352 *
353 * @return `0` on success.
354 */
355int io_seek(IOHANDLE io, int64_t offset, ESeekOrigin origin);
356
357/**
358 * Gets the current position in the file.
359 *
360 * @ingroup File-IO
361 *
362 * @param io Handle to the file.
363 *
364 * @return The current position, or `-1` on failure.
365 */
366int64_t io_tell(IOHANDLE io);
367
368/**
369 * Gets the total length of the file. Resets cursor to the beginning.
370 *
371 * @ingroup File-IO
372 *
373 * @param io Handle to the file.
374 *
375 * @return The total size, or `-1` on failure.
376 */
377int64_t io_length(IOHANDLE io);
378
379/**
380 * Writes data from a buffer to a file.
381 *
382 * @ingroup File-IO
383 *
384 * @param io Handle to the file.
385 * @param buffer Pointer to the data that should be written.
386 * @param size Number of bytes to write.
387 *
388 * @return Number of bytes written.
389 */
390unsigned io_write(IOHANDLE io, const void *buffer, unsigned size);
391
392/**
393 * Writes a platform dependent newline to a file.
394 *
395 * @ingroup File-IO
396 *
397 * @param io Handle to the file.
398 *
399 * @return `true` on success, `false` on failure.
400 */
401bool io_write_newline(IOHANDLE io);
402
403/**
404 * Closes a file.
405 *
406 * @ingroup File-IO
407 *
408 * @param io Handle to the file.
409 *
410 * @return `0` on success.
411 */
412int io_close(IOHANDLE io);
413
414/**
415 * Empties all buffers and writes all pending data.
416 *
417 * @ingroup File-IO
418 *
419 * @param io Handle to the file.
420 *
421 * @return `0` on success.
422 */
423int io_flush(IOHANDLE io);
424
425/**
426 * Synchronize file changes to disk.
427 *
428 * @ingroup File-IO
429 *
430 * @param io Handle to the file.
431 *
432 * @return `0` on success.
433 */
434int io_sync(IOHANDLE io);
435
436/**
437 * Checks whether an error occurred during I/O with the file.
438 *
439 * @ingroup File-IO
440 *
441 * @param io Handle to the file.
442 *
443 * @return `0` on success, or non-`0` on error.
444 */
445int io_error(IOHANDLE io);
446
447/**
448 * Returns a handle for the standard input.
449 *
450 * @ingroup File-IO
451 *
452 * @return An @link IOHANDLE @endlink for the standard input.
453 *
454 * @remark The handle must not be closed.
455 */
456IOHANDLE io_stdin();
457
458/**
459 * Returns a handle for the standard output.
460 *
461 * @ingroup File-IO
462 *
463 * @return An @link IOHANDLE @endlink for the standard output.
464 *
465 * @remark The handle must not be closed.
466 */
467IOHANDLE io_stdout();
468
469/**
470 * Returns a handle for the standard error.
471 *
472 * @ingroup File-IO
473 *
474 * @return An @link IOHANDLE @endlink for the standard error.
475 *
476 * @remark The handle must not be closed.
477 */
478IOHANDLE io_stderr();
479
480/**
481 * Returns a handle for the current executable.
482 *
483 * @ingroup File-IO
484 *
485 * @return An @link IOHANDLE @endlink for the current executable.
486 */
487IOHANDLE io_current_exe();
488
489/**
490 * Wrapper for asynchronously writing to an @link IOHANDLE @endlink.
491 *
492 * @ingroup File-IO
493 */
494typedef struct ASYNCIO ASYNCIO;
495
496/**
497 * Wraps a @link IOHANDLE @endlink for asynchronous writing.
498 *
499 * @ingroup File-IO
500 *
501 * @param io Handle to the file.
502 *
503 * @return The handle for asynchronous writing.
504 */
505ASYNCIO *aio_new(IOHANDLE io);
506
507/**
508 * Locks the `ASYNCIO` structure so it can't be written into by
509 * other threads.
510 *
511 * @ingroup File-IO
512 *
513 * @param aio Handle to the file.
514 */
515void aio_lock(ASYNCIO *aio);
516
517/**
518 * Unlocks the `ASYNCIO` structure after finishing the contiguous
519 * write.
520 *
521 * @ingroup File-IO
522 *
523 * @param aio Handle to the file.
524 */
525void aio_unlock(ASYNCIO *aio);
526
527/**
528 * Queues a chunk of data for writing.
529 *
530 * @ingroup File-IO
531 *
532 * @param aio Handle to the file.
533 * @param buffer Pointer to the data that should be written.
534 * @param size Number of bytes to write.
535 */
536void aio_write(ASYNCIO *aio, const void *buffer, unsigned size);
537
538/**
539 * Queues a newline for writing.
540 *
541 * @ingroup File-IO
542 *
543 * @param aio Handle to the file.
544 */
545void aio_write_newline(ASYNCIO *aio);
546
547/**
548 * Queues a chunk of data for writing. The `ASYNCIO` struct must be
549 * locked using @link aio_lock @endlink first.
550 *
551 * @ingroup File-IO
552 *
553 * @param aio Handle to the file.
554 * @param buffer Pointer to the data that should be written.
555 * @param size Number of bytes to write.
556 */
557void aio_write_unlocked(ASYNCIO *aio, const void *buffer, unsigned size);
558
559/**
560 * Queues a newline for writing. The `ASYNCIO` struct must be locked
561 * using @link aio_lock @endlink first.
562 *
563 * @ingroup File-IO
564 *
565 * @param aio Handle to the file.
566 */
567void aio_write_newline_unlocked(ASYNCIO *aio);
568
569/**
570 * Checks whether errors have occurred during the asynchronous writing.
571 *
572 * Call this function regularly to see if there are errors. Call this
573 * function after @link aio_wait @endlink to see if the process of writing
574 * to the file succeeded.
575 *
576 * @ingroup File-IO
577 *
578 * @param aio Handle to the file.
579 *
580 * @return `0` on success, or non-`0` on error.
581 */
582int aio_error(ASYNCIO *aio);
583
584/**
585 * Queues file closing.
586 *
587 * @ingroup File-IO
588 *
589 * @param aio Handle to the file.
590 */
591void aio_close(ASYNCIO *aio);
592
593/**
594 * Wait for the asynchronous operations to complete.
595 *
596 * @ingroup File-IO
597 *
598 * @param aio Handle to the file.
599 */
600void aio_wait(ASYNCIO *aio);
601
602/**
603 * Frees the resources associated with the asynchronous file handle.
604 *
605 * @ingroup File-IO
606 *
607 * @param aio Handle to the file.
608 */
609void aio_free(ASYNCIO *aio);
610
611/**
612 * Threading related functions.
613 *
614 * @defgroup Threads Threading
615 *
616 * @see Locks
617 * @see Semaphore
618 */
619
620/**
621 * Creates a new thread.
622 *
623 * @ingroup Threads
624 *
625 * @param threadfunc Entry point for the new thread.
626 * @param user Pointer to pass to the thread.
627 * @param name Name describing the use of the thread.
628 *
629 * @return Handle for the new thread.
630 */
631void *thread_init(void (*threadfunc)(void *), void *user, const char *name);
632
633/**
634 * Waits for a thread to be done or destroyed.
635 *
636 * @ingroup Threads
637 *
638 * @param thread Thread to wait for.
639 */
640void thread_wait(void *thread);
641
642/**
643 * Yield the current thread's execution slice.
644 *
645 * @ingroup Threads
646 */
647void thread_yield();
648
649/**
650 * Puts the thread in the detached state, guaranteeing that
651 * resources of the thread will be freed immediately when the
652 * thread terminates.
653 *
654 * @ingroup Threads
655 *
656 * @param thread Thread to detach.
657 */
658void thread_detach(void *thread);
659
660/**
661 * Creates a new thread and detaches it.
662 *
663 * @ingroup Threads
664 *
665 * @param threadfunc Entry point for the new thread.
666 * @param user Pointer to pass to the thread.
667 * @param name Name describing the use of the thread.
668 */
669void thread_init_and_detach(void (*threadfunc)(void *), void *user, const char *name);
670
671/**
672 * @defgroup Semaphore Semaphores
673 *
674 * @see Threads
675 */
676
677#if defined(CONF_FAMILY_WINDOWS)
678typedef void *SEMAPHORE;
679#elif defined(CONF_PLATFORM_MACOS)
680#include <semaphore.h>
681typedef sem_t *SEMAPHORE;
682#elif defined(CONF_FAMILY_UNIX)
683#include <semaphore.h>
684typedef sem_t SEMAPHORE;
685#else
686#error not implemented on this platform
687#endif
688
689/**
690 * @ingroup Semaphore
691 */
692void sphore_init(SEMAPHORE *sem);
693/**
694 * @ingroup Semaphore
695 */
696void sphore_wait(SEMAPHORE *sem);
697/**
698 * @ingroup Semaphore
699 */
700void sphore_signal(SEMAPHORE *sem);
701/**
702 * @ingroup Semaphore
703 */
704void sphore_destroy(SEMAPHORE *sem);
705
706/**
707 * Time utilities.
708 *
709 * @defgroup Time Time
710 */
711
712/**
713 * Timestamp related functions.
714 *
715 * @defgroup Timestamp Timestamps
716 */
717
718/**
719 * @ingroup Time
720 */
721void set_new_tick();
722
723/**
724 * Fetches a sample from a high resolution timer.
725 *
726 * @ingroup Time
727 *
728 * @return Current value of the timer.
729 *
730 * @remark To know how fast the timer is ticking, see @link time_freq @endlink.
731 *
732 * @see time_freq
733 */
734int64_t time_get_impl();
735
736/**
737 * Fetches a sample from a high resolution timer.
738 *
739 * @ingroup Time
740 *
741 * @return Current value of the timer.
742 *
743 * @remark To know how fast the timer is ticking, see @link time_freq @endlink.
744 * @remark Uses @link time_get_impl @endlink to fetch the sample.
745 *
746 * @see time_freq time_get_impl
747 */
748int64_t time_get();
749
750/**
751 * @ingroup Time
752 *
753 * @return The frequency of the high resolution timer.
754 */
755int64_t time_freq();
756
757/**
758 * Retrieves the current time as a UNIX timestamp.
759 *
760 * @ingroup Timestamp
761 *
762 * @return The time as a UNIX timestamp.
763 */
764int64_t time_timestamp();
765
766/**
767 * Retrieves the hours since midnight (0..23).
768 *
769 * @ingroup Time
770 *
771 * @return The current hour of the day.
772 */
773int time_houroftheday();
774
775/**
776 * @ingroup Time
777 */
778enum ETimeSeason
779{
780 SEASON_SPRING = 0,
781 SEASON_SUMMER,
782 SEASON_AUTUMN,
783 SEASON_WINTER,
784 SEASON_EASTER,
785 SEASON_HALLOWEEN,
786 SEASON_XMAS,
787 SEASON_NEWYEAR
788};
789
790/**
791 * Retrieves the current season of the year.
792 *
793 * @ingroup Time
794 *
795 * @return One of the SEASON_* enum literals.
796 *
797 * @see SEASON_SPRING
798 */
799ETimeSeason time_season();
800
801/**
802 * @defgroup Network Networking
803 */
804
805/**
806 * @defgroup Network-General General networking
807 *
808 * @ingroup Network
809 */
810
811/**
812 * @ingroup Network-General
813 */
814extern const NETADDR NETADDR_ZEROED;
815
816#ifdef CONF_FAMILY_UNIX
817/**
818 * @ingroup Network-General
819 */
820typedef int UNIXSOCKET;
821/**
822 * @ingroup Network-General
823 */
824typedef struct sockaddr_un UNIXSOCKETADDR;
825#endif
826
827/**
828 * Initiates network functionality.
829 *
830 * @ingroup Network-General
831 *
832 * @remark You must call this function before using any other network functions.
833 */
834void net_init();
835
836/**
837 * Looks up the ip of a hostname.
838 *
839 * @ingroup Network-General
840 *
841 * @param hostname Host name to look up.
842 * @param addr The output address to write to.
843 * @param types The type of IP that should be returned.
844 *
845 * @return `0` on success.
846 */
847int net_host_lookup(const char *hostname, NETADDR *addr, int types);
848
849/**
850 * Compares two network addresses.
851 *
852 * @ingroup Network-General
853 *
854 * @param a Address to compare.
855 * @param b Address to compare to.
856 *
857 * @return `< 0` if address a is less than address b.
858 * @return `0` if address a is equal to address b.
859 * @return `> 0` if address a is greater than address b.
860 */
861int net_addr_comp(const NETADDR *a, const NETADDR *b);
862
863/**
864 * Compares two network addresses ignoring port.
865 *
866 * @ingroup Network-General
867 *
868 * @param a Address to compare.
869 * @param b Address to compare to.
870 *
871 * @return `< 0` if address a is less than address b.
872 * @return `0` if address a is equal to address b.
873 * @return `> 0` if address a is greater than address b.
874 */
875int net_addr_comp_noport(const NETADDR *a, const NETADDR *b);
876
877/**
878 * Turns a network address into a representative string.
879 *
880 * @ingroup Network-General
881 *
882 * @param addr Address to turn into a string.
883 * @param string Buffer to fill with the string.
884 * @param max_length Maximum size of the string.
885 * @param add_port Whether to add the port to the string.
886 *
887 * @remark The string will always be null-terminated.
888 */
889void net_addr_str(const NETADDR *addr, char *string, int max_length, bool add_port);
890
891/**
892 * Turns url string into a network address struct.
893 * The url format is tw-0.6+udp://{ipaddr}[:{port}]
894 * ipaddr: can be ipv4 or ipv6
895 * port: is a optional internet protocol port
896 *
897 * This format is used for parsing the master server, be careful before changing it.
898 *
899 * Examples:
900 * tw-0.6+udp://127.0.0.1
901 * tw-0.6+udp://127.0.0.1:8303
902 *
903 * @ingroup Network-General
904 *
905 * @param addr Address to fill in.
906 * @param string String to parse.
907 * @param host_buf Pointer to a buffer to write the host to
908 * It will include the port if one is included in the url
909 * It can also be set to `nullptr` then it will be ignored.
910 * @param host_buf_size Size of the host buffer or 0 if no host_buf pointer is given.
911 *
912 * @return `0` on success.
913 * @return `> 0` if the input wasn't a valid DDNet URL,
914 * @return `< 0` if the input is a valid DDNet URL but the host part was not a valid IPv4/IPv6 address
915 */
916int net_addr_from_url(NETADDR *addr, const char *string, char *host_buf, size_t host_buf_size);
917
918/**
919 * Checks if an address is local.
920 *
921 * @ingroup Network-General
922 *
923 * @param addr Address to check.
924 *
925 * @return `true` if the address is local, `false` otherwise.
926 */
927bool net_addr_is_local(const NETADDR *addr);
928
929/**
930 * Turns string into a network address.
931 *
932 * @ingroup Network-General
933 *
934 * @param addr Address to fill in.
935 * @param string String to parse.
936 *
937 * @return `0` on success.
938 */
939int net_addr_from_str(NETADDR *addr, const char *string);
940
941/**
942 * Make a socket not block on operations
943 *
944 * @ingroup Network-General
945 *
946 * @param sock The socket to set the mode on.
947 *
948 * @returns `0` on success.
949 */
950int net_set_non_blocking(NETSOCKET sock);
951
952/**
953 * Make a socket block on operations.
954 *
955 * @param sock The socket to set the mode on.
956 *
957 * @returns `0` on success.
958 */
959int net_set_blocking(NETSOCKET sock);
960
961/**
962 * If a network operation failed, the error code.
963 *
964 * @ingroup Network-General
965 *
966 * @returns The error code.
967 */
968int net_errno();
969
970/**
971 * If a network operation failed, the platform-specific error code and string.
972 *
973 * @ingroup Network-General
974 *
975 * @returns The error code and string combined into one string.
976 */
977std::string net_error_message();
978
979/**
980 * Determines whether a network operation would block.
981 *
982 * @ingroup Network-General
983 *
984 * @returns `0` if wouldn't block, `1` if would block.
985 */
986int net_would_block();
987
988/**
989 * Waits for a socket to have data available to receive up the specified timeout duration.
990 *
991 * @ingroup Network-General
992 *
993 * @param sock Socket to wait on.
994 * @param nanoseconds Timeout duration to wait.
995 *
996 * @return `1` if data was received within the timeout duration, `0` otherwise.
997 */
998int net_socket_read_wait(NETSOCKET sock, std::chrono::nanoseconds nanoseconds);
999
1000/**
1001 * @defgroup Network-UDP UDP Networking
1002 *
1003 * @ingroup Network
1004 */
1005
1006/**
1007 * Determine a socket's type.
1008 *
1009 * @ingroup Network-General
1010 *
1011 * @param sock Socket whose type should be determined.
1012 *
1013 * @return The socket type, a bitset of `NETTYPE_IPV4`, `NETTYPE_IPV6`, `NETTYPE_WEBSOCKET_IPV4`
1014 * and `NETTYPE_WEBSOCKET_IPV6`, or `NETTYPE_INVALID` if the socket is invalid.
1015 */
1016int net_socket_type(NETSOCKET sock);
1017
1018/**
1019 * Creates a UDP socket and binds it to a port.
1020 *
1021 * @ingroup Network-UDP
1022 *
1023 * @param bindaddr Address to bind the socket to.
1024 *
1025 * @return On success it returns an handle to the socket. On failure it returns `nullptr`.
1026 */
1027NETSOCKET net_udp_create(NETADDR bindaddr);
1028
1029/**
1030 * Sends a packet over an UDP socket.
1031 *
1032 * @ingroup Network-UDP
1033 *
1034 * @param sock Socket to use.
1035 * @param addr Where to send the packet.
1036 * @param data Pointer to the packet data to send.
1037 * @param size Size of the packet.
1038 *
1039 * @return On success it returns the number of bytes sent. Returns `-1` on error.
1040 */
1041int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size);
1042
1043/**
1044 * Receives a packet over an UDP socket.
1045 *
1046 * @ingroup Network-UDP
1047 *
1048 * @param sock Socket to use.
1049 * @param addr Pointer to an NETADDR that will receive the address.
1050 * @param data Received data. Will be invalidated when this function is called again.
1051 *
1052 * @return On success it returns the number of bytes received. Returns `-1` on error.
1053 */
1054int net_udp_recv(NETSOCKET sock, NETADDR *addr, unsigned char **data);
1055
1056/**
1057 * Closes an UDP socket.
1058 *
1059 * @ingroup Network-UDP
1060 *
1061 * @param sock Socket to close.
1062 */
1063void net_udp_close(NETSOCKET sock);
1064
1065/**
1066 * @defgroup Network-TCP TCP Networking
1067 *
1068 * @ingroup Network
1069 */
1070
1071/**
1072 * Creates a TCP socket.
1073 *
1074 * @ingroup Network-TCP
1075 *
1076 * @param bindaddr Address to bind the socket to.
1077 *
1078 * @return On success it returns an handle to the socket. On failure it returns `nullptr`.
1079 */
1080NETSOCKET net_tcp_create(NETADDR bindaddr);
1081
1082/**
1083 * Makes the socket start listening for new connections.
1084 *
1085 * @ingroup Network-TCP
1086 *
1087 * @param sock Socket to start listen to.
1088 * @param backlog Size of the queue of incoming connections to keep.
1089 *
1090 * @return `0` on success.
1091 */
1092int net_tcp_listen(NETSOCKET sock, int backlog);
1093
1094/**
1095 * Polls a listening socket for a new connection.
1096 *
1097 * @ingroup Network-TCP
1098 *
1099 * @param sock Listening socket to poll.
1100 * @param new_sock Pointer to a socket to fill in with the new socket.
1101 * @param addr Pointer to an address that will be filled in the remote address, can be `nullptr`.
1102 *
1103 * @return A non-negative integer on success. Negative integer on failure.
1104 */
1105int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *addr);
1106
1107/**
1108 * Connects one socket to another.
1109 *
1110 * @ingroup Network-TCP
1111 *
1112 * @param sock Socket to connect.
1113 * @param addr Address to connect to.
1114 *
1115 * @return `0` on success.
1116 *
1117 */
1118int net_tcp_connect(NETSOCKET sock, const NETADDR *addr);
1119
1120/**
1121 * Connect a socket to a TCP address without blocking.
1122 *
1123 * @ingroup Network-TCP
1124 *
1125 * @param sock The socket to connect with.
1126 * @param bindaddr The address to connect to.
1127 *
1128 * @returns `0` on success.
1129 */
1130int net_tcp_connect_non_blocking(NETSOCKET sock, NETADDR bindaddr);
1131
1132/**
1133 * Sends data to a TCP stream.
1134 *
1135 * @ingroup Network-TCP
1136 *
1137 * @param sock Socket to send data to.
1138 * @param data Pointer to the data to send.
1139 * @param size Size of the data to send.
1140 *
1141 * @return Number of bytes sent. Negative value on failure.
1142 */
1143int net_tcp_send(NETSOCKET sock, const void *data, int size);
1144
1145/**
1146 * Receives data from a TCP stream.
1147 *
1148 * @ingroup Network-TCP
1149 *
1150 * @param sock Socket to recvive data from.
1151 * @param data Pointer to a buffer to write the data to.
1152 * @param maxsize Maximum of data to write to the buffer.
1153 *
1154 * @return Number of bytes recvived. Negative value on failure. When in
1155 * non-blocking mode, it returns 0 when there is no more data to be fetched.
1156 */
1157int net_tcp_recv(NETSOCKET sock, void *data, int maxsize);
1158
1159/**
1160 * Closes a TCP socket.
1161 *
1162 * @ingroup Network-TCP
1163 *
1164 * @param sock Socket to close.
1165 */
1166void net_tcp_close(NETSOCKET sock);
1167
1168#if defined(CONF_FAMILY_UNIX)
1169/**
1170 * @defgroup Network-Unix-Sockets UNIX Socket Networking
1171 *
1172 * @ingroup Network
1173 */
1174
1175/**
1176 * Creates an unnamed unix datagram socket.
1177 *
1178 * @ingroup Network-Unix-Sockets
1179 *
1180 * @return On success it returns a handle to the socket. On failure it returns `-1`.
1181 */
1182UNIXSOCKET net_unix_create_unnamed();
1183
1184/**
1185 * Sends data to a Unix socket.
1186 *
1187 * @ingroup Network-Unix-Sockets
1188 *
1189 * @param sock Socket to use.
1190 * @param addr Where to send the packet.
1191 * @param data Pointer to the packet data to send.
1192 * @param size Size of the packet.
1193 *
1194 * @return Number of bytes sent. Negative value on failure.
1195 */
1196int net_unix_send(UNIXSOCKET sock, UNIXSOCKETADDR *addr, void *data, int size);
1197
1198/**
1199 * Sets the unixsocketaddress for a path to a socket file.
1200 *
1201 * @ingroup Network-Unix-Sockets
1202 *
1203 * @param addr Pointer to the `UNIXSOCKETADDR` to fill.
1204 * @param path Path to the (named) unix socket.
1205 */
1206void net_unix_set_addr(UNIXSOCKETADDR *addr, const char *path);
1207
1208/**
1209 * Closes a Unix socket.
1210 *
1211 * @ingroup Network-Unix-Sockets
1212 *
1213 * @param sock Socket to close.
1214 */
1215void net_unix_close(UNIXSOCKET sock);
1216
1217#endif
1218
1219/**
1220 * String related functions.
1221 *
1222 * @defgroup Strings Strings
1223 */
1224
1225/**
1226 * Performs printf formatting into a buffer.
1227 *
1228 * @ingroup Strings
1229 *
1230 * @param buffer Pointer to the buffer to receive the formatted string.
1231 * @param buffer_size Size of the buffer.
1232 * @param format printf formatting string.
1233 * @param args The variable argument list.
1234 *
1235 * @return Length of written string, even if it has been truncated.
1236 *
1237 * @remark See the C manual for syntax for the printf formatting string.
1238 * @remark The strings are treated as null-terminated strings.
1239 * @remark Guarantees that buffer string will contain null-termination.
1240 */
1241[[gnu::format(printf, 3, 0)]] int str_format_v(char *buffer, int buffer_size, const char *format, va_list args);
1242
1243/**
1244 * Performs printf formatting into a buffer.
1245 *
1246 * @ingroup Strings
1247 *
1248 * @param buffer Pointer to the buffer to receive the formatted string.
1249 * @param buffer_size Size of the buffer.
1250 * @param format printf formatting string.
1251 * @param ... Parameters for the formatting.
1252 *
1253 * @return Length of written string, even if it has been truncated.
1254 *
1255 * @remark See the C manual for syntax for the printf formatting string.
1256 * @remark The strings are treated as null-terminated strings.
1257 * @remark Guarantees that buffer string will contain null-termination.
1258 */
1259[[gnu::format(printf, 3, 4)]] int str_format(char *buffer, int buffer_size, const char *format, ...);
1260
1261#if !defined(CONF_DEBUG)
1262int str_format_int(char *buffer, size_t buffer_size, int value);
1263
1264template<typename... Args>
1265int str_format_opt(char *buffer, int buffer_size, const char *format, Args... args)
1266{
1267 static_assert(sizeof...(args) > 0, "Use str_copy instead of str_format without format arguments");
1268 return str_format(buffer, buffer_size, format, args...);
1269}
1270
1271template<>
1272inline int str_format_opt(char *buffer, int buffer_size, const char *format, int val) // NOLINT(readability-inconsistent-declaration-parameter-name)
1273{
1274 if(strcmp(format, "%d") == 0)
1275 {
1276 return str_format_int(buffer, buffer_size, val);
1277 }
1278 else
1279 {
1280 return str_format(buffer, buffer_size, format, val);
1281 }
1282}
1283
1284#define str_format str_format_opt
1285#endif
1286
1287/**
1288 * Computes the edit distance between two strings.
1289 *
1290 * @param a First string for the edit distance.
1291 * @param b Second string for the edit distance.
1292 *
1293 * @return The edit distance between the both strings.
1294 *
1295 * @remark The strings are treated as null-terminated strings.
1296 */
1297int str_utf8_dist(const char *a, const char *b);
1298
1299/**
1300 * Computes the edit distance between two strings, allows buffers
1301 * to be passed in.
1302 *
1303 * @ingroup Strings
1304 *
1305 * @param a First string for the edit distance.
1306 * @param b Second string for the edit distance.
1307 * @param buf Buffer for the function.
1308 * @param buf_len Length of the buffer, must be at least as long as
1309 * twice the length of both strings combined plus two.
1310 *
1311 * @return The edit distance between the both strings.
1312 *
1313 * @remark The strings are treated as null-terminated strings.
1314 */
1315int str_utf8_dist_buffer(const char *a, const char *b, int *buf, int buf_len);
1316
1317/**
1318 * Computes the edit distance between two strings, allows buffers
1319 * to be passed in.
1320 *
1321 * @ingroup Strings
1322 *
1323 * @param a First string for the edit distance.
1324 * @param a_len Length of the first string.
1325 * @param b Second string for the edit distance.
1326 * @param b_len Length of the second string.
1327 * @param buf Buffer for the function.
1328 * @param buf_len Length of the buffer, must be at least as long as
1329 * the length of both strings combined plus two.
1330 *
1331 * @return The edit distance between the both strings.
1332 *
1333 * @remark The strings are treated as null-terminated strings.
1334 */
1335int str_utf32_dist_buffer(const int *a, int a_len, const int *b, int b_len, int *buf, int buf_len);
1336
1337/**
1338 * Copies a timestamp in the format year-month-day_hour-minute-second to the string.
1339 *
1340 * @ingroup Timestamp
1341 *
1342 * @param buffer Pointer to a buffer that shall receive the timestamp string.
1343 * @param buffer_size Size of the buffer.
1344 *
1345 * @remark Guarantees that buffer string will contain null-termination.
1346 */
1347void str_timestamp(char *buffer, int buffer_size);
1348[[gnu::format(strftime, 3, 0)]] void str_timestamp_format(char *buffer, int buffer_size, const char *format);
1349[[gnu::format(strftime, 4, 0)]] void str_timestamp_ex(time_t time, char *buffer, int buffer_size, const char *format);
1350
1351/**
1352 * Parses a string into a timestamp following a specified format.
1353 *
1354 * @ingroup Timestamp
1355 *
1356 * @param string Pointer to the string to parse.
1357 * @param format The time format to use (for example `FORMAT_NOSPACE` below).
1358 * @param timestamp Pointer to the timestamp result.
1359 *
1360 * @return true on success, false if the string could not be parsed with the specified format
1361 */
1362[[gnu::format(strftime, 2, 0)]] bool timestamp_from_str(const char *string, const char *format, time_t *timestamp);
1363
1364#define FORMAT_TIME "%H:%M:%S"
1365#define FORMAT_SPACE "%Y-%m-%d %H:%M:%S"
1366#define FORMAT_NOSPACE "%Y-%m-%d_%H-%M-%S"
1367
1368enum
1369{
1370 TIME_DAYS,
1371 TIME_HOURS,
1372 TIME_MINS,
1373 TIME_HOURS_CENTISECS,
1374 TIME_MINS_CENTISECS,
1375 TIME_SECS_CENTISECS,
1376};
1377
1378/**
1379 * Formats a time string.
1380 *
1381 * @ingroup Timestamp
1382 *
1383 * @param centisecs Time in centiseconds.
1384 * @param format Format of the time string, see enum above, for example `TIME_DAYS`.
1385 * @param buffer Pointer to a buffer that shall receive the timestamp string.
1386 * @param buffer_size Size of the buffer.
1387 *
1388 * @return Number of bytes written, `-1` on invalid format or `buffer_size <= 0`.
1389 */
1390int str_time(int64_t centisecs, int format, char *buffer, int buffer_size);
1391
1392/**
1393 * Formats a time string.
1394 *
1395 * @ingroup Timestamp
1396 *
1397 * @param secs Time in seconds.
1398 * @param format Format of the time string, see enum above, for example `TIME_DAYS`.
1399 * @param buffer Pointer to a buffer that shall receive the timestamp string.
1400 * @param buffer_size Size of the buffer.
1401 *
1402 * @remark The time is rounded to the nearest centisecond.
1403 *
1404 * @return Number of bytes written, `-1` on invalid format or `buffer_size <= 0`.
1405 */
1406int str_time_float(float secs, int format, char *buffer, int buffer_size);
1407
1408/**
1409 * Utilities for accessing the file system.
1410 *
1411 * @defgroup Filesystem Filesystem
1412 */
1413
1414/**
1415 * Lists the files and folders in a directory.
1416 *
1417 * @ingroup Filesystem
1418 *
1419 * @param dir Directory to list.
1420 * @param cb Callback function to call for each entry.
1421 * @param type Type of the directory.
1422 * @param user Pointer to give to the callback.
1423 *
1424 * @remark The strings are treated as null-terminated strings.
1425 */
1426void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user);
1427
1428/**
1429 * Lists the files and folders in a directory and gets additional file information.
1430 *
1431 * @ingroup Filesystem
1432 *
1433 * @param dir Directory to list.
1434 * @param cb Callback function to call for each entry.
1435 * @param type Type of the directory.
1436 * @param user Pointer to give to the callback.
1437 *
1438 * @remark The strings are treated as null-terminated strings.
1439 */
1440void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int type, void *user);
1441
1442/**
1443 * Recursively creates parent directories for a file or directory.
1444 *
1445 * @ingroup Filesystem
1446 *
1447 * @param path File or directory for which to create parent directories.
1448 *
1449 * @return `0` on success. Negative value on failure.
1450 *
1451 * @remark The strings are treated as null-terminated strings.
1452 */
1453int fs_makedir_rec_for(const char *path);
1454
1455/**
1456 * Fetches per user configuration directory.
1457 *
1458 * @ingroup Filesystem
1459 *
1460 * @param appname Name of the application.
1461 * @param path Buffer that will receive the storage path.
1462 * @param max Size of the buffer.
1463 *
1464 * @return `0` on success. Negative value on failure.
1465 *
1466 * @remark Returns ~/.appname on UNIX based systems.
1467 * @remark Returns ~/Library/Applications Support/appname on macOS.
1468 * @remark Returns %APPDATA%/Appname on Windows based systems.
1469 *
1470 * @remark The strings are treated as null-terminated strings.
1471 */
1472int fs_storage_path(const char *appname, char *path, int max);
1473
1474/**
1475 * Checks if a file exists.
1476 *
1477 * @ingroup Filesystem
1478 *
1479 * @param path The path to check.
1480 *
1481 * @return `1` if a file with the given path exists.
1482 * @return `0` on failure or if the file does not exist.
1483 *
1484 * @remark The strings are treated as null-terminated strings.
1485 */
1486int fs_is_file(const char *path);
1487
1488/**
1489 * Checks if a folder exists.
1490 *
1491 * @ingroup Filesystem
1492 *
1493 * @param path The path to check.
1494 *
1495 * @return `1` if a folder with the given path exists.
1496 * @return `0` on failure or if the folder does not exist.
1497 *
1498 * @remark The strings are treated as null-terminated strings.
1499 */
1500int fs_is_dir(const char *path);
1501
1502/**
1503 * Checks whether a given path is relative or absolute.
1504 *
1505 * @ingroup Filesystem
1506 *
1507 * @param path Path to check.
1508 *
1509 * @return `1` if relative, `0` if absolute.
1510 *
1511 * @remark The strings are treated as null-terminated strings.
1512 */
1513int fs_is_relative_path(const char *path);
1514
1515/**
1516 * Changes the current working directory.
1517 *
1518 * @ingroup Filesystem
1519 *
1520 * @param path New working directory path.
1521 *
1522 * @return `0` on success. `1` on failure.
1523 *
1524 * @remark The strings are treated as null-terminated strings.
1525 */
1526int fs_chdir(const char *path);
1527
1528/**
1529 * Gets the current working directory.
1530 *
1531 * @ingroup Filesystem
1532 *
1533 * @param buffer Buffer that will receive the current working directory.
1534 * @param buffer_size Size of the buffer.
1535 *
1536 * @return Pointer to the buffer on success, `nullptr` on failure.
1537 *
1538 * @remark The strings are treated as null-terminated strings.
1539 */
1540char *fs_getcwd(char *buffer, int buffer_size);
1541
1542/**
1543 * Gets the name of a file or folder specified by a path,
1544 * i.e. the last segment of the path.
1545 *
1546 * @ingroup Filesystem
1547 *
1548 * @param path Path from which to retrieve the filename.
1549 *
1550 * @return Filename of the path.
1551 *
1552 * @remark Supports forward and backward slashes as path segment separator.
1553 * @remark No distinction between files and folders is being made.
1554 * @remark The strings are treated as null-terminated strings.
1555 */
1556const char *fs_filename(const char *path);
1557
1558/**
1559 * Splits a filename into name (without extension) and file extension.
1560 *
1561 * @ingroup Filesystem
1562 *
1563 * @param filename The filename to split.
1564 * @param name Buffer that will receive the name without extension, may be nullptr.
1565 * @param name_size Size of the name buffer (ignored if name is nullptr).
1566 * @param extension Buffer that will receive the extension, may be nullptr.
1567 * @param extension_size Size of the extension buffer (ignored if extension is nullptr).
1568 *
1569 * @remark Does NOT handle forward and backward slashes.
1570 * @remark No distinction between files and folders is being made.
1571 * @remark The strings are treated as null-terminated strings.
1572 */
1573void fs_split_file_extension(const char *filename, char *name, size_t name_size, char *extension = nullptr, size_t extension_size = 0);
1574
1575/**
1576 * Normalizes the given path: replaces backslashes with regular slashes
1577 * and removes trailing slashes.
1578 *
1579 * @ingroup Filesystem
1580 *
1581 * @param path Path to normalize.
1582 *
1583 * @remark The strings are treated as null-terminated strings.
1584 */
1585void fs_normalize_path(char *path);
1586
1587/**
1588 * Get the parent directory of a directory.
1589 *
1590 * @ingroup Filesystem
1591 *
1592 * @param path Path of the directory. The parent will be store in this buffer as well.
1593 *
1594 * @return `0` on success. `1` on failure.
1595 *
1596 * @remark The strings are treated as null-terminated strings.
1597 */
1598int fs_parent_dir(char *path);
1599
1600/**
1601 * Deletes a file.
1602 *
1603 * @ingroup Filesystem
1604 *
1605 * @param filename Path of the file to delete.
1606 *
1607 * @return `0` on success. `1` on failure.
1608 *
1609 * @remark The strings are treated as null-terminated strings.
1610 * @remark Returns an error if the path specifies a directory name.
1611 */
1612int fs_remove(const char *filename);
1613
1614/**
1615 * Renames the file or directory. If the paths differ the file will be moved.
1616 *
1617 * @ingroup Filesystem
1618 *
1619 * @param oldname The current path of a file or directory.
1620 * @param newname The new path for the file or directory.
1621 *
1622 * @return `0` on success. `1` on failure.
1623 *
1624 * @remark The strings are treated as null-terminated strings.
1625 */
1626int fs_rename(const char *oldname, const char *newname);
1627
1628/**
1629 * Gets the creation and the last modification date of a file or directory.
1630 *
1631 * @ingroup Filesystem
1632 *
1633 * @param name Path of a file or directory.
1634 * @param created Pointer where the creation time will be stored.
1635 * @param modified Pointer where the modification time will be stored.
1636 *
1637 * @return `0` on success. non-zero on failure.
1638 *
1639 * @remark The strings are treated as null-terminated strings.
1640 * @remark Returned time is in seconds since UNIX Epoch.
1641 */
1642int fs_file_time(const char *name, time_t *created, time_t *modified);
1643
1644/**
1645 * Swaps the endianness of data. Each element is swapped individually by reversing its bytes.
1646 *
1647 * @param data Pointer to data to be swapped.
1648 * @param elem_size Size in bytes of each element.
1649 * @param num Number of elements.
1650 *
1651 * @remark The caller must ensure that the data is at least `elem_size * num` bytes in size.
1652 */
1653void swap_endian(void *data, unsigned elem_size, unsigned num);
1654
1655void net_stats(NETSTATS *stats);
1656
1657int str_utf8_to_skeleton(const char *str, int *buf, int buf_len);
1658
1659/**
1660 * Checks if two strings only differ by confusable characters.
1661 *
1662 * @ingroup Strings
1663 *
1664 * @param str1 String to compare.
1665 * @param str2 String to compare.
1666 *
1667 * @return `0` if the strings are confusables.
1668 */
1669int str_utf8_comp_confusable(const char *str1, const char *str2);
1670
1671/**
1672 * Converts the given Unicode codepoint to lowercase (locale insensitive).
1673 *
1674 * @ingroup Strings
1675 *
1676 * @param code Unicode codepoint to convert.
1677 *
1678 * @return Lowercase codepoint, or the original codepoint if there is no lowercase version.
1679 */
1680int str_utf8_tolower_codepoint(int code);
1681
1682/**
1683 * Packs 4 big endian bytes into an unsigned.
1684 *
1685 * @param bytes Pointer to an array of bytes that will be packed.
1686 *
1687 * @return The packed unsigned.
1688 *
1689 * @remark Assumes the passed array is least 4 bytes in size.
1690 * @remark Assumes unsigned is 4 bytes in size.
1691 *
1692 * @see uint_to_bytes_be
1693 */
1694unsigned bytes_be_to_uint(const unsigned char *bytes);
1695
1696/**
1697 * Packs an unsigned into 4 big endian bytes.
1698 *
1699 * @param bytes Pointer to an array where the bytes will be stored.
1700 * @param value The values that will be packed into the array.
1701 *
1702 * @remark Assumes the passed array is least 4 bytes in size.
1703 * @remark Assumes unsigned is 4 bytes in size.
1704 *
1705 * @see bytes_be_to_uint
1706 */
1707void uint_to_bytes_be(unsigned char *bytes, unsigned value);
1708
1709/**
1710 * Shell, process management, OS specific functionality.
1711 *
1712 * @defgroup Shell Shell
1713 */
1714
1715/**
1716 * Returns the ID of the current process.
1717 *
1718 * @ingroup Shell
1719 *
1720 * @return PID of the current process.
1721 */
1722int pid();
1723
1724/**
1725 * Fixes the command line arguments to be encoded in UTF-8 on all systems.
1726 *
1727 * @ingroup Shell
1728 *
1729 * @param argc A pointer to the argc parameter that was passed to the main function.
1730 * @param argv A pointer to the argv parameter that was passed to the main function.
1731 *
1732 * @remark You need to call @link cmdline_free @endlink once you're no longer using the results.
1733 */
1734void cmdline_fix(int *argc, const char ***argv);
1735
1736/**
1737 * Frees memory that was allocated by @link cmdline_fix @endlink.
1738 *
1739 * @ingroup Shell
1740 *
1741 * @param argc The argc obtained from `cmdline_fix`.
1742 * @param argv The argv obtained from `cmdline_fix`.
1743 */
1744void cmdline_free(int argc, const char **argv);
1745
1746#if !defined(CONF_PLATFORM_ANDROID)
1747/**
1748 * Determines the initial window state when using @link shell_execute @endlink
1749 * to execute a process.
1750 *
1751 * @ingroup Shell
1752 *
1753 * @remark Currently only supported on Windows.
1754 */
1755enum class EShellExecuteWindowState
1756{
1757 /**
1758 * The process window is opened in the foreground and activated.
1759 */
1760 FOREGROUND,
1761
1762 /**
1763 * The process window is opened in the background without focus.
1764 */
1765 BACKGROUND,
1766};
1767
1768/**
1769 * Executes a given file.
1770 *
1771 * @ingroup Shell
1772 *
1773 * @param file The file to execute.
1774 * @param window_state The window state how the process window should be shown.
1775 * @param arguments Optional array of arguments to pass to the process.
1776 * @param num_arguments The number of arguments.
1777 *
1778 * @return Handle of the new process, or @link INVALID_PROCESS @endlink on error.
1779 */
1780PROCESS shell_execute(const char *file, EShellExecuteWindowState window_state, const char **arguments = nullptr, size_t num_arguments = 0);
1781
1782/**
1783 * Sends kill signal to a process.
1784 *
1785 * @ingroup Shell
1786 *
1787 * @param process Handle of the process to kill.
1788 *
1789 * @return `1` on success, `0` on error.
1790 */
1791int kill_process(PROCESS process);
1792
1793/**
1794 * Checks if a process is alive.
1795 *
1796 * @ingroup Shell
1797 *
1798 * @param process Handle/PID of the process.
1799 *
1800 * @return `true` if the process is currently running,
1801 * @return `false` if the process is not running (dead).
1802 */
1803bool is_process_alive(PROCESS process);
1804
1805/**
1806 * Opens a link in the browser.
1807 *
1808 * @ingroup Shell
1809 *
1810 * @param link The link to open in a browser.
1811 *
1812 * @return `1` on success, `0` on failure.
1813 *
1814 * @remark The strings are treated as null-terminated strings.
1815 * @remark This may not be called with untrusted input or it'll result in arbitrary code execution, especially on Windows.
1816 */
1817int open_link(const char *link);
1818
1819/**
1820 * Opens a file or directory with the default program.
1821 *
1822 * @ingroup Shell
1823 *
1824 * @param path The file or folder to open with the default program.
1825 *
1826 * @return `1` on success, `0` on failure.
1827 *
1828 * @remark The strings are treated as null-terminated strings.
1829 * @remark This may not be called with untrusted input or it'll result in arbitrary code execution, especially on Windows.
1830 */
1831int open_file(const char *path);
1832#endif // !defined(CONF_PLATFORM_ANDROID)
1833
1834/**
1835 * Secure random number generation.
1836 *
1837 * @defgroup Secure-Random Secure Random
1838 */
1839
1840/**
1841 * Generates a null-terminated password of length `2 * random_length`.
1842 *
1843 * @ingroup Secure-Random
1844 *
1845 * @param buffer Pointer to the start of the output buffer.
1846 * @param length Length of the buffer.
1847 * @param random Pointer to a randomly-initialized array of shorts.
1848 * @param random_length Length of the short array.
1849 */
1850void generate_password(char *buffer, unsigned length, const unsigned short *random, unsigned random_length);
1851
1852/**
1853 * Fills the buffer with the specified amount of random password characters.
1854 *
1855 * @ingroup Secure-Random
1856 *
1857 * @param buffer Pointer to the start of the buffer.
1858 * @param length Length of the buffer.
1859 * @param pw_length Length of the desired password.
1860 *
1861 * @remark The desired password length must be greater or equal to 6,
1862 * even and smaller or equal to 128.
1863 */
1864void secure_random_password(char *buffer, unsigned length, unsigned pw_length);
1865
1866/**
1867 * Fills the buffer with the specified amount of random bytes.
1868 *
1869 * @ingroup Secure-Random
1870 *
1871 * @param bytes Pointer to the start of the buffer.
1872 * @param length Length of the buffer.
1873 */
1874void secure_random_fill(void *bytes, unsigned length);
1875
1876/**
1877 * Returns random `int`.
1878 *
1879 * @ingroup Secure-Random
1880 *
1881 * @return Random int.
1882 *
1883 * @remark Can be used as a replacement for the `rand` function.
1884 */
1885int secure_rand();
1886
1887/**
1888 * Returns a random nonnegative integer below the given number,
1889 * with a uniform distribution.
1890 *
1891 * @ingroup Secure-Random
1892 *
1893 * @param below Upper limit (exclusive) of integers to return.
1894 *
1895 * @return Random nonnegative below the given number.
1896 */
1897int secure_rand_below(int below);
1898
1899/**
1900 * Returns a human-readable version string of the operating system.
1901 *
1902 * @ingroup Shell
1903 *
1904 * @param version Buffer to use for the output.
1905 * @param length Length of the output buffer.
1906 *
1907 * @return `true` on success, `false` on failure.
1908 */
1909bool os_version_str(char *version, size_t length);
1910
1911/**
1912 * Returns a string of the preferred locale of the user / operating system.
1913 * The string conforms to [RFC 3066](https://www.ietf.org/rfc/rfc3066.txt)
1914 * and only contains the characters `a`-`z`, `A`-`Z`, `0`-`9` and `-`.
1915 * If the preferred locale could not be determined this function
1916 * falls back to the locale `"en-US"`.
1917 *
1918 * @ingroup Shell
1919 *
1920 * @param locale Buffer to use for the output.
1921 * @param length Length of the output buffer.
1922 *
1923 * @remark The strings are treated as null-terminated strings.
1924 */
1925void os_locale_str(char *locale, size_t length);
1926
1927/**
1928 * @defgroup Crash-Dumping Crash Dumping
1929 */
1930
1931/**
1932 * Initializes the crash dumper and sets the filename to write the crash dump
1933 * to, if support for crash logging was compiled in. Otherwise does nothing.
1934 *
1935 * @ingroup Crash-Dumping
1936 *
1937 * @param log_file_path Absolute path to which crash log file should be written.
1938 */
1939void crashdump_init_if_available(const char *log_file_path);
1940
1941/**
1942 * Fetches a sample from a high resolution timer and converts it in nanoseconds.
1943 *
1944 * @ingroup Time
1945 *
1946 * @return Current value of the timer in nanoseconds.
1947 */
1948std::chrono::nanoseconds time_get_nanoseconds();
1949
1950/**
1951 * Fixes the command line arguments to be encoded in UTF-8 on all systems.
1952 * This is a RAII wrapper for @link cmdline_fix @endlink and @link cmdline_free @endlink.
1953 *
1954 * @ingroup Shell
1955 */
1956class CCmdlineFix
1957{
1958 int m_Argc;
1959 const char **m_ppArgv;
1960
1961public:
1962 CCmdlineFix(int *pArgc, const char ***pppArgv)
1963 {
1964 cmdline_fix(argc: pArgc, argv: pppArgv);
1965 m_Argc = *pArgc;
1966 m_ppArgv = *pppArgv;
1967 }
1968 ~CCmdlineFix()
1969 {
1970 cmdline_free(argc: m_Argc, argv: m_ppArgv);
1971 }
1972 CCmdlineFix(const CCmdlineFix &) = delete;
1973};
1974
1975#endif
1976