]> git.proxmox.com Git - mirror_lxc.git/blob - CODING_STYLE.md
CODING_STYLE: Mention kernel style in introduction
[mirror_lxc.git] / CODING_STYLE.md
1 LXC Coding Style Guide
2 ======================
3
4 In general the LXC project follows the Linux kernel coding style. There are
5 however are a few differences, these are outlined in this document.
6
7 The Linux kernel coding style guide can be found within the kernel tree:
8
9 Documentation/process/coding-style.rst
10
11 It can be accessed online too:
12
13 https://www.kernel.org/doc/html/latest/process/coding-style.html
14
15 #### General Notes
16
17 - The coding style guide refers to new code. But legacy code can be cleaned up
18 and we are happy to take those patches.
19 - Just because there is still code in LXC that doesn't adhere to the coding
20 standards outlined here does not license not adhering to the coding style. In
21 other words: please stick to the coding style.
22 - Maintainers are free to ignore rules specified here when merging pull
23 requests. This guideline might seem a little weird but it exits to ease new
24 developers into the code base and to prevent unnecessary bikeshedding. If
25 a maintainer feels hat enforcing a specific rule in a given commit would do
26 more harm than good they should always feel free to ignore the rule.
27
28 Furthermore, when merging pull requests that do not adhere to our coding
29 style maintainers should feel free to grab the commit, adapt it to our coding
30 style and add their Signed-off-by line to it. This is especially helpful to
31 make it easier for first-time contributors and to prevent having pull
32 requests being stuck in the merge queue because of minor details.
33 - We currently do not provide automatic coding style checks but if a suitable
34 tool is found we are happy to integrate it into our test suite. It is
35 possible and recommended to use the `clang-format` binary to check your code.
36 The following options are an approximation of the coding style used here.
37 Simply create a file called `.clang-format` in your home directory with the
38 following options:
39 ```sh
40 cat << EOF > "${HOME}"/.clang-format
41 AlignEscapedNewlines: Left
42 BreakBeforeBraces: Attach
43 AlwaysBreakBeforeMultilineStrings: false
44 BreakBeforeBinaryOperators: None
45 MaxEmptyLinesToKeep: 1
46 PenaltyBreakBeforeFirstCallParameter: 1000000
47 BinPackArguments: true
48 BinPackParameters: true
49 AllowAllParametersOfDeclarationOnNextLine: false
50 AlignAfterOpenBracket: true
51 SpacesInSquareBrackets: false
52 SpacesInCStyleCastParentheses: false
53 SpaceInEmptyParentheses: false
54 SpaceBeforeParens: ControlStatements
55 SpaceAfterCStyleCast: false
56 SortIncludes: true
57 PenaltyReturnTypeOnItsOwnLine: 10000
58 PenaltyExcessCharacter: 10
59 Language: Cpp
60 ForEachMacros: ['lxc_list_for_each', 'lxc_list_for_each_safe']
61 AllowShortLoopsOnASingleLine: false
62 AllowShortIfStatementsOnASingleLine: false
63 AllowShortFunctionsOnASingleLine: None
64 AllowShortCaseLabelsOnASingleLine: false
65 AllowShortBlocksOnASingleLine: false
66 BasedOnStyle: LLVM
67 TabWidth: 8
68 IndentWidth: 8
69 UseTab: Always
70 BreakBeforeBraces: Linux
71 AllowShortIfStatementsOnASingleLine: false
72 IndentCaseLabels: false
73 EOF
74 ```
75 However, it will not handle all cases correctly. For example, most `struct`
76 initializations will not be correct. In such cases please refer to the coding
77 style here.
78
79 #### Only Use Tabs
80
81 - LXC uses tabs.
82
83 #### Only use `/* */` Style Comments
84
85 - Any comments that are added must use `/* */`.
86 - All comments should start on the same line as the opening `/*`.
87 - Single-line comments should simply be placed between `/* */`. For example:
88 ```C
89 /* Define pivot_root() if missing from the C library */
90 ```
91 - Multi-line comments should end with the closing `*/` on a separate line. For
92 example:
93 ```C
94 /* At this point the old-root is mounted on top of our new-root
95 * To unmounted it we must not be chdir()ed into it, so escape back
96 * to old-root.
97 */
98 ```
99
100 #### Try To Wrap At 80chars
101
102 - This is not strictly enforced. It is perfectly valid to sometimes
103 overflow this limit if it helps clarity. Nonetheless, try to stick to it
104 and use common sense to decide when not to.
105
106 #### Error Messages
107
108 - Error messages must start with a capital letter and must **not** end with a
109 punctuation sign.
110 - They should be descriptive, without being needlessly long. It is best to just
111 use already existing error messages as examples.
112 - Examples of acceptable error messages are:
113 ```C
114 SYSERROR("Failed to create directory \"%s\"", path);
115 WARN("\"/dev\" directory does not exist. Proceeding without autodev being set up");
116 ```
117
118 #### Return Error Codes
119
120 - When writing a function that can fail in a non-binary way try to return
121 meaningful negative error codes (e.g. `return -EINVAL;`).
122
123 #### All Unexported Functions Must Be Declared `static`
124
125 - Functions which are only used in the current file and are not exported
126 within the codebase need to be declared with the `static` attribute.
127
128 #### All Exported Functions Must Be Declared `extern` In A Header File
129
130 - Functions which are used in different files in the library should be declared
131 in a suitable `*.c` file and exposed in a suitable `*.h` file. When defining
132 the function in the `*.c` file the function signature should not be preceded
133 by the `extern` keyword. When declaring the function signature in the `*.h`
134 file it must be preceded by the `extern` keyword. For example:
135 ```C
136 /* Valid function definition in a *.c file */
137 ssize_t lxc_write_nointr(int fd, const void* buf, size_t count)
138 {
139 ssize_t ret;
140 again:
141 ret = write(fd, buf, count);
142 if (ret < 0 && errno == EINTR)
143 goto again;
144 return ret;
145 }
146
147 /* Valid function declaration in a *.h file */
148 extern ssize_t lxc_write_nointr(int fd, const void* buf, size_t count);
149 ```
150
151 #### All Names Must Be In lower_case
152
153 - All functions and variable names must use lower case.
154
155 #### Declaring Variables
156
157 - variables should be declared at the top of the function or at the beginning
158 of a new scope but **never** in the middle of a scope
159 1. uninitialized variables
160 - put base types before complex types
161 - put standard types defined by libc before types defined by LXC
162 - put multiple declarations of the same type on the same line
163 2. initialized variables
164 - put base types before complex types
165 - put standard types defined by libc before types defined by LXC
166 - put multiple declarations of the same type on the same line
167 - Examples of good declarations can be seen in the following function:
168 ```C
169 int lxc_clear_procs(struct lxc_conf *c, const char *key)
170 {
171 struct lxc_list *it, *next;
172 bool all = false;
173 const char *k = NULL;
174
175 if (strcmp(key, "lxc.proc") == 0)
176 all = true;
177 else if (strncmp(key, "lxc.proc.", sizeof("lxc.proc.") - 1) == 0)
178 k = key + sizeof("lxc.proc.") - 1;
179 else
180 return -1;
181
182 lxc_list_for_each_safe(it, &c->procs, next) {
183 struct lxc_proc *proc = it->elem;
184
185 if (!all && strcmp(proc->filename, k) != 0)
186 continue;
187 lxc_list_del(it);
188 free(proc->filename);
189 free(proc->value);
190 free(proc);
191 free(it);
192 }
193
194 return 0;
195 }
196 ```
197
198 #### Single-line `if` blocks should not be enclosed in `{}`
199
200 - This also affects `if-else` ladders if and only if all constituting
201 conditions are
202 single-line conditions. If there is at least one non-single-line
203 condition `{}` must be used.
204 - For example:
205 ```C
206 /* no brackets needed */
207 if (size > INT_MAX)
208 return -EFBIG;
209
210 /* The else branch has more than one-line and so needs {}. This entails that
211 * the if branch also needs to have {}.
212 */
213 if ( errno == EROFS ) {
214 WARN("Warning: Read Only file system while creating %s", path);
215 } else {
216 SYSERROR("Error creating %s", path);
217 return -1;
218 }
219
220 /* also fine */
221 for (i = 0; list[i]; i++)
222 if (strcmp(list[i], entry) == 0)
223 return true;
224
225 /* also fine */
226 if (ret < 0)
227 WARN("Failed to set FD_CLOEXEC flag on slave fd %d of "
228 "pty device \"%s\": %s", pty_info->slave,
229 pty_info->name, strerror(errno));
230
231 /* also fine */
232 if (ret == 0)
233 for (i = 0; i < sizeof(limit_opt)/sizeof(limit_opt[0]); ++i) {
234 if (strcmp(res, limit_opt[i].name) == 0)
235 return limit_opt[i].value;
236 }
237 ```
238
239 #### Functions Not Returning Booleans Must Assign Return Value Before Performing Checks
240
241 - When checking whether a function not returning booleans was successful or not
242 the returned value must be assigned before it is checked (`str{n}cmp()`
243 functions being one notable exception). For example:
244 ```C
245 /* assign value to "ret" first */
246 ret = mount(sourcepath, cgpath, "cgroup", remount_flags, NULL);
247 /* check whether function was successful */
248 if (ret < 0) {
249 SYSERROR("Failed to remount \"%s\" ro", cgpath);
250 free(sourcepath);
251 return -1;
252 }
253 ```
254 Functions returning booleans can be checked directly. For example:
255 ```C
256 extern bool lxc_string_in_array(const char *needle, const char **haystack);
257
258 /* check right away */
259 if (lxc_string_in_array("ns", (const char **)h->subsystems))
260 continue;
261 ```
262
263 #### Non-Boolean Functions That Behave Like Boolean Functions Must Explicitly Check Against A Value
264
265 - This rule mainly exists for `str{n}cmp()` type functions. In most cases they
266 are used like a boolean function to check whether a string matches or not.
267 But they return an integer. It is perfectly fine to check `str{n}cmp()`
268 functions directly but you must compare explicitly against a value. That is
269 to say, while they are conceptually boolean functions they shouldn't be
270 treated as such since they don't really behave like boolean functions. So
271 `if (!str{n}cmp())` and `if (str{n}cmp())` checks must not be used. Good
272 examples are found in the following functions:
273 ```C
274 static int set_config_hooks(const char *key, const char *value,
275 struct lxc_conf *lxc_conf, void *data)
276
277 char *copy;
278
279 if (lxc_config_value_empty(value))
280 return lxc_clear_hooks(lxc_conf, key);
281
282 if (strcmp(key + 4, "hook") == 0) {
283 ERROR("lxc.hook must not have a value");
284 return -1;
285 }
286
287 copy = strdup(value);
288 if (!copy)
289 return -1;
290
291 if (strcmp(key + 9, "pre-start") == 0)
292 return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
293 else if (strcmp(key + 9, "start-host") == 0)
294 return add_hook(lxc_conf, LXCHOOK_START_HOST, copy);
295 else if (strcmp(key + 9, "pre-mount") == 0)
296 return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy);
297 else if (strcmp(key + 9, "autodev") == 0)
298 return add_hook(lxc_conf, LXCHOOK_AUTODEV, copy);
299 else if (strcmp(key + 9, "mount") == 0)
300 return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
301 else if (strcmp(key + 9, "start") == 0)
302 return add_hook(lxc_conf, LXCHOOK_START, copy);
303 else if (strcmp(key + 9, "stop") == 0)
304 return add_hook(lxc_conf, LXCHOOK_STOP, copy);
305 else if (strcmp(key + 9, "post-stop") == 0)
306 return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
307 else if (strcmp(key + 9, "clone") == 0)
308 return add_hook(lxc_conf, LXCHOOK_CLONE, copy);
309 else if (strcmp(key + 9, "destroy") == 0)
310 return add_hook(lxc_conf, LXCHOOK_DESTROY, copy);
311
312 free(copy);
313 return -1;
314 }
315 ```
316
317 #### Do Not Use C99 Variable Length Arrays (VLA)
318
319 - They are made optional and there is no guarantee that future C standards
320 will support them.
321
322 #### Use Standard libc Macros When Exiting
323
324 - libc provides `EXIT_FAILURE` and `EXIT_SUCCESS`. Use them whenever possible
325 in the child of `fork()`ed process or when exiting from a `main()` function.
326
327 #### Use `goto`s
328
329 `goto`s are an essential language construct of C and are perfect to perform
330 cleanup operations or simplify the logic of functions. However, here are the
331 rules to use them:
332 - use descriptive `goto` labels.
333 For example, if you know that this label is only used as an error path you
334 should use something like `on_error` instead of `out` as label name.
335 - **only** jump downwards unless you are handling `EAGAIN` errors and want to
336 avoid `do-while` constructs.
337 - An example of a good usage of `goto` is:
338 ```C
339 static int set_config_idmaps(const char *key, const char *value,
340 struct lxc_conf *lxc_conf, void *data)
341 {
342 unsigned long hostid, nsid, range;
343 char type;
344 int ret;
345 struct lxc_list *idmaplist = NULL;
346 struct id_map *idmap = NULL;
347
348 if (lxc_config_value_empty(value))
349 return lxc_clear_idmaps(lxc_conf);
350
351 idmaplist = malloc(sizeof(*idmaplist));
352 if (!idmaplist)
353 goto on_error;
354
355 idmap = malloc(sizeof(*idmap));
356 if (!idmap)
357 goto on_error;
358 memset(idmap, 0, sizeof(*idmap));
359
360 ret = parse_idmaps(value, &type, &nsid, &hostid, &range);
361 if (ret < 0) {
362 ERROR("Failed to parse id mappings");
363 goto on_error;
364 }
365
366 INFO("Read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range);
367 if (type == 'u')
368 idmap->idtype = ID_TYPE_UID;
369 else if (type == 'g')
370 idmap->idtype = ID_TYPE_GID;
371 else
372 goto on_error;
373
374 idmap->hostid = hostid;
375 idmap->nsid = nsid;
376 idmap->range = range;
377 idmaplist->elem = idmap;
378 lxc_list_add_tail(&lxc_conf->id_map, idmaplist);
379
380 if (!lxc_conf->root_nsuid_map && idmap->idtype == ID_TYPE_UID)
381 if (idmap->nsid == 0)
382 lxc_conf->root_nsuid_map = idmap;
383
384
385 if (!lxc_conf->root_nsgid_map && idmap->idtype == ID_TYPE_GID)
386 if (idmap->nsid == 0)
387 lxc_conf->root_nsgid_map = idmap;
388
389 idmap = NULL;
390
391 return 0;
392
393 on_error:
394 free(idmaplist);
395 free(idmap);
396
397 return -1;
398 }
399 ```
400
401 #### Use Booleans instead of integers
402
403 - When something can be conceptualized in a binary way use a boolean not
404 an integer.
405
406 #### Cleanup Functions Must Handle The Object's Null Type And Being Passed Already Cleaned Up Objects
407
408 - If you implement a custom cleanup function to e.g. free a complex type
409 you declared you must ensure that the object's null type is handled and
410 treated as a NOOP. For example:
411 ```C
412 void lxc_free_array(void **array, lxc_free_fn element_free_fn)
413 {
414 void **p;
415 for (p = array; p && *p; p++)
416 element_free_fn(*p);
417 free((void*)array);
418 }
419 ```
420 - Cleanup functions should also expect to be passed already cleaned up objects.
421 One way to handle this cleanly is to initialize the cleaned up variable to
422 a special value that signals the function that the element has already been
423 freed on the next call. For example, the following function cleans up file
424 descriptors and sets the already closed file descriptors to `-EBADF`. On the
425 next call it can simply check whether the file descriptor is positive and
426 move on if it isn't:
427 ```C
428 static void lxc_put_attach_clone_payload(struct attach_clone_payload *p)
429 {
430 if (p->ipc_socket >= 0) {
431 shutdown(p->ipc_socket, SHUT_RDWR);
432 close(p->ipc_socket);
433 p->ipc_socket = -EBADF;
434 }
435
436 if (p->pty_fd >= 0) {
437 close(p->pty_fd);
438 p->pty_fd = -EBADF;
439 }
440
441 if (p->init_ctx) {
442 lxc_proc_put_context_info(p->init_ctx);
443 p->init_ctx = NULL;
444 }
445 }
446 ```
447
448 ### Cast to `(void)` When Intentionally Ignoring Return Values
449
450 - There are cases where you do not care about the return value of a function.
451 Please cast the return value to `(void)` when doing so.
452 - Standard library functions or functions which are known to be ignored by
453 default do not need to be cast to `(void)`. Classical candidates are
454 `close()` and `fclose()`.
455 - A good example is:
456 ```C
457 for (i = 0; hierarchies[i]; i++) {
458 char *fullpath;
459 char *path = hierarchies[i]->fullcgpath;
460
461 ret = chowmod(path, destuid, nsgid, 0755);
462 if (ret < 0)
463 return -1;
464
465 /* failures to chown() these are inconvenient but not
466 * detrimental we leave these owned by the container launcher,
467 * so that container root can write to the files to attach. we
468 * chmod() them 664 so that container systemd can write to the
469 * files (which systemd in wily insists on doing).
470 */
471
472 if (hierarchies[i]->version == cgroup_super_magic) {
473 fullpath = must_make_path(path, "tasks", null);
474 (void)chowmod(fullpath, destuid, nsgid, 0664);
475 free(fullpath);
476 }
477
478 fullpath = must_make_path(path, "cgroup.procs", null);
479 (void)chowmod(fullpath, destuid, 0, 0664);
480 free(fullpath);
481
482 if (hierarchies[i]->version != cgroup2_super_magic)
483 continue;
484
485 fullpath = must_make_path(path, "cgroup.subtree_control", null);
486 (void)chowmod(fullpath, destuid, nsgid, 0664);
487 free(fullpath);
488
489 fullpath = must_make_path(path, "cgroup.threads", null);
490 (void)chowmod(fullpath, destuid, nsgid, 0664);
491 free(fullpath);
492 }
493 ```
494
495 #### Use `for (;;)` instead of `while (1)` or `while (true)`
496
497 - Let's be honest, it is really the only sensible way to do this.
498
499 #### Use The Set Of Supported DCO Statements
500
501 - Signed-off-by: Random J Developer <random@developer.org>
502 - You did write this code or have the right to contribute it to LXC.
503 - Acked-by: Random J Developer <random@developer.org>
504 - You did read the code and think it is correct. This is usually only used by
505 maintainers or developers that have made significant contributions and can
506 vouch for the correctness of someone else's code.
507 - Reviewed-by: Random J Developer <random@developer.org>
508 - You did review the code and vouch for its correctness, i.e. you'd be
509 prepared to fix bugs it might cause. This is usually only used by
510 maintainers or developers that have made significant contributions and can
511 vouch for the correctness of someone else's code.
512 - Co-developed-by: Random J Developer <random@developer.org>
513 - The code can not be reasonably attributed to a single developer, i.e.
514 you worked on this together.
515 - Tested-by: Random J Developer <random@developer.org>
516 - You verified that the code fixes a given bug or is behaving as advertised.
517 - Reported-by: Random J Developer <random@developer.org>
518 - You found and reported the bug.
519 - Suggested-by: Random J Developer <random@developer.org>
520 - You wrote the code but someone contributed the idea. This line is usually
521 overlooked but it is a sign of good etiquette and coding ethics: if someone
522 helped you solve a problem or had a clever idea do not silently claim it by
523 slapping your Signed-off-by underneath. Be honest and add a Suggested-by.
524
525 #### Commit Message Outline
526
527 - You **must** stick to the 80chars limit especially in the title of the commit
528 message.
529 - Please use English commit messages only.
530 - use meaningful commit messages.
531 - Use correct spelling and grammar.
532 If you are not a native speaker and/or feel yourself struggling with this it
533 is perfectly fine to point this out and there's no need to apologize. Usually
534 developers will be happy to pull your branch and adopt the commit message.
535 - Please always use the affected file (without the file type suffix) or module
536 as a prefix in the commit message.
537 - Examples of good commit messages are:
538 ```Diff
539 commit b87243830e3b5e95fa31a17cf1bfebe55353bf13
540 Author: Felix Abecassis <fabecassis@nvidia.com>
541 Date: Fri Feb 2 06:19:13 2018 -0800
542
543 hooks: change the semantic of NVIDIA_VISIBLE_DEVICES=""
544
545 With LXC, you can override the value of an environment variable to
546 null, but you can't unset an existing variable.
547
548 The NVIDIA hook was previously activated when NVIDIA_VISIBLE_DEVICES
549 was set to null. As a result, it was not possible to disable the hook
550 by overriding the environment variable in the configuration.
551
552 The hook can now be disabled by setting NVIDIA_VISIBLE_DEVICES to
553 null or to the new special value "void".
554
555 Signed-off-by: Felix Abecassis <fabecassis@nvidia.com>
556
557
558 commit d6337a5f9dc7311af168aa3d586fdf239f5a10d3
559 Author: Christian Brauner <christian.brauner@ubuntu.com>
560 Date: Wed Jan 31 16:25:11 2018 +0100
561
562 cgroups: get controllers on the unified hierarchy
563
564 Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
565
566 ```
567 #### Use `_exit()` To Terminate `fork()`ed Child Processes
568
569 - When `fork()`ing off a child process use `_exit()` to terminate it instead of
570 `exit()`. The `exit()` function is not thread-safe and thus not suited for
571 the shared library which must ensure that it is thread-safe.
572
573 #### Keep Arrays of `struct`s Aligned Horizontally When Initializing
574
575 - Arrays of `struct`s are:
576 ```C
577 struct foo_struct {
578 int n;
579 int m;
580 int p;
581 };
582
583 struct foo_struct new_instance[] = {
584 { 1, 2, 3 },
585 { 4, 5, 6 },
586 { 7, 8, 9 },
587 };
588 ```
589 - Leave a single space after the opening `{` and before closing `}` of the
590 largest member of the last column.
591 - Always leave a single space between the largest member of the current column
592 and the member in the next column.
593 - A good example is
594 ```C
595 struct signame {
596 int num;
597 const char *name;
598 };
599
600 static const struct signame signames[] = {
601 { SIGHUP, "HUP" },
602 { SIGINT, "INT" },
603 { SIGQUIT, "QUIT" },
604 { SIGILL, "ILL" },
605 { SIGABRT, "ABRT" },
606 { SIGFPE, "FPE" },
607 { SIGKILL, "KILL" },
608 { SIGSEGV, "SEGV" },
609 { SIGPIPE, "PIPE" },
610 { SIGALRM, "ALRM" },
611 { SIGTERM, "TERM" },
612 { SIGUSR1, "USR1" },
613 { SIGUSR2, "USR2" },
614 { SIGCHLD, "CHLD" },
615 { SIGCONT, "CONT" },
616 { SIGSTOP, "STOP" },
617 { SIGTSTP, "TSTP" },
618 { SIGTTIN, "TTIN" },
619 { SIGTTOU, "TTOU" },
620 #ifdef SIGTRAP
621 { SIGTRAP, "TRAP" },
622 #endif
623 #ifdef SIGIOT
624 { SIGIOT, "IOT" },
625 #endif
626 #ifdef SIGEMT
627 { SIGEMT, "EMT" },
628 #endif
629 #ifdef SIGBUS
630 { SIGBUS, "BUS" },
631 #endif
632 #ifdef SIGSTKFLT
633 { SIGSTKFLT, "STKFLT" },
634 #endif
635 #ifdef SIGCLD
636 { SIGCLD, "CLD" },
637 #endif
638 #ifdef SIGURG
639 { SIGURG, "URG" },
640 #endif
641 #ifdef SIGXCPU
642 { SIGXCPU, "XCPU" },
643 #endif
644 #ifdef SIGXFSZ
645 { SIGXFSZ, "XFSZ" },
646 #endif
647 #ifdef SIGVTALRM
648 { SIGVTALRM, "VTALRM" },
649 #endif
650 #ifdef SIGPROF
651 { SIGPROF, "PROF" },
652 #endif
653 #ifdef SIGWINCH
654 { SIGWINCH, "WINCH" },
655 #endif
656 #ifdef SIGIO
657 { SIGIO, "IO" },
658 #endif
659 #ifdef SIGPOLL
660 { SIGPOLL, "POLL" },
661 #endif
662 #ifdef SIGINFO
663 { SIGINFO, "INFO" },
664 #endif
665 #ifdef SIGLOST
666 { SIGLOST, "LOST" },
667 #endif
668 #ifdef SIGPWR
669 { SIGPWR, "PWR" },
670 #endif
671 #ifdef SIGUNUSED
672 { SIGUNUSED, "UNUSED" },
673 #endif
674 #ifdef SIGSYS
675 { SIGSYS, "SYS" },
676 #endif
677 };
678 ```
679
680 #### Use `strlcpy()` instead of `strncpy()`
681
682 When copying strings always use `strlcpy()` instead of `strncpy()`. The
683 advantage of `strlcpy()` is that it will always append a `\0` byte to the
684 string.
685
686 Unless you have a valid reason to accept truncation you must check whether
687 truncation has occurred, treat it as an error, and handle the error
688 appropriately.
689
690 #### Use `strlcat()` instead of `strncat()`
691
692 When concatenating strings always use `strlcat()` instead of `strncat()`. The
693 advantage of `strlcat()` is that it will always append a `\0` byte to the
694 string.
695
696 Unless you have a valid reason to accept truncation you must check whether
697 truncation has occurred, treat it as an error, and handle the error
698 appropriately.