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)
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 */
38 # include <sys/resource.h>
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
;
50 static int close_func
__P((void *, int));
55 register const char *str
;
59 if ((cp
= malloc(strlen(str
) + 1)) == NULL
)
68 register const char *str
;
73 if ((cp
= malloc(n
+ 1)) == NULL
)
77 bcopy((char *)str
, cp
, n
);
83 /* cheap strstr replacement */
89 int npat
= strlen(pat
);
91 if (!strncmp(str
, pat
, npat
))
102 extern char *sys_errlist
[];
105 if (err
> 0 && err
< sys_nerr
)
106 return sys_errlist
[err
];
107 sprintf(er
, "Error %d", err
);
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
);
133 struct mchar mchar_dol
;
135 mchar_dol
= mchar_blank
;
136 mchar_dol
.image
= '$';
140 if (n
> flayer
->l_width
- 1)
141 n
= flayer
->l_width
- 1;
142 LPutStr(flayer
, str
, n
, &mchar_blank
, 0, y
);
144 LPutChar(flayer
, &mchar_dol
, n
, y
);
152 register char *p
= s
;
171 /* unixware has /dev/pts012 as synonym for /dev/pts/12 */
172 if (!strncmp(nam
, "/dev/pts", 8) && nam
[8] >= '0' && nam
[8] <= '9')
175 sprintf(b
, "pts/%d", atoi(nam
+ 8));
179 if (p
= strstr(nam
,"/dev/"))
184 if (strncmp(nam
, "/dev/", 5) == 0)
196 sigret_t (*xsignal(sig
, func
))
203 sigret_t (*func
) __P(SIGPROTOARG
);
205 struct sigaction osa
, sa
;
206 sa
.sa_handler
= func
;
207 (void)sigemptyset(&sa
.sa_mask
);
209 sa
.sa_flags
= (sig
== SIGCHLD
? SA_RESTART
: 0);
213 if (sigaction(sig
, &sa
, &osa
))
214 return (sigret_t (*)__P(SIGPROTOARG
))-1;
215 return osa
.sa_handler
;
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
)
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
;
251 if (seteuid(euid
) == 0)
255 Panic(errno
, "seteuid");
263 Panic(errno
, "setegid");
266 #else /* HAVE_SETEUID */
267 # ifdef HAVE_SETREUID
278 if ((int)getuid() != euid
)
280 if (setreuid(oeuid
, euid
))
281 Panic(errno
, "setreuid");
293 if ((int)getgid() != egid
)
295 if (setregid(oegid
, egid
))
296 Panic(errno
, "setregid");
299 # endif /* HAVE_SETREUID */
300 #endif /* HAVE_SETEUID */
304 #ifdef NEED_OWN_BCOPY
307 register char *s1
, *s2
;
310 if (s1
< s2
&& s2
< s1
+ len
)
321 #endif /* NEED_OWN_BCOPY */
328 bcopy((char *)blank
, p
, n
);
338 (void) kill(pid
, sig
);
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.
348 close_func(cb_data
, fd
)
352 int except
= *(int *)cb_data
;
353 if (fd
> 2 && fd
!= except
)
359 closeallfiles(except
)
362 (void)fdwalk(close_func
, &except
);
365 #else /* HAVE_FDWALK */
368 closeallfiles(except
)
375 if ((getrlimit(RLIMIT_NOFILE
, &rl
) == 0) && rl
.rlim_max
!= RLIM_INFINITY
)
379 #if defined(SYSV) && defined(NOFILE) && !defined(ISC)
381 #else /* SYSV && !ISC */
383 #endif /* SYSV && !ISC */
389 #endif /* HAVE_FDWALK */
393 * Security - switch to real uid
398 static sigret_t (*Usersigcld
)__P(SIGPROTOARG
);
406 if (eff_uid
== real_uid
&& eff_gid
== real_gid
)
408 Usersigcld
= signal(SIGCHLD
, SIG_DFL
);
409 debug("UserContext: forking.\n");
410 switch (UserPID
= fork())
416 signal(SIGHUP
, SIG_DFL
);
417 signal(SIGINT
, SIG_IGN
);
418 signal(SIGQUIT
, SIG_DFL
);
419 signal(SIGTERM
, SIG_DFL
);
421 signal(SIGTTIN
, SIG_DFL
);
422 signal(SIGTTOU
, SIG_DFL
);
442 if (eff_uid
== real_uid
&& eff_gid
== real_gid
)
464 if (eff_uid
== real_uid
&& eff_gid
== real_gid
)
468 while ((errno
= 0, i
= wait(&wstat
)) != UserPID
)
469 if (i
< 0 && errno
!= EINTR
)
471 (void) signal(SIGCHLD
, Usersigcld
);
474 return WEXITSTATUS(wstat
);
486 if (link(old
, new) < 0)
500 if (ch
< ' ' || ch
== 0x7f)
508 *p
++ = (ch
>> 6 & 7) + '0';
509 *p
++ = (ch
>> 3 & 7) + '0';
510 *p
++ = (ch
>> 0 & 7) + '0';
518 AddXChars(buf
, len
, str
)
529 len
-= 4; /* longest sequence produced by AddXChar() */
530 for (p
= buf
; p
< buf
+ len
&& *str
; str
++)
535 p
+= AddXChar(p
, *str
);
544 opendebug(new, shout
)
550 mode_t oumask
= umask(0);
552 int oumask
= umask(0);
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")))
562 (void)chmod(buf
, 0666);
565 debug("opendebug: done.\n");
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
595 if ((buf
= (char *)malloc((l
= strlen(var
)) +
596 strlen(value
) + 2)) == NULL
)
603 strcpy(buf
+ l
+ 1, value
);
607 * we use our own putenv(), knowing that it does a malloc()
608 * the string space, we can free our buf now.
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 */
622 setenv(var
, value
, 1);
625 # endif /* HAVE_SETENV_3 */
626 #endif /* USESETENV */
631 * This is a replacement for the buggy _delay function from the termcap
632 * emulation of libcurses, which ignores ospeed.
637 int (*outc
) __P((int));
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
)))
647 pad
=osp2pad
[ospeed
];
648 delay
= (delay
+ pad
/ 2) / pad
;
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));
667 xtputs(str
, affcnt
, outc
)
670 int (*outc
) __P((int));
672 extern int tputs
__P((const char *, int, int (*)(int)));
674 tputs(str
, affcnt
, outc
);
678 _nc_timed_wait(mode
, ms
, tlp
)
681 _delay(ms
* 10, save_outc
);
687 #endif /* TERMINFO */
693 # define xva_arg(s, t, tn) (*(t *)(s += xsnoff(tn, 0, 0), s - xsnoff(tn, 0, 0)))
694 # define xva_list char *
702 return a
? (char *)&c
- (char *)&b
: (char *)&b
- (char *)&a
;
706 xsnprintf(s
, n
, fmt
, p1
, p2
, p3
, p4
, p5
, p6
)
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));
718 # define xva_arg(s, t, tn) va_arg(s, t)
719 # define xva_list va_list
724 #if !defined(USEVARARGS) || !defined(HAVE_VSNPRINTF)
727 xvsnprintf(s
, n
, fmt
, stack
)
735 char myf
[10], buf
[20];
741 while(arg
|| (sf
= index(f
, '%')) || (sf
= f
+ strlen(f
)))
750 i
= argl
> n
- 1 ? n
- 1 : argl
;
769 while (((*f
>= '0' && *f
<='9') || *f
== '#') && myfp
- myf
< 8)
784 i
= xva_arg(stack
, int, 0);
785 sprintf(buf
, myf
, i
);
789 arg
= xva_arg(stack
, char *, 1);