Document the onsilent/onactivity event.
[screen-lua.git] / src / misc.c
blobc56d87a34133237f26042b9643f50dea7c771e49
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, 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, 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)
129 char *str;
130 int y;
132 int l, n;
133 struct mchar mchar_dol;
135 mchar_dol = mchar_blank;
136 mchar_dol.image = '$';
138 ASSERT(flayer);
139 l = n = strlen(str);
140 if (n > flayer->l_width - 1)
141 n = flayer->l_width - 1;
142 LPutStr(flayer, str, n, &mchar_blank, 0, y);
143 if (n != l)
144 LPutChar(flayer, &mchar_dol, n, y);
148 char *
149 Filename(s)
150 char *s;
152 register char *p = s;
154 if (p)
155 while (*p)
156 if (*p++ == '/')
157 s = p;
158 return s;
161 char *
162 stripdev(nam)
163 char *nam;
165 #ifdef apollo
166 char *p;
168 if (nam == NULL)
169 return NULL;
170 # ifdef SVR4
171 /* unixware has /dev/pts012 as synonym for /dev/pts/12 */
172 if (!strncmp(nam, "/dev/pts", 8) && nam[8] >= '0' && nam[8] <= '9')
174 static char b[13];
175 sprintf(b, "pts/%d", atoi(nam + 8));
176 return b;
178 # endif /* SVR4 */
179 if (p = strstr(nam,"/dev/"))
180 return p + 5;
181 #else /* apollo */
182 if (nam == NULL)
183 return NULL;
184 if (strncmp(nam, "/dev/", 5) == 0)
185 return nam + 5;
186 #endif /* apollo */
187 return nam;
192 * Signal handling
195 #ifdef POSIX
196 sigret_t (*xsignal(sig, func))
197 # ifndef __APPLE__
198 __P(SIGPROTOARG)
199 # else
201 # endif
202 int sig;
203 sigret_t (*func) __P(SIGPROTOARG);
205 struct sigaction osa, sa;
206 sa.sa_handler = func;
207 (void)sigemptyset(&sa.sa_mask);
208 #ifdef SA_RESTART
209 sa.sa_flags = (sig == SIGCHLD ? SA_RESTART : 0);
210 #else
211 sa.sa_flags = 0;
212 #endif
213 if (sigaction(sig, &sa, &osa))
214 return (sigret_t (*)__P(SIGPROTOARG))-1;
215 return osa.sa_handler;
218 #else
219 # ifdef hpux
221 * hpux has berkeley signal semantics if we use sigvector,
222 * but not, if we use signal, so we define our own signal() routine.
224 void (*xsignal(sig, func)) __P(SIGPROTOARG)
225 int sig;
226 void (*func) __P(SIGPROTOARG);
228 struct sigvec osv, sv;
230 sv.sv_handler = func;
231 sv.sv_mask = sigmask(sig);
232 sv.sv_flags = SV_BSDSIG;
233 if (sigvector(sig, &sv, &osv) < 0)
234 return (void (*)__P(SIGPROTOARG))(BADSIG);
235 return osv.sv_handler;
237 # endif /* hpux */
238 #endif /* POSIX */
242 * uid/gid handling
245 #ifdef HAVE_SETEUID
247 void
248 xseteuid(euid)
249 int euid;
251 if (seteuid(euid) == 0)
252 return;
253 seteuid(0);
254 if (seteuid(euid))
255 Panic(errno, "seteuid");
258 void
259 xsetegid(egid)
260 int egid;
262 if (setegid(egid))
263 Panic(errno, "setegid");
266 #else /* HAVE_SETEUID */
267 # ifdef HAVE_SETREUID
269 void
270 xseteuid(euid)
271 int euid;
273 int oeuid;
275 oeuid = geteuid();
276 if (oeuid == euid)
277 return;
278 if ((int)getuid() != euid)
279 oeuid = getuid();
280 if (setreuid(oeuid, euid))
281 Panic(errno, "setreuid");
284 void
285 xsetegid(egid)
286 int egid;
288 int oegid;
290 oegid = getegid();
291 if (oegid == egid)
292 return;
293 if ((int)getgid() != egid)
294 oegid = getgid();
295 if (setregid(oegid, egid))
296 Panic(errno, "setregid");
299 # endif /* HAVE_SETREUID */
300 #endif /* HAVE_SETEUID */
304 #ifdef NEED_OWN_BCOPY
305 void
306 xbcopy(s1, s2, len)
307 register char *s1, *s2;
308 register int len;
310 if (s1 < s2 && s2 < s1 + len)
312 s1 += len;
313 s2 += len;
314 while (len-- > 0)
315 *--s2 = *--s1;
317 else
318 while (len-- > 0)
319 *s2++ = *s1++;
321 #endif /* NEED_OWN_BCOPY */
323 void
324 bclear(p, n)
325 char *p;
326 int n;
328 bcopy((char *)blank, p, n);
332 void
333 Kill(pid, sig)
334 int pid, sig;
336 if (pid < 2)
337 return;
338 (void) kill(pid, sig);
341 #ifdef HAVE_FDWALK
343 * Modern versions of Solaris include fdwalk(3c) which allows efficient
344 * implementation of closing open descriptors; this is helpful because
345 * the default file descriptor limit has risen to 65k.
347 static int
348 close_func(cb_data, fd)
349 void *cb_data;
350 int fd;
352 int except = *(int *)cb_data;
353 if (fd > 2 && fd != except)
354 (void)close(fd);
355 return (0);
358 void
359 closeallfiles(except)
360 int except;
362 (void)fdwalk(close_func, &except);
365 #else /* HAVE_FDWALK */
367 void
368 closeallfiles(except)
369 int except;
371 int f;
372 #ifdef SVR4
373 struct rlimit rl;
375 if ((getrlimit(RLIMIT_NOFILE, &rl) == 0) && rl.rlim_max != RLIM_INFINITY)
376 f = rl.rlim_max;
377 else
378 #endif /* SVR4 */
379 #if defined(SYSV) && defined(NOFILE) && !defined(ISC)
380 f = NOFILE;
381 #else /* SYSV && !ISC */
382 f = getdtablesize();
383 #endif /* SYSV && !ISC */
384 while (--f > 2)
385 if (f != except)
386 close(f);
389 #endif /* HAVE_FDWALK */
393 * Security - switch to real uid
396 #ifndef USE_SETEUID
397 static int UserPID;
398 static sigret_t (*Usersigcld)__P(SIGPROTOARG);
399 #endif
400 static int UserSTAT;
403 UserContext()
405 #ifndef USE_SETEUID
406 if (eff_uid == real_uid && eff_gid == real_gid)
407 return 1;
408 Usersigcld = signal(SIGCHLD, SIG_DFL);
409 debug("UserContext: forking.\n");
410 switch (UserPID = fork())
412 case -1:
413 Msg(errno, "fork");
414 return -1;
415 case 0:
416 signal(SIGHUP, SIG_DFL);
417 signal(SIGINT, SIG_IGN);
418 signal(SIGQUIT, SIG_DFL);
419 signal(SIGTERM, SIG_DFL);
420 # ifdef BSDJOBS
421 signal(SIGTTIN, SIG_DFL);
422 signal(SIGTTOU, SIG_DFL);
423 # endif
424 setuid(real_uid);
425 setgid(real_gid);
426 return 1;
427 default:
428 return 0;
430 #else
431 xseteuid(real_uid);
432 xsetegid(real_gid);
433 return 1;
434 #endif
437 void
438 UserReturn(val)
439 int val;
441 #ifndef USE_SETEUID
442 if (eff_uid == real_uid && eff_gid == real_gid)
443 UserSTAT = val;
444 else
445 _exit(val);
446 #else
447 xseteuid(eff_uid);
448 xsetegid(eff_gid);
449 UserSTAT = val;
450 #endif
454 UserStatus()
456 #ifndef USE_SETEUID
457 int i;
458 # ifdef BSDWAIT
459 union wait wstat;
460 # else
461 int wstat;
462 # endif
464 if (eff_uid == real_uid && eff_gid == real_gid)
465 return UserSTAT;
466 if (UserPID < 0)
467 return -1;
468 while ((errno = 0, i = wait(&wstat)) != UserPID)
469 if (i < 0 && errno != EINTR)
470 break;
471 (void) signal(SIGCHLD, Usersigcld);
472 if (i == -1)
473 return -1;
474 return WEXITSTATUS(wstat);
475 #else
476 return UserSTAT;
477 #endif
480 #ifndef HAVE_RENAME
482 rename (old, new)
483 char *old;
484 char *new;
486 if (link(old, new) < 0)
487 return -1;
488 return unlink(old);
490 #endif
494 AddXChar(buf, ch)
495 char *buf;
496 int ch;
498 char *p = buf;
500 if (ch < ' ' || ch == 0x7f)
502 *p++ = '^';
503 *p++ = ch ^ 0x40;
505 else if (ch >= 0x80)
507 *p++ = '\\';
508 *p++ = (ch >> 6 & 7) + '0';
509 *p++ = (ch >> 3 & 7) + '0';
510 *p++ = (ch >> 0 & 7) + '0';
512 else
513 *p++ = ch;
514 return p - buf;
518 AddXChars(buf, len, str)
519 char *buf, *str;
520 int len;
522 char *p;
524 if (str == 0)
526 *buf = 0;
527 return 0;
529 len -= 4; /* longest sequence produced by AddXChar() */
530 for (p = buf; p < buf + len && *str; str++)
532 if (*str == ' ')
533 *p++ = *str;
534 else
535 p += AddXChar(p, *str);
537 *p = 0;
538 return p - buf;
542 #ifdef DEBUG
543 void
544 opendebug(new, shout)
545 int new, shout;
547 char buf[256];
549 #ifdef _MODE_T
550 mode_t oumask = umask(0);
551 #else
552 int oumask = umask(0);
553 #endif
555 ASSERT(!dfp);
557 (void) mkdir(DEBUGDIR, 0777);
558 sprintf(buf, shout ? "%s/SCREEN.%d" : "%s/screen.%d", DEBUGDIR, getpid());
559 if (!(dfp = fopen(buf, new ? "w" : "a")))
560 dfp = stderr;
561 else
562 (void)chmod(buf, 0666);
564 (void)umask(oumask);
565 debug("opendebug: done.\n");
567 #endif /* DEBUG */
569 void
570 sleep1000(msec)
571 int msec;
574 struct timeval t;
576 t.tv_sec = (long) (msec / 1000);
577 t.tv_usec = (long) ((msec % 1000) * 1000);
578 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
583 * This uses either setenv() or putenv(). If it is putenv() we cannot dare
584 * to free the buffer after putenv(), unless it it the one found in putenv.c
586 void
587 xsetenv(var, value)
588 char *var;
589 char *value;
591 #ifndef USESETENV
592 char *buf;
593 int l;
595 if ((buf = (char *)malloc((l = strlen(var)) +
596 strlen(value) + 2)) == NULL)
598 Msg(0, strnomem);
599 return;
601 strcpy(buf, var);
602 buf[l] = '=';
603 strcpy(buf + l + 1, value);
604 putenv(buf);
605 # ifdef NEEDPUTENV
607 * we use our own putenv(), knowing that it does a malloc()
608 * the string space, we can free our buf now.
610 free(buf);
611 # else /* NEEDSETENV */
613 * For all sysv-ish systems that link a standard putenv()
614 * the string-space buf is added to the environment and must not
615 * be freed, or modified.
616 * We are sorry to say that memory is lost here, when setting
617 * the same variable again and again.
619 # endif /* NEEDSETENV */
620 #else /* USESETENV */
621 # if HAVE_SETENV_3
622 setenv(var, value, 1);
623 # else
624 setenv(var, value);
625 # endif /* HAVE_SETENV_3 */
626 #endif /* USESETENV */
629 #ifdef TERMINFO
631 * This is a replacement for the buggy _delay function from the termcap
632 * emulation of libcurses, which ignores ospeed.
635 _delay(delay, outc)
636 register int delay;
637 int (*outc) __P((int));
639 int pad;
640 extern short ospeed;
641 static short osp2pad[] = {
642 0,2000,1333,909,743,666,500,333,166,83,55,41,20,10,5,2,1,1
645 if (ospeed <= 0 || ospeed >= (int)(sizeof(osp2pad)/sizeof(*osp2pad)))
646 return 0;
647 pad =osp2pad[ospeed];
648 delay = (delay + pad / 2) / pad;
649 while (delay-- > 0)
650 (*outc)(0);
651 return 0;
654 # ifdef linux
656 /* stupid stupid linux ncurses! It won't to padding with
657 * zeros but sleeps instead. This breaks CalcCost, of course.
658 * Also, the ncurses wait functions use a global variable
659 * to store the current outc function. Oh well...
662 int (*save_outc) __P((int));
664 # undef tputs
666 void
667 xtputs(str, affcnt, outc)
668 char *str;
669 int affcnt;
670 int (*outc) __P((int));
672 extern int tputs __P((const char *, int, int (*)(int)));
673 save_outc = outc;
674 tputs(str, affcnt, outc);
678 _nc_timed_wait(mode, ms, tlp)
679 int mode, ms, *tlp;
681 _delay(ms * 10, save_outc);
682 return 0;
685 # endif /* linux */
687 #endif /* TERMINFO */
691 #ifndef USEVARARGS
693 # define xva_arg(s, t, tn) (*(t *)(s += xsnoff(tn, 0, 0), s - xsnoff(tn, 0, 0)))
694 # define xva_list char *
696 static int
697 xsnoff(a, b, c)
698 int a;
699 char *b;
700 int c;
702 return a ? (char *)&c - (char *)&b : (char *)&b - (char *)&a;
706 xsnprintf(s, n, fmt, p1, p2, p3, p4, p5, p6)
707 char *s;
708 int n;
709 char *fmt;
710 unsigned long p1, p2, p3, p4, p5, p6;
712 int xvsnprintf __P((char *, int, char *, xva_list));
713 return xvsnprintf(s, n, fmt, (char *)&fmt + xsnoff(1, 0, 0));
716 #else
718 # define xva_arg(s, t, tn) va_arg(s, t)
719 # define xva_list va_list
721 #endif
724 #if !defined(USEVARARGS) || !defined(HAVE_VSNPRINTF)
727 xvsnprintf(s, n, fmt, stack)
728 char *s;
729 int n;
730 char *fmt;
731 xva_list stack;
733 char *f, *sf = 0;
734 int i, on, argl = 0;
735 char myf[10], buf[20];
736 char *arg, *myfp;
738 on = n;
739 f = fmt;
740 arg = 0;
741 while(arg || (sf = index(f, '%')) || (sf = f + strlen(f)))
743 if (arg == 0)
745 arg = f;
746 argl = sf - f;
748 if (argl)
750 i = argl > n - 1 ? n - 1 : argl;
751 strncpy(s, arg, i);
752 s += i;
753 n -= i;
754 if (i < argl)
756 *s = 0;
757 return on;
760 arg = 0;
761 if (sf == 0)
762 continue;
763 f = sf;
764 sf = 0;
765 if (!*f)
766 break;
767 myfp = myf;
768 *myfp++ = *f++;
769 while (((*f >= '0' && *f <='9') || *f == '#') && myfp - myf < 8)
770 *myfp++ = *f++;
771 *myfp++ = *f;
772 *myfp = 0;
773 if (!*f++)
774 break;
775 switch(f[-1])
777 case '%':
778 arg = "%";
779 break;
780 case 'c':
781 case 'o':
782 case 'd':
783 case 'x':
784 i = xva_arg(stack, int, 0);
785 sprintf(buf, myf, i);
786 arg = buf;
787 break;
788 case 's':
789 arg = xva_arg(stack, char *, 1);
790 if (arg == 0)
791 arg = "NULL";
792 break;
793 default:
794 arg = "";
795 break;
797 argl = strlen(arg);
799 *s = 0;
800 return on - n;
803 #endif