Fix build with -Werror=format-security
[screen-lua.git] / src / misc.c
blobff3bebbbb213b944087eb8784f111ca1e8d0271d
1 /* Copyright (c) 2008, 2009
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
14 * any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include <sys/types.h>
30 #include <sys/stat.h> /* mkdir() declaration */
31 #include <signal.h>
33 #include "config.h"
34 #include "screen.h"
35 #include "extern.h"
37 #ifdef SVR4
38 # include <sys/resource.h>
39 #endif
41 extern struct layer *flayer;
43 extern int eff_uid, real_uid;
44 extern int eff_gid, real_gid;
45 extern struct mline mline_old;
46 extern struct mchar mchar_blank;
47 extern unsigned char *null, *blank;
49 #ifdef HAVE_FDWALK
50 static int close_func __P((void *, int));
51 #endif
53 char *
54 SaveStr(str)
55 register const char *str;
57 register char *cp;
59 if ((cp = malloc(strlen(str) + 1)) == NULL)
60 Panic(0, "%s", strnomem);
61 else
62 strcpy(cp, str);
63 return cp;
66 char *
67 SaveStrn(str, n)
68 register const char *str;
69 int n;
71 register char *cp;
73 if ((cp = malloc(n + 1)) == NULL)
74 Panic(0, "%s", strnomem);
75 else
77 bcopy((char *)str, cp, n);
78 cp[n] = 0;
80 return cp;
83 /* cheap strstr replacement */
84 char *
85 InStr(str, pat)
86 char *str;
87 const char *pat;
89 int npat = strlen(pat);
90 for (;*str; str++)
91 if (!strncmp(str, pat, npat))
92 return str;
93 return 0;
96 #ifndef HAVE_STRERROR
97 char *
98 strerror(err)
99 int err;
101 extern int sys_nerr;
102 extern char *sys_errlist[];
104 static char er[20];
105 if (err > 0 && err < sys_nerr)
106 return sys_errlist[err];
107 sprintf(er, "Error %d", err);
108 return er;
110 #endif
112 void
113 centerline(str, y)
114 char *str;
115 int y;
117 int l, n;
119 ASSERT(flayer);
120 n = strlen(str);
121 if (n > flayer->l_width - 1)
122 n = flayer->l_width - 1;
123 l = (flayer->l_width - 1 - n) / 2;
124 LPutStr(flayer, str, n, &mchar_blank, l, y);
127 void
128 leftline(str, y, rend)
129 char *str;
130 int y;
131 struct mchar *rend;
133 int l, n;
134 struct mchar mchar_dol;
136 mchar_dol = mchar_blank;
137 mchar_dol.image = '$';
139 ASSERT(flayer);
140 l = n = strlen(str);
141 if (n > flayer->l_width - 1)
142 n = flayer->l_width - 1;
143 LPutStr(flayer, str, n, rend ? rend : &mchar_blank, 0, y);
144 if (n != l)
145 LPutChar(flayer, &mchar_dol, n, y);
149 char *
150 Filename(s)
151 char *s;
153 register char *p = s;
155 if (p)
156 while (*p)
157 if (*p++ == '/')
158 s = p;
159 return s;
162 char *
163 stripdev(nam)
164 char *nam;
166 #ifdef apollo
167 char *p;
169 if (nam == NULL)
170 return NULL;
171 # ifdef SVR4
172 /* unixware has /dev/pts012 as synonym for /dev/pts/12 */
173 if (!strncmp(nam, "/dev/pts", 8) && nam[8] >= '0' && nam[8] <= '9')
175 static char b[13];
176 sprintf(b, "pts/%d", atoi(nam + 8));
177 return b;
179 # endif /* SVR4 */
180 if (p = strstr(nam,"/dev/"))
181 return p + 5;
182 #else /* apollo */
183 if (nam == NULL)
184 return NULL;
185 if (strncmp(nam, "/dev/", 5) == 0)
186 return nam + 5;
187 #endif /* apollo */
188 return nam;
193 * Signal handling
196 #ifdef POSIX
197 sigret_t (*xsignal(sig, func))
198 # ifndef __APPLE__
199 __P(SIGPROTOARG)
200 # else
202 # endif
203 int sig;
204 sigret_t (*func) __P(SIGPROTOARG);
206 struct sigaction osa, sa;
207 sa.sa_handler = func;
208 (void)sigemptyset(&sa.sa_mask);
209 #ifdef SA_RESTART
210 sa.sa_flags = (sig == SIGCHLD ? SA_RESTART : 0);
211 #else
212 sa.sa_flags = 0;
213 #endif
214 if (sigaction(sig, &sa, &osa))
215 return (sigret_t (*)__P(SIGPROTOARG))-1;
216 return osa.sa_handler;
219 #else
220 # ifdef hpux
222 * hpux has berkeley signal semantics if we use sigvector,
223 * but not, if we use signal, so we define our own signal() routine.
225 void (*xsignal(sig, func)) __P(SIGPROTOARG)
226 int sig;
227 void (*func) __P(SIGPROTOARG);
229 struct sigvec osv, sv;
231 sv.sv_handler = func;
232 sv.sv_mask = sigmask(sig);
233 sv.sv_flags = SV_BSDSIG;
234 if (sigvector(sig, &sv, &osv) < 0)
235 return (void (*)__P(SIGPROTOARG))(BADSIG);
236 return osv.sv_handler;
238 # endif /* hpux */
239 #endif /* POSIX */
243 * uid/gid handling
246 #ifdef HAVE_SETEUID
248 void
249 xseteuid(euid)
250 int euid;
252 if (seteuid(euid) == 0)
253 return;
254 seteuid(0);
255 if (seteuid(euid))
256 Panic(errno, "seteuid");
259 void
260 xsetegid(egid)
261 int egid;
263 if (setegid(egid))
264 Panic(errno, "setegid");
267 #else /* HAVE_SETEUID */
268 # ifdef HAVE_SETREUID
270 void
271 xseteuid(euid)
272 int euid;
274 int oeuid;
276 oeuid = geteuid();
277 if (oeuid == euid)
278 return;
279 if ((int)getuid() != euid)
280 oeuid = getuid();
281 if (setreuid(oeuid, euid))
282 Panic(errno, "setreuid");
285 void
286 xsetegid(egid)
287 int egid;
289 int oegid;
291 oegid = getegid();
292 if (oegid == egid)
293 return;
294 if ((int)getgid() != egid)
295 oegid = getgid();
296 if (setregid(oegid, egid))
297 Panic(errno, "setregid");
300 # endif /* HAVE_SETREUID */
301 #endif /* HAVE_SETEUID */
305 #ifdef NEED_OWN_BCOPY
306 void
307 xbcopy(s1, s2, len)
308 register char *s1, *s2;
309 register int len;
311 if (s1 < s2 && s2 < s1 + len)
313 s1 += len;
314 s2 += len;
315 while (len-- > 0)
316 *--s2 = *--s1;
318 else
319 while (len-- > 0)
320 *s2++ = *s1++;
322 #endif /* NEED_OWN_BCOPY */
324 void
325 bclear(p, n)
326 char *p;
327 int n;
329 bcopy((char *)blank, p, n);
333 void
334 Kill(pid, sig)
335 int pid, sig;
337 if (pid < 2)
338 return;
339 (void) kill(pid, sig);
342 #ifdef HAVE_FDWALK
344 * Modern versions of Solaris include fdwalk(3c) which allows efficient
345 * implementation of closing open descriptors; this is helpful because
346 * the default file descriptor limit has risen to 65k.
348 static int
349 close_func(cb_data, fd)
350 void *cb_data;
351 int fd;
353 int except = *(int *)cb_data;
354 if (fd > 2 && fd != except)
355 (void)close(fd);
356 return (0);
359 void
360 closeallfiles(except)
361 int except;
363 (void)fdwalk(close_func, &except);
366 #else /* HAVE_FDWALK */
368 void
369 closeallfiles(except)
370 int except;
372 int f;
373 #ifdef SVR4
374 struct rlimit rl;
376 if ((getrlimit(RLIMIT_NOFILE, &rl) == 0) && rl.rlim_max != RLIM_INFINITY)
377 f = rl.rlim_max;
378 else
379 #endif /* SVR4 */
380 #if defined(SYSV) && defined(NOFILE) && !defined(ISC)
381 f = NOFILE;
382 #else /* SYSV && !ISC */
383 f = getdtablesize();
384 #endif /* SYSV && !ISC */
385 while (--f > 2)
386 if (f != except)
387 close(f);
390 #endif /* HAVE_FDWALK */
394 * Security - switch to real uid
397 #ifndef USE_SETEUID
398 static int UserPID;
399 static sigret_t (*Usersigcld)__P(SIGPROTOARG);
400 #endif
401 static int UserSTAT;
404 UserContext()
406 #ifndef USE_SETEUID
407 if (eff_uid == real_uid && eff_gid == real_gid)
408 return 1;
409 Usersigcld = signal(SIGCHLD, SIG_DFL);
410 debug("UserContext: forking.\n");
411 switch (UserPID = fork())
413 case -1:
414 Msg(errno, "fork");
415 return -1;
416 case 0:
417 signal(SIGHUP, SIG_DFL);
418 signal(SIGINT, SIG_IGN);
419 signal(SIGQUIT, SIG_DFL);
420 signal(SIGTERM, SIG_DFL);
421 # ifdef BSDJOBS
422 signal(SIGTTIN, SIG_DFL);
423 signal(SIGTTOU, SIG_DFL);
424 # endif
425 setuid(real_uid);
426 setgid(real_gid);
427 return 1;
428 default:
429 return 0;
431 #else
432 xseteuid(real_uid);
433 xsetegid(real_gid);
434 return 1;
435 #endif
438 void
439 UserReturn(val)
440 int val;
442 #ifndef USE_SETEUID
443 if (eff_uid == real_uid && eff_gid == real_gid)
444 UserSTAT = val;
445 else
446 _exit(val);
447 #else
448 xseteuid(eff_uid);
449 xsetegid(eff_gid);
450 UserSTAT = val;
451 #endif
455 UserStatus()
457 #ifndef USE_SETEUID
458 int i;
459 # ifdef BSDWAIT
460 union wait wstat;
461 # else
462 int wstat;
463 # endif
465 if (eff_uid == real_uid && eff_gid == real_gid)
466 return UserSTAT;
467 if (UserPID < 0)
468 return -1;
469 while ((errno = 0, i = wait(&wstat)) != UserPID)
470 if (i < 0 && errno != EINTR)
471 break;
472 (void) signal(SIGCHLD, Usersigcld);
473 if (i == -1)
474 return -1;
475 return WEXITSTATUS(wstat);
476 #else
477 return UserSTAT;
478 #endif
481 #ifndef HAVE_RENAME
483 rename (old, new)
484 char *old;
485 char *new;
487 if (link(old, new) < 0)
488 return -1;
489 return unlink(old);
491 #endif
495 AddXChar(buf, ch)
496 char *buf;
497 int ch;
499 char *p = buf;
501 if (ch < ' ' || ch == 0x7f)
503 *p++ = '^';
504 *p++ = ch ^ 0x40;
506 else if (ch >= 0x80)
508 *p++ = '\\';
509 *p++ = (ch >> 6 & 7) + '0';
510 *p++ = (ch >> 3 & 7) + '0';
511 *p++ = (ch >> 0 & 7) + '0';
513 else
514 *p++ = ch;
515 return p - buf;
519 AddXChars(buf, len, str)
520 char *buf, *str;
521 int len;
523 char *p;
525 if (str == 0)
527 *buf = 0;
528 return 0;
530 len -= 4; /* longest sequence produced by AddXChar() */
531 for (p = buf; p < buf + len && *str; str++)
533 if (*str == ' ')
534 *p++ = *str;
535 else
536 p += AddXChar(p, *str);
538 *p = 0;
539 return p - buf;
543 #ifdef DEBUG
544 void
545 opendebug(new, shout)
546 int new, shout;
548 char buf[256];
550 #ifdef _MODE_T
551 mode_t oumask = umask(0);
552 #else
553 int oumask = umask(0);
554 #endif
556 ASSERT(!dfp);
558 (void) mkdir(DEBUGDIR, 0777);
559 sprintf(buf, shout ? "%s/SCREEN.%d" : "%s/screen.%d", DEBUGDIR, getpid());
560 if (!(dfp = fopen(buf, new ? "w" : "a")))
561 dfp = stderr;
562 else
563 (void)chmod(buf, 0666);
565 (void)umask(oumask);
566 debug("opendebug: done.\n");
568 #endif /* DEBUG */
570 void
571 sleep1000(msec)
572 int msec;
575 struct timeval t;
577 t.tv_sec = (long) (msec / 1000);
578 t.tv_usec = (long) ((msec % 1000) * 1000);
579 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
584 * This uses either setenv() or putenv(). If it is putenv() we cannot dare
585 * to free the buffer after putenv(), unless it it the one found in putenv.c
587 void
588 xsetenv(var, value)
589 char *var;
590 char *value;
592 #ifndef USESETENV
593 char *buf;
594 int l;
596 if ((buf = (char *)malloc((l = strlen(var)) +
597 strlen(value) + 2)) == NULL)
599 Msg(0, strnomem);
600 return;
602 strcpy(buf, var);
603 buf[l] = '=';
604 strcpy(buf + l + 1, value);
605 putenv(buf);
606 # ifdef NEEDPUTENV
608 * we use our own putenv(), knowing that it does a malloc()
609 * the string space, we can free our buf now.
611 free(buf);
612 # else /* NEEDSETENV */
614 * For all sysv-ish systems that link a standard putenv()
615 * the string-space buf is added to the environment and must not
616 * be freed, or modified.
617 * We are sorry to say that memory is lost here, when setting
618 * the same variable again and again.
620 # endif /* NEEDSETENV */
621 #else /* USESETENV */
622 # if HAVE_SETENV_3
623 setenv(var, value, 1);
624 # else
625 setenv(var, value);
626 # endif /* HAVE_SETENV_3 */
627 #endif /* USESETENV */
630 #ifdef TERMINFO
632 * This is a replacement for the buggy _delay function from the termcap
633 * emulation of libcurses, which ignores ospeed.
636 _delay(delay, outc)
637 register int delay;
638 int (*outc) __P((int));
640 int pad;
641 extern short ospeed;
642 static short osp2pad[] = {
643 0,2000,1333,909,743,666,500,333,166,83,55,41,20,10,5,2,1,1
646 if (ospeed <= 0 || ospeed >= (int)(sizeof(osp2pad)/sizeof(*osp2pad)))
647 return 0;
648 pad =osp2pad[ospeed];
649 delay = (delay + pad / 2) / pad;
650 while (delay-- > 0)
651 (*outc)(0);
652 return 0;
655 #endif /* TERMINFO */
659 #ifndef USEVARARGS
661 # define xva_arg(s, t, tn) (*(t *)(s += xsnoff(tn, 0, 0), s - xsnoff(tn, 0, 0)))
662 # define xva_list char *
664 static int
665 xsnoff(a, b, c)
666 int a;
667 char *b;
668 int c;
670 return a ? (char *)&c - (char *)&b : (char *)&b - (char *)&a;
674 xsnprintf(s, n, fmt, p1, p2, p3, p4, p5, p6)
675 char *s;
676 int n;
677 char *fmt;
678 unsigned long p1, p2, p3, p4, p5, p6;
680 int xvsnprintf __P((char *, int, char *, xva_list));
681 return xvsnprintf(s, n, fmt, (char *)&fmt + xsnoff(1, 0, 0));
684 #else
686 # define xva_arg(s, t, tn) va_arg(s, t)
687 # define xva_list va_list
689 #endif
692 #if !defined(USEVARARGS) || !defined(HAVE_VSNPRINTF)
695 xvsnprintf(s, n, fmt, stack)
696 char *s;
697 int n;
698 char *fmt;
699 xva_list stack;
701 char *f, *sf = 0;
702 int i, on, argl = 0;
703 char myf[10], buf[20];
704 char *arg, *myfp;
706 on = n;
707 f = fmt;
708 arg = 0;
709 while(arg || (sf = index(f, '%')) || (sf = f + strlen(f)))
711 if (arg == 0)
713 arg = f;
714 argl = sf - f;
716 if (argl)
718 i = argl > n - 1 ? n - 1 : argl;
719 strncpy(s, arg, i);
720 s += i;
721 n -= i;
722 if (i < argl)
724 *s = 0;
725 return on;
728 arg = 0;
729 if (sf == 0)
730 continue;
731 f = sf;
732 sf = 0;
733 if (!*f)
734 break;
735 myfp = myf;
736 *myfp++ = *f++;
737 while (((*f >= '0' && *f <='9') || *f == '#') && myfp - myf < 8)
738 *myfp++ = *f++;
739 *myfp++ = *f;
740 *myfp = 0;
741 if (!*f++)
742 break;
743 switch(f[-1])
745 case '%':
746 arg = "%";
747 break;
748 case 'c':
749 case 'o':
750 case 'd':
751 case 'x':
752 i = xva_arg(stack, int, 0);
753 sprintf(buf, myf, i);
754 arg = buf;
755 break;
756 case 's':
757 arg = xva_arg(stack, char *, 1);
758 if (arg == 0)
759 arg = "NULL";
760 break;
761 default:
762 arg = "";
763 break;
765 argl = strlen(arg);
767 *s = 0;
768 return on - n;
771 #endif