1 /*
2  * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4.
3  * Copyright (C) 2013-2021 Gary V. Vaughan
4  * Copyright (C) 2010-2013 Reuben Thomas <rrt@sc3d.org>
5  * Copyright (C) 2008-2010 Natanael Copa <natanael.copa@gmail.com>
6  * Clean up and bug fixes by Leo Razoumov <slonik.az@gmail.com> 2006-10-11
7  * Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br> 07 Apr 2006 23:17:49
8  * Based on original by Claudio Terra for Lua 3.x.
9  * With contributions by Roberto Ierusalimschy.
10  * With documentation from Steve Donovan 2012
11  */
12 /***
13  Unix Standard APIs.
14 
15  Where the underlying system does not support one of these functions, it
16  will have a `nil` value in the module table.
17 
18 @module posix.unistd
19 */
20 
21 #if HAVE_CRYPT_H
22 #  include <crypt.h>
23 #endif
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <grp.h>
27 #include <pwd.h>
28 #include <unistd.h>
29 
30 #include "_helpers.c"
31 
32 static uid_t
mygetuid(lua_State * L,int i)33 mygetuid(lua_State *L, int i)
34 {
35 	if (lua_isnoneornil(L, i))
36 		return (uid_t)-1;
37 	else if (lua_isinteger(L, i))
38 		return (uid_t) lua_tointeger(L, i);
39 	else if (lua_isstring(L, i))
40 	{
41 		struct passwd *p = getpwnam(lua_tostring(L, i));
42 		return (p == NULL) ? (uid_t) -1 : p->pw_uid;
43 	}
44 	else
45 		return argtypeerror(L, i, "int, string or nil");
46 }
47 
48 static gid_t
mygetgid(lua_State * L,int i)49 mygetgid(lua_State *L, int i)
50 {
51 	if (lua_isnoneornil(L, i))
52 		return (gid_t)-1;
53 	else if (lua_isinteger(L, i))
54 		return (gid_t) lua_tointeger(L, i);
55 	else if (lua_isstring(L, i))
56 	{
57 		struct group *g = getgrnam(lua_tostring(L, i));
58 		return (g == NULL) ? (uid_t) -1 : g->gr_gid;
59 	}
60 	else
61 		return argtypeerror(L, i, "int, string or nil");
62 }
63 
64 /***
65 Terminate the calling process.
66 @function _exit
67 @int status process exit status
68 @see _exit(2)
69 */
70 static int
P_exit(lua_State * L)71 P_exit(lua_State *L)
72 {
73 	pid_t ret = checkint(L, 1);
74 	checknargs(L, 1);
75 	_exit(ret);
76 	return 0; /* Avoid a compiler warning (or possibly cause one
77 		     if the compiler's too clever, sigh). */
78 }
79 
80 
81 /***
82 Check real user's permissions for a file.
83 @function access
84 @string path file to act on
85 @string[opt="f"] mode can contain 'r','w','x' and 'f'
86 @treturn[1] int `0`, if successful
87 @return[2] nil
88 @treturn[2] string error message
89 @treturn[2] int errnum
90 @see access(2)
91 @usage
92   local unistd = require "posix.unistd"
93   status, errstr, errno = unistd.access("/etc/passwd", "rw")
94 */
95 static int
Paccess(lua_State * L)96 Paccess(lua_State *L)
97 {
98 	int mode=F_OK;
99 	const char *path=luaL_checkstring(L, 1);
100 	const char *s;
101 	checknargs(L, 2);
102 	for (s=optstring(L, 2, "f"); *s!=0 ; s++)
103 		switch (*s)
104 		{
105 			case ' ': break;
106 			case 'r': mode |= R_OK; break;
107 			case 'w': mode |= W_OK; break;
108 			case 'x': mode |= X_OK; break;
109 			case 'f': mode |= F_OK; break;
110 			default: badoption(L, 2, "mode", *s); break;
111 		}
112 	return pushresult(L, access(path, mode), path);
113 }
114 
115 
116 /***
117 Schedule an alarm signal.
118 @function alarm
119 @int seconds number of seconds to send SIGALRM in
120 @return int number of seconds remaining in previous alarm or `0`
121 @see alarm(2)
122 @usage
123   local unistd = require "posix.unistd"
124   seconds = unistd.alarm(10)
125 */
126 static int
Palarm(lua_State * L)127 Palarm(lua_State *L)
128 {
129 	int seconds = checkint(L, 1);
130 	checknargs(L, 1);
131 	return pushintresult(alarm(seconds));
132 }
133 /***
134 Set the working directory.
135 @function chdir
136 @string path file to act on
137 @treturn[1] int `0`, if successful
138 @return[2] nil
139 @treturn[2] string error message
140 @treturn[2] int errnum
141 @see chdir(2)
142 @usage
143   local unistd = require "posix.unistd"
144   status, errstr, errno = unistd.chdir ("/var/tmp")
145 */
146 static int
Pchdir(lua_State * L)147 Pchdir(lua_State *L)
148 {
149 	const char *path = luaL_checkstring(L, 1);
150 	checknargs(L, 1);
151 	return pushresult(L, chdir(path), path);
152 }
153 
154 
155 /***
156 Change ownership of a file.
157 @function chown
158 @string path existing file path
159 @tparam string|int uid new owner user id
160 @tparam string|int gid new owner group id
161 @treturn[1] int `0`, if successful
162 @return[2] nil
163 @treturn[2] string error messoge
164 @treturn[2] int errnum
165 @see chown(2)
166 @usage
167   local unistd = require "posix.unistd"
168   -- will fail for a normal user, and print an error
169   print(unistd.chown ("/etc/passwd", 100, 200))
170 */
171 static int
Pchown(lua_State * L)172 Pchown(lua_State *L)
173 {
174 	const char *path = luaL_checkstring(L, 1);
175 	uid_t uid = mygetuid(L, 2);
176 	gid_t gid = mygetgid(L, 3);
177 	checknargs(L, 3);
178 	return pushresult(L, chown(path, uid, gid), path);
179 }
180 
181 
182 /***
183 Close an open file descriptor.
184 @function close
185 @int fd file descriptor to act on
186 @treturn[1] int `0`, if successful
187 @return[2] nil
188 @treturn[2] string error message
189 @treturn[2] int errnum
190 @see close(2)
191 @usage
192   local unistd = require "posix.unistd"
193   local ok, errmsg = unistd.close (log)
194   if not ok then error (errmsg) end
195 */
196 static int
Pclose(lua_State * L)197 Pclose(lua_State *L)
198 {
199 	int fd = checkint(L, 1);
200 	checknargs(L, 1);
201 	return pushresult(L, close(fd), NULL);
202 }
203 
204 
205 #if defined HAVE_CRYPT
206 /***
207 Encrypt a password.
208 Not recommended for general encryption purposes.
209 @function crypt
210 @string trypass string to hash
211 @string salt two-character string from [a-zA-Z0-9./]
212 @return encrypted string
213 @see crypt(3)
214 @usage
215   local pwd = require "posix.pwd"
216   local unistd = require "posix.unistd"
217 
218   local salt, hash = pwd.pwent:match ":$6$(.-)$([^:]+)"
219   if unistd.crypt (trypass, salt) ~= hash then
220     error "wrong password"
221   end
222 */
223 static int
Pcrypt(lua_State * L)224 Pcrypt(lua_State *L)
225 {
226 	const char *str, *salt;
227 	char *r;
228 
229 	str = luaL_checkstring(L, 1);
230 	salt = luaL_checkstring(L, 2);
231 	if (strlen(salt) < 2)
232 		luaL_error(L, "not enough salt");
233 	checknargs(L, 2);
234 
235 	r = crypt(str, salt);
236 	return pushstringresult(r);
237 }
238 #endif
239 
240 
241 /***
242 Duplicate an open file descriptor.
243 @function dup
244 @int fd file descriptor to act on
245 @treturn[1] int new file descriptor duplicating *fd*, if successful
246 @return[2] nil
247 @treturn[2] string error message
248 @treturn[2] int errnum
249 @see dup(2)
250 @usage
251   local stdio = require "posix.stdio"
252   local unistd = require "posix.unistd"
253 
254   outfd = unistd.dup (stdio.fileno (io.stdout))
255 */
256 static int
Pdup(lua_State * L)257 Pdup(lua_State *L)
258 {
259 	int fd = checkint(L, 1);
260 	checknargs(L, 1);
261 	return pushresult(L, dup(fd), NULL);
262 }
263 
264 
265 /***
266 Duplicate one open file descriptor to another.
267 If *newfd* references an open file already, it is closed before being
268 reallocated to *fd*.
269 @function dup2
270 @int fd an open file descriptor to act on
271 @int newfd new descriptor to duplicate *fd*
272 @treturn[1] int new file descriptor, if successful
273 @return[2] nil
274 @treturn[2] string error message
275 @treturn[2] int errnum
276 @see dup2(2)
277 */
278 static int
Pdup2(lua_State * L)279 Pdup2(lua_State *L)
280 {
281 	int fd = checkint(L, 1);
282 	int newfd = checkint(L, 2);
283 	checknargs(L, 2);
284 	return pushresult(L, dup2(fd, newfd), NULL);
285 }
286 
287 
288 static int
runexec(lua_State * L,int use_shell)289 runexec(lua_State *L, int use_shell)
290 {
291 	char **argv;
292 	const char *path = luaL_checkstring(L, 1);
293 	int i, n;
294 	checknargs(L, 2);
295 
296 	if (lua_type(L, 2) != LUA_TTABLE)
297 		argtypeerror(L, 2, "table");
298 
299 	n = lua_objlen(L, 2);
300 	argv = lua_newuserdata(L, (n + 2) * sizeof(char*));
301 
302 	/* Set argv[0], defaulting to command */
303 	argv[0] = (char*) path;
304 	lua_pushinteger(L, 0);
305 	lua_gettable(L, 2);
306 	if (lua_type(L, -1) == LUA_TSTRING)
307 		argv[0] = (char*)lua_tostring(L, -1);
308 	else
309 		lua_pop(L, 1);
310 
311 	/* Read argv[1..n] from table. */
312 	for (i=1; i<=n; i++)
313 	{
314 		lua_pushinteger(L, i);
315 		lua_gettable(L, 2);
316 		argv[i] = (char*)lua_tostring(L, -1);
317 	}
318 	argv[n+1] = NULL;
319 
320 	(use_shell ? execvp : execv) (path, argv);
321 	return pusherror(L, path);
322 }
323 
324 
325 /***
326 Execute a program at exactly *path*.
327 @function exec
328 @string path
329 @tparam table argt arguments (table can include index 0)
330 @return nil
331 @treturn string error message
332 @treturn int errnum
333 @see execve(2)
334 @usage exec ("/bin/bash", {[0] = "-sh", "--norc"})
335 */
336 static int
Pexec(lua_State * L)337 Pexec(lua_State *L)
338 {
339 	return runexec(L, 0);
340 }
341 
342 
343 /***
344 Execute a program found using command PATH search, like the shell.
345 @function execp
346 @string path
347 @tparam table argt arguments (table can include index 0)
348 @return nil
349 @treturn string error message
350 @treturn int errnum
351 @see execve(2)
352 */
353 static int
Pexecp(lua_State * L)354 Pexecp(lua_State *L)
355 {
356 	return runexec(L, 1);
357 }
358 
359 
360 #if HAVE_FDATASYNC
361 
362 #if !HAVE_DECL_FDATASYNC
363 extern int fdatasync ();
364 #endif
365 
366 /***
367 Synchronize a file's in-core state with storage device without metadata.
368 @function fdatasync
369 @int fd
370 @treturn[1] int `0`, if successful
371 @return[2] nil
372 @treturn[2] string error message
373 @treturn[2] int errnum
374 @see fdatasync(2)
375 */
376 static int
Pfdatasync(lua_State * L)377 Pfdatasync(lua_State *L)
378 {
379   int fd = checkint(L, 1);
380   checknargs(L, 1);
381   return pushresult(L, fdatasync(fd), NULL);
382 }
383 #endif
384 
385 
386 /***
387 Fork this program.
388 @function fork
389 @treturn[1] int `0` in the resulting child process
390 @treturn[2] int process id of child, in the calling process
391 @return[3] nil
392 @treturn[3] string error message
393 @treturn[3] int errnum
394 @see fork(2)
395 @see fork.lua
396 @see fork2.lua
397 @usage
398   local unistd = require "posix.unistd"
399 
400   local pid, errmsg = unistd.fork ()
401   if pid == nil then
402     error (errmsg)
403   elseif pid == 0 then
404     print ("in child:", unistd.getpid "pid")
405   else
406     print (require "posix.sys.wait".wait (pid))
407   end
408   os.exit ()
409 */
410 static int
Pfork(lua_State * L)411 Pfork(lua_State *L)
412 {
413 	checknargs(L, 0);
414 	return pushresult(L, fork(), NULL);
415 }
416 
417 
418 /***
419 Synchronize a file's in-core state with storage device.
420 @function fsync
421 @int fd
422 @treturn[1] int `0`, if successful
423 @return[2] nil
424 @treturn[2] string error message
425 @treturn[2] int errnum
426 @see fsync(2)
427 @see sync
428 */
429 static int
Pfsync(lua_State * L)430 Pfsync(lua_State *L)
431 {
432   int fd = checkint(L, 1);
433   checknargs(L, 1);
434   return pushresult(L, fsync(fd), NULL);
435 }
436 
437 
438 /***
439 Current working directory for this process.
440 @function getcwd
441 @treturn[1] string path of current working directory, if successful
442 @return[2] nil
443 @treturn[2] string error message
444 @treturn[2] int errnum
445 @see getcwd(3)
446 */
447 static int
Pgetcwd(lua_State * L)448 Pgetcwd(lua_State *L)
449 {
450 #ifdef __GNU__
451 	char *b = get_current_dir_name();
452 	checknargs(L, 0);
453 	if (b == NULL)
454 		/* we return the same error as below */
455 		return pusherror(L, ".");
456 	return pushstringresult(b);
457 #else
458 	long size = pathconf(".", _PC_PATH_MAX);
459 	void *ud;
460 	lua_Alloc lalloc;
461 	char *b, *r;
462 	checknargs(L, 0);
463 	lalloc = lua_getallocf(L, &ud);
464 	if (size == -1)
465 		size = _POSIX_PATH_MAX; /* FIXME: Retry if this is not long enough */
466 	if ((b = lalloc(ud, NULL, 0, (size_t)size + 1)) == NULL)
467 		return pusherror(L, "lalloc");
468 	r = getcwd(b, (size_t)size);
469 	if (r != NULL)
470 		lua_pushstring(L, b);
471 	lalloc(ud, b, (size_t)size + 1, 0);
472 	return (r == NULL) ? pusherror(L, ".") : 1;
473 #endif
474 }
475 
476 
477 /***
478 Return effective group id of calling process.
479 @function getegid
480 @treturn int effective group id of calling process
481 @see getgid
482 */
483 static int
Pgetegid(lua_State * L)484 Pgetegid(lua_State *L)
485 {
486 	checknargs(L, 0);
487 	return pushintresult(getegid ());
488 }
489 
490 
491 /***
492 Return effective user id of calling process.
493 @function geteuid
494 @treturn int effective user id of calling process
495 @see getuid
496 */
497 static int
Pgeteuid(lua_State * L)498 Pgeteuid(lua_State *L)
499 {
500 	checknargs(L, 0);
501 	return pushintresult(geteuid ());
502 }
503 
504 
505 /***
506 Return group id of calling process.
507 @function getgid
508 @treturn int group id of calling process
509 @see getegid
510 */
511 static int
Pgetgid(lua_State * L)512 Pgetgid(lua_State *L)
513 {
514 	checknargs(L, 0);
515 	return pushintresult(getgid ());
516 }
517 
518 
519 #if LPOSIX_2001_COMPLIANT
520 /***
521 Get list of supplementary group ids.
522 @function getgroups
523 @treturn[1] table group id, if successful
524 @return[2] nil
525 @treturn[2] string error message
526 @treturn[2] int errnum
527 @see getgroups(2)
528 */
529 static int
Pgetgroups(lua_State * L)530 Pgetgroups(lua_State *L)
531 {
532 	int n_group_slots = getgroups(0, NULL);
533 	checknargs(L, 0);
534 
535 	if (n_group_slots < 0)
536 		return pusherror(L, NULL);
537 	else if (n_group_slots == 0)
538 		lua_newtable(L);
539 	else
540 	{
541 		gid_t  *group;
542 		int     n_groups;
543 		int     i;
544 
545 		group = lua_newuserdata(L, sizeof(*group) * n_group_slots);
546 
547 		n_groups = getgroups(n_group_slots, group);
548 		if (n_groups < 0)
549 			return pusherror(L, NULL);
550 
551 		lua_createtable(L, n_groups, 0);
552 		for (i = 0; i < n_groups; i++)
553 		{
554 			lua_pushinteger(L, group[i]);
555 			lua_rawseti(L, -2, i + 1);
556 		}
557 	}
558 
559 	return 1;
560 }
561 #endif
562 
563 
564 /***
565 Current logged-in user.
566 @treturn[1] string username, if successful
567 @return[2] nil
568 @see getlogin(3)
569 */
570 static int
Pgetlogin(lua_State * L)571 Pgetlogin(lua_State *L)
572 {
573 	checknargs(L, 0);
574 	return pushstringresult(getlogin());
575 }
576 
577 
578 static int
iter_getopt(lua_State * L)579 iter_getopt(lua_State *L)
580 {
581 	int r, argc = lua_tointeger(L, lua_upvalueindex(1));
582 	char **argv = (char **)lua_touserdata(L, lua_upvalueindex(3));
583 	char c;
584 
585 	if (argv == NULL) /* If we have already completed, return now. */
586 		return 0;
587 
588 	/* Fetch upvalues to pass to getopt. */
589 	r = getopt(argc, argv, lua_tostring(L, lua_upvalueindex(2)));
590 	if (r == -1)
591 		return 0;
592 
593 	c = (char) r;
594 	lua_pushlstring(L, &c, 1);
595 	lua_pushstring(L, optarg);
596 	lua_pushinteger(L, optind);
597 	return 3;
598 }
599 
600 
601 /***
602 Parse command-line options.
603 @function getopt
604 @param arg command line arguments
605 @string opts short option specifier
606 @int[opt=0] opterr index of the option with an error
607 @int[opt=1] optind index of the next unprocessed option
608 @treturn option iterator, returning 3 values
609 @see getopt(3)
610 @see getopt.lua
611 @usage
612 local getopt = require "posix.getopt".getopt
613 for opt, opterr, i in getopt (arg, "ho:v", opterr, i) do
614   process (arg, opterr, i)
615 end
616 */
617 static int
Pgetopt(lua_State * L)618 Pgetopt(lua_State *L)
619 {
620 	int argc, i;
621 	const char *optstring;
622 	char **argv;
623 
624 	checknargs(L, 4);
625 	checktype(L, 1, LUA_TTABLE, "list");
626 	optstring = luaL_checkstring(L, 2);
627 	opterr = optint(L, 3, 0);
628 	optind = optint(L, 4, 1);
629 
630 	argc = (int)lua_objlen(L, 1) + 1;
631 
632 	lua_pushinteger(L, argc);
633 	lua_pushstring(L, optstring);
634 
635 	argv = lua_newuserdata(L, (argc + 1) * sizeof(char *));
636 	argv[argc] = NULL;
637 	for (i = 0; i < argc; i++)
638 	{
639 		lua_pushinteger(L, i);
640 		lua_gettable(L, 1);
641 		argv[i] = (char *)luaL_checkstring(L, -1);
642 	}
643 
644 	/* Push remaining upvalues, and make and push closure. */
645 	lua_pushcclosure(L, iter_getopt, 3 + argc);
646 
647 	return 1;
648 }
649 
650 
651 /***
652 Return process group id of calling process.
653 @function getpgrp
654 @treturn int process group id of calling process
655 @see getpid
656 */
657 static int
Pgetpgrp(lua_State * L)658 Pgetpgrp(lua_State *L)
659 {
660 	checknargs(L, 0);
661 	return pushintresult(getpgrp ());
662 }
663 
664 
665 /***
666 Return process id of calling process.
667 @function getpid
668 @treturn int process id of calling process
669 */
670 static int
Pgetpid(lua_State * L)671 Pgetpid(lua_State *L)
672 {
673 	checknargs(L, 0);
674 	return pushintresult(getpid ());
675 }
676 
677 
678 /***
679 Return parent process id of calling process.
680 @function getppid
681 @treturn int parent process id of calling process
682 @see getpid
683 */
684 static int
Pgetppid(lua_State * L)685 Pgetppid(lua_State *L)
686 {
687 	checknargs(L, 0);
688 	return pushintresult(getppid ());
689 }
690 
691 
692 /***
693 Return user id of calling process.
694 @function getuid
695 @treturn int user id of calling process
696 @see geteuid
697 */
698 static int
Pgetuid(lua_State * L)699 Pgetuid(lua_State *L)
700 {
701 	checknargs(L, 0);
702 	return pushintresult(getuid ());
703 }
704 
705 
706 /***
707 Get host id.
708 @function gethostid
709 @treturn[1] int host id, if successful
710 @return[2] nil
711 @treturn[2] string error message
712 @see gethostid(3)
713 */
714 static int
Pgethostid(lua_State * L)715 Pgethostid(lua_State *L)
716 {
717 	checknargs(L, 0);
718 #if HAVE_GETHOSTID
719 	return pushintresult(gethostid());
720 #else
721 	lua_pushnil(L);
722 	lua_pushliteral(L, "unsupported by this host");
723 	return 2;
724 #endif
725 }
726 
727 
728 /***
729 Test whether a file descriptor refers to a terminal.
730 @function isatty
731 @int fd file descriptor to act on
732 @treturn[1] int `1` if *fd* is open and refers to a terminal, if successful
733 @return[2] nil
734 @treturn[2] string error message
735 @treturn[2] int errnum
736 @see isatty(3)
737 */
738 static int
Pisatty(lua_State * L)739 Pisatty(lua_State *L)
740 {
741 	int fd = checkint(L, 1);
742 	checknargs(L, 1);
743 	return pushresult(L, isatty(fd) == 0 ? -1 : 1, "isatty");
744 }
745 
746 
747 #if LPOSIX_2001_COMPLIANT
748 /***
749 This is like `chown`, but does not dereference symbolic links.
750 In other words, if a file is a symlink, then it changes ownership of the
751 symlink itself.
752 @function lchown
753 @string path existing file path
754 @tparam string|int uid new owner user id
755 @tparam string|int gid new owner group id
756 @treturn[1] int `0`, if successful
757 @return[2] nil
758 @treturn[2] string error messoge
759 @treturn[2] int errnum
760 @see lchown(2)
761 @usage
762   local unistd = require "posix.unistd"
763   -- will fail for a normal user, and print an error
764   print(unistd.lchown ("/etc/passwd", 100, 200))
765 */
766 static int
Plchown(lua_State * L)767 Plchown(lua_State *L)
768 {
769 	const char *path = luaL_checkstring(L, 1);
770 	uid_t uid = mygetuid(L, 2);
771 	gid_t gid = mygetgid(L, 3);
772 	checknargs(L, 3);
773 	return pushresult(L, lchown(path, uid, gid), path);
774 }
775 #endif
776 
777 
778 /***
779 Create a link.
780 @function link
781 @string target name
782 @string link name
783 @bool[opt=false] soft link
784 @treturn[1] int `0`, if successful
785 @return[2] nil
786 @treturn[2] string error message
787 @treturn[2] int errnum
788 @see link(2)
789 @see symlink(2)
790 */
791 static int
Plink(lua_State * L)792 Plink(lua_State *L)
793 {
794 	const char *oldpath = luaL_checkstring(L, 1);
795 	const char *newpath = luaL_checkstring(L, 2);
796 	int symbolicp = optboolean(L, 3, 0);
797 	checknargs(L, 3);
798 	return pushresult(L, (symbolicp ? symlink : link)(oldpath, newpath), NULL);
799 }
800 
801 
802 /***
803 Create a link at specified directory.
804 @function linkat
805 @int targetdir fd
806 @string target name
807 @int linkdir fd
808 @string link name
809 @int flags
810 @treturn[1] int `0`, if successful
811 @return[2] nil
812 @treturn[2] string error message
813 @treturn[2] int errnum
814 @see linkat(2)
815 */
816 static int
Plinkat(lua_State * L)817 Plinkat(lua_State *L)
818 {
819 	int olddirfd = checkint(L, 1);
820 	const char *oldpath = luaL_checkstring(L, 2);
821 	int newdirfd = checkint(L, 3);
822 	const char *newpath = luaL_checkstring(L, 4);
823 	int flags = checkint(L, 5);
824 	checknargs(L, 5);
825 	return pushresult(L, linkat(olddirfd, oldpath, newdirfd, newpath, flags), NULL);
826 }
827 
828 
829 /***
830 reposition read/write file offset
831 @function lseek
832 @int fd open file descriptor to act on
833 @int offset bytes to seek
834 @int whence one of `SEEK_SET`, `SEEK_CUR` or `SEEK_END`
835 @treturn[1] int new offset, if successful
836 @return[2] nil
837 @treturn[2] string error message
838 @treturn[2] int errnum
839 @see lseek(2)
840 */
841 static int
Plseek(lua_State * L)842 Plseek(lua_State *L)
843 {
844 	int fd = checkint(L, 1);
845 	int offset = checkint(L, 2);
846 	int whence = checkint(L, 3);
847 	checknargs(L, 3);
848 	return pushresult(L, lseek(fd, offset, whence), NULL);
849 }
850 
851 
852 /***
853 change process priority
854 @function nice
855 @int inc adds inc to the nice value for the calling process
856 @treturn[1] int new nice value, if successful
857 @return[2] nil
858 @return[2] string error message
859 @treturn[2] int errnum
860 @see nice(2)
861 */
862 static int
Pnice(lua_State * L)863 Pnice(lua_State *L)
864 {
865 	int inc = checkint(L, 1);
866 	checknargs(L, 1);
867 	return pushresult(L, nice(inc), "nice");
868 }
869 
870 
871 /***
872 Get a value for a configuration option for a filename.
873 @function pathconf
874 @string path optional
875 @int key one of `_PC_LINK_MAX`, `_PC_MAX_CANON`, `_PC_NAME_MAX`,
876   `_PC_PIPE_BUF`, `_PC_CHOWN_RESTRICTED`, `_PC_NO_TRUNC` or
877   `_PC_VDISABLE`
878 @treturn int associated path configuration value
879 @see pathconf(3)
880 @usage
881   local unistd = require "posix.unistd"
882   for a, b in pairs (unistd.pathconf "/dev/tty") do print(a, b) end
883 */
884 static int
Ppathconf(lua_State * L)885 Ppathconf(lua_State *L)
886 {
887 	const char *path = luaL_checkstring(L, 1);
888 	checknargs(L, 2);
889 	return pushintresult(pathconf(path, checkint(L, 2)));
890 }
891 
892 
893 /***
894 Creates a pipe.
895 @function pipe
896 @treturn[1] int read end file descriptor
897 @treturn[1] int write end file descriptor, if successful
898 @return[2] nil
899 @treturn[2] string error message
900 @treturn[2] int errnum
901 @see pipe(2)
902 @see fork.lua
903 */
904 static int
Ppipe(lua_State * L)905 Ppipe(lua_State *L)
906 {
907 	int pipefd[2];
908 	int rc;
909 	checknargs(L, 0);
910 	rc = pipe(pipefd);
911 	if (rc < 0)
912 		return pusherror(L, "pipe");
913 	lua_pushinteger(L, pipefd[0]);
914 	lua_pushinteger(L, pipefd[1]);
915 	return 2;
916 }
917 
918 
919 /***
920 Read bytes from a file.
921 @function read
922 @int fd the file descriptor to act on
923 @int count maximum number of bytes to read
924 @treturn[1] string string from *fd* with at most *count* bytes, if successful
925 @return[2] nil
926 @treturn[2] string error message
927 @treturn[2] int errnum
928 @see read(2)
929 */
930 static int
Pread(lua_State * L)931 Pread(lua_State *L)
932 {
933 	int fd = checkint(L, 1);
934 	int count = checkint(L, 2), ret;
935 	void *ud, *buf;
936 	lua_Alloc lalloc;
937 
938 	checknargs(L, 2);
939 	lalloc = lua_getallocf(L, &ud);
940 
941 	/* Reset errno in case lalloc doesn't set it */
942 	errno = 0;
943 	if ((buf = lalloc(ud, NULL, 0, count)) == NULL && count > 0)
944 		return pusherror(L, "lalloc");
945 
946 	ret = read(fd, buf, count);
947 	if (ret >= 0)
948 		lua_pushlstring(L, buf, ret);
949 	lalloc(ud, buf, count, 0);
950 	return (ret < 0) ? pusherror(L, NULL) : 1;
951 }
952 
953 
954 /***
955 Read value of a symbolic link.
956 @function readlink
957 @string path file to act on
958 @treturn[1] string link target, if successful
959 @return[2] nil
960 @treturn[2] string error message
961 @treturn[2] int errnum
962 @see readlink(2)
963 */
964 static int
Preadlink(lua_State * L)965 Preadlink(lua_State *L)
966 {
967 	char *b;
968 	struct stat s;
969 	const char *path = luaL_checkstring(L, 1);
970 	void *ud;
971 	lua_Alloc lalloc;
972 	ssize_t n, bufsiz;
973 	int err;
974 	checknargs(L, 1);
975 	lalloc = lua_getallocf(L, &ud);
976 
977 	errno = 0; /* ignore outstanding unreported errors */
978 
979 	/* s.st_size is length of linkname, with no trailing \0 */
980 	if (lstat(path, &s) < 0)
981 		return pusherror(L, path);
982 
983 	/* diagnose non-symlinks */
984 	if (!S_ISLNK(s.st_mode))
985 	{
986 		lua_pushnil(L);
987 		lua_pushfstring(L, "%s: not a symbolic link", path);
988 		lua_pushinteger(L, EINVAL);
989 		return 3;
990 	}
991 
992 	/* allocate a buffer for linkname, with no trailing \0 */
993 	bufsiz = s.st_size > 0 ? s.st_size : PATH_MAX;
994 	if ((b = lalloc(ud, NULL, 0, bufsiz)) == NULL)
995 		return pusherror(L, "lalloc");
996 
997 	n = readlink(path, b, bufsiz);
998 	err = errno; /* save readlink error code, if any */
999 	if (n > 0)
1000 		lua_pushlstring(L, b, n);
1001 	lalloc(ud, b, bufsiz, 0);
1002 
1003 	/* report new errors from this function */
1004 	if (n < 0)
1005 	{
1006 		errno = err; /* restore readlink error code */
1007 		return pusherror(L, "readlink");
1008 	}
1009 	else if (n < s.st_size)
1010 	{
1011 		lua_pushnil(L);
1012 		lua_pushfstring(L, "%s: readlink wrote only %d of %d bytes", path, n, s.st_size);
1013 		return 2;
1014 	}
1015 
1016 	return 1;
1017 }
1018 
1019 
1020 /***
1021 Remove a directory.
1022 @function rmdir
1023 @string path file to act on
1024 @treturn[1] int `0`, if successful
1025 @return[2] nil
1026 @treturn[2] string error message
1027 @treturn[2] int errnum
1028 @see rmdir(2)
1029 */
1030 static int
Prmdir(lua_State * L)1031 Prmdir(lua_State *L)
1032 {
1033 	const char *path = luaL_checkstring(L, 1);
1034 	checknargs(L, 1);
1035 	return pushresult(L, rmdir(path), path);
1036 }
1037 
1038 
1039 /***
1040 Set the uid, euid, gid, egid, sid or pid & gid.
1041 @function setpid
1042 @string what one of 'u', 'U', 'g', 'G', 's', 'p' (upper-case means "effective")
1043 @int id (uid, gid or pid for every value of `what` except 's')
1044 @int[opt] gid (only for `what` value 'p')
1045 @treturn[1] int `0`, if successful
1046 @return[2] nil
1047 @treturn[2] string error message
1048 @treturn[2] int errnum
1049 @see setuid(2)
1050 @see seteuid(2)
1051 @see setgid(2)
1052 @see setegid(2)
1053 @see setsid(2)
1054 @see setpgid(2)
1055 */
1056 static int
Psetpid(lua_State * L)1057 Psetpid(lua_State *L)
1058 {
1059 	const char *what=luaL_checkstring(L, 1);
1060 	checknargs(L, *what == 'p' ? 3 : 2);
1061 	switch (*what)
1062 	{
1063 		case 'U':
1064 			return pushresult(L, seteuid(mygetuid(L, 2)), NULL);
1065 		case 'u':
1066 			return pushresult(L, setuid(mygetuid(L, 2)), NULL);
1067 		case 'G':
1068 			return pushresult(L, setegid(mygetgid(L, 2)), NULL);
1069 		case 'g':
1070 			return pushresult(L, setgid(mygetgid(L, 2)), NULL);
1071 		case 's':
1072 			return pushresult(L, setsid(), NULL);
1073 		case 'p':
1074 		{
1075 			pid_t pid  = checkint(L, 2);
1076 			pid_t pgid = checkint(L, 3);
1077 			return pushresult(L, setpgid(pid,pgid), NULL);
1078 		}
1079 		default:
1080 			badoption(L, 1, "id", *what);
1081 			return 0;
1082 	}
1083 }
1084 
1085 
1086 /***
1087 Sleep for a number of seconds.
1088 @function sleep
1089 @int seconds minimum numebr of seconds to sleep
1090 @treturn[1] int `0` if the requested time has elapsed
1091 @treturn[2] int unslept seconds remaining, if interrupted
1092 @see sleep(3)
1093 @see posix.time.nanosleep
1094 */
1095 static int
Psleep(lua_State * L)1096 Psleep(lua_State *L)
1097 {
1098 	unsigned int seconds = checkint(L, 1);
1099 	checknargs(L, 1);
1100 	return pushintresult(sleep(seconds));
1101 }
1102 
1103 
1104 /***
1105 Commit buffer cache to disk.
1106 @function sync
1107 @see fsync
1108 @see sync(2)
1109 */
1110 static int
Psync(lua_State * L)1111 Psync(lua_State *L)
1112 {
1113 	checknargs(L, 0);
1114 	sync();
1115 	return 0;
1116 }
1117 
1118 
1119 /***
1120 Get configuration information at runtime.
1121 @function sysconf
1122 @int key one of `_SC_ARG_MAX`, `_SC_CHILD_MAX`, `_SC_CLK_TCK`, `_SC_JOB_CONTROL`,
1123   `_SC_OPEN_MAX`, `_SC_NGROUPS_MAX`, `_SC_SAVED_IDS`, `_SC_STREAM_MAX`,
1124   `_SC_PAGESIZE`, `_SC_TZNAME_MAX` or `_SC_VERSION`,
1125 @treturn int associated system configuration value
1126 @see sysconf(3)
1127 */
1128 static int
Psysconf(lua_State * L)1129 Psysconf(lua_State *L)
1130 {
1131 	checknargs(L, 1);
1132 	return pushintresult(sysconf(checkint(L, 1)));
1133 }
1134 
1135 
1136 /***
1137 Name of a terminal device.
1138 @function ttyname
1139 @int[opt=0] fd file descriptor to process
1140 @treturn[1] string name, if successful
1141 @return[2] nil
1142 @treturn[2] string error message
1143 @treturn[2] int errnum
1144 @see ttyname(3)
1145 */
1146 static int
Pttyname(lua_State * L)1147 Pttyname(lua_State *L)
1148 {
1149 	int fd=optint(L, 1, 0);
1150 	char *name;
1151 	checknargs(L, 1);
1152 	name = ttyname(fd);
1153 	if (name != NULL)
1154 		return pushstringresult(name);
1155 	if (errno != 0)
1156 		return pusherror(L, "ttyname");
1157 	lua_pushnil(L);
1158 	lua_pushliteral(L, "not a tty");
1159 	return 2;
1160 }
1161 
1162 
1163 #if LPOSIX_2001_COMPLIANT
1164 /***
1165 Get id of foreground process group of terminal *fd*.
1166 @function tcgetpgrp
1167 @int fd the file descriptor of the controlling terminal of the current process
1168 @treturn[1] int id of foreground process group, if successful
1169 @return[2] nil
1170 @treturn[2] string error message
1171 @treturn[2] int errnum
1172 @see tcgetpgrp(2)
1173 */
1174 static int
Ptcgetpgrp(lua_State * L)1175 Ptcgetpgrp(lua_State *L)
1176 {
1177 	int fd = checkint(L, 1);
1178 	return pushresult(L, tcgetpgrp(fd), NULL);
1179 }
1180 
1181 
1182 /***
1183 Make process group *pgid* the foreground process group of terminal *fd*.
1184 @function tcsetpgrp
1185 @int fd the file descriptor of the controlling terminal of the current process
1186 @int pgid id of the process group to make foreground process group
1187 @treturn[1] int `0`, if successful
1188 @return[2] nil
1189 @treturn[2] string error message
1190 @treturn[2] int errnum
1191 @see tcsetpgrp(2)
1192 */
1193 static int
Ptcsetpgrp(lua_State * L)1194 Ptcsetpgrp(lua_State *L)
1195 {
1196 	int fd = checkint(L, 1);
1197 	int pgid = checkint(L, 2);
1198 	return pushresult(L, tcsetpgrp(fd, pgid), NULL);
1199 }
1200 #endif
1201 
1202 
1203 /***
1204 Unlink a file.
1205 @function unlink
1206 @string path
1207 @treturn[1] int `0`, if successful
1208 @return[2] nil
1209 @treturn[2] string error message
1210 @treturn[2] int errnum
1211 @see unlink(2)
1212 */
1213 static int
Punlink(lua_State * L)1214 Punlink(lua_State *L)
1215 {
1216 	const char *path = luaL_checkstring(L, 1);
1217 	checknargs(L, 1);
1218 	return pushresult(L, unlink(path), path);
1219 }
1220 
1221 
1222 /***
1223 Write bytes to a file.
1224 @function write
1225 @int fd the file descriptor to act on
1226 @string buf containing bytes to write
1227 @treturn[1] int number of bytes written, if successful
1228 @return[2] nil
1229 @treturn[2] string error message
1230 @treturn[2] int errnum
1231 @see write(2)
1232 */
1233 static int
Pwrite(lua_State * L)1234 Pwrite(lua_State *L)
1235 {
1236 	int fd = checkint(L, 1);
1237 	const char *buf = luaL_checkstring(L, 2);
1238 	checknargs(L, 2);
1239 	return pushresult(L, write(fd, buf, lua_objlen(L, 2)), NULL);
1240 }
1241 
1242 /***
1243 Truncate a file to a specified length.
1244 @function ftruncate
1245 @int fd the file descriptor to act on
1246 @int length the length to truncate to
1247 @treturn[1] int `0`, if successful
1248 @return[2] nil
1249 @treturn[2] string error message
1250 @treturn[2] int errnum
1251 @see ftruncate(2)
1252 */
1253 static int
Pftruncate(lua_State * L)1254 Pftruncate(lua_State *L)
1255 {
1256 	int fd = checkint(L, 1);
1257 	off_t length = checkint(L, 2);
1258 	checknargs(L, 2);
1259 	return pushresult(L, ftruncate(fd, length), NULL);
1260 }
1261 
1262 /***
1263 Truncate a file to a specified length.
1264 @function truncate
1265 @string path file to act on
1266 @int length the length to truncate to
1267 @treturn[1] int `0`, if successful
1268 @return[2] nil
1269 @treturn[2] string error message
1270 @treturn[2] int errnum
1271 @see ftruncate(2)
1272 */
1273 static int
Ptruncate(lua_State * L)1274 Ptruncate(lua_State *L)
1275 {
1276 	const char *path = luaL_checkstring(L, 1);
1277 	off_t length = checkint(L, 2);
1278 	checknargs(L, 2);
1279 	return pushresult(L, truncate(path, length), NULL);
1280 }
1281 
1282 static const luaL_Reg posix_unistd_fns[] =
1283 {
1284 	LPOSIX_FUNC( P_exit		),
1285 	LPOSIX_FUNC( Paccess		),
1286 	LPOSIX_FUNC( Palarm		),
1287 	LPOSIX_FUNC( Pchdir		),
1288 	LPOSIX_FUNC( Pchown		),
1289 	LPOSIX_FUNC( Pclose		),
1290 #if defined HAVE_CRYPT
1291 	LPOSIX_FUNC( Pcrypt		),
1292 #endif
1293 	LPOSIX_FUNC( Pdup		),
1294 	LPOSIX_FUNC( Pdup2		),
1295 	LPOSIX_FUNC( Pexec		),
1296 	LPOSIX_FUNC( Pexecp		),
1297 #if HAVE_FDATASYNC
1298 	LPOSIX_FUNC( Pfdatasync		),
1299 #endif
1300 	LPOSIX_FUNC( Pfork		),
1301 	LPOSIX_FUNC( Pfsync		),
1302 	LPOSIX_FUNC( Pgetcwd		),
1303 #if LPOSIX_2001_COMPLIANT
1304 	LPOSIX_FUNC( Pgetgroups		),
1305 #endif
1306 	LPOSIX_FUNC( Pgetegid		),
1307 	LPOSIX_FUNC( Pgeteuid		),
1308 	LPOSIX_FUNC( Pgetgid		),
1309 	LPOSIX_FUNC( Pgetlogin		),
1310 	LPOSIX_FUNC( Pgetopt		),
1311 	LPOSIX_FUNC( Pgetpgrp		),
1312 	LPOSIX_FUNC( Pgetpid		),
1313 	LPOSIX_FUNC( Pgetppid		),
1314 	LPOSIX_FUNC( Pgetuid		),
1315 	LPOSIX_FUNC( Pgethostid		),
1316 	LPOSIX_FUNC( Pisatty		),
1317 #if LPOSIX_2001_COMPLIANT
1318 	LPOSIX_FUNC( Plchown		),
1319 #endif
1320 	LPOSIX_FUNC( Plink		),
1321 	LPOSIX_FUNC( Plinkat		),
1322 	LPOSIX_FUNC( Plseek		),
1323 	LPOSIX_FUNC( Pnice		),
1324 	LPOSIX_FUNC( Ppathconf		),
1325 	LPOSIX_FUNC( Ppipe		),
1326 	LPOSIX_FUNC( Pread		),
1327 	LPOSIX_FUNC( Preadlink		),
1328 	LPOSIX_FUNC( Prmdir		),
1329 	LPOSIX_FUNC( Psetpid		),
1330 	LPOSIX_FUNC( Psleep		),
1331 	LPOSIX_FUNC( Psync		),
1332 	LPOSIX_FUNC( Psysconf		),
1333 	LPOSIX_FUNC( Pttyname		),
1334 #if LPOSIX_2001_COMPLIANT
1335 	LPOSIX_FUNC( Ptcgetpgrp		),
1336 	LPOSIX_FUNC( Ptcsetpgrp		),
1337 #endif
1338 	LPOSIX_FUNC( Punlink		),
1339 	LPOSIX_FUNC( Pwrite		),
1340 	LPOSIX_FUNC( Pftruncate		),
1341 	LPOSIX_FUNC( Ptruncate		),
1342 	{NULL, NULL}
1343 };
1344 
1345 
1346 /***
1347 Constants.
1348 @section constants
1349 */
1350 
1351 /***
1352 Standard constants.
1353 Any constants not available in the underlying system will be `nil` valued.
1354 @table posix.unistd
1355 @int _PC_CHOWN_RESTRICTED return 1 if chown requires appropriate privileges, 0 otherwise
1356 @int _PC_LINK_MAX maximum file link count
1357 @int _PC_MAX_CANON maximum bytes in terminal canonical input line
1358 @int _PC_MAX_INPUT maximum number of bytes in a terminal input queue
1359 @int _PC_NAME_MAX maximum number of bytes in a file name
1360 @int _PC_NO_TRUNC return 1 if over-long file names are truncated
1361 @int _PC_PATH_MAXmaximum number of bytes in a pathname
1362 @int _PC_PIPE_BUF maximum number of bytes in an atomic pipe write
1363 @int _PC_VDISABLE terminal character disabling value
1364 @int _SC_ARG_MAX maximum bytes of argument to @{posix.unistd.execp}
1365 @int _SC_CHILD_MAX maximum number of processes per user
1366 @int _SC_CLK_TCK statistics clock frequency
1367 @int _SC_JOB_CONTROL return 1 if system has job control, -1 otherwise
1368 @int _SC_NGROUPS_MAX maximum number of supplemental groups
1369 @int _SC_OPEN_MAX maximum number of open files per user
1370 @int _SC_SAVED_IDS return 1 if system supports saved user and group ids, -1 otherwise
1371 @int _SC_STREAM_MAX maximum number of streams per process
1372 @int _SC_TZNAME_MAX maximum number of timezone types
1373 @int _SC_VERSION POSIX.1 compliance version
1374 @int SEEK_CUR relative file pointer position
1375 @int SEEK_END set file pointer to the end of file
1376 @int SEEK_SET absolute file pointer position
1377 @int STDERR_FILENO standard error file descriptor
1378 @int STDIN_FILENO standard input file descriptor
1379 @int STDOUT_FILENO standard output file descriptor
1380 @usage
1381   -- Print unistd constants supported on this host.
1382   for name, value in pairs (require "posix.unistd") do
1383     if type (value) == "number" then
1384       print (name, value)
1385      end
1386   end
1387 */
1388 
1389 LUALIB_API int
luaopen_posix_unistd(lua_State * L)1390 luaopen_posix_unistd(lua_State *L)
1391 {
1392 	luaL_newlib(L, posix_unistd_fns);
1393 	lua_pushstring(L, LPOSIX_VERSION_STRING("unistd"));
1394 	lua_setfield(L, -2, "version");
1395 
1396 	/* pathconf arguments */
1397 	LPOSIX_CONST( _PC_CHOWN_RESTRICTED	);
1398 	LPOSIX_CONST( _PC_LINK_MAX		);
1399 	LPOSIX_CONST( _PC_MAX_CANON		);
1400 	LPOSIX_CONST( _PC_MAX_INPUT		);
1401 	LPOSIX_CONST( _PC_NAME_MAX		);
1402 	LPOSIX_CONST( _PC_NO_TRUNC		);
1403 	LPOSIX_CONST( _PC_PATH_MAX		);
1404 	LPOSIX_CONST( _PC_PIPE_BUF		);
1405 	LPOSIX_CONST( _PC_VDISABLE		);
1406 
1407 	/* sysconf arguments */
1408 	LPOSIX_CONST( _SC_ARG_MAX	);
1409 	LPOSIX_CONST( _SC_CHILD_MAX	);
1410 	LPOSIX_CONST( _SC_CLK_TCK	);
1411 	LPOSIX_CONST( _SC_JOB_CONTROL	);
1412 	LPOSIX_CONST( _SC_NGROUPS_MAX	);
1413 	LPOSIX_CONST( _SC_OPEN_MAX	);
1414 	LPOSIX_CONST( _SC_PAGESIZE	);
1415 	LPOSIX_CONST( _SC_SAVED_IDS	);
1416 	LPOSIX_CONST( _SC_STREAM_MAX	);
1417 	LPOSIX_CONST( _SC_TZNAME_MAX	);
1418 	LPOSIX_CONST( _SC_VERSION	);
1419 
1420 	/* lseek arguments */
1421 	LPOSIX_CONST( SEEK_CUR		);
1422 	LPOSIX_CONST( SEEK_END		);
1423 	LPOSIX_CONST( SEEK_SET		);
1424 
1425 	/* Miscellaneous */
1426 	LPOSIX_CONST( STDERR_FILENO	);
1427 	LPOSIX_CONST( STDIN_FILENO	);
1428 	LPOSIX_CONST( STDOUT_FILENO	);
1429 
1430 	return 1;
1431 }
1432