diff --git a/common/Makefile b/common/Makefile index bb5b3bdae..0855c0dfe 100644 --- a/common/Makefile +++ b/common/Makefile @@ -7,4 +7,9 @@ SUBDIR:= bbs osdep sys SUBDIR+= fbs .endif +all: + +install: all + @true + .include diff --git a/common/diet/Makefile b/common/diet/Makefile deleted file mode 100644 index 72c02fbe1..000000000 --- a/common/diet/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $Id$ - -SRCROOT:= ../.. -.include "$(SRCROOT)/pttbbs.mk" - -SRCS:= alloc.c random.c time.c -LIB:= cmdiet - -install: - -.include diff --git a/common/diet/alloc.c b/common/diet/alloc.c deleted file mode 100644 index d57104339..000000000 --- a/common/diet/alloc.c +++ /dev/null @@ -1,255 +0,0 @@ -#ifdef __dietlibc__ -/* - * malloc/free by O.Dreesen - * - * first TRY: - * lists w/magics - * and now the second TRY - * let the kernel map all the stuff (if there is something to do) - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include /* for PAGE_SIZE */ - - -/* -- HELPER CODE --------------------------------------------------------- */ - -#ifndef MAP_FAILED -#define MAP_FAILED ((void*)-1) -#endif - -#ifndef NULL -#define NULL ((void*)0) -#endif - -typedef struct { - void* next; - size_t size; -} __alloc_t; - -#define BLOCK_START(b) (((void*)(b))-sizeof(__alloc_t)) -#define BLOCK_RET(b) (((void*)(b))+sizeof(__alloc_t)) - -#define MEM_BLOCK_SIZE PAGE_SIZE -#define PAGE_ALIGN(s) (((s)+MEM_BLOCK_SIZE-1)&(unsigned long)(~(MEM_BLOCK_SIZE-1))) - -/* a simple mmap :) */ -#if defined(__i386__) -#define REGPARM(x) __attribute__((regparm(x))) -#else -#define REGPARM(x) -#endif - -static void REGPARM(1) *do_mmap(size_t size) { - return mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, (size_t)0); -} - -/* -- SMALL MEM ----------------------------------------------------------- */ - -static __alloc_t* __small_mem[8]; - -static int smallalloc[8]; -static int smallalloc_max[8]; - -#define __SMALL_NR(i) (MEM_BLOCK_SIZE/(i)) - -#define __MIN_SMALL_SIZE __SMALL_NR(256) /* 16 / 32 */ -#define __MAX_SMALL_SIZE __SMALL_NR(2) /* 2048 / 4096 */ - -#define GET_SIZE(s) (__MIN_SMALL_SIZE<>__ind_shift(); - while(size) { size>>=1; ++idx; } -// } - return idx; -} - -/* small mem */ -static void __small_free(void*_ptr,size_t _size) REGPARM(2); - -static void REGPARM(2) __small_free(void*_ptr,size_t _size) { - __alloc_t* ptr=BLOCK_START(_ptr); - size_t size=_size; - size_t idx=get_index(size); - - memset(ptr,0,size); /* allways zero out small mem */ - - ptr->next=__small_mem[idx]; - __small_mem[idx]=ptr; - - smallalloc[idx]--; - - if (MEM_BLOCK_SIZE == PAGE_SIZE && - smallalloc[idx] == 0 && - smallalloc_max[idx] < __SMALL_NR(size)) { - __alloc_t* p = __small_mem[idx]; - __alloc_t* ph = p - (size_t)p%PAGE_SIZE; - munmap(ph, MEM_BLOCK_SIZE); - __small_mem[idx] = 0; - } -} - -static void* REGPARM(1) __small_malloc(size_t _size) { - __alloc_t *ptr; - size_t size=_size; - size_t idx; - - idx=get_index(size); - ptr=__small_mem[idx]; - - if (ptr==0) { /* no free blocks ? */ - register int i,nr; - ptr=do_mmap(MEM_BLOCK_SIZE); - if (ptr==MAP_FAILED) return MAP_FAILED; - - __small_mem[idx]=ptr; - - nr=__SMALL_NR(size)-1; - for (i=0;inext=(((void*)ptr)+size); - ptr=ptr->next; - } - ptr->next=0; - - ptr=__small_mem[idx]; - } - - /* get a free block */ - __small_mem[idx]=ptr->next; - ptr->next=0; - - smallalloc[idx]++; - if(smallalloc[idx] > smallalloc_max[idx]) - smallalloc_max[idx] = smallalloc[idx]; - - return ptr; -} - -/* -- PUBLIC FUNCTIONS ---------------------------------------------------- */ - -static void _alloc_libc_free(void *ptr) { - register size_t size; - if (ptr) { - size=((__alloc_t*)BLOCK_START(ptr))->size; - if (size) { - if (size<=__MAX_SMALL_SIZE) - __small_free(ptr,size); - else - munmap(BLOCK_START(ptr),size); - } - } -} -void __libc_free(void *ptr) __attribute__((alias("_alloc_libc_free"))); -void free(void *ptr) __attribute__((weak,alias("_alloc_libc_free"))); -void if_freenameindex(void* ptr) __attribute__((alias("free"))); - -#ifdef WANT_MALLOC_ZERO -static __alloc_t zeromem[2]; -#endif - -static void* _alloc_libc_malloc(size_t size) { - __alloc_t* ptr; - size_t need; -#ifdef WANT_MALLOC_ZERO - if (!size) return BLOCK_RET(zeromem); -#else - if (!size) goto err_out; -#endif - size+=sizeof(__alloc_t); - if (sizesize=need; - return BLOCK_RET(ptr); -err_out: - (*__errno_location())=ENOMEM; - return 0; -} -void* __libc_malloc(size_t size) __attribute__((alias("_alloc_libc_malloc"))); -void* malloc(size_t size) __attribute__((weak,alias("_alloc_libc_malloc"))); - -void* __libc_calloc(size_t nmemb, size_t _size); -void* __libc_calloc(size_t nmemb, size_t _size) { - register size_t size=_size*nmemb; - if (nmemb && size/nmemb!=_size) { - (*__errno_location())=ENOMEM; - return 0; - } - return malloc(size); -} -void* calloc(size_t nmemb, size_t _size) __attribute__((weak,alias("__libc_calloc"))); - -void* __libc_realloc(void* ptr, size_t _size); -void* __libc_realloc(void* ptr, size_t _size) { - register size_t size=_size; - if (ptr) { - if (size) { - __alloc_t* tmp=BLOCK_START(ptr); - size+=sizeof(__alloc_t); - if (sizesize!=size) { - if ((tmp->size<=__MAX_SMALL_SIZE)) { - void *new=_alloc_libc_malloc(_size); - if (new) { - register __alloc_t* foo=BLOCK_START(new); - size=foo->size; - if (size>tmp->size) size=tmp->size; - if (size) memcpy(new,ptr,size-sizeof(__alloc_t)); - _alloc_libc_free(ptr); - } - ptr=new; - } - else { - register __alloc_t* foo; - size=PAGE_ALIGN(size); - foo=mremap(tmp,tmp->size,size,MREMAP_MAYMOVE); - if (foo==MAP_FAILED) { -retzero: - (*__errno_location())=ENOMEM; - ptr=0; - } - else { - foo->size=size; - ptr=BLOCK_RET(foo); - } - } - } - } - else { /* size==0 */ - _alloc_libc_free(ptr); - ptr = NULL; - } - } - else { /* ptr==0 */ - if (size) { - ptr=_alloc_libc_malloc(size); - } - } - return ptr; -} -void* realloc(void* ptr, size_t size) __attribute__((weak,alias("__libc_realloc"))); -#endif diff --git a/common/diet/random.c b/common/diet/random.c deleted file mode 100644 index dd369c41c..000000000 --- a/common/diet/random.c +++ /dev/null @@ -1,711 +0,0 @@ -#ifdef __dietlibc__ -/* - Copyright (C) 1995 Free Software Foundation - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* - Copyright (C) 1983 Regents of the University of California. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE.*/ - -/* - * This is derived from the Berkeley source: - * @(#)random.c 5.5 (Berkeley) 7/6/88 - * It was reworked for the GNU C Library by Roland McGrath. - * Rewritten to be reentrant by Ulrich Drepper, 1995 - */ - -#include -#include -#include -#include -struct random_data - { - int32_t *fptr; /* Front pointer. */ - int32_t *rptr; /* Rear pointer. */ - int32_t *state; /* Array of state values. */ - int rand_type; /* Type of random number generator. */ - int rand_deg; /* Degree of random number generator. */ - int rand_sep; /* Distance between front and rear. */ - int32_t *end_ptr; /* Pointer behind state table. */ - }; -int __random_r (struct random_data *buf, int32_t *result); - - - -/* An improved random number generation package. In addition to the standard - rand()/srand() like interface, this package also has a special state info - interface. The initstate() routine is called with a seed, an array of - bytes, and a count of how many bytes are being passed in; this array is - then initialized to contain information for random number generation with - that much state information. Good sizes for the amount of state - information are 32, 64, 128, and 256 bytes. The state can be switched by - calling the setstate() function with the same array as was initialized - with initstate(). By default, the package runs with 128 bytes of state - information and generates far better random numbers than a linear - congruential generator. If the amount of state information is less than - 32 bytes, a simple linear congruential R.N.G. is used. Internally, the - state information is treated as an array of longs; the zeroth element of - the array is the type of R.N.G. being used (small integer); the remainder - of the array is the state information for the R.N.G. Thus, 32 bytes of - state information will give 7 longs worth of state information, which will - allow a degree seven polynomial. (Note: The zeroth word of state - information also has some other information stored in it; see setstate - for details). The random number generation technique is a linear feedback - shift register approach, employing trinomials (since there are fewer terms - to sum up that way). In this approach, the least significant bit of all - the numbers in the state table will act as a linear feedback shift register, - and will have period 2^deg - 1 (where deg is the degree of the polynomial - being used, assuming that the polynomial is irreducible and primitive). - The higher order bits will have longer periods, since their values are - also influenced by pseudo-random carries out of the lower bits. The - total period of the generator is approximately deg*(2**deg - 1); thus - doubling the amount of state information has a vast influence on the - period of the generator. Note: The deg*(2**deg - 1) is an approximation - only good for large deg, when the period of the shift register is the - dominant factor. With deg equal to seven, the period is actually much - longer than the 7*(2**7 - 1) predicted by this formula. */ - - - -/* For each of the currently supported random number generators, we have a - break value on the amount of state information (you need at least this many - bytes of state info to support this random number generator), a degree for - the polynomial (actually a trinomial) that the R.N.G. is based on, and - separation between the two lower order coefficients of the trinomial. */ - -/* Linear congruential. */ -#define TYPE_0 0 -#define BREAK_0 8 -#define DEG_0 0 -#define SEP_0 0 - -/* x**7 + x**3 + 1. */ -#define TYPE_1 1 -#define BREAK_1 32 -#define DEG_1 7 -#define SEP_1 3 - -/* x**15 + x + 1. */ -#define TYPE_2 2 -#define BREAK_2 64 -#define DEG_2 15 -#define SEP_2 1 - -/* x**31 + x**3 + 1. */ -#define TYPE_3 3 -#define BREAK_3 128 -#define DEG_3 31 -#define SEP_3 3 - -/* x**63 + x + 1. */ -#define TYPE_4 4 -#define BREAK_4 256 -#define DEG_4 63 -#define SEP_4 1 - - -/* Array versions of the above information to make code run faster. - Relies on fact that TYPE_i == i. */ - -#define MAX_TYPES 5 /* Max number of types above. */ - -struct random_poly_info -{ - int seps[MAX_TYPES]; - int degrees[MAX_TYPES]; -}; - -static const struct random_poly_info random_poly_info = -{ - { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }, - { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 } -}; - - - - -/* Initialize the random number generator based on the given seed. If the - type is the trivial no-state-information type, just remember the seed. - Otherwise, initializes state[] based on the given "seed" via a linear - congruential generator. Then, the pointers are set to known locations - that are exactly rand_sep places apart. Lastly, it cycles the state - information a given number of times to get rid of any initial dependencies - introduced by the L.C.R.N.G. Note that the initialization of randtbl[] - for default usage relies on values produced by this routine. */ -int -__srandom_r (seed, buf) - unsigned int seed; - struct random_data *buf; -{ - int type; - int32_t *state; - long int i; - long int word; - int32_t *dst; - int kc; - - if (buf == NULL) - goto fail; - type = buf->rand_type; - if ((unsigned int) type >= MAX_TYPES) - goto fail; - - state = buf->state; - /* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */ - if (seed == 0) - seed = 1; - state[0] = seed; - if (type == TYPE_0) - goto done; - - dst = state; - word = seed; - kc = buf->rand_deg; - for (i = 1; i < kc; ++i) - { - /* This does: - state[i] = (16807 * state[i - 1]) % 2147483647; - but avoids overflowing 31 bits. */ - long int hi = word / 127773; - long int lo = word % 127773; - word = 16807 * lo - 2836 * hi; - if (word < 0) - word += 2147483647; - *++dst = word; - } - - buf->fptr = &state[buf->rand_sep]; - buf->rptr = &state[0]; - kc *= 10; - while (--kc >= 0) - { - int32_t discard; - (void) __random_r (buf, &discard); - } - - done: - return 0; - - fail: - return -1; -} - - -/* Initialize the state information in the given array of N bytes for - future random number generation. Based on the number of bytes we - are given, and the break values for the different R.N.G.'s, we choose - the best (largest) one we can and set things up for it. srandom is - then called to initialize the state information. Note that on return - from srandom, we set state[-1] to be the type multiplexed with the current - value of the rear pointer; this is so successive calls to initstate won't - lose this information and will be able to restart with setstate. - Note: The first thing we do is save the current state, if any, just like - setstate so that it doesn't matter when initstate is called. - Returns a pointer to the old state. */ -int -__initstate_r (seed, arg_state, n, buf) - unsigned int seed; - char *arg_state; - size_t n; - struct random_data *buf; -{ - int type; - int degree; - int separation; - int32_t *state; - - if (buf == NULL) - goto fail; - - if (n >= BREAK_3) - type = n < BREAK_4 ? TYPE_3 : TYPE_4; - else if (n < BREAK_1) - { - if (n < BREAK_0) - { - __set_errno (EINVAL); - goto fail; - } - type = TYPE_0; - } - else - type = n < BREAK_2 ? TYPE_1 : TYPE_2; - - degree = random_poly_info.degrees[type]; - separation = random_poly_info.seps[type]; - - buf->rand_type = type; - buf->rand_sep = separation; - buf->rand_deg = degree; - state = &((int32_t *) arg_state)[1]; /* First location. */ - /* Must set END_PTR before srandom. */ - buf->end_ptr = &state[degree]; - - buf->state = state; - - __srandom_r (seed, buf); - - state[-1] = TYPE_0; - if (type != TYPE_0) - state[-1] = (buf->rptr - state) * MAX_TYPES + type; - - return 0; - - fail: - __set_errno (EINVAL); - return -1; -} - - -/* Restore the state from the given state array. - Note: It is important that we also remember the locations of the pointers - in the current state information, and restore the locations of the pointers - from the old state information. This is done by multiplexing the pointer - location into the zeroth word of the state information. Note that due - to the order in which things are done, it is OK to call setstate with the - same state as the current state - Returns a pointer to the old state information. */ -int -__setstate_r (arg_state, buf) - char *arg_state; - struct random_data *buf; -{ - int32_t *new_state = 1 + (int32_t *) arg_state; - int type; - int old_type; - int32_t *old_state; - int degree; - int separation; - - if (arg_state == NULL || buf == NULL) - goto fail; - - old_type = buf->rand_type; - old_state = buf->state; - if (old_type == TYPE_0) - old_state[-1] = TYPE_0; - else - old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type; - - type = new_state[-1] % MAX_TYPES; - if (type < TYPE_0 || type > TYPE_4) - goto fail; - - buf->rand_deg = degree = random_poly_info.degrees[type]; - buf->rand_sep = separation = random_poly_info.seps[type]; - buf->rand_type = type; - - if (type != TYPE_0) - { - int rear = new_state[-1] / MAX_TYPES; - buf->rptr = &new_state[rear]; - buf->fptr = &new_state[(rear + separation) % degree]; - } - buf->state = new_state; - /* Set end_ptr too. */ - buf->end_ptr = &new_state[degree]; - - return 0; - - fail: - __set_errno (EINVAL); - return -1; -} - - -/* If we are using the trivial TYPE_0 R.N.G., just do the old linear - congruential bit. Otherwise, we do our fancy trinomial stuff, which is the - same in all the other cases due to all the global variables that have been - set up. The basic operation is to add the number at the rear pointer into - the one at the front pointer. Then both pointers are advanced to the next - location cyclically in the table. The value returned is the sum generated, - reduced to 31 bits by throwing away the "least random" low bit. - Note: The code takes advantage of the fact that both the front and - rear pointers can't wrap on the same call by not testing the rear - pointer if the front one has wrapped. Returns a 31-bit random number. */ - -int -__random_r (buf, result) - struct random_data *buf; - int32_t *result; -{ - int32_t *state; - - if (buf == NULL || result == NULL) - goto fail; - - state = buf->state; - - if (buf->rand_type == TYPE_0) - { - int32_t val = state[0]; - val = ((state[0] * 1103515245) + 12345) & 0x7fffffff; - state[0] = val; - *result = val; - } - else - { - int32_t *fptr = buf->fptr; - int32_t *rptr = buf->rptr; - int32_t *end_ptr = buf->end_ptr; - int32_t val; - - val = *fptr += *rptr; - /* Chucking least random bit. */ - *result = (val >> 1) & 0x7fffffff; - ++fptr; - if (fptr >= end_ptr) - { - fptr = state; - ++rptr; - } - else - { - ++rptr; - if (rptr >= end_ptr) - rptr = state; - } - buf->fptr = fptr; - buf->rptr = rptr; - } - return 0; - - fail: - __set_errno (EINVAL); - return -1; -} - -/* Copyright (C) 1995 Free Software Foundation - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* - * This is derived from the Berkeley source: - * @(#)random.c 5.5 (Berkeley) 7/6/88 - * It was reworked for the GNU C Library by Roland McGrath. - * Rewritten to use reentrant functions by Ulrich Drepper, 1995. - */ - -/* - Copyright (C) 1983 Regents of the University of California. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE.*/ - -#include -#include -#include - - -/* An improved random number generation package. In addition to the standard - rand()/srand() like interface, this package also has a special state info - interface. The initstate() routine is called with a seed, an array of - bytes, and a count of how many bytes are being passed in; this array is - then initialized to contain information for random number generation with - that much state information. Good sizes for the amount of state - information are 32, 64, 128, and 256 bytes. The state can be switched by - calling the setstate() function with the same array as was initialized - with initstate(). By default, the package runs with 128 bytes of state - information and generates far better random numbers than a linear - congruential generator. If the amount of state information is less than - 32 bytes, a simple linear congruential R.N.G. is used. Internally, the - state information is treated as an array of longs; the zeroth element of - the array is the type of R.N.G. being used (small integer); the remainder - of the array is the state information for the R.N.G. Thus, 32 bytes of - state information will give 7 longs worth of state information, which will - allow a degree seven polynomial. (Note: The zeroth word of state - information also has some other information stored in it; see setstate - for details). The random number generation technique is a linear feedback - shift register approach, employing trinomials (since there are fewer terms - to sum up that way). In this approach, the least significant bit of all - the numbers in the state table will act as a linear feedback shift register, - and will have period 2^deg - 1 (where deg is the degree of the polynomial - being used, assuming that the polynomial is irreducible and primitive). - The higher order bits will have longer periods, since their values are - also influenced by pseudo-random carries out of the lower bits. The - total period of the generator is approximately deg*(2**deg - 1); thus - doubling the amount of state information has a vast influence on the - period of the generator. Note: The deg*(2**deg - 1) is an approximation - only good for large deg, when the period of the shift register is the - dominant factor. With deg equal to seven, the period is actually much - longer than the 7*(2**7 - 1) predicted by this formula. */ - - - -/* For each of the currently supported random number generators, we have a - break value on the amount of state information (you need at least this many - bytes of state info to support this random number generator), a degree for - the polynomial (actually a trinomial) that the R.N.G. is based on, and - separation between the two lower order coefficients of the trinomial. */ - -/* Linear congruential. */ -#define TYPE_0 0 -#define BREAK_0 8 -#define DEG_0 0 -#define SEP_0 0 - -/* x**7 + x**3 + 1. */ -#define TYPE_1 1 -#define BREAK_1 32 -#define DEG_1 7 -#define SEP_1 3 - -/* x**15 + x + 1. */ -#define TYPE_2 2 -#define BREAK_2 64 -#define DEG_2 15 -#define SEP_2 1 - -/* x**31 + x**3 + 1. */ -#define TYPE_3 3 -#define BREAK_3 128 -#define DEG_3 31 -#define SEP_3 3 - -/* x**63 + x + 1. */ -#define TYPE_4 4 -#define BREAK_4 256 -#define DEG_4 63 -#define SEP_4 1 - - -/* Array versions of the above information to make code run faster. - Relies on fact that TYPE_i == i. */ - -#define MAX_TYPES 5 /* Max number of types above. */ - - -/* Initially, everything is set up as if from: - initstate(1, randtbl, 128); - Note that this initialization takes advantage of the fact that srandom - advances the front and rear pointers 10*rand_deg times, and hence the - rear pointer which starts at 0 will also end up at zero; thus the zeroth - element of the state information, which contains info about the current - position of the rear pointer is just - (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */ - -static int32_t randtbl[DEG_3 + 1] = - { - TYPE_3, - - -1726662223, 379960547, 1735697613, 1040273694, 1313901226, - 1627687941, -179304937, -2073333483, 1780058412, -1989503057, - -615974602, 344556628, 939512070, -1249116260, 1507946756, - -812545463, 154635395, 1388815473, -1926676823, 525320961, - -1009028674, 968117788, -123449607, 1284210865, 435012392, - -2017506339, -911064859, -370259173, 1132637927, 1398500161, - -205601318, - }; - - -static struct random_data unsafe_state = - { -/* FPTR and RPTR are two pointers into the state info, a front and a rear - pointer. These two pointers are always rand_sep places aparts, as they - cycle through the state information. (Yes, this does mean we could get - away with just one pointer, but the code for random is more efficient - this way). The pointers are left positioned as they would be from the call: - initstate(1, randtbl, 128); - (The position of the rear pointer, rptr, is really 0 (as explained above - in the initialization of randtbl) because the state table pointer is set - to point to randtbl[1] (as explained below).) */ - - .fptr = &randtbl[SEP_3 + 1], - .rptr = &randtbl[1], - -/* The following things are the pointer to the state information table, - the type of the current generator, the degree of the current polynomial - being used, and the separation between the two pointers. - Note that for efficiency of random, we remember the first location of - the state information, not the zeroth. Hence it is valid to access - state[-1], which is used to store the type of the R.N.G. - Also, we remember the last location, since this is more efficient than - indexing every time to find the address of the last element to see if - the front and rear pointers have wrapped. */ - - .state = &randtbl[1], - - .rand_type = TYPE_3, - .rand_deg = DEG_3, - .rand_sep = SEP_3, - - .end_ptr = &randtbl[sizeof (randtbl) / sizeof (randtbl[0])] -}; - -/* POSIX.1c requires that there is mutual exclusion for the `rand' and - `srand' functions to prevent concurrent calls from modifying common - data. */ - -/* Initialize the random number generator based on the given seed. If the - type is the trivial no-state-information type, just remember the seed. - Otherwise, initializes state[] based on the given "seed" via a linear - congruential generator. Then, the pointers are set to known locations - that are exactly rand_sep places apart. Lastly, it cycles the state - information a given number of times to get rid of any initial dependencies - introduced by the L.C.R.N.G. Note that the initialization of randtbl[] - for default usage relies on values produced by this routine. */ -void -__srandom (x) - unsigned int x; -{ - (void) __srandom_r (x, &unsafe_state); -} - - -/* Initialize the state information in the given array of N bytes for - future random number generation. Based on the number of bytes we - are given, and the break values for the different R.N.G.'s, we choose - the best (largest) one we can and set things up for it. srandom is - then called to initialize the state information. Note that on return - from srandom, we set state[-1] to be the type multiplexed with the current - value of the rear pointer; this is so successive calls to initstate won't - lose this information and will be able to restart with setstate. - Note: The first thing we do is save the current state, if any, just like - setstate so that it doesn't matter when initstate is called. - Returns a pointer to the old state. */ -char * -__initstate (seed, arg_state, n) - unsigned int seed; - char *arg_state; - size_t n; -{ - int32_t *ostate; - - - ostate = &unsafe_state.state[-1]; - - __initstate_r (seed, arg_state, n, &unsafe_state); - - - return (char *) ostate; -} - - -/* Restore the state from the given state array. - Note: It is important that we also remember the locations of the pointers - in the current state information, and restore the locations of the pointers - from the old state information. This is done by multiplexing the pointer - location into the zeroth word of the state information. Note that due - to the order in which things are done, it is OK to call setstate with the - same state as the current state - Returns a pointer to the old state information. */ -char * -__setstate (arg_state) - char *arg_state; -{ - int32_t *ostate; - - - ostate = &unsafe_state.state[-1]; - - if (__setstate_r (arg_state, &unsafe_state) < 0) - ostate = NULL; - - - return (char *) ostate; -} - - -/* If we are using the trivial TYPE_0 R.N.G., just do the old linear - congruential bit. Otherwise, we do our fancy trinomial stuff, which is the - same in all the other cases due to all the global variables that have been - set up. The basic operation is to add the number at the rear pointer into - the one at the front pointer. Then both pointers are advanced to the next - location cyclically in the table. The value returned is the sum generated, - reduced to 31 bits by throwing away the "least random" low bit. - Note: The code takes advantage of the fact that both the front and - rear pointers can't wrap on the same call by not testing the rear - pointer if the front one has wrapped. Returns a 31-bit random number. */ - -long int -__random (void) -{ - int32_t retval; - - - (void) __random_r (&unsafe_state, &retval); - - - return retval; -} - -long int glibc_random(void) { return __random(); } -void glibc_srandom(unsigned int seed) { __srandom(seed); } -char *glibc_initstate(unsigned int seed, char *state, size_t n) { return __initstate(seed,state,n); } -char *glibc_setstate(char *state) { return __setstate(state); } -#endif diff --git a/common/diet/time.c b/common/diet/time.c deleted file mode 100644 index 11f963c31..000000000 --- a/common/diet/time.c +++ /dev/null @@ -1,20 +0,0 @@ -#ifdef __dietlibc__ -#include -#warning "hardcoded time zone as GMT+8!" -extern void __maplocaltime(void); -extern time_t __tzfile_map(time_t t, int *isdst, int forward); -extern time_t timegm(struct tm *const t); - -time_t mktime(register struct tm* const t) { - time_t x=timegm(t); - x-=8*3600; - return x; -} - -struct tm* localtime_r(const time_t* t, struct tm* r) { - time_t tmp; - tmp=*t; - tmp+=8*3600; - return gmtime_r(&tmp,r); -} -#endif diff --git a/common/sys/lock.c b/common/sys/lock.c index 4b28bab1d..a8a6a04fc 100644 --- a/common/sys/lock.c +++ b/common/sys/lock.c @@ -7,13 +7,13 @@ * @param mode F_WRLCK, F_UNLCK */ void -PttLock(int fd, int start, int size, int mode) +PttLock(int fd, int offset, int size, int mode) { static struct flock lock_it; int ret; - lock_it.l_whence = SEEK_CUR;/* from current point */ - lock_it.l_start = start; /* -"- */ + lock_it.l_whence = SEEK_SET;/* provided offset, we should use SEEK_SET */ + lock_it.l_start = offset; /* -"- */ lock_it.l_len = size; /* length of data */ lock_it.l_type = mode; /* set exclusive/write lock */ lock_it.l_pid = 0; /* pid not actually interesting */ diff --git a/daemon/boardd/board_service_impl.cpp b/daemon/boardd/board_service_impl.cpp index 6cc13c9e7..ca1c48fee 100644 --- a/daemon/boardd/board_service_impl.cpp +++ b/daemon/boardd/board_service_impl.cpp @@ -208,13 +208,11 @@ Status DoSelect(const std::string &fn, const std::string &consistency_token, select_result_t result; Evbuffer buf; - RETURN_ON_FAIL(SelectStatus(select_article(buf.Get(), &result, &spec))); + RETURN_ON_FAIL(SelectStatus(select_article(buf.GetBuffer(), &result, &spec))); if (!buf.ConvertUTF8()) return Status(StatusCode::INTERNAL, "convert utf8 failed"); - content->mutable_content()->assign( - reinterpret_cast(evbuffer_pullup(buf.Get(), -1)), - evbuffer_get_length(buf.Get())); + content->mutable_content()->assign(buf.StringView()); content->set_consistency_token(result.cachekey); content->set_offset(result.sel_offset); content->set_length(result.sel_size); diff --git a/daemon/boardd/evbuffer.cpp b/daemon/boardd/evbuffer.cpp index d7a32d1ea..6e40b827e 100644 --- a/daemon/boardd/evbuffer.cpp +++ b/daemon/boardd/evbuffer.cpp @@ -1,4 +1,5 @@ #include "daemon/boardd/evbuffer.hpp" +#include extern "C" { #include } @@ -14,3 +15,8 @@ bool Evbuffer::ConvertUTF8() { buf_ = evbuffer_new(); return false; } + +std::string_view Evbuffer::StringView() { + size_t len = evbuffer_get_length(buf_); + return {reinterpret_cast(evbuffer_pullup(buf_, len)), len}; +} diff --git a/daemon/boardd/evbuffer.hpp b/daemon/boardd/evbuffer.hpp index 704ba5aef..ddcf30902 100644 --- a/daemon/boardd/evbuffer.hpp +++ b/daemon/boardd/evbuffer.hpp @@ -1,6 +1,7 @@ #ifndef _PTTBBS_DAEMON_BOARDD_EVBUFFER_HPP_ #define _PTTBBS_DAEMON_BOARDD_EVBUFFER_HPP_ #include "daemon/boardd/macros.hpp" +#include extern "C" { #include #include "daemon/boardd/boardd.h" @@ -11,8 +12,9 @@ class Evbuffer final { Evbuffer(); ~Evbuffer(); - evbuffer *Get() { return buf_; } + evbuffer *GetBuffer() { return buf_; } bool ConvertUTF8(); + std::string_view StringView(); private: DISABLE_COPY_AND_ASSIGN(Evbuffer); diff --git a/daemon/boardd/macros.hpp b/daemon/boardd/macros.hpp index acb7f9034..e0fe74f30 100644 --- a/daemon/boardd/macros.hpp +++ b/daemon/boardd/macros.hpp @@ -7,7 +7,7 @@ #define RETURN_ON_FAIL(Expr) \ do { \ - Status s = (Expr); \ + auto s = (Expr); \ if (!s.ok()) \ return s; \ } while (0) diff --git a/daemon/mand/Makefile b/daemon/mand/Makefile index 9ba85ba84..bdfc97e0f 100644 --- a/daemon/mand/Makefile +++ b/daemon/mand/Makefile @@ -35,7 +35,7 @@ UTILDIR= $(SRCROOT)/util UTILOBJ= $(UTILDIR)/util_var.o COMMONFLAGS= -I$(SRCROOT) -I../boardd -CXXFLAGS+= -std=c++11 $(COMMONFLAGS) +CXXFLAGS+= -std=c++17 $(COMMONFLAGS) CFLAGS+= $(LIBEVENT_CFLAGS) $(COMMONFLAGS) LDFLAGS+= diff --git a/daemon/mand/man_service_impl.cpp b/daemon/mand/man_service_impl.cpp index 8abd030a7..fb22970b7 100644 --- a/daemon/mand/man_service_impl.cpp +++ b/daemon/mand/man_service_impl.cpp @@ -106,14 +106,12 @@ Status ManServiceImpl::Article(ServerContext *context, select_result_t result; Evbuffer buf; - if (select_article(buf.Get(), &result, &spec) < 0) + if (select_article(buf.GetBuffer(), &result, &spec) < 0) return Status(StatusCode::INTERNAL, "select_article failed"); if (!buf.ConvertUTF8()) return Status(StatusCode::INTERNAL, "convert utf8 failed"); - rep->mutable_content()->assign( - reinterpret_cast(evbuffer_pullup(buf.Get(), -1)), - evbuffer_get_length(buf.Get())); + rep->mutable_content()->assign(buf.StringView()); rep->set_cache_key(result.cachekey); rep->set_file_size(result.size); rep->set_selected_offset(result.sel_offset); diff --git a/docs/pfterm.txt b/docs/pfterm.txt index a97bd62c2..bb7432eb7 100644 --- a/docs/pfterm.txt +++ b/docs/pfterm.txt @@ -6,8 +6,9 @@ API Manual 函式說明手冊 - VERSION 1.1 - 最後更新: 2007/12/24 18:00 piaip + VERSION 1.2 + v1.1: 2007/12/24 18:00 piaip + 最後更新: 2023/06/01 01:55 IID ============================================================================= @@ -32,9 +33,16 @@ // initialization 初始化 void initscr (void); 初始系統 -int resizeterm (int rows, int cols); 調整視窗大小為(rows,col) +int resizeterm (int rows, int cols); 調整畫面大小為(rows,cols) +int resizeterm_within( 調整顯示範圍為終端機畫面的部分區域: + int rows, int cols, 顯示範圍大小為(rows,cols), + int rows_full, int cols_full); 實際終端機則為(rows_full,cols_full) int endwin (void); 結束系統 + resizeterm() 假設顯示範圍大小 (rows,cols) 即為實際終端機大小。 + 但當顯示範圍與實際終端機大小不符時,畫面捲動行為將會不正確; + 可用 resizeterm_within() 指定實際終端機大小 (rows_full,cols_full)。 + // cursor 游標 void getyx (int *y, int *x); 取得目前游標位置 void move (int y, int x); 移動游標 diff --git a/include/bbs.h b/include/bbs.h index 7892f646a..8514feb42 100644 --- a/include/bbs.h +++ b/include/bbs.h @@ -38,10 +38,6 @@ extern "C" { #include "cmsys.h" #include "cmbbs.h" -#ifdef __dietlibc__ -#include "cmdiet.h" -#endif - #include "ansi.h" #include "vtkbd.h" #include "vtuikit.h" diff --git a/include/cmdiet.h b/include/cmdiet.h deleted file mode 100644 index 3e56a1fe9..000000000 --- a/include/cmdiet.h +++ /dev/null @@ -1,17 +0,0 @@ -/* $Id$ */ - -#ifndef CMDIET_H -#define CMDIET_H - -#ifdef __dietlibc__ -#define random glibc_random -#define srandom glibc_srandom -#define initstate glibc_initstate -#define setstate glibc_setstate -long int random(void); -void srandom(unsigned int seed); -char *initstate(unsigned int seed, char *state, size_t n); -char *setstate(char *state); -#endif - -#endif diff --git a/include/proto.h b/include/proto.h index b2ccb6847..c14027ec6 100644 --- a/include/proto.h +++ b/include/proto.h @@ -390,6 +390,7 @@ int m_read(void); int doforward(const char *direct, const fileheader_t *fh, int mode); int mail_reply(int ent, fileheader_t *fhdr, const char *direct); int bsmtp(const char *fpath, const char *title, const char *rcpt, const char *from); +int notify_password_change(const char *userid, const char *email); void hold_mail(const char *fpath, const char *receiver, const char *title); void m_init(void); int chkmailbox(void); @@ -577,11 +578,10 @@ int regform_estimate_queuesize(); void ensure_user_agreement_version(); void new_register(void); void check_register(void); -bool user_has_email(const userec_t *u); bool check_email_allow_reject_lists( char *email, const char **errmsg, const char **notice_file); void register_mail_complete_and_exit(); -void change_contact_email(); +int change_contact_email(bool skip_same_email_check); /* register_sms */ void u_sms_verification(); @@ -596,6 +596,7 @@ ChessInfo* reversi_replay(FILE* fp); /* screen/pfterm (ncurses-like) */ void initscr (void); int resizeterm (int rows, int cols); +int resizeterm_within(int rows, int cols, int rows_full, int cols_full); void getyx (int *py, int *px); void move (int y, int x); void clear (void); diff --git a/mbbsd/Makefile b/mbbsd/Makefile index 70d8a9fc4..ae98b9756 100644 --- a/mbbsd/Makefile +++ b/mbbsd/Makefile @@ -24,16 +24,6 @@ OBJS:= admin.o assess.o edit.o xyz.o var.o vote.o voteboard.o comments.o \ $(UIOBJS) $(PAGEROBJS) $(PLUGOBJS) \ $(CHESSOBJS) $(GAMEOBJS) -####################################################################### -# special library (DIET) configuration -####################################################################### - -.if defined(DIET) -LDFLAGS+= -L$(SRCROOT)/common/diet -LDLIBS+= -ldiet -DIETCC:= diet -Os -.endif - # reduce .bss align overhead .if !defined(DEBUG) && $(OSTYPE)!="Darwin" LDFLAGS+=-Wl,--sort-common @@ -119,9 +109,6 @@ testsz: $(SRCROOT)/pttbbs.conf $(SRCROOT)/include/*.h testsz.c @./testsz @printf "\033[0;1;32mData size configuration OK\033[m\n" -mbbsd.o: mbbsd.c $(SRCROOT)/include/var.h - $(DIETCC) $(CC) $(CFLAGS) -c $< - ctags: ctags *.c $(SRCROOT)/include/*.h $(SRCROOT)/common/sys/*.c $(SRCROOT)/common/bbs/*.c diff --git a/mbbsd/angel.c b/mbbsd/angel.c index f364666c3..2368dff71 100644 --- a/mbbsd/angel.c +++ b/mbbsd/angel.c @@ -759,7 +759,7 @@ FindAngel(void){ } #ifdef BN_NEWBIE -static inline void +static void GotoNewHand(){ char old_board[IDLEN + 1] = ""; int canRead = 1; @@ -785,7 +785,7 @@ GotoNewHand(){ #endif -static inline void +static void NoAngelFound(const char* msg){ // don't worry about the screen - // it should have been backuped before entering here. @@ -807,7 +807,7 @@ NoAngelFound(const char* msg){ #endif } -static inline void +static void AngelNotOnline(){ char msg_fn[PATHLEN]; diff --git a/mbbsd/announce.c b/mbbsd/announce.c index 59fe39156..b64650ec0 100644 --- a/mbbsd/announce.c +++ b/mbbsd/announce.c @@ -1081,7 +1081,7 @@ isvisible_man(const menu_t * me) return 0; if (fhdr->filemode & FILE_HIDE) { - if (currstat == ANNOUNCE || + if (currstat == ANNOUNCE || currstat == EDITEXP || !is_hidden_board_friend(me->bid, currutmp->uid)) return 0; } diff --git a/mbbsd/bbslua.c b/mbbsd/bbslua.c index 782660fd7..222edc729 100644 --- a/mbbsd/bbslua.c +++ b/mbbsd/bbslua.c @@ -411,6 +411,8 @@ bl_getstr(lua_State* L) if (n > 2) pmsg = lua_tostring(L, 3); + echo &= ~GCARRY; // avoid assertion failure + if (len < 2) len = 2; if (len >= (int)sizeof(buf)) diff --git a/mbbsd/board.c b/mbbsd/board.c index 5c1b7a1ff..636ad715f 100644 --- a/mbbsd/board.c +++ b/mbbsd/board.c @@ -54,18 +54,6 @@ static time4_t last_save_fav_and_brc; #define IS_LISTING_FAV() (yank_flag == 0) #define IS_LISTING_BRD() (yank_flag == 1) -inline int getbid(const boardheader_t *fh) -{ - return (fh - bcache); -} -inline boardheader_t *getparent(const boardheader_t *fh) -{ - if(fh->parent>0) - return getbcache(fh->parent); - else - return NULL; -} - // 程式中有特別用途所以不得自行 post / 修改的看板 int is_readonly_board(const char *bname) @@ -153,7 +141,7 @@ save_brdbuf(void) fav_free(); } -static inline int +static int HasBoardPermNormally(boardheader_t *bptr) { register int level, brdattr; @@ -1330,7 +1318,7 @@ brdlist_foot(void) } -static inline const char * +static const char * make_class_color(char *name) { /* 0;34 is too dark */ diff --git a/mbbsd/brc.c b/mbbsd/brc.c index fa0afac72..c44dc2183 100644 --- a/mbbsd/brc.c +++ b/mbbsd/brc.c @@ -137,7 +137,7 @@ brc_putrecord(char *ptr, char *endp, brcbid_t bid, return ptr; } -static inline int +static int brc_enlarge_buf(void) { char *buffer; @@ -175,7 +175,7 @@ brc_enlarge_buf(void) #undef THE_FREE } -static inline void +static void brc_get_buf(int size){ if (!size) brc_alloc = BRC_BLOCKSIZE; @@ -187,7 +187,7 @@ brc_get_buf(int size){ assert(brc_buf); } -static inline void +static void brc_insert_record(brcbid_t bid, brcnbrd_t num, const brc_rec* list) { char *ptr; diff --git a/mbbsd/ccw.c b/mbbsd/ccw.c index bc9b334ab..6095300b0 100644 --- a/mbbsd/ccw.c +++ b/mbbsd/ccw.c @@ -98,7 +98,7 @@ typedef struct CCW_CTX { // CCW helpers #ifndef DEBUG -# define CCW_PROTO static inline +# define CCW_PROTO static #else # define CCW_PROTO #endif diff --git a/mbbsd/chess.c b/mbbsd/chess.c index dff841e55..96756567a 100644 --- a/mbbsd/chess.c +++ b/mbbsd/chess.c @@ -225,7 +225,7 @@ ChessRedraw(const ChessInfo* info) ChessDrawLine(info, i); } -inline static int +static int ChessTimeCountDownCalc(ChessInfo* info, int who, int length) { info->lefttime[who] -= length; @@ -272,7 +272,7 @@ ChessStepMade(ChessInfo* info, int who) /* * Start of the network communication function. */ -inline static ChessStepType +static ChessStepType ChessRecvMove(ChessInfo* info, int sock, void *step) { if (read(sock, step, info->constants->step_entry_size) @@ -281,7 +281,7 @@ ChessRecvMove(ChessInfo* info, int sock, void *step) return *(ChessStepType*) step; } -inline static int +static int ChessSendMove(ChessInfo* info, int sock, const void *step) { if (write(sock, step, info->constants->step_entry_size) @@ -290,7 +290,7 @@ ChessSendMove(ChessInfo* info, int sock, const void *step) return 1; } -inline static int +static int ChessStepSendOpposite(ChessInfo* info, const void* step) { void (*orig_handler)(int); @@ -310,7 +310,7 @@ ChessStepSendOpposite(ChessInfo* info, const void* step) return result; } -inline static void +static void ChessStepBroadcast(ChessInfo* info, const void *step) { ChessBroadcastListNode *p = &(info->broadcast_list.head); @@ -350,7 +350,7 @@ ChessMessageSend(ChessInfo* info, ChessStepType type) return ChessStepSend(info, &type); } -static inline int +static int ChessCheckAlive(ChessInfo* info) { ChessStepType type = CHESS_STEP_NOP; @@ -373,7 +373,7 @@ ChessStepReceive(ChessInfo* info, void* step) return result; } -inline static void +static void ChessReplayUntil(ChessInfo* info, int n) { const void* step; @@ -1649,7 +1649,7 @@ ChessShowRequest(void) } } -inline static const char* +static const char* ChessTimeStr(int second) { static char buf[10]; @@ -1724,7 +1724,7 @@ ChessDrawExtraInfo(const ChessInfo* info, int line, int space) prints(ANSI_COLOR(1;33) "%s" ANSI_RESET, info->myturn == info->turn ? "輪到你下棋了" : "等待對方下棋"); - } else if (line == CHESS_DRAWING_REAL_STEP_ROW && info->last_movestr) { + } else if (line == CHESS_DRAWING_REAL_STEP_ROW && info->last_movestr[0]) { outs(info->last_movestr); } else if (line == CHESS_DRAWING_REAL_TIME_ROW1) { if (info->lefthand[0]) diff --git a/mbbsd/edit.c b/mbbsd/edit.c index 9f82115d7..3f76d4ef8 100644 --- a/mbbsd/edit.c +++ b/mbbsd/edit.c @@ -54,7 +54,6 @@ #if 0 #define DEBUG -#define inline #endif /** @@ -182,7 +181,7 @@ static editor_internal_t *curr_buf = NULL; static const char * const fp_bak = "bak"; // forward declare -static inline int has_block_selection(void); +static int has_block_selection(void); static textline_t * alloc_line(short length); static void block_cancel(void); @@ -283,7 +282,7 @@ fix_cursor(char *str, int pos, int dir) #endif /* 記憶體管理與編輯處理 */ -static inline void +static void edit_buffer_constructor(editor_internal_t *buf) { /* all unspecified columns are 0 */ @@ -297,7 +296,7 @@ edit_buffer_constructor(editor_internal_t *buf) } -static inline void +static void enter_edit_buffer(void) { editor_internal_t *p = curr_buf; @@ -307,7 +306,7 @@ enter_edit_buffer(void) edit_buffer_constructor(curr_buf); } -static inline void +static void free_line(textline_t *p) { if (p == curr_buf->oldcurrline) @@ -318,7 +317,7 @@ free_line(textline_t *p) free(p); } -static inline void +static void edit_buffer_destructor(void) { textline_t *p, *pnext; @@ -335,7 +334,7 @@ edit_buffer_destructor(void) free(curr_buf->sitesig_string); } -static inline void +static void exit_edit_buffer(void) { editor_internal_t *p = curr_buf; @@ -406,7 +405,7 @@ n2ansi(short nx, textline_t * line) /* 螢幕處理:輔助訊息、顯示編輯內容 */ -static inline void +static void show_phone_mode_panel(void) { int i; @@ -515,7 +514,7 @@ edit_buffer_check_healthy(textline_t *line) #endif } -static inline int visible_window_height(void); +static int visible_window_height(void); static void edit_check_healthy() @@ -597,7 +596,7 @@ edit_check_healthy() /** * return the middle line of the window. */ -static inline int +static int middle_line(void) { return p_lines / 2 + 1; @@ -624,7 +623,7 @@ back_line(textline_t * pos, int num, bool changeln) return pos; } -static inline int +static int visible_window_height(void) { if (curr_buf->phone_mode) @@ -657,7 +656,7 @@ forward_line(textline_t * pos, int num, bool changeln) /** * move the cursor to the next line with ansimode fixed. */ -static inline void +static void cursor_to_next_line(void) { short pos; @@ -682,7 +681,7 @@ cursor_to_next_line(void) /** * opposite to cursor_to_next_line. */ -static inline void +static void cursor_to_prev_line(void) { short pos; @@ -704,7 +703,7 @@ cursor_to_prev_line(void) } } -static inline void +static void edit_window_adjust(void) { int offset = 0; @@ -731,7 +730,7 @@ edit_window_adjust(void) } } -static inline void +static void edit_window_adjust_middle(void) { if (curr_buf->currln < middle_line()) { @@ -2081,7 +2080,7 @@ write_file(const char *fpath, int saveheader, char mytitle[STRLEN], return 0; } -static inline int +static int has_block_selection(void) { return curr_buf->blockln >= 0; @@ -2104,7 +2103,7 @@ block_cancel(void) } } -static inline void +static void setup_block_begin_end(textline_t **begin, textline_t **end) { if (curr_buf->currln >= curr_buf->blockln) { @@ -2919,7 +2918,7 @@ detect_attr(const char *ps, size_t len) return attr; } -static inline void +static void display_textline_internal(textline_t *p, int i) { short tmp; @@ -3364,7 +3363,7 @@ insert_ansi_code(void) curr_buf->insert_mode = ch; } -static inline void +static void phone_mode_switch(void) { if (curr_buf->phone_mode) @@ -3403,7 +3402,7 @@ phone_char(char c) * When get the key for phone mode, handle it (e.g. edit_msg) and return the * key. Otherwise return 0. */ -static inline char +static char phone_mode_filter(char ch) { if (!curr_buf->phone_mode) diff --git a/mbbsd/fav.c b/mbbsd/fav.c index f79dfcea5..57bde8b8b 100644 --- a/mbbsd/fav.c +++ b/mbbsd/fav.c @@ -61,15 +61,15 @@ static void fav_free_branch(fav_t *fp); * cast_(board|line|folder) 一族用於將 base class 作轉型 * (不檢查實際 data type) */ -inline static fav_board_t *cast_board(fav_type_t *p){ +static fav_board_t *cast_board(fav_type_t *p){ return (fav_board_t *)p->fp; } -inline static fav_line_t *cast_line(fav_type_t *p){ +static fav_line_t *cast_line(fav_type_t *p){ return (fav_line_t *)p->fp; } -inline static fav_folder_t *cast_folder(fav_type_t *p){ +static fav_folder_t *cast_folder(fav_type_t *p){ return (fav_folder_t *)p->fp; } @@ -103,11 +103,11 @@ inline int get_item_type(fav_type_t *ft){ /** * 將一個指定的 dir pointer 存下來,之後可用 fav_get_tmp_fav 來存用 */ -inline static void fav_set_tmp_folder(fav_t *fp){ +static void fav_set_tmp_folder(fav_t *fp){ fav_tmp = fp; } -inline static fav_t *fav_get_tmp_fav(void){ +static fav_t *fav_get_tmp_fav(void){ return fav_tmp; } @@ -156,11 +156,11 @@ static void fav_increase(fav_t *fp, fav_type_t *ft) fp->DataTail++; } -inline static int get_folder_num(fav_t *fp) { +static int get_folder_num(fav_t *fp) { return fp->nFolders; } -inline static int get_line_num(fav_t *fp) { +static int get_line_num(fav_t *fp) { return fp->nLines; } @@ -228,7 +228,7 @@ static int get_type_size(int type) return 0; } -inline static void* fav_malloc(int size){ +static void* fav_malloc(int size){ void *p; assert(size>0); p = (void *)malloc(size); @@ -240,7 +240,7 @@ inline static void* fav_malloc(int size){ /** * 只複製 fav_type_t */ -inline static void +static void fav_item_copy(fav_type_t *target, const fav_type_t *source){ target->type = source->type; target->attr = source->attr; @@ -391,20 +391,20 @@ inline int fav_stack_full(void){ return fav_stack_num >= FAV_MAXDEPTH; } -inline static int fav_stack_push_fav(fav_t *fp){ +static int fav_stack_push_fav(fav_t *fp){ if (fav_stack_full()) return -1; fav_stack[fav_stack_num++] = fp; return 0; } -inline static int fav_stack_push(fav_type_t *ft){ +static int fav_stack_push(fav_type_t *ft){ // if (ft->type != FAVT_FOLDER) // return -1; return fav_stack_push_fav(get_fav_folder(ft)); } -inline static void fav_stack_pop(void){ +static void fav_stack_pop(void){ fav_stack[--fav_stack_num] = NULL; } @@ -629,7 +629,7 @@ int fav_save(void) /** * remove ft (設為 invalid,實際上會等到 save 時才清除) */ -static inline void fav_free_item(fav_type_t *ft) +static void fav_free_item(fav_type_t *ft) { set_attr(ft, 0xFFFF, FALSE); } @@ -770,7 +770,7 @@ int fav_getid(fav_type_t *ft) return -1; } -inline static int is_maxsize(void){ +static int is_maxsize(void){ return fav_number >= MAX_FAV; } @@ -872,7 +872,7 @@ void move_in_current_folder(int from, int to) /** * allocate 一個 folder entry */ -inline static fav_t *alloc_folder_item(void){ +static fav_t *alloc_folder_item(void){ fav_t *fp = (fav_t *)fav_malloc(sizeof(fav_t)); fp->nAllocs = FAV_PRE_ALLOC; fp->favh = (fav_type_t *)fav_malloc(sizeof(fav_type_t) * FAV_PRE_ALLOC); @@ -993,7 +993,7 @@ static int remove_tagged_item(fav_t *fp, fav_type_t *ft) return fav_remove(fp, ft); } -inline static int fav_remove_tagged_item(fav_t *fp){ +static int fav_remove_tagged_item(fav_t *fp){ fav_dosomething_tagged_item(fp, remove_tagged_item); return 0; } @@ -1031,7 +1031,7 @@ static int add_and_remove_tag(fav_t *fp, fav_type_t *ft) return 0; } -inline static int fav_add_tagged_item(fav_t *fp){ +static int fav_add_tagged_item(fav_t *fp){ if (fp == fav_get_tmp_fav()) return -1; fav_dosomething_tagged_item(fp, add_and_remove_tag); @@ -1075,13 +1075,13 @@ void fav_add_all_tagged_item(void) fav_dosomething_all_tagged_item(fav_add_tagged_item); } -inline static int remove_tag(fav_t *fp GCC_UNUSED, fav_type_t *ft) +static int remove_tag(fav_t *fp GCC_UNUSED, fav_type_t *ft) { set_attr(ft, FAVH_TAG, FALSE); return 0; } -inline static int remove_tags(fav_t *fp) +static int remove_tags(fav_t *fp) { fav_dosomething_tagged_item(fp, remove_tag); return 0; diff --git a/mbbsd/friend.c b/mbbsd/friend.c index 462347f9e..d1dc264cb 100644 --- a/mbbsd/friend.c +++ b/mbbsd/friend.c @@ -58,7 +58,7 @@ setfriendfile(char *fpath, int type) setbfile(fpath, currboard, friend_file[type]); } -inline static int +static int friend_count(const char *fname) { return file_count_line(fname); @@ -395,7 +395,7 @@ friend_editdesc(const char *uident, int type) fclose(nfp); } -static inline void friend_load_real(int tosort, int maxf, +static void friend_load_real(int tosort, int maxf, short *destn, int *destar, const char *fn) { char genbuf[PATHLEN]; diff --git a/mbbsd/io.c b/mbbsd/io.c index 5d72558ce..54bde4470 100644 --- a/mbbsd/io.c +++ b/mbbsd/io.c @@ -333,7 +333,7 @@ process_pager_keys(int ch) static int i_newfd = 0; static struct timeval i_to, *i_top = NULL; -static inline void +static void add_io(int fd, int timeout) { i_newfd = fd; @@ -346,13 +346,13 @@ add_io(int fd, int timeout) i_top = NULL; } -static inline int +static int num_in_buf(void) { return vbuf_size(pvin); } -static inline void +static void drop_input(void) { vbuf_clear(pvin); @@ -363,7 +363,7 @@ drop_input(void) * =0 if nothing read * <0 if need to read again */ -static inline ssize_t +static ssize_t read_vin() { // Note: buf should be larger than pvin buffer size. unsigned char buf[IBUFSIZE]; @@ -502,7 +502,7 @@ dogetch(void) // virtual terminal keyboard context static VtkbdCtx vtkbd_ctx; -static inline int +static int igetch(void) { register int ch; @@ -562,7 +562,7 @@ igetch(void) * if f < 0, wait forever. * Return 1 if anything available. */ -static inline int +static int wait_input(float f, int bIgnoreBuf) { int sel = 0; diff --git a/mbbsd/mail.c b/mbbsd/mail.c index 94bfb56e7..40cb1a8e3 100644 --- a/mbbsd/mail.c +++ b/mbbsd/mail.c @@ -2575,3 +2575,20 @@ bsmtp(const char *fpath, const char *title, const char *rcpt, const char *from) return chrono; } #endif /* USE_BSMTP */ + +/* + * Simple wrapper to send password changed notification letter to + * designated email address. + */ +int notify_password_change(const char *userid, const char *email) +{ + char subject[128]; + int ret; + + snprintf(subject, sizeof(subject), " %s - %s (%s) - 密碼已變更", + BBSNAME, userid, fromhost); + + ret = bsmtp("etc/passwdchanged", subject, email, "non-exist"); + + return ret > 0 ? 0 : -1; +} diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c index 24eee1732..8023ad1a4 100644 --- a/mbbsd/mbbsd.c +++ b/mbbsd/mbbsd.c @@ -1036,7 +1036,7 @@ setup_utmp(int mode) nice(3); } -inline static void welcome_msg(void) +static void welcome_msg(void) { prints(ANSI_RESET " 歡迎您再度拜訪,上次您是從 " ANSI_COLOR(1;33) "%s" ANSI_COLOR(0;37) " 連往本站。" @@ -1044,7 +1044,7 @@ inline static void welcome_msg(void) pressanykey(); } -inline static void check_bad_login(void) +static void check_bad_login(void) { char genbuf[200]; setuserfile(genbuf, FN_BADLOGIN); @@ -1120,7 +1120,7 @@ check_bad_clients(void) { vmsg("謝謝您的合作。如果您想提供更多資訊歡迎至" BN_BUGREPORT "報告"); } -inline static void append_log_recent_login() +static void append_log_recent_login() { char buf[STRLEN], logfn[PATHLEN]; int szlogfn = 0, szlogentry = 0; @@ -1140,7 +1140,7 @@ inline static void append_log_recent_login() log_file(logfn, LOG_CREAT, buf); } -inline static void check_mailbox_quota(void) +static void check_mailbox_quota(void) { if (!HasUserPerm(PERM_READMAIL)) return; @@ -1157,7 +1157,7 @@ static void init_guest_info(void) } #if FOREIGN_REG_DAY > 0 -inline static void foreign_warning(void){ +static void foreign_warning(void){ if ((HasUserFlag(UF_FOREIGN)) && !(HasUserFlag(UF_LIVERIGHT))){ if (login_start_time - cuser.firstlogin > (FOREIGN_REG_DAY - 5) * 24 * 3600){ mail_muser(cuser, "[出入境管理局]", "etc/foreign_expired_warn"); diff --git a/mbbsd/nios.c b/mbbsd/nios.c index 3deb52ef3..7ccefdb31 100644 --- a/mbbsd/nios.c +++ b/mbbsd/nios.c @@ -44,7 +44,7 @@ #endif #ifndef DEBUG -#define CIN_PROTO static inline +#define CIN_PROTO static #define VKEY_PROTO inline #else #define CIN_PROTO diff --git a/mbbsd/pfterm.c b/mbbsd/pfterm.c index e6438a0c3..09bc1f0a1 100644 --- a/mbbsd/pfterm.c +++ b/mbbsd/pfterm.c @@ -241,7 +241,8 @@ typedef struct ftchar *dmap; // dirty map ftchar *dcmap; // processed display map ftattr attr; - int rows, cols; + int rows, cols; // the (possibly cropped) display region size + int rows_full, cols_full; // the full terminal size int y, x; int sy,sx; // stored cursor int mi; // map index, mi = current map and (1-mi) = old map @@ -346,6 +347,7 @@ static FlatTerm ft; // initialization void initscr (void); int resizeterm (int rows, int cols); +int resizeterm_within(int rows, int cols, int rows_full, int cols_full); int endwin (void); // attributes @@ -497,9 +499,19 @@ endwin(void) int resizeterm(int rows, int cols) +{ + // assume that the full terminal size == the display region size + return resizeterm_within(rows, cols, rows, cols); +} + +int +resizeterm_within(int rows, int cols, int rows_full, int cols_full) { int dirty = 0, mi = 0, i = 0; + ft.rows_full = rows_full; + ft.cols_full = cols_full; + rows = ranged(rows, FTSZ_MIN_ROW, FTSZ_MAX_ROW); cols = ranged(cols, FTSZ_MIN_COL, FTSZ_MAX_COL); @@ -2187,9 +2199,15 @@ fterm_rawscroll (int dy) // we are not going to preserve (rx,ry) // so don't use fterm_move*. if (dy > 0) - fterm_rawcmd2(ft.rows, 1, 1, 'H'); + { + fterm_rawcmd2(ft.rows_full, 1, 1, 'H'); + } else + { + fterm_rawcmd2(ft.rows + 1 - ady, 1, 1, 'H'); + fterm_raws(ESC_STR "[J"); fterm_rawcmd2(1, 1, 1, 'H'); + } for (; ady > 0; ady--) { diff --git a/mbbsd/pmore.c b/mbbsd/pmore.c index 4f3a1ae06..87d8bd081 100644 --- a/mbbsd/pmore.c +++ b/mbbsd/pmore.c @@ -366,7 +366,7 @@ static int debug = 0; # define MFFPROTO #else # define MFPROTO static -# define MFFPROTO inline static +# define MFFPROTO static #endif /* DBCS users tend to write unsigned char. let's make compiler happy */ diff --git a/mbbsd/recover.cc b/mbbsd/recover.cc index 086bc9dd5..f6169fbc5 100644 --- a/mbbsd/recover.cc +++ b/mbbsd/recover.cc @@ -157,16 +157,6 @@ void AccountRecovery::LogToSecurity(const UserHandle &user, post_msg(BN_SECURITY, title.c_str(), msg.c_str(), "[系統安全局]"); } -// static -void AccountRecovery::NotifyUser(const std::string &userid, - const std::string &email) { - std::string subject; - subject.append(" " BBSNAME " - "); - subject.append(userid); - subject.append(", 您的密碼已更變"); - bsmtp("etc/passwdchanged", subject.c_str(), email.c_str(), "non-exist"); -} - // static std::string AccountRecovery::GenCode(size_t len) { std::string s(len, '\0'); @@ -181,8 +171,10 @@ void AccountRecovery::UserErrorExit() { } void AccountRecovery::InputUserEmail() { - mvprints(y_++, 0, "目前僅能取回使用 Email 註冊之帳號。"); - y_++; +#ifndef USEREC_EMAIL_IS_CONTACT + mvprints(y_, 0, "目前僅能取回使用 Email 註冊之帳號。"); +#endif + y_ += 2; // Input userid. char userid[IDLEN + 1] = {}; @@ -316,7 +308,7 @@ void AccountRecovery::ResetPasswd() { LogToSecurity(user_.value(), email_); for (const auto &email : all_emails_) { - NotifyUser(user_->userid, email); + notify_password_change(user_->userid.c_str(), email.c_str()); } // Log to user security. diff --git a/mbbsd/register.c b/mbbsd/register.c index d5cf462b3..d8d423bb3 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -250,29 +250,6 @@ check_and_expire_account(int uid, const userec_t * urec, int expireRange) return val; } -//////////////////////////////////////////////////////////////////////////// -// Regcode Support -//////////////////////////////////////////////////////////////////////////// - -#define REGCODE_INITIAL "v6" // always 2 characters -#define REGCODE_LEN (13) -#define REGCODE_SZ (REGCODE_LEN + 1) - -static void -makeregcode(char *buf) -{ - int i; - // prevent ambigious characters: oOlI - const char *alphabet = "qwertyuipasdfghjkzxcvbnmoQWERTYUPASDFGHJKLZXCVBNM"; - - /* generate a new regcode */ - buf[REGCODE_LEN] = 0; - buf[0] = REGCODE_INITIAL[0]; - buf[1] = REGCODE_INITIAL[1]; - for( i = 2 ; i < REGCODE_LEN ; ++i ) - buf[i] = alphabet[random() % strlen(alphabet)]; -} - //////////////////////////////////////////////////////////////////////////// // Justify Utilities //////////////////////////////////////////////////////////////////////////// @@ -572,8 +549,25 @@ query_yn(int y, const char *msg) // New Registration (Phase 1: Create Account) ///////////////////////////////////////////////////////////////////////////// +// register_email_verification +// +// given the email input, generate a random code and send to +// the email address to verify the validity of the email. +// +// Params: +// ein: email input information. +// +// skip_same_email_check: +// whether to skip checking the input email is the same as the original +// email. +// 0: not skip checking (to check whether they are the same.) +// 1: skip checking (not to check whether they are the same.) +// +// Return: +// 0 (REGISTER_OK): ok +// < 0: error code static int -register_email_verification(email_input_t *ein) +register_email_verification(email_input_t *ein, bool skip_same_email_check) { char *email = ein->email; clear(); @@ -592,11 +586,16 @@ register_email_verification(email_input_t *ein) " 註: 本站不接受 yahoo, kimo等免費的 E-Mail\n"); } outs("\n" - "**********************************************************\n" - "* 若過久未收到請到郵件垃圾桶檢查是否被當作垃圾信(SPAM)了,*\n" - "* 另外若輸入後發生認證碼錯誤請先確認輸入是否為最後一封 *\n" - "* 收到的認證信,若真的仍然不行請再重填一次 E-Mail. *\n" - "**********************************************************\n"); + "**********************************************************************\n" + "* 請填寫您能夠長期持有的信箱,勿填寫學校或公司的信箱等暫時信箱, *\n" + "* 避免畢業或離職時信箱被收回。 *\n" + "* 信箱可在【忘記密碼】或【帳號被他人使用】時,用來重置您的帳號密碼。 *\n" + "* 變更【密碼】與【聯絡信箱】時,也將會需要透過聯絡信箱來驗證。 *\n" + "* *\n" + "* 若過久未收到請到郵件垃圾桶檢查是否被當作垃圾信(SPAM)了。 *\n" + "* 另外若輸入後發生認證碼錯誤請先確認輸入是否為最後一封。 *\n" + "* 收到的認證信,若真的仍然不行請再重填一次 E-Mail. *\n" + "**********************************************************************\n"); // Get a valid email from user. int err; @@ -643,15 +642,21 @@ register_email_verification(email_input_t *ein) } while (err != REGISTER_OK); // Nothing changed. - if (!strcmp(email, orig)) { + if (!skip_same_email_check && !strcmp(email, orig)) { vmsg("E-Mail 與原本相同。"); return REGISTER_ERR_CANCEL; } +#define REGCODE_INITIAL "v6" // always 2 characters +#define REGCODE_LEN (13) + // Send and check regcode. - char inregcode[REGCODE_SZ] = {0}, regcode[REGCODE_SZ]; + char inregcode[REGCODE_LEN + 1] = {0}; + char regcode[REGCODE_LEN + 1] = REGCODE_INITIAL; char buf[80]; - makeregcode(regcode); + + random_text_code(regcode + strlen(REGCODE_INITIAL), + REGCODE_LEN - strlen(REGCODE_INITIAL)); tries = 0; int num_sent = 0; @@ -750,7 +755,7 @@ new_register(void) ein.warn_untrusted = true; # endif // ALLOW_REGISTER_WITH_ONLY_CONTACT_EMAIL - if (register_email_verification(&ein) == REGISTER_OK) { + if (register_email_verification(&ein, 0) == REGISTER_OK) { email_verified = ein.is_trusted; } else { exit(1); @@ -992,8 +997,8 @@ normalize_email(char *email) { char *c = strchr(email, '@'); - // reject no '@' or multiple '@' - if (c == NULL || c != strrchr(email, '@')) + // reject no '@' or invalid email address + if (!c || !is_valid_email(email)) return false; // domain tolower @@ -1002,14 +1007,6 @@ normalize_email(char *email) return true; } -bool -user_has_email(const userec_t *u) -{ - char email[sizeof(u->email)]; - strlcpy(email, u->email, sizeof(email)); - return normalize_email(email); -} - bool check_email_allow_reject_lists(char *email, const char **errmsg, const char **notice_file) { @@ -1166,6 +1163,26 @@ void check_register(void) { char fn[PATHLEN]; + int ret = 0; + +#ifdef USEREC_EMAIL_IS_CONTACT + // 確認一定要有聯絡信箱 + if (!is_valid_email(cuser.email)) { + more("etc/ensurevalidcontactemail", NA); + pressanykey(); + + // additional parentheses around "ret =" to please compiler + while ((ret = change_contact_email(0))); +#ifdef FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN + } else if (last_login_time < FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN) { + more("etc/forceupdatecontactemail", NA); + pressanykey(); + + // additional parentheses around "ret =" to please compiler + while ((ret = change_contact_email(1))); +#endif //FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN + } +#endif //USEREC_EMAIL_IS_CONTACT // 已經通過的就不用了 if (HasUserPerm(PERM_LOGINOK) || HasUserPerm(PERM_SYSOP)) @@ -1447,7 +1464,7 @@ u_email_verification() email_input_t ein = {}; ein.email = email; - if (register_email_verification(&ein) != REGISTER_OK) + if (register_email_verification(&ein, 0) != REGISTER_OK) return; assert(ein.is_trusted); @@ -1695,8 +1712,32 @@ u_register() #ifdef USEREC_EMAIL_IS_CONTACT -void -change_contact_email() +static int notify_email_change(const char *userid, const char *email) +{ + char subject[128]; + int ret; + + snprintf(subject, sizeof(subject), " %s - %s (%s) - 聯絡信箱已變更", + BBSNAME, userid, fromhost); + + ret = bsmtp("etc/emailchanged", subject, email, "non-exist"); + + return ret > 0 ? 0 : -1; +} + +// change_contact_email +// +// Params: +// skip_same_email_check: +// whether to skip checking the input email is the same as the original +// email. +// 0: not skip checking (to check whether they are the same.) +// 1: skip checking (not to check whether they are the same.) +// +// Return: +// int: 0: ok -1: err +int +change_contact_email(bool skip_same_email_check) { char email[EMAILSZ] = {}; memcpy(email, cuser.email, sizeof(email)); @@ -1704,8 +1745,8 @@ change_contact_email() email_input_t ein = {}; ein.email = email; ein.allow_untrusted = true; - if (register_email_verification(&ein) != REGISTER_OK) - return; + if (register_email_verification(&ein, skip_same_email_check) != REGISTER_OK) + return -1; // Log. char logfn[PATHLEN]; @@ -1713,10 +1754,16 @@ change_contact_email() log_filef(logfn, LOG_CREAT, "%s %s (ContactEmail) %s -> %s\n", Cdatelite(&now), fromhost, cuser.email, email); + // Send notification to old email address if it was valid + if (is_valid_email(cuser.email)) + notify_email_change(cuser.userid, cuser.email); + // Write. pwcuSetEmail(email); vmsg("聯絡信箱更新完成。"); + + return 0; } #endif diff --git a/mbbsd/screen.c b/mbbsd/screen.c index ff32910ab..65461657d 100644 --- a/mbbsd/screen.c +++ b/mbbsd/screen.c @@ -78,6 +78,16 @@ initscr(void) } } +int +resizeterm_within(int rows, int cols, int rows_full GCC_UNUSED, int cols_full GCC_UNUSED) +{ + // FIXME: rows_full instead of b_lines should be used for forward scrolling + if (rows != t_lines || cols != t_columns) { + return resizeterm(rows, cols); + } + return 0; +} + int resizeterm(int w, int h) { diff --git a/mbbsd/talk.c b/mbbsd/talk.c index cecdb1b20..0dc6ac830 100644 --- a/mbbsd/talk.c +++ b/mbbsd/talk.c @@ -2151,7 +2151,7 @@ call_in(const userinfo_t * uentp, int fri_stat) return 0; } -inline static void +static void userlist(void) { pickup_t *currpickup; diff --git a/mbbsd/term.c b/mbbsd/term.c index 735abcb96..05bd13689 100644 --- a/mbbsd/term.c +++ b/mbbsd/term.c @@ -52,18 +52,17 @@ void term_resize(int w, int h) /* make sure reasonable size */ - h = MAX(24, MIN(100, h)); - w = MAX(80, MIN(200, w)); + int h_crop = MAX(24, MIN(100, h)); + int w_crop = MAX(80, MIN(200, w)); - if (w != t_columns || h != t_lines) + // invoke terminal system resize + resizeterm_within(h_crop, w_crop, h, w); + if (w_crop != t_columns || h_crop != t_lines) { - // invoke terminal system resize - resizeterm(h, w); - - t_lines = h; - t_columns = w; dorefresh = 1; } + t_lines = h_crop; + t_columns = w_crop; b_lines = t_lines - 1; p_lines = t_lines - 4; diff --git a/mbbsd/user.c b/mbbsd/user.c index 5430450a4..4f2ec8b5f 100644 --- a/mbbsd/user.c +++ b/mbbsd/user.c @@ -673,7 +673,11 @@ uinfo_query(const char *orig_uid, int adminmode, int unum) } ans = vans(adminmode ? +#ifdef USEREC_EMAIL_IS_CONTACT + "(1)改資料(2)密碼(3)權限(4)砍帳(5)改ID(6)寵物(7)審判(8)退文(M)信箱(V)認證 " : +#else "(1)改資料(2)密碼(3)權限(4)砍帳(5)改ID(6)寵物(7)審判(8)退文(V)認證 [0]結束 " : +#endif #ifdef USEREC_EMAIL_IS_CONTACT "請選擇 (1)修改資料 (2)設定密碼 (M)聯絡信箱 (V)認證資料 [0]結束 "); #else @@ -709,9 +713,60 @@ uinfo_query(const char *orig_uid, int adminmode, int unum) switch (ans) { #ifdef USEREC_EMAIL_IS_CONTACT case 'm': - if (!adminmode) - change_contact_email(); - return; + if (!adminmode) { + change_contact_email(0); + return; + } else { + char email[EMAILSZ]; + + move(y+1, 0); + outs("請注意在此修改聯絡信箱將跳過黑白名單檢查。"); + + if (!getdata_str(y++, 0, "請修改聯絡信箱: ", email, sizeof(email), + DOECHO, x.email)) + return; + + // Nothing changed. + if (!strcmp(email, x.email)) { + vmsg("E-Mail 與原本相同。"); + fail++; + break; + } + + char reason[30]; + while (!getdata(y++, 0, "請輸入理由以示負責:", + reason, sizeof(reason), DOECHO)); + + if (vans(msg_sure_ny) != 'y') { + fail++; + break; + } + + pre_confirmed = 1; + + // Log change for security reasons. + char title[TTLEN], buf[STRLEN + EMAILSZ*2 + sizeof(reason)]; + snprintf(title, sizeof(title), "%s 的聯絡信箱變更通知 (by %s)", + orig_uid, cuser.userid); + snprintf(buf, sizeof(buf), "站長 %s 修改 %s 的聯絡信箱 %s -> %s\n理由:%s\n", + cuser.userid, orig_uid, x.email, email, reason); + post_msg(BN_SECURITY, title, buf, "[系統安全局]"); + + // Notify user + strlcpy(title, "聯絡信箱變更通知", sizeof(title)); + snprintf(buf, sizeof(buf), "您的聯絡信箱已變更為 %s\n", email); + mail_log2id_text(orig_uid, title, buf, cuser.userid, 1); + + // Log to user log. + char logfn[PATHLEN]; + sethomefile(logfn, x.userid, FN_USERSECURITY); + log_filef(logfn, LOG_CREAT, "%s %s (ContactEmail) %s -> %s\n", + Cdatelite(&now), "[Admin]", x.email, email); + + strlcpy(x.email, email, sizeof(x.email)); + } + + break; #endif case '1': @@ -947,7 +1002,7 @@ uinfo_query(const char *orig_uid, int adminmode, int unum) if (!adminmode) { #ifdef USEREC_EMAIL_IS_CONTACT # ifdef REQUIRE_CONTACT_EMAIL_TO_CHANGE_PASSWORD - if (!user_has_email(&cuser)) { + if (!is_valid_email(cuser.email)) { move(y, 0); outs("設定聯絡信箱後才能修改密碼唷!"); fail++; @@ -1052,6 +1107,12 @@ uinfo_query(const char *orig_uid, int adminmode, int unum) log_filef(logfn, LOG_CREAT, "%s %s (Passwd)\n", Cdatelite(&now), adminmode ? "[Admin]" : fromhost); } + + // Send notification email if user has email set. + // Only do so if not Admin to avoid confusing user. + if (is_valid_email(cuser.email) && !adminmode) + notify_password_change(cuser.userid, cuser.email); + break; case '3': diff --git a/mbbsd/verifydb.cc b/mbbsd/verifydb.cc index 33c48bd98..734a91a35 100644 --- a/mbbsd/verifydb.cc +++ b/mbbsd/verifydb.cc @@ -203,7 +203,7 @@ int verifydb_change_userid(const char *from_userid, const char *to_userid, // (by using an empty vkey). Also, make sure the insert is successful // before deleting. if (verifydb_set(to_userid, entry->generation(), entry->vmethod(), - entry->vkey()->c_str(), entry->timestamp() < 0) || + entry->vkey()->c_str(), entry->timestamp()) < 0 || verifydb_set(from_userid, entry->generation(), entry->vmethod(), "", 0) < 0) ok = false; diff --git a/mbbsd/verifydb_info.cc b/mbbsd/verifydb_info.cc index 2bd5fbae8..a690581f9 100644 --- a/mbbsd/verifydb_info.cc +++ b/mbbsd/verifydb_info.cc @@ -131,7 +131,7 @@ void verify_entry_email_edit(const VerifyDb::Entry *entry, bool *dirty) { // clang-format off outs(ANSI_COLOR(1;33)); // clang-format on - outs(" 如需修改認證狀態, 請使用權限更變選項."); + outs(" 如需修改認證狀態, 請使用權限變更選項."); outs(ANSI_RESET); char confirm[2] = {}; diff --git a/mbbsd/vtuikit.c b/mbbsd/vtuikit.c index 1efcaf812..ad6fa6a1a 100644 --- a/mbbsd/vtuikit.c +++ b/mbbsd/vtuikit.c @@ -64,7 +64,7 @@ nblank(int n) outnc(n, ' '); } -static inline void +static void fillns(int n, const char *s) { while (n > 0 && *s) @@ -73,7 +73,7 @@ fillns(int n, const char *s) outnc(n, ' '); } -static inline void +static void fillns_ansi(int n, const char *s) { int d = strat_ansi(n, s); @@ -1117,7 +1117,7 @@ InputHistoryNext(char *s, int sz) // vget*: mini editbox //////////////////////////////////////////////////////////////////////// -static inline int +static int _vgetcbhandler(VGET_FCALLBACK cbptr, int *pabort, int c, VGET_RUNTIME *prt, void *instance) { if (!cbptr) diff --git a/sample/etc/Makefile b/sample/etc/Makefile index faef18186..e39181912 100644 --- a/sample/etc/Makefile +++ b/sample/etc/Makefile @@ -5,9 +5,11 @@ INSTALLTAG=$(TARGET).installed FILES= Welcome Welcome_login \ Logout goodbye bad_host today_boring \ register registered registermail registeredmail \ + reg.methods reg.sms.notes \ feast sysop banip.conf \ ve.hlp board.help boardlist.help \ editable expire2.conf domain_name_query.cidr \ + passwdchanged emailchanged \ banemail whitemail whitemail.notice ziphome.exclude all: diff --git a/sample/etc/editable b/sample/etc/editable index 51716e249..af288ed92 100644 --- a/sample/etc/editable +++ b/sample/etc/editable @@ -58,6 +58,8 @@ etc/regnotes/phone etc/regnotes/mobile 註冊細項說明[手機] etc/regnotes/birthday 註冊細項說明[生日] etc/regnotes/sex 註冊細項說明[性別] +etc/passwdchanged 密碼更動通知信 +etc/emailchanged 聯絡信箱更動通知信 # ---------------------------------------- # 按鍵說明系列 # ---------------------------------------- diff --git a/sample/etc/emailchanged b/sample/etc/emailchanged new file mode 100644 index 000000000..599d8e92e --- /dev/null +++ b/sample/etc/emailchanged @@ -0,0 +1,23 @@ +Message below is written in Chinese/Big5. +If you cannot read Chinese/Big5, skip to English section. +------------------------------------------------------------- +親愛的使用者您好: + + 您的聯絡信箱已經變更. + + 如此為您本人操作, 請忽略此封信. + + 如非您本人操作, 請立刻登入並修改您的密碼及聯絡信箱. + +------------------------------------------------------------- +Dear user, + + This mail is to confirm your contact email address + has been changed. + + If it was you, you may discard this email. + + If it was not you, please login immediately and + change your password and contact email. + +------------------------------------------------------------- diff --git a/sample/etc/ensurevalidcontactemail b/sample/etc/ensurevalidcontactemail new file mode 100644 index 000000000..79a216314 --- /dev/null +++ b/sample/etc/ensurevalidcontactemail @@ -0,0 +1,5 @@ +您的聯絡信箱不是有效的信箱, +請重新設定您的聯絡信箱。 + +如果無法使用 app 設定, +請使用網頁版 https://term.ptt.cc diff --git a/sample/etc/forceupdatecontactemail b/sample/etc/forceupdatecontactemail new file mode 100644 index 000000000..500775dee --- /dev/null +++ b/sample/etc/forceupdatecontactemail @@ -0,0 +1,5 @@ +您上次上站在 2022-12-20 00:00:00 之前, +請重新設定您的聯絡信箱。 + +如果無法使用 app 設定, +請使用網頁版 https://term.ptt.cc diff --git a/sample/etc/passwdchanged b/sample/etc/passwdchanged index c1fbe383d..16ee0680e 100644 --- a/sample/etc/passwdchanged +++ b/sample/etc/passwdchanged @@ -3,7 +3,7 @@ If you cannot read Chinese/Big5, skip to English section. ------------------------------------------------------------- 親愛的使用者您好: - 您的密碼已經更變. + 您的密碼已經變更. 如此為您本人操作, 請忽略此封信. diff --git a/sample/pttbbs.conf b/sample/pttbbs.conf index c78c1826b..b81b79678 100644 --- a/sample/pttbbs.conf +++ b/sample/pttbbs.conf @@ -200,7 +200,7 @@ //#define SAFE_ARTICLE_DELETE /* 若定義, 則在傳送水球的時候, 不會直接 kill 該程序. 理論上可以減少大 - 量的系統負和 */ + 量的系統負荷 */ //#define NOKILLWATERBALL /* 若定義, 則在系統超過負荷的時候, 新接的連線會留住 OVERLOADBLOCKFDS @@ -287,6 +287,9 @@ //#define REQUIRE_CONTACT_EMAIL_TO_CHANGE_PASSWORD +/* 如果使用者上次 login 在 FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN 之前, 則重新設定聯絡信箱 */ +//#define FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN 0 + /* 前進站畫面 */ #define INSCREEN \ "前進站畫面 (請至 pttbbs.conf 修改您的前進站畫面)" diff --git a/util/expire.c b/util/expire.c index b53b0c326..a7a26bf35 100644 --- a/util/expire.c +++ b/util/expire.c @@ -182,18 +182,19 @@ life_t db, table[MAX_BOARD], *key; void toexpire(char *brdname) { - if( brdname[0] > ' ' && brdname[0] != '.' ){ - key = NULL; + if (!is_valid_brdname(brdname)) + return; - if( count ) - key = (life_t *)bsearch(brdname, table, count, - sizeof(life_t), (QCAST)strcasecmp); - if( key == NULL ) - key = &db; + key = NULL; - strcpy(key->bname, brdname); - expire(key); - } + if( count ) + key = (life_t *)bsearch(brdname, table, count, + sizeof(life_t), (QCAST)strcasecmp); + if( key == NULL ) + key = &db; + + strcpy(key->bname, brdname); + expire(key); } void visitdir(char c) diff --git a/util/outmail.c b/util/outmail.c index d8177da37..ba91036b3 100644 --- a/util/outmail.c +++ b/util/outmail.c @@ -1,13 +1,16 @@ +#include + #include "bbs.h" #define SPOOL BBSHOME "/out" #define INDEX SPOOL "/.DIR" -#define NEWINDEX SPOOL "/.DIR.sending" +#define NEWINDEX_PATTERN SPOOL "/.DIR.sending.%d" #define FROM ".bbs@" MYHOSTNAME #define SMTPPORT 25 char *smtpname; int smtpport; char disclaimer[1024]; +bool one_shot; int waitReply(int sock) { char buf[256]; @@ -88,7 +91,7 @@ void doSendBody(int sock, FILE *fp, char *from, char *to, char *subject) { "From: %s <%s>\r\n" "To: %s\r\n" "Subject: %s\r\n" - "X-Sender: outmail of pttbbs\r\n" + "X-Sender: outmail of pttbbs " __DATE__ "\r\n" "Mime-Version: 1.0\r\n" "Content-Type: text/plain; charset=\"big5\"\r\n" "Content-Transfer-Encoding: 8bit\r\n" @@ -115,6 +118,9 @@ void doSendBody(int sock, FILE *fp, char *from, char *to, char *subject) { void doSendMail(int sock, FILE *fp, char *from, char *to, char *subject) { char buf[256]; + if (sendRequest(sock, "rset\n") || waitReply(sock) != 2) + return; + snprintf(buf, sizeof(buf), "mail from: %s\n", from); if(sendRequest(sock, buf) || waitReply(sock) != 2) return; @@ -133,11 +139,16 @@ void doSendMail(int sock, FILE *fp, char *from, char *to, char *subject) { } void sendMail() { - int fd, smtpsock; + int fd, smtpsock, counter = 0; + long int total_count; + char spool_path[PATHLEN]; + struct stat st; MailQueue mq; - - if(access(NEWINDEX, R_OK | W_OK)) { - if(link(INDEX, NEWINDEX) || unlink(INDEX)) + + snprintf(spool_path, sizeof(spool_path), NEWINDEX_PATTERN, getpid()); + + if(access(spool_path, R_OK | W_OK)) { + if(link(INDEX, spool_path) || unlink(INDEX)) /* nothing to do */ return; } @@ -149,16 +160,21 @@ void sendMail() { return; } - fd = open(NEWINDEX, O_RDONLY); + fd = open(spool_path, O_RDONLY); flock(fd, LOCK_EX); + fstat(fd, &st); + total_count = st.st_size / sizeof(mq); + while(read(fd, &mq, sizeof(mq)) > 0) { FILE *fp; char buf[256]; + counter++; snprintf(buf, sizeof(buf), "%s%s", mq.sender, FROM); if((fp = fopen(mq.filepath, "r"))) { - setproctitle("outmail: sending %s", mq.filepath); - printf("mailto: %s, relay server: %s:%d\n", mq.rcpt, smtpname, smtpport); + setproctitle("outmail: sending %d/%ld %s", counter, total_count, mq.filepath); + printf("mailto: %s, %d of %ld, relay server: %s:%d\n", mq.rcpt, counter, total_count, + smtpname, smtpport); doSendMail(smtpsock, fp, buf, mq.rcpt, mq.subject); fclose(fp); unlink(mq.filepath); @@ -168,7 +184,7 @@ void sendMail() { } flock(fd, LOCK_UN); close(fd); - unlink(NEWINDEX); + unlink(spool_path); disconnectMailServer(smtpsock); } @@ -227,12 +243,16 @@ int main(int argc, char **argv, char **envp) { case 's': parseserver(optarg, &smtpname, &smtpport); break; + case 'o': + one_shot = true; + break; case 'q': listQueue(); return 0; default: - printf("usage:\toutmail [-qh] -s host[:port]\n" + printf("usage:\toutmail [-qoh] -s host[:port]\n" "\t-q\tlistqueue\n" + "\t-o\texit when current spool is fully processed (One-shot)\n" "\t-h\thelp\n" "\t-s\tset default smtp server to host[:port]\n"); return 0; @@ -249,10 +269,11 @@ int main(int argc, char **argv, char **envp) { } qp_encode(disclaimer, sizeof(disclaimer), "[" BBSNAME "]對本信內容恕不負責", "big5"); - for(;;) { + do { sendMail(); setproctitle("outmail: sleeping"); sleep(60); /* send mail every minute */ - } + } while (!one_shot); + return 0; } diff --git a/util/permreport.c b/util/permreport.c index 0d34897d9..85f6d0e3b 100644 --- a/util/permreport.c +++ b/util/permreport.c @@ -32,6 +32,7 @@ int main(void) { PERMCHECK(PERM_POLICE_MAN), PERMCHECK(PERM_SYSSUPERSUBOP), PERMCHECK(PERM_ACCTREG), + PERMCHECK(PERM_POLICE), #if 0 PERMCHECK(PERM_SYSSUBOP), PERMCHECK(PERM_ACTION),