Пример #1
0
/* shell_dealloc():
 *	Remove the requested shell variable from the list.  Return 0 if
 *	the variable was removed successfully, otherwise return -1.
 */
static int
shell_dealloc(char *name)
{
	struct	s_shell *sp;

	sp = shell_vars;
	while(1) {
		if (sp->name == (char *)0) {
			if (sp->next == (struct s_shell *)0)
				return(-1);
			else {
				sp = sp->next;
				continue;
			}
		}
		if (strcmp(name,sp->name) == 0) {
			env_free(sp->name);
			env_free(sp->val);
			sp->name = (char *)0;
			sp->val = (char *)0;
			return(0);
		}
		
		if (sp->next == (struct s_shell *)0)
			return(-1);
		else
			sp = sp->next;
	}
}
Пример #2
0
    struct envelope *
env_create( const char *dir, const char *id, const char *e_mail,
	const struct envelope *parent )
{
    struct envelope	*env;
    struct timeval		tv_now;
    int				pid;
    /* way bigger than we should ever need */
    char			buf[ 1024 ];

    env = calloc( 1, sizeof( struct envelope ));

    if (( id == NULL ) || ( *id == '\0' )) {
	if ( simta_gettimeofday( &tv_now ) != 0 ) {
	    env_free( env );
	    return( NULL );
	}

	if (( pid = getpid()) < 0 ) {
	    syslog( LOG_ERR, "Syserror: env_set_id getpid: %m" );
	    env_free( env );
	    return( NULL );
	}

	snprintf( buf, 1023, "%lX.%lX.%d", (unsigned long)tv_now.tv_sec,
		(unsigned long)tv_now.tv_usec, pid );

	id = buf;
    }

    env->e_id = strdup( id );

    if ( e_mail != NULL ) {
	if ( env_sender( env, e_mail ) != 0 ) {
	    env_free( env );
	    return( NULL );
	}
    }

    if ( parent ) {
	env->e_dinode = parent->e_dinode;
	env->e_n_exp_level = parent->e_n_exp_level + 1;
	env_jail_set( env, parent->e_jail );
    } else if ( simta_rqueue_policy == RQUEUE_POLICY_JAIL ) {
	env_jail_set( env, ENV_JAIL_PRISONER );
    }

    env->e_dir = dir;

    return( env );
}
Пример #3
0
/* clearenv():
 * Clear out the entire environment.
 */
void
clearenv(void)
{
	struct	s_shell *sp;

	for(sp = shell_vars;sp != (struct s_shell *)0;sp = sp->next) {
		if (sp->name != (char *)0) {
			env_free(sp->name);
			env_free(sp->val);
			sp->name = (char *)0;
			sp->val = (char *)0;
		}
	}
}
Пример #4
0
void
trap(struct Trapframe *tf)
{
	// The environment may have set DF and some versions
	// of GCC rely on DF being clear
	asm volatile("cld" ::: "cc");

	// Halt the CPU if some other CPU has called panic()
	extern char *panicstr;
	if (panicstr)
		asm volatile("hlt");

	// Re-acqurie the big kernel lock if we were halted in
	// sched_yield()
	if (xchg(&thiscpu->cpu_status, CPU_STARTED) == CPU_HALTED)
		lock_kernel();
	// Check that interrupts are disabled.  If this assertion
	// fails, DO NOT be tempted to fix it by inserting a "cli" in
	// the interrupt path.
	assert(!(read_eflags() & FL_IF));

	if ((tf->tf_cs & 3) == 3) {
		// Trapped from user mode.
		// Acquire the big kernel lock before doing any
		// serious kernel work.
		// LAB 4: Your code here.

		assert(curenv);
		lock_kernel();

		// Garbage collect if current enviroment is a zombie
		if (curenv->env_status == ENV_DYING) {
			env_free(curenv);
			curenv = NULL;
			sched_yield();
		}

		// Copy trap frame (which is currently on the stack)
		// into 'curenv->env_tf', so that running the environment
		// will restart at the trap point.
		curenv->env_tf = *tf;
		// The trapframe on the stack should be ignored from here on.
		tf = &curenv->env_tf;
	}

	// Record that tf is the last real trapframe so
	// print_trapframe can print some additional information.
	last_tf = tf;

	// Dispatch based on what type of trap occurred
	trap_dispatch(tf);

	// If we made it to this point, then no other environment was
	// scheduled, so we should return to the current environment
	// if doing so makes sense.
	if (curenv && curenv->env_status == ENV_RUNNING)
		env_run(curenv);
	else
		sched_yield();
}
Пример #5
0
void
free_entry(entry *e) {
	free(e->cmd);
	free(e->pwd);
	env_free(e->envp);
	free(e);
}
Пример #6
0
Файл: env.c Проект: gojdic/samba
void
hx509_env_free(hx509_env *env)
{
    if (*env)
	env_free(*env);
    *env = NULL;
}
Пример #7
0
static void	core_free(t_core *core)
{
  free(core->name_term);
  cut_tab_free(core->cut_tab);
  env_free(core->env);
  jobs_free(core->jobs);
  close_modules(core->mods);
}
Пример #8
0
//
// Frees environment e.
// If e was the current env, then runs a new environment (and does not return
// to the caller).
//
void
env_destroy(struct Env *e) 
{
	env_free(e);

	//cprintf("Destroyed the only environment - nothing more to do!\n");
	while (1)
		run_command_prompt();
}
Пример #9
0
//
// Frees environment e.
// If e was the current env, then runs a new environment (and does not return
// to the caller).
//
void
env_destroy(struct Env *e) 
{
	env_free(e);

	cprintf("Destroyed the only environment - nothing more to do!\n");
	while (1)
		monitor(NULL);
}
Пример #10
0
//
// Frees environment e.
// If e was the current env, then runs a new environment (and does not return
// to the caller).
//
void
env_destroy(struct Env *e) 
{
	env_free(e);

	if (curenv == e) {
		curenv = NULL;
		sched_yield();
	}
}
Пример #11
0
Файл: env.c Проект: ahma88/magro
ENV* env_stackout(ENV* env)
{
	ENV* parent;
	assert(env != NULL);
	
	parent = env->parent;
	env_free(env);
	
	return parent;	
}
Пример #12
0
Файл: env.c Проект: ichaos/jos
//
// Frees environment e.
// If e was the current env, then runs a new environment (and does not return
// to the caller).
//
void
env_destroy(struct Env *e)
{
    env_free(e);

    if (curenv == e) {
        //cprintf("here\n");
        curenv = NULL;
        sched_yield();
    }
}
Пример #13
0
int run_prompt() {

    Node *ptree;
    AstNode *stree;
    EmCodeObject *co;
    Environment *env;
    EmObject *retval;

    env = newenv(vm->topenv);

    while (1) {
        ptree = parse();
        if (ptree) {

            if (ptree->type != MAGIC_COMMAND) {
                // printtree(ptree);

                stree = ast_from_ptree(ptree);

                // printstree(stree);

                co = compile_ast_tree(stree);

                INCREF(&nulobj);
                retval = run_codeobject(co, env, &nulobj);

                if (retval)
                    DECREF(retval);

                vm_reset_for_prompt();

                freetree(ptree);
                freestree(stree);

            } else { // MAGIC_COMMAND
                printf("got magic command %d\n", CHILD(ptree,0)->type);
                if (NCH(ptree) == 2) {
                    printf("magic command arg = %s\n",
                    CHILD(ptree,1)->lexeme);
                }
                if (CHILD(ptree,0)->type == MCA_EXIT) {
                    freetree(ptree); // release memory before exit
                    break;
                }
                // Always release memory of parse tree
                freetree(ptree);
            }
        }
    }
    env_free(env);

    return 1;
}
Пример #14
0
int main()
{
    int tx_port = 0;
    char *source = "test/test_defs.b";

    sys_init(0);
    tx_server(source, "bin/state", &tx_port);
    vol_init(0, "bin/volume");

    char *code = sys_load(source);
    env = env_new(source, code);
    mem_free(code);

    int len = 0;
    char **files = sys_list("test/data", &len);

    vars = vars_new(len);
    rvars = vars_new(len);
    for (int i = 0; i < len; ++i) {
        vars_add(rvars, files[i], 0, NULL);
        vars_add(vars, files[i], 0, NULL);
    }
    vars_add(vars, "___param", 0, NULL);

    test_vars();
    test_load();
    test_param();
    test_clone();
    test_eq();
    test_store();
    test_select();
    test_rename();
    test_extend();
    test_join();
    test_project();
    test_semidiff();
    test_summary();
    test_union();
    test_compound();
    test_call();

    tx_free();
    env_free(env);
    mem_free(files);
    vars_free(vars);
    vars_free(rvars);

    return 0;
}
Пример #15
0
void 
render(struct page *p)
{
    int depth;
    FILE *out;
    struct lacy_env env;
    struct page_stack p_stack;
    struct ut_str outfile;

    str_init(&curtok);

    if (NULL == p)
        return;

    str_init(&outfile);
    str_append_str(&outfile, conf.output_dir.s);
    str_append(&outfile, '/');
    str_append_str(&outfile, p->file_path);

    /* depth - 1 since we added output dir to path */
    depth = build_depth(outfile.s) - 1;
    if (NULL == (out = fopen(outfile.s, "w"))) 
        fatal("Unable to open: %: ", outfile.s);

    p_stack.size = 0;
    p_stack.pos = 0;
    /* Build Environment */
    env.depth = depth;
    env.p_stack = &p_stack;
    env.sym_tbl = NULL;

    env_build(p, &env);
    /* set stack back to top */
    p_stack.pos = 0;

    /* do it already */
    build_tree(&env);
    write_tree(out, &env);

    env_free(&env);
    fclose(out);

    str_free(&curtok);

    if (verbosity > 0) {
        printf("Rendered %s\n", outfile.s);
    }
    str_free(&outfile);
}
Пример #16
0
Файл: env.c Проект: gzs715/JOS
//
// Frees environment e.
// If e was the current env, then runs a new environment (and does not return
// to the caller).
//
void
env_destroy(struct Env *e) 
{
	env_free(e);

	//after free the env, clean the tickets of the env
	global_tickets -= e->tickets;
	e->tickets = 0;
	if (curenv == e)
	{
		curenv = NULL;	
		sched_yield();
	}
	
}
Пример #17
0
Файл: env.c Проект: gojdic/samba
static void
env_free(hx509_env b)
{
    while(b) {
	hx509_env next = b->next;

	if (b->type == env_string)
	    free(b->u.string);
	else if (b->type == env_list)
	    env_free(b->u.list);

	free(b->name);
	free(b);
	b = next;
    }
}
Пример #18
0
void execute_external(int argc, char **argv)
{
  UCHAR       LoadError[255];
  PSZ         Args;
  PSZ         Envs;
  RESULTCODES ChildRC;
  APIRET      rc;  /* Return code */
  char        *env;
  int         i;

  log("execute_external():\n");
  log("argc=%d\n", argc);

  for (i = 0; i < argc; i++)
    log("argv[%d]=%s\n", i, argv[i]);

  env = env_get();

  rc = DosExecPgm(LoadError,           /* Object name buffer           */
                  sizeof(LoadError),   /* Length of object name buffer */
                  EXEC_SYNC,           /* Asynchronous/Trace flags     */
                  argv[0],             /* Argument string              */
                  env,                 /* Environment string           */
                  &ChildRC,            /* Termination codes            */
                  argv[0]);            /* Program file name            */

  env_free(env);

  if (rc != NO_ERROR) {
//     printf("DosExecPgm error: return code = %u\n",rc);
     VioWrtTTY("DosExecPgm error\r\n", 18, 0); //: return code = %u\n",rc);
     return ;
  } else {
//     printf("DosExecPgm complete.  Termination Code: %u  Return Code: %u\n",
//             ChildRC.codeTerminate,
//             ChildRC.codeResult);  /* This is explicitly set by other pgm */
  } /* endif */
}
Пример #19
0
    void
cleanup_envelope_list( struct envelope **env_p )
{
    struct envelope             *env;
    while ( *env_p != NULL ) {
        env = *env_p;
        env_p = &(env->e_next);

        /* unlink if written to disk */
        if (( env->e_flags & ENV_FLAG_EFILE ) != 0 ) {
            queue_remove_envelope( env );
            if ( env_unlink( env ) == 0 ) {
                syslog( LOG_INFO, "Expand env <%s>: Message Deleted: "
                        "System error, unwinding expansion", env->e_id );
            } else {
                syslog( LOG_ERR, "Expand env <%s>: "
                        "System error, can't unwind expansion", env->e_id );
            }
        }

        env_free( env );
    }
}
Пример #20
0
static int
shell_alloc(char *name,char *value)
{
	int	namelen, valuelen;
	struct s_shell *sp;

	sp = shell_vars;
	namelen = strlen(name);
	valuelen = strlen(value);
	while(1) {
		if (sp->name == (char *)0) {
			if (sp->next != (struct s_shell *)0) {
				sp = sp->next;
				continue;
			}
			else
				break;
		}
		if (strcmp(sp->name,name) == 0) {
			if (sp->vsize < valuelen+1) {		/* If new value is smaller	*/
				env_free(sp->val);				/* than the old value, then */
				sp->val = env_alloc(valuelen+1);/* don't re-allocate any	*/
				if (!sp->val)					/* memory, just copy into	*/
					return(-1);					/* the space used by the	*/
				sp->vsize = valuelen+1;			/* previous value.			*/
			}
			strcpy(sp->val,value);
			return(0);
		}
		if (sp->next == (struct s_shell *)0) 
			break;
		sp = sp->next;
	}
	sp = shell_vars;
	while(1) {
		if (sp->name == (char *)0) {
			sp->name = env_alloc(namelen+1);
			if (!sp->name)
				return(-1);
			strcpy(sp->name,name);
			sp->val = env_alloc(valuelen+1);
			if (!sp->val)
				return(-1);
			sp->vsize = valuelen+1;
			strcpy(sp->val,value);
			return(0);
		}
		if (sp->next != (struct s_shell *)0)
			sp = sp->next;
		else {
			sp->next = (struct s_shell *)env_alloc(sizeof(struct s_shell));
			if (!sp->next)
				return(-1);
			sp = sp->next;
			sp->name = env_alloc(namelen+1);
			if (!sp->name)
				return(-1);
			strcpy(sp->name,name);
			sp->val = env_alloc(valuelen+1);
			if (!sp->val)
				return(-1);
			sp->vsize = valuelen+1;
			strcpy(sp->val,value);
			sp->next = (struct s_shell *)0;
			return(0);
		}
	}
}
Пример #21
0
/* envToExec():
   Create a file of "set" commands that can be run to recreate the
   current environment.
   Changed Oct 2008 to eliminate use of getAppRamStart().
*/
int
envToExec(char *filename)
{
	int		err, vartot, size, rc;
	char	*buf, *bp, *cp;
	register struct	s_shell *sp;

	sp = shell_vars;
	vartot = size = rc = 0;

	/* First go through the list to see how much space we need
	 * to allocate...
	 */
	while(1) {
		if (validEnvToExecVar(sp->name)) {
			size += strlen(sp->name) + 6;
			cp = sp->val;
			while(*cp) {
				if (*cp == '$')
					size++;
				size++;
				cp++;
			}
			size += 3;
			vartot++;
		}
		if (sp->next != (struct s_shell *)0)
			sp = sp->next;
		else
			break;
	}
	if (size == 0)
		return(0);

	/* Now that we know the space needed (stored in 'size' variable),
	 * allocate it and build the new file in that space, then use tfsadd()
	 * to create the file...
	 */
	vartot = 0;
	sp = shell_vars;
	buf = bp = (char *)env_alloc(size);
	while(1) {
		/* Note: if this code changes, then the code above that is used to
		 * allocate the buffer size may also need to change...
		 */
		if (validEnvToExecVar(sp->name)) {
			bp += sprintf(bp,"set %s \"",sp->name);
			cp = sp->val;
			while(*cp) {
				if (*cp == '$')
					*bp++ = '\\';
				*bp++ = *cp++;
			}
			*bp++ = '\"';
			*bp++ = '\n';
			*bp = 0;
			vartot++;
		}
		if (sp->next != (struct s_shell *)0)
			sp = sp->next;
		else
			break;
	}
	if (vartot > 0) {
		err = tfsadd(filename,"envsetup","e",(unsigned char *)buf,strlen(buf));
		if (err != TFS_OKAY) {
			printf("%s: %s\n",filename,(char *)tfsctrl(TFS_ERRMSG,err,0));
			rc = -1;
		}
	}
	env_free(buf);
	return(rc);
}
Пример #22
0
    int
main( int argc, char *argv[])
{
    struct envelope	*env;

    const char		*sender = "*****@*****.**";
    int			c;
    int			nextargc = 1;
    int			exp_level = 0;
    int			error = 0;

    extern int          optind;
    extern char         *optarg;

    simta_debug 	= 1;
    simta_expand_debug	= 1;

    while ((c = getopt(argc, argv, "f:x:")) != EOF)
    {
	switch (c)
	{
	case 'x':
	    if (( exp_level = atoi( optarg )) < 0 ) {
		error++;
	    }
	    nextargc = nextargc + 2;
	    break;

	case 'f':
	    sender = strdup( optarg );
	    nextargc = nextargc + 2;
	    break;

	default:
	    error++;
	    nextargc++;
	    break;
	}
    }
    if (( argc < 3 ) | ( error )) {
	fprintf( stderr, "Usage: %s [ -x level ] [-f sendermail] conf_file "
		"address\n", argv[ 0 ]);
	exit( EX_USAGE );
    }

    if ( simta_read_config( argv[ nextargc ] ) < 0 ) {
	fprintf( stderr, "simta_read_config error: %s\n", argv[ nextargc ] );
	exit( EX_DATAERR );
    }

    /* init simta config / defaults */
    if ( simta_config( ) != 0 ) {
	fprintf( stderr, "simta_config error\n" );
	exit( EX_DATAERR );
    }

    simta_openlog( 0, 0 );

    env = env_create( NULL, "DEAD60FF", sender, NULL );

    env->e_n_exp_level = exp_level;

    do {
	nextargc++;

	printf( "Original Recipient: %s\n", argv[ nextargc ]);
	env_recipient( env, argv[ nextargc ]);

    } while ( nextargc < argc - 1 );

    if ( expand( env ) != 0 ) {
	return( 1 );
    }
    env_free( env );

    return( 0 );
}
Пример #23
0
/* return NULL if eof or syntax error occurs;
 * otherwise return a pointer to a new entry.
 */
entry *
load_entry(FILE *file, void (*error_func)(const char *), struct passwd *pw,
    char **envp) {
	/* this function reads one crontab entry -- the next -- from a file.
	 * it skips any leading blank lines, ignores comments, and returns
	 * NULL if for any reason the entry can't be read and parsed.
	 *
	 * the entry is also parsed here.
	 *
	 * syntax:
	 *   user crontab:
	 *	minutes hours doms months dows cmd\n
	 *   system crontab (/etc/crontab):
	 *	minutes hours doms months dows USERNAME cmd\n
	 */

	ecode_e	ecode = e_none;
	entry *e;
	int ch;
	char cmd[MAX_COMMAND];
	char envstr[MAX_ENVSTR];
	char **tenvp;

	Debug(DPARS, ("load_entry()...about to eat comments\n"));

	skip_comments(file);

	ch = get_char(file);
	if (ch == EOF)
		return (NULL);

	/* ch is now the first useful character of a useful line.
	 * it may be an @special or it may be the first character
	 * of a list of minutes.
	 */

	e = calloc(sizeof(*e), sizeof(char));

	if (ch == '@') {
		/* all of these should be flagged and load-limited; i.e.,
		 * instead of @hourly meaning "0 * * * *" it should mean
		 * "close to the front of every hour but not 'til the
		 * system load is low".  Problems are: how do you know
		 * what "low" means? (save me from /etc/cron.conf!) and:
		 * how to guarantee low variance (how low is low?), which
		 * means how to we run roughly every hour -- seems like
		 * we need to keep a history or let the first hour set
		 * the schedule, which means we aren't load-limited
		 * anymore.  too much for my overloaded brain. (vix, jan90)
		 * HINT
		 */
		ch = get_string(cmd, MAX_COMMAND, file, " \t\n");
		if (!strcmp("reboot", cmd)) {
			e->flags |= WHEN_REBOOT;
		} else if (!strcmp("yearly", cmd) || !strcmp("annually", cmd)){
			bit_set(e->minute, 0);
			bit_set(e->hour, 0);
			bit_set(e->dom, 0);
			bit_set(e->month, 0);
			bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
			e->flags |= DOW_STAR;
		} else if (!strcmp("monthly", cmd)) {
			bit_set(e->minute, 0);
			bit_set(e->hour, 0);
			bit_set(e->dom, 0);
			bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
			bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
			e->flags |= DOW_STAR;
		} else if (!strcmp("weekly", cmd)) {
			bit_set(e->minute, 0);
			bit_set(e->hour, 0);
			bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
			bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
			bit_set(e->dow, 0);
			e->flags |= DOM_STAR;
		} else if (!strcmp("daily", cmd) || !strcmp("midnight", cmd)) {
			bit_set(e->minute, 0);
			bit_set(e->hour, 0);
			bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
			bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
			bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
			e->flags |= DOM_STAR | DOW_STAR;
		} else if (!strcmp("hourly", cmd)) {
			bit_set(e->minute, 0);
			bit_nset(e->hour, 0, (LAST_HOUR-FIRST_HOUR+1));
			bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
			bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
			bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
			e->flags |= DOM_STAR | DOW_STAR;
		} else {
			ecode = e_timespec;
			goto eof;
		}
		/* Advance past whitespace between shortcut and
		 * username/command.
		 */
		Skip_Blanks(ch, file);
		if (ch == EOF || ch == '\n') {
			ecode = e_cmd;
			goto eof;
		}
	} else {
		Debug(DPARS, ("load_entry()...about to parse numerics\n"));

		if (ch == '*')
			e->flags |= MIN_STAR;
		ch = get_list(e->minute, FIRST_MINUTE, LAST_MINUTE,
			      PPC_NULL, ch, file);
		if (ch == EOF) {
			ecode = e_minute;
			goto eof;
		}

		/* hours
		 */

		if (ch == '*')
			e->flags |= HR_STAR;
		ch = get_list(e->hour, FIRST_HOUR, LAST_HOUR,
			      PPC_NULL, ch, file);
		if (ch == EOF) {
			ecode = e_hour;
			goto eof;
		}

		/* DOM (days of month)
		 */

		if (ch == '*')
			e->flags |= DOM_STAR;
		ch = get_list(e->dom, FIRST_DOM, LAST_DOM,
			      PPC_NULL, ch, file);
		if (ch == EOF) {
			ecode = e_dom;
			goto eof;
		}

		/* month
		 */

		ch = get_list(e->month, FIRST_MONTH, LAST_MONTH,
			      MonthNames, ch, file);
		if (ch == EOF) {
			ecode = e_month;
			goto eof;
		}

		/* DOW (days of week)
		 */

		if (ch == '*')
			e->flags |= DOW_STAR;
		ch = get_list(e->dow, FIRST_DOW, LAST_DOW,
			      DowNames, ch, file);
		if (ch == EOF) {
			ecode = e_dow;
			goto eof;
		}
	}

	/* make sundays equivalent */
	if (bit_test(e->dow, 0) || bit_test(e->dow, 7)) {
		bit_set(e->dow, 0);
		bit_set(e->dow, 7);
	}

	/* check for permature EOL and catch a common typo */
	if (ch == '\n' || ch == '*') {
		ecode = e_cmd;
		goto eof;
	}

	/* ch is the first character of a command, or a username */
	unget_char(ch, file);

	if (!pw) {
		char		*username = cmd;	/* temp buffer */

		Debug(DPARS, ("load_entry()...about to parse username\n"));
		ch = get_string(username, MAX_COMMAND, file, " \t\n");

		Debug(DPARS, ("load_entry()...got %s\n",username));
		if (ch == EOF || ch == '\n' || ch == '*') {
			ecode = e_cmd;
			goto eof;
		}

		pw = getpwnam(username);
		if (pw == NULL) {
			ecode = e_username;
			goto eof;
		}
		Debug(DPARS, ("load_entry()...uid %ld, gid %ld\n",
			      (long)pw->pw_uid, (long)pw->pw_gid));
	}

	if ((e->pwd = pw_dup(pw)) == NULL) {
		ecode = e_memory;
		goto eof;
	}
	(void)memset(e->pwd->pw_passwd, 0, strlen(e->pwd->pw_passwd));

	/* copy and fix up environment.  some variables are just defaults and
	 * others are overrides.
	 */
	if ((e->envp = env_copy(envp)) == NULL) {
		ecode = e_memory;
		goto eof;
	}
	if (!env_get("SHELL", e->envp)) {
		if (glue_strings(envstr, sizeof envstr, "SHELL",
				 _PATH_BSHELL, '=')) {
			if ((tenvp = env_set(e->envp, envstr)) == NULL) {
				ecode = e_memory;
				goto eof;
			}
			e->envp = tenvp;
		} else
			log_it("CRON", getpid(), "error", "can't set SHELL");
	}
	if (!env_get("HOME", e->envp)) {
		if (glue_strings(envstr, sizeof envstr, "HOME",
				 pw->pw_dir, '=')) {
			if ((tenvp = env_set(e->envp, envstr)) == NULL) {
				ecode = e_memory;
				goto eof;
			}
			e->envp = tenvp;
		} else
			log_it("CRON", getpid(), "error", "can't set HOME");
	}
	/* If login.conf is in used we will get the default PATH later. */
	if (!env_get("PATH", e->envp)) {
		if (glue_strings(envstr, sizeof envstr, "PATH",
				 _PATH_DEFPATH, '=')) {
			if ((tenvp = env_set(e->envp, envstr)) == NULL) {
				ecode = e_memory;
				goto eof;
			}
			e->envp = tenvp;
		} else
			log_it("CRON", getpid(), "error", "can't set PATH");
	}
	if (glue_strings(envstr, sizeof envstr, "LOGNAME",
			 pw->pw_name, '=')) {
		if ((tenvp = env_set(e->envp, envstr)) == NULL) {
			ecode = e_memory;
			goto eof;
		}
		e->envp = tenvp;
	} else
		log_it("CRON", getpid(), "error", "can't set LOGNAME");
#if defined(BSD) || defined(__linux)
	if (glue_strings(envstr, sizeof envstr, "USER",
			 pw->pw_name, '=')) {
		if ((tenvp = env_set(e->envp, envstr)) == NULL) {
			ecode = e_memory;
			goto eof;
		}
		e->envp = tenvp;
	} else
		log_it("CRON", getpid(), "error", "can't set USER");
#endif

	Debug(DPARS, ("load_entry()...about to parse command\n"));

	/* If the first character of the command is '-' it is a cron option.
	 */
	while ((ch = get_char(file)) == '-') {
		switch (ch = get_char(file)) {
		case 'q':
			e->flags |= DONT_LOG;
			Skip_Nonblanks(ch, file);
			break;
		default:
			ecode = e_option;
			goto eof;
		}
		Skip_Blanks(ch, file);
		if (ch == EOF || ch == '\n') {
			ecode = e_cmd;
			goto eof;
		}
	}
	unget_char(ch, file);

	/* Everything up to the next \n or EOF is part of the command...
	 * too bad we don't know in advance how long it will be, since we
	 * need to malloc a string for it... so, we limit it to MAX_COMMAND.
	 */ 
	ch = get_string(cmd, MAX_COMMAND, file, "\n");

	/* a file without a \n before the EOF is rude, so we'll complain...
	 */
	if (ch == EOF) {
		ecode = e_cmd;
		goto eof;
	}

	/* got the command in the 'cmd' string; save it in *e.
	 */
	if ((e->cmd = strdup(cmd)) == NULL) {
		ecode = e_memory;
		goto eof;
	}

	Debug(DPARS, ("load_entry()...returning successfully\n"));

	/* success, fini, return pointer to the entry we just created...
	 */
	return (e);

 eof:
	if (e->envp)
		env_free(e->envp);
	if (e->pwd)
		free(e->pwd);
	if (e->cmd)
		free(e->cmd);
	free(e);
	while (ch != '\n' && !feof(file))
		ch = get_char(file);
	if (ecode != e_none && error_func)
		(*error_func)(ecodes[(int)ecode]);
	return (NULL);
}
Пример #24
0
void spawn() {
  int i;
  char** env = NULL;

  env = env_copy(environ, env);

  child = malloc(sizeof(uv_process_t));
  uv_stdio_container_t stdio[4];
  uv_process_options_t options;

  uv_pipe_init(loop, &child_stdout, 0);
  uv_pipe_init(loop, &child_stderr, 0);
  uv_pipe_init(loop, &child_ipc, 0);

  //
  // Setup child's stdio. stdout and stderr are pipes so that we can read
  // child process' output.
  // FD 3 is a pipe used for IPC.
  //
  options.stdio_count = 4;
  stdio[0].flags = UV_INHERIT_FD;
  stdio[0].data.fd = 0;
  stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
  stdio[1].data.stream = (uv_stream_t*) &child_stdout;
  stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
  stdio[2].data.stream = (uv_stream_t*) &child_stderr;
  stdio[3].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
  stdio[3].data.stream = (uv_stream_t*) &child_ipc;

  options.env = env;
  options.cwd = NULL;
  options.file = arguments[0];
  options.args = arguments;
  options.flags = 0;
  options.stdio = stdio;
  options.exit_cb = on_process_exit;

  for (i = 0; i < PLUGIN_COUNT; i++) {
    if (plugins[i].process_options_cb) {
      plugins[i].process_options_cb(&options);
    }
  }

  if (uv_spawn(loop, child, options)) {
    fprintf(stderr, "uv_spawn: %s\n", uv_err_name(uv_last_error(loop)));
    return;
  }

  for (i = 0; i < PLUGIN_COUNT; i++) {
    if (plugins[i].process_spawned_cb) {
      plugins[i].process_spawned_cb(child, &options);
    }
  }

  uv_read_start(options.stdio[1].data.stream, forza__on_alloc, forza__on_stdout_read);
  uv_read_start(options.stdio[2].data.stream, forza__on_alloc, forza__on_stderr_read);
  uv_read_start(options.stdio[3].data.stream, forza__on_alloc, forza__on_ipc_read);

  // Switch to using `options->env` here instead of `env`, since plugins can
  // override `options->env` using, for example `env_set`, like in the start
  // plugin.
  env_free(options.env);
}
Пример #25
0
    int
expand( struct envelope *unexpanded_env )
{
    struct expand               exp;
    struct envelope             *base_error_env;
    struct envelope             *env_dead = NULL;
    struct envelope             *env;
    struct envelope             **env_p;
    struct recipient            *rcpt;
    struct expand_output        *host_stab = NULL;
    struct expand_output        *eo;
    struct expand_output        *eo_free;
    struct exp_addr             *e_addr;
    struct exp_addr             *next_e_addr;
    struct simta_red            *hq_red;
    char                        *domain;
    SNET                        *snet = NULL;
    int                         n_rcpts;
    int                         return_value = 1;
    int                         env_out = 0;
    int                         fast_file_start;
    int                         sendermatch;
    char                        e_original[ MAXPATHLEN ];
    char                        d_original[ MAXPATHLEN ];
    char                        d_out[ MAXPATHLEN ];
    /* RFC 5321 4.5.3.1.3.  Path
     * The maximum total length of a reverse-path or forward-path is 256
     * octets (including the punctuation and element separators).
     */
    char                        header[ 270 ];
#ifdef HAVE_LDAP
    char                        *p;
    int                         loop_color = 1;
    struct exp_link             *memonly;
    struct exp_link             *parent;
#endif /* HAVE_LDAP */

    if ( unexpanded_env->e_hostname != NULL ) {
        syslog( LOG_INFO, "Expand env <%s>: already expanded for host %s",
                unexpanded_env->e_id, unexpanded_env->e_hostname );
        return_value = 0;
        goto done;
    }

    memset( &exp, 0, sizeof( struct expand ));
    exp.exp_env = unexpanded_env;
    fast_file_start = simta_fast_files;

    /* call address_expand on each address in the expansion list.
     *
     * if an address is expandable, the address(es) that it expands to will
     * be added to the expansion list. These non-terminal addresses must
     * have their st_data set to NULL to specify that they are not to be
     * included in the terminal expansion list.
     *
     * Any address in the expansion list whose st_data is not NULL is
     * considered a terminal address and will be written out as one
     * of the addresses in expanded envelope(s).
     */

    if (( base_error_env = address_bounce_create( &exp )) == NULL ) {
        syslog( LOG_ERR, "Expand env <%s>: address_bounce_create: %m",
                unexpanded_env->e_id );
        goto done;
    }

    if ( env_recipient( base_error_env, unexpanded_env->e_mail ) != 0 ) {
        syslog( LOG_ERR, "Expand env <%s>: env_recipient: %m",
                unexpanded_env->e_id );
        goto done;
    }

    /* add all of the original recipients to the expansion list */
    for ( rcpt = unexpanded_env->e_rcpt; rcpt != NULL; rcpt = rcpt->r_next ) {
        if ( add_address( &exp, rcpt->r_rcpt, base_error_env,
                ADDRESS_TYPE_EMAIL, exp.exp_env->e_mail ) != 0 ) {
            /* add_address syslogs errors */
            goto cleanup1;
        }
    }

    /* process the expansion list */
    for ( exp.exp_addr_cursor = exp.exp_addr_head;
            exp.exp_addr_cursor != NULL;
            exp.exp_addr_cursor = exp.exp_addr_cursor->e_addr_next ) {
        switch ( address_expand( &exp )) {
        case ADDRESS_EXCLUDE:
            exp.exp_addr_cursor->e_addr_terminal = 0;
            /* the address is not a terminal local address */
            break;

        case ADDRESS_FINAL:
            exp.exp_addr_cursor->e_addr_terminal = 1;
            break;

        case ADDRESS_SYSERROR:
            goto cleanup1;

        default:
            panic( "Expand: address_expand out of range" );
        }
    }

#ifdef HAVE_LDAP
    /* Members-only processing */
    for ( memonly = exp.exp_memonly; memonly != NULL;
            memonly = memonly->el_next ) {
        if ((( p = parent_permitted( memonly->el_exp_addr )) != NULL ) ||
                ( sender_is_child( memonly->el_exp_addr->e_addr_children,
                loop_color++ ))) {
            if ( p != NULL ) {
                syslog( LOG_INFO, "Expand env <%s>: members-only group %s OK: "
                        "parent %s permitted",
                        unexpanded_env->e_id, memonly->el_exp_addr->e_addr, p );

            } else {
                syslog( LOG_INFO, "Expand env <%s>: members-only group %s OK: "
                        "sender is child",
                        unexpanded_env->e_id, memonly->el_exp_addr->e_addr );
            }
            memonly->el_exp_addr->e_addr_ldap_flags =
                    ( memonly->el_exp_addr->e_addr_ldap_flags &
                    ( ~STATUS_LDAP_MEMONLY ));
            if ( memonly->el_exp_addr->e_addr_env_moderated != NULL ) {
                env_free( memonly->el_exp_addr->e_addr_env_moderated );
                memonly->el_exp_addr->e_addr_env_moderated = NULL;
            }

        } else {
            syslog( LOG_NOTICE,
                    "Expand env <%s>: members-only group %s suppressed",
                    unexpanded_env->e_id, memonly->el_exp_addr->e_addr );
            memonly->el_exp_addr->e_addr_ldap_flags |= STATUS_LDAP_SUPPRESSOR;
            suppress_addrs( memonly->el_exp_addr->e_addr_children,
                    loop_color++ );
        }
    }
#endif /* HAVE_LDAP */

    sprintf( d_original, "%s/D%s", unexpanded_env->e_dir,
            unexpanded_env->e_id );

    /* Create one expanded envelope for every host we expanded address for */
    for ( e_addr = exp.exp_addr_head; e_addr != NULL;
            e_addr = e_addr->e_addr_next ) {

#ifdef HAVE_LDAP
        if ((( e_addr->e_addr_ldap_flags & STATUS_LDAP_SUPPRESSED ) != 0 ) &&
                ( !unblocked_path_to_root( e_addr, loop_color++ ))) {
            if ( simta_expand_debug != 0 ) {
                printf( "Suppressed: %s\n", e_addr->e_addr );
            }
            continue;
        }
        if ( e_addr->e_addr_env_gmailfwd != NULL ) {
            e_addr->e_addr_env_gmailfwd->e_attributes =
                    unexpanded_env->e_attributes | ENV_ATTR_ARCHIVE_ONLY;

            if ( simta_expand_debug != 0 ) {
                printf( "Group mail forwarding: %s\n", e_addr->e_addr );
                env_stdout( e_addr->e_addr_env_gmailfwd );
                continue;
            }

            sprintf( d_out, "%s/D%s", e_addr->e_addr_env_gmailfwd->e_dir,
                    e_addr->e_addr_env_gmailfwd->e_id );
            if ( env_dfile_copy( e_addr->e_addr_env_gmailfwd, d_original,
                    NULL ) == 0 ) {
                syslog( LOG_ERR, "Expand env <%s>: %s: env_dfile_copy failed",
                        unexpanded_env->e_id,
                        e_addr->e_addr_env_gmailfwd->e_id );
                goto cleanup3;
            }

            simta_debuglog( 2, "Expand env <%s>: group mail env %s dinode %d",
                    unexpanded_env->e_id,
                    e_addr->e_addr_env_gmailfwd->e_id,
                    (int)e_addr->e_addr_env_gmailfwd->e_dinode );

            sendermatch = !strcasecmp( unexpanded_env->e_mail,
                    e_addr->e_addr_env_gmailfwd->e_mail );

            n_rcpts = 0;
            for ( rcpt = e_addr->e_addr_env_gmailfwd->e_rcpt; rcpt != NULL;
                    rcpt = rcpt->r_next ) {
                n_rcpts++;
                if ( sendermatch ) {
                    syslog( LOG_INFO, "Expand env <%s>: %s: To <%s> From <%s>",
                            unexpanded_env->e_id,
                            e_addr->e_addr_env_gmailfwd->e_id, rcpt->r_rcpt,
                            e_addr->e_addr_env_gmailfwd->e_mail );
                } else {
                    syslog( LOG_INFO,
                            "Expand env <%s>: %s: To <%s> From <%s> (%s)",
                            unexpanded_env->e_id,
                            e_addr->e_addr_env_gmailfwd->e_id, rcpt->r_rcpt,
                            e_addr->e_addr_env_gmailfwd->e_mail,
                            unexpanded_env->e_mail );
                }

            }
            syslog( LOG_INFO,
                    "Expand env <%s>: %s: Expanded %d group mail forwarders",
                    unexpanded_env->e_id, e_addr->e_addr_env_gmailfwd->e_id,
                    n_rcpts );

            if ( env_outfile( e_addr->e_addr_env_gmailfwd ) != 0 ) {
                /* env_outfile syslogs errors */
                if ( unlink( d_out ) != 0 ) {
                    syslog( LOG_ERR, "Syserror: expand unlink %s: %m", d_out );
                }
                goto cleanup3;
            }
            env_out++;
            queue_envelope( e_addr->e_addr_env_gmailfwd );
            continue;

        }

        if ( e_addr->e_addr_env_moderated != NULL ) {
            e_addr->e_addr_env_moderated->e_attributes =
                    unexpanded_env->e_attributes;

            if ( simta_expand_debug != 0 ) {
                printf( "Moderated: %s\n", e_addr->e_addr );
                env_stdout( e_addr->e_addr_env_moderated );
                continue;
            }

            sprintf( d_out, "%s/D%s", e_addr->e_addr_env_moderated->e_dir,
                    e_addr->e_addr_env_moderated->e_id );
            if ( env_dfile_copy( e_addr->e_addr_env_moderated, d_original,
                    NULL ) == 0 ) {
                syslog( LOG_ERR, "Expand env <%s>: %s: env_dfile_copy failed",
                        unexpanded_env->e_id,
                        e_addr->e_addr_env_moderated->e_id );
                goto cleanup3;
            }

            simta_debuglog( 2, "Expand env <%s>: %s: moderation env dinode %d",
                    unexpanded_env->e_id, e_addr->e_addr_env_moderated->e_id,
                    (int)e_addr->e_addr_env_moderated->e_dinode );

            sendermatch = !strcasecmp( unexpanded_env->e_mail,
                    e_addr->e_addr_env_moderated->e_mail );

            n_rcpts = 0;
            for ( rcpt = e_addr->e_addr_env_moderated->e_rcpt; rcpt != NULL;
                    rcpt = rcpt->r_next ) {
                n_rcpts++;
                if ( sendermatch ) {
                    syslog( LOG_INFO, "Expand env <%s>: %s: To <%s> From <%s>",
                            unexpanded_env->e_id,
                            e_addr->e_addr_env_moderated->e_id, rcpt->r_rcpt,
                            e_addr->e_addr_env_moderated->e_mail );
                } else {
                    syslog( LOG_INFO,
                            "Expand env <%s>: %s: To <%s> From <%s> (%s)",
                            unexpanded_env->e_id,
                            e_addr->e_addr_env_moderated->e_id, rcpt->r_rcpt,
                            e_addr->e_addr_env_moderated->e_mail,
                            unexpanded_env->e_mail );
                }

            }
            syslog( LOG_INFO,
                    "Expand env <%s>: %s: Expanded %d moderators",
                    unexpanded_env->e_id, e_addr->e_addr_env_moderated->e_id,
                    n_rcpts );

            if ( env_outfile( e_addr->e_addr_env_moderated ) != 0 ) {
                /* env_outfile syslogs errors */
                if ( unlink( d_out ) != 0 ) {
                    syslog( LOG_ERR, "expand unlink %s: %m", d_out );
                }
                goto cleanup3;
            }
            env_out++;
            queue_envelope( e_addr->e_addr_env_moderated );
            continue;

        } else if ( e_addr->e_addr_ldap_flags & STATUS_LDAP_SUPPRESSOR ) {
            for ( parent = e_addr->e_addr_parents; parent != NULL;
                    parent = parent->el_next ) {
                if ( parent->el_exp_addr == NULL ) {
                    if ( bounce_text( base_error_env, TEXT_ERROR,
                            "Members only group conditions not met: ",
                            e_addr->e_addr, NULL ) != 0 ) {
                        goto cleanup3;
                    }

                    if ( bounce_text( base_error_env, TEXT_ERROR,
            "If you have any questions, please contact the group owner: ",
                            e_addr->e_addr_owner, NULL ) != 0 ) {
                        goto cleanup3;
                    }

                } else if (( e_addr->e_addr_ldap_flags &
                        STATUS_LDAP_PRIVATE ) == 0 ) {
                    if ( bounce_text( parent->el_exp_addr->e_addr_errors,
                            TEXT_ERROR,
                            "Members only group conditions not met: ",
                            e_addr->e_addr, NULL ) != 0 ) {
                        goto cleanup3;
                    }

                    if ( bounce_text( parent->el_exp_addr->e_addr_errors,
                            TEXT_ERROR,
            "If you have any questions, please contact the group owner: ",
                            e_addr->e_addr_owner, NULL ) != 0 ) {
                        goto cleanup3;
                    }
                }
            }

            continue;
        }
#endif /* HAVE_LDAP */

        if ( e_addr->e_addr_terminal == 0 ) {
            if ( simta_expand_debug != 0 ) {
                printf( "Non-terminal: %s\n", e_addr->e_addr );
            }
            /* not a terminal expansion, do not add */
            continue;
        }

        if ( simta_expand_debug != 0 ) {
            printf( "Terminal: %s\n", e_addr->e_addr );
        }

        switch ( e_addr->e_addr_type ) {
        case ADDRESS_TYPE_EMAIL:
            if (( domain = strchr( e_addr->e_addr, '@' )) == NULL ) {
                syslog( LOG_ERR, "Expand env <%s>: strchr blivet",
                        unexpanded_env->e_id );
                goto cleanup3;
            }
            domain++;
            env = eo_lookup( host_stab, domain, e_addr->e_addr_from );
            break;

        case ADDRESS_TYPE_DEAD:
            domain = NULL;
            env = env_dead;
            break;

        default:
            panic( "expand: address type out of range" );
        }

        if ( env == NULL ) {
            /* Create envelope and add it to list */
            if (( env = env_create( domain ? simta_dir_fast : simta_dir_dead,
                    NULL, e_addr->e_addr_from, unexpanded_env )) == NULL ) {
                syslog( LOG_ERR, "Expand env <%s>: env_create: %m",
                        unexpanded_env->e_id );
                goto cleanup3;
            }

            simta_debuglog( 2, "Expand env <%s>: %s: expansion env dinode %d",
                    unexpanded_env->e_id, env->e_id, (int)env->e_dinode );

            /* fill in env */
            env->e_attributes = unexpanded_env->e_attributes;
            if ( domain != NULL ) {
                if ( env_hostname( env, domain ) != 0 ) {
                    env_free( env );
                    goto cleanup3;
                }
            } else {
                env_dead = env;
            }

            /* Add env to host_stab */
            if ( eo_insert( &host_stab, env ) != 0 ) {
                syslog( LOG_ERR, "Expand env <%s>: eo_insert %s failed: %m",
                        unexpanded_env->e_id, env->e_id );
                env_free( env );
                goto cleanup3;
            }
        }

        if ( env_recipient( env, e_addr->e_addr ) != 0 ) {
            goto cleanup3;
        }

        syslog( LOG_NOTICE,
                "Expand env <%s>: %s: recipient <%s> added to env for host %s",
                unexpanded_env->e_id, env->e_id, e_addr->e_addr,
                env->e_hostname ? env->e_hostname : "NULL" );
    }

    /* Write out all expanded envelopes and place them in to the host_q */
    for ( eo = host_stab; eo != NULL; eo = eo->eo_next ) {
        env = eo->eo_env;

        if ( simta_expand_debug == 0 ) {
            sprintf( d_out, "%s/D%s", env->e_dir, env->e_id );

            /* RFC 5321 4.4 Trace Information
             * When the delivery SMTP server makes the "final delivery" of a
             * message, it inserts a return-path line at the beginning of the
             * mail data.  This use of return-path is required; mail systems
             * MUST support it.  The return-path line preserves the
             * information in the <reverse-path> from the MAIL command.
             * Here, final delivery means the message has left the SMTP
             * environment.
             */
            if ((( hq_red = red_host_lookup( eo->eo_hostname )) != NULL ) &&
                    ( hq_red->red_deliver_type == RED_DELIVER_BINARY )) {
                if ( snprintf( header, 270,
                        "Return-Path: <%s>", env->e_mail ) >= 270 ) {
                    syslog( LOG_ERR,
                            "Expand env <%s>: %s: return path is too large",
                            unexpanded_env->e_id, env->e_id );
                }
                if ( env_dfile_copy( env, d_original, header ) == 0 ) {
                    syslog( LOG_ERR, "Expand env <%s>: %s: env_dfile_copy failed",
                            unexpanded_env->e_id, env->e_id );
                    goto cleanup4;
                }
            } else {
                /* Dfile: link Dold_id env->e_dir/Dnew_id */
                if ( link( d_original, d_out ) != 0 ) {
                    syslog( LOG_ERR, "Syserror: expand link %s %s: %m",
                            d_original, d_out );
                    goto cleanup4;
                }
            }

            sendermatch = !strcasecmp( unexpanded_env->e_mail, env->e_mail );

            n_rcpts = 0;
            for ( rcpt = env->e_rcpt; rcpt != NULL; rcpt = rcpt->r_next ) {
                n_rcpts++;
                if ( sendermatch ) {
                    syslog( LOG_INFO, "Expand env <%s>: %s: To <%s> From <%s>",
                            unexpanded_env->e_id, env->e_id, rcpt->r_rcpt,
                            env->e_mail );
                } else {
                    syslog( LOG_INFO,
                            "Expand env <%s>: %s: To <%s> From <%s> (%s)",
                            unexpanded_env->e_id, env->e_id, rcpt->r_rcpt,
                            env->e_mail, unexpanded_env->e_mail );
                }
            }

            syslog( LOG_INFO,
                    "Expand env <%s>: %s: Expanded %d recipients",
                    unexpanded_env->e_id, env->e_id, n_rcpts );

            /* Efile: write env->e_dir/Enew_id for all recipients at host */
            syslog( LOG_NOTICE, "Expand env <%s>: %s: writing Efile for %s",
                    unexpanded_env->e_id, env->e_id,
                    env->e_hostname ? env->e_hostname : "NULL" );
            if ( env_outfile( env ) != 0 ) {
                /* env_outfile syslogs errors */
                if ( unlink( d_out ) != 0 ) {
                    syslog( LOG_ERR, "Syserror: expand unlink %s: %m", d_out );
                }
                goto cleanup4;
            }

            env_out++;
            queue_envelope( env );

        } else {
            printf( "\n" );
            env_stdout( env );
        }
    }

    if ( env_out == 0 ) {
        syslog( LOG_NOTICE, "Expand env <%s>: no terminal recipients, "
                "deleting message", unexpanded_env->e_id );
    }

    /* write errors out to disk */
    env_p = &(exp.exp_errors);
    while (( env = *env_p ) != NULL ) {
        if ( simta_expand_debug == 0 ) {
            if ( env->e_error != 0 ) {
                env_p = &(env->e_next);

                if ( snet == NULL ) {
                    if (( snet = snet_open( d_original, O_RDONLY, 0,
                            1024 * 1024 )) == NULL ) {
                        syslog( LOG_ERR, "Liberror: expand snet_open %s: %m",
                                d_original );
                        goto cleanup5;
                    }
                } else {
                    if ( lseek( snet_fd( snet ), (off_t)0, SEEK_SET ) != 0 ) {
                        syslog( LOG_ERR, "Syserror: q_deliver lseek: %m" );
                        panic( "q_deliver lseek fail" );
                    }
                }

                /* write out error text, get Dfile inode */
                if ( bounce_dfile_out( env, snet ) == 0 ) {
                    if ( snet != NULL ) {
                        if ( snet_close( snet ) != 0 ) {
                            syslog( LOG_ERR,
                                    "Liberror: expand snet_close %s: %m",
                                    d_original );
                        }
                    }

                    goto cleanup5;
                }

                simta_debuglog( 2, "Expand env <%s>: %s: errors env dinode %d",
                        unexpanded_env->e_id, env->e_id, (int)env->e_dinode );

                line_file_free( env->e_err_text );
                env->e_err_text = NULL;
                env->e_error = 0;

                if ( env_outfile( env ) != 0 ) {
                    /* env_outfile syslogs errors */
                    sprintf( d_out, "%s/D%s", env->e_dir, env->e_id );
                    if ( unlink( d_out ) != 0 ) {
                        syslog( LOG_ERR, "Syserror: expand unlink %s: %m",
                                d_out );
                    }
                    goto cleanup5;
                }

                sendermatch = !strcasecmp( unexpanded_env->e_mail,
                        env->e_mail );

                n_rcpts = 0;
                for ( rcpt = env->e_rcpt; rcpt != NULL; rcpt = rcpt->r_next ) {
                    n_rcpts++;
                    if ( sendermatch ) {
                        syslog( LOG_INFO,
                                "Expand env <%s>: %s: To <%s> From <%s>",
                                unexpanded_env->e_id, env->e_id, rcpt->r_rcpt,
                                env->e_mail );
                    } else {
                        syslog( LOG_INFO,
                                "Expand env <%s>: %s: To <%s> From <%s> (%s)",
                                unexpanded_env->e_id, env->e_id, rcpt->r_rcpt,
                                env->e_mail, unexpanded_env->e_mail );
                    }
                }

                syslog( LOG_NOTICE, "Expand env <%s>: %s: Expanded %d bounces",
                        unexpanded_env->e_id, env->e_id, n_rcpts );

                queue_envelope( env );

            } else {
                *env_p = env->e_next;
                env_free( env );
            }

        } else {
            *env_p = env->e_next;
            bounce_stdout( env );
            env_free( env );
        }
    }

    if ( snet != NULL ) {
        if ( snet_close( snet ) != 0 ) {
            syslog( LOG_ERR, "Liberror: expand snet_close %s: %m", d_original );
            sprintf( d_out, "%s/D%s", env->e_dir, env->e_id );
            if ( unlink( d_out ) != 0 ) {
                syslog( LOG_ERR, "Syserror: expand unlink %s: %m", d_out );
            }
            goto cleanup5;
        }
        snet = NULL;
    }

    syslog( LOG_INFO, "Expand env <%s>: Metric %d entries %d levels",
            unexpanded_env->e_id, exp.exp_entries, exp.exp_max_level );

    if ( simta_expand_debug != 0 ) {
        return_value = 0;
        goto cleanup2;
    }

    if ( utime( d_original, NULL ) != 0 ) {
        syslog( LOG_ERR, "Syserror: expand utime %s: %m", d_original );
        goto cleanup5;
    }

    if ( unexpanded_env->e_dir != simta_dir_fast ) {
        /* truncate orignal Efile */
        sprintf( e_original, "%s/E%s", unexpanded_env->e_dir,
                unexpanded_env->e_id );

        if ( truncate( e_original, (off_t)0 ) != 0 ) {
            syslog( LOG_ERR, "Syserror: expand truncate %s: %m", e_original );
            goto cleanup5;
        }
    }

    /* delete original message */
    if ( env_unlink( unexpanded_env ) != 0 ) {
        syslog( LOG_ERR,
                "Expand env <%s>: Expansion complete, can't delete message",
                unexpanded_env->e_id );
    } else {
        syslog( LOG_INFO,
                "Expand env <%s>: Expansion complete, message deleted",
                unexpanded_env->e_id );
    }

    return_value = 0;
    goto cleanup2;

cleanup5:
    cleanup_envelope_list( &exp.exp_errors );
#ifdef HAVE_LDAP
    cleanup_envelope_list( &exp.exp_gmailfwding );
#endif /* HAVE_LDAP */

cleanup4:
    for ( eo = host_stab; eo != NULL; eo = eo->eo_next ) {
        env = eo->eo_env;
        eo->eo_env = NULL;

        if (( env->e_flags & ENV_FLAG_EFILE ) != 0 ) {
            queue_remove_envelope( env );
            if ( env_unlink( env ) == 0 ) {
                syslog( LOG_WARNING, "Expand env <%s>: Message Deleted: "
                        "System error, unwinding expansion", env->e_id );
            } else {
                syslog( LOG_ERR, "Expand env <%s>: "
                        "System error, can't unwind expansion", env->e_id );
            }
        }

        env_free( env );
    }

cleanup3:
#ifdef HAVE_LDAP
    for ( memonly = exp.exp_memonly; memonly != NULL;
            memonly = memonly->el_next ) {
        if (( memonly->el_exp_addr->e_addr_env_moderated != NULL ) &&
                (( memonly->el_exp_addr->e_addr_env_moderated->e_flags &
                ENV_FLAG_EFILE ) != 0 )) {
            env_unlink( memonly->el_exp_addr->e_addr_env_moderated );
            env_free( memonly->el_exp_addr->e_addr_env_moderated );
            memonly->el_exp_addr->e_addr_env_moderated = NULL;
        }
    }
#endif /* HAVE_LDAP */

    if ( simta_fast_files != fast_file_start ) {
        syslog( LOG_ERR, "Expand env <%s>: could not unwind expansion",
                unexpanded_env->e_id );
        return_value = 1;
    }

cleanup2:
    /* free host_stab */
    eo = host_stab;
    while ( eo != NULL ) {
        eo_free = eo;
        eo = eo->eo_next;
        free( eo_free );
    }

cleanup1:
#ifdef HAVE_LDAP
    exp_addr_link_free( exp.exp_memonly );
#endif /* HAVE_LDAP */

    /* free the expansion list */
    for ( e_addr = exp.exp_addr_head; e_addr != NULL; e_addr = next_e_addr ) {
        next_e_addr = e_addr->e_addr_next;

#ifdef HAVE_LDAP
        exp_addr_link_free( e_addr->e_addr_parents );
        exp_addr_link_free( e_addr->e_addr_children );
        permitted_destroy( e_addr );
        if (( e_addr->e_addr_env_moderated != NULL ) &&
                (( e_addr->e_addr_env_moderated->e_flags &
                ENV_FLAG_EFILE ) == 0 )) {
            env_free( e_addr->e_addr_env_moderated );
        }

        if ( e_addr->e_addr_owner ) {
            free( e_addr->e_addr_owner );
        }

        if ( e_addr->e_addr_dn ) {
            free( e_addr->e_addr_dn );
        }
#endif

        free( e_addr->e_addr );
        free( e_addr->e_addr_from );
        free( e_addr );
    }

done:
    if ( return_value != 0 ) {
        syslog( LOG_ERR, "Expand env <%s>: Expansion failed",
                unexpanded_env->e_id );
    }

    return( return_value );
}
Пример #26
0
user *
load_user(int crontab_fd, struct passwd	*pw, const char *name) {
	char envstr[MAX_ENVSTR];
	FILE *file;
	user *u;
	entry *e;
	int status, save_errno;
	char **envp, **tenvp;

	if (!(file = fdopen(crontab_fd, "r"))) {
		perror("fdopen on crontab_fd in load_user");
		return (NULL);
	}

	Debug(DPARS, ("load_user()\n"))

	/* file is open.  build user entry, then read the crontab file.
	 */
	if ((u = (user *) malloc(sizeof(user))) == NULL)
		return (NULL);
	if ((u->name = strdup(name)) == NULL) {
		save_errno = errno;
		free(u);
		errno = save_errno;
		return (NULL);
	}
	u->crontab = NULL;

	/* init environment.  this will be copied/augmented for each entry.
	 */
	if ((envp = env_init()) == NULL) {
		save_errno = errno;
		free(u->name);
		free(u);
		errno = save_errno;
		return (NULL);
	}

	/* load the crontab
	 */
	while ((status = load_env(envstr, file)) >= OK) {
		switch (status) {
		case ERR:
			free_user(u);
			u = NULL;
			goto done;
		case FALSE:
			e = load_entry(file, NULL, pw, envp);
			if (e) {
				e->next = u->crontab;
				u->crontab = e;
			}
			break;
		case TRUE:
			if ((tenvp = env_set(envp, envstr)) == NULL) {
				save_errno = errno;
				free_user(u);
				u = NULL;
				errno = save_errno;
				goto done;
			}
			envp = tenvp;
			break;
		}
	}

 done:
	env_free(envp);
	fclose(file);
	Debug(DPARS, ("...load_user() done\n"))
	return (u);
}
Пример #27
0
static void processor(const char *tx_addr, int port)
{
    sys_init(1);
    sys_log('E', "started port=%d, tx=%s\n", port, tx_addr);

    /* connect to the control thread */
    char addr[MAX_ADDR];
    sys_address(addr, port);
    IO *io = sys_connect(addr, IO_CHUNK);

    tx_attach(tx_addr);

    /* get env code from the tx */
    char *code = tx_program();
    char *res = mem_alloc(MAX_BLOCK);

    while (!io->stop) {
        sys_iready(io, -1);

        int status = -1;
        long long sid = 0LL, time = sys_millis();

        Env *env = NULL;
        Arg *arg = NULL;
        Vars *v = vars_new(0), *r = NULL, *w = NULL;

        Http_Req *req = http_parse_req(io);
        if (io->stop)
            goto exit;

        if (req == NULL) {
            status = http_400(io);
            goto exit;
        }

        if (req->method == OPTIONS) {
            status = http_opts(io);
            goto exit;
        }

        env = env_new("net", code);

        if (str_idx(req->path, "/fn") == 0) {
            int idx = (req->path[3] == '/') ? 4 : 3;
            int i = 0, len = 1, cnt = 0;
            Func **fns = env_funcs(env, req->path + idx, &cnt);

            status = http_200(io);
            while (status == 200 && len) {
                len = pack_fn2csv(fns, cnt, res, MAX_BLOCK, &i);
                status = http_chunk(io, res, len);
            }

            mem_free(fns);
            goto exit;
        }

        /* compare the request with the function defintion */
        Func *fn = env_func(env, req->path + 1);
        if (fn == NULL) {
            Error *err = error_new("unknown function '%s'", req->path + 1);
            status = http_404(io, err->msg);
            mem_free(err);
            goto exit;
        }

        if (fn->rp.name != NULL && req->method != POST) {
            status = http_405(io, POST);
            goto exit;
        }

        if (fn->rp.name == NULL && req->method == POST) {
            status = http_405(io, GET);
            goto exit;
        }

        /* TODO: think what to do with duplicate parameter values */
        for (int i = 0; i < req->args->len; ++i) {
            char *name = req->args->names[i];
            if (array_freq(req->args->names, req->args->len, name) > 1) {
                Error *err = error_new("duplicate parameter '%s' "
                                       "(not supported)",
                                       name);
                status = http_404(io, err->msg);
                mem_free(err);
                goto exit;
            }
        }

        if (fn->pp.len != req->args->len) {
            Error *err = error_new("expected %d primitive parameters, got %d",
                                   fn->pp.len, req->args->len);
            status = http_404(io, err->msg);
            mem_free(err);
            goto exit;
        }

        arg = mem_alloc(sizeof(Arg));
        for (int i = 0; i < fn->pp.len; ++i) {
            char *name = fn->pp.names[i];
            Type t = fn->pp.types[i];

            int idx = array_scan(req->args->names, req->args->len, name);
            if (idx < 0) {
                Error *err = error_new("unknown parameter '%s'", name);
                status = http_404(io, err->msg);
                mem_free(err);
                goto exit;
            }

            char *val = req->args->vals[idx];
            int error = 0;
            if (t == Int) {
                arg->vals[i].v_int = str_int(val, &error);
            } else if (t == Real)
                arg->vals[i].v_real = str_real(val, &error);
            else if (t == Long)
                arg->vals[i].v_long = str_long(val, &error);
            else if (t == String) {
                error = str_len(val) > MAX_STRING;
                if (!error)
                    str_cpy(arg->vals[i].v_str, val);
            }

            if (error) {
                Error *err = error_new("value '%s' (parameter '%s') "
                                       "is not of type '%s'",
                                       val, name, type_to_str(t));
                status = http_404(io, err->msg);
                mem_free(err);
                goto exit;
            }
        }

        if (fn->rp.name != NULL) {
            TBuf *body = NULL;
            if (req->len > 0) {
                Error *err = pack_csv2rel(req->body, fn->rp.head, &body);
                if (err != NULL) {
                    status = http_404(io, err->msg);
                    mem_free(err);
                    goto exit;
                }
            } else {
                body = tbuf_new();
            }

            vars_add(v, fn->rp.name, 0, body);

            /* project the parameter */
            Rel *param = rel_project(rel_load(fn->rp.head, fn->rp.name),
                                     fn->rp.head->names,
                                     fn->rp.head->len);

            rel_eval(param, v, arg);

            /* clean the previous version */
            tbuf_clean(body);
            tbuf_free(body);

            /* replace with the new body */
            int vpos = array_scan(v->names, v->len, fn->rp.name);
            v->vals[vpos] = param->body;

            param->body = NULL;
            rel_free(param);
        }

        /* start a transaction */
        r = vars_new(fn->r.len);
        w = vars_new(fn->w.len);
        for (int i = 0; i < fn->r.len; ++i)
            vars_add(r, fn->r.names[i], 0, NULL);
        for (int i = 0; i < fn->w.len; ++i)
            vars_add(w, fn->w.names[i], 0, NULL);

        sid = tx_enter(addr, r, w);

        /* prepare variables */
        for (int i = 0; i < r->len; ++i) {
            TBuf *body = vol_read(r->vols[i], r->names[i], r->vers[i]);
            vars_add(v, r->names[i], 0, body);
        }
        for (int i = 0; i < w->len; ++i) {
            int pos = array_scan(v->names, v->len, w->names[i]);
            if (pos < 0)
                vars_add(v, w->names[i], 0, NULL);
        }
        for (int i = 0; i < fn->t.len; ++i)
            vars_add(v, fn->t.names[i], 0, NULL);

        /* evaluate the function body */
        for (int i = 0; i < fn->slen; ++i)
            rel_eval(fn->stmts[i], v, arg);

        /* prepare the return value. note, the resulting relation
           is just a container for the body, so it is not freed */
        Rel *ret = NULL;
        if (fn->ret != NULL)
            ret = fn->stmts[fn->slen - 1];

        /* persist the global variables */
        for (int i = 0; i < w->len; ++i) {
            int idx = array_scan(v->names, v->len, w->names[i]);
            if (idx < 0) {
                status = http_500(io);
                goto exit;
            }

            vol_write(w->vols[i], v->vals[idx], w->names[i], w->vers[i]);
            tbuf_free(v->vals[idx]);
            v->vals[idx] = NULL;
        }

        /* confirm a success and send the result back */
        status = http_200(io);
        if (status != 200)
            goto exit;

        tx_commit(sid);

        /* N.B. there is no explicit revert as the transaction manager handles
           nested tx_enter and a connectivity failure as a rollback */

        int len = 1, i = 0;
        while (status == 200 && len) {
            len = pack_rel2csv(ret, res, MAX_BLOCK, i++);
            status = http_chunk(io, res, len);
        }
exit:
        if (status != -1)
            sys_log('E', "%016llX method %c, path %s, time %lldms - %3d\n",
                         sid,
                         (req == NULL) ? '?' : req->method,
                         (req == NULL) ? "malformed" : req->path,
                         sys_millis() - time,
                         status);


        if (r != NULL)
            vars_free(r);
        if (w != NULL)
            vars_free(w);
        if (arg != NULL)
            mem_free(arg);
        if (req != NULL)
            http_free_req(req);
        if (env != NULL)
            env_free(env);
        for (int i = 0; i < v->len; ++i)
            if (v->vals[i] != NULL) {
                tbuf_clean(v->vals[i]);
                tbuf_free(v->vals[i]);
            }
        vars_free(v);

        sys_term(io);
    }

    mem_free(code);
    mem_free(res);
    tx_detach();
    sys_close(io);
}
Пример #28
0
/*
 * Get data from the keyboard.  If we finish a character, return it.  Else 0.
 * Return -1 if no data.
 */
static int
kbd_proc_data(void)
{
	int c;
	uint8_t data;
	static uint32_t shift;

	if ((inb(KBSTATP) & KBS_DIB) == 0)
		return -1;

	data = inb(KBDATAP);

	if (data == 0xE0) {
		// E0 escape character
		shift |= E0ESC;
		return 0;
	} else if (data & 0x80) {
		// Key released
		data = (shift & E0ESC ? data : data & 0x7F);
		shift &= ~(shiftcode[data] | E0ESC);
		return 0;
	} else if (shift & E0ESC) {
		// Last character was an E0 escape; or with 0x80
		data |= 0x80;
		shift &= ~E0ESC;
	}

	shift |= shiftcode[data];
	shift ^= togglecode[data];

	c = charcode[shift & (CTL | SHIFT)][data];
	//cprintf("shift:%08x,c:%08x\n",shift, c);
	if (shift & CAPSLOCK) {
		if ('a' <= c && c <= 'z')
			c += 'A' - 'a';
		else if ('A' <= c && c <= 'Z')
			c += 'a' - 'A';
	}
	if((shift & CTL ) && c == 0x3) {
		//cprintf("ctrl+c\n");
		struct Env *env;
		//env->env_status = ENV_NOT_RUNNABLE;
		//sched_yield();
		int i;
		for(i = NENV - 1; i >= 0; i--)
		{
			env = &envs[i];
			//cprintf("i:%08x\n",i);
			while(env->env_id != envs[0].env_id)
			{
				//cprintf("shforkid position:%08x\n",ENVX(shforkid));
				//cprintf("envid->parent_id:%08x\n",env->env_parent_id);
				if(env->env_id == shforkid)
				{
					//cprintf("destroy %08x\n",i);
					env_free(&envs[i]);
					//after free the env, clean the tickets of the env
					global_tickets -= envs[i].tickets;
					envs[i].tickets = 0;
					break;
				}
				env = &envs[ENVX(env->env_parent_id)];
				if(ENVX(env->env_id) < ENVX(shforkid))
					break;
				//cprintf("envid position:%08x\n",ENVX(env->env_id));

			}
			/*
			if(envs[i].env_parent_id == curenv ->env_id 
					||envs[i].env_id == curenv -> env_parent_id)
			{
				cprintf("destroy i:%08x\n",i);
				env_destroy(&envs[i]);
			}
			*/
		}
		//env_destroy(curenv);
	}
	// Process special keys
	// Ctrl-Alt-Del: reboot
	if (!(~shift & (CTL | ALT)) && c == KEY_DEL) {
		cprintf("Rebooting!\n");
		outb(0x92, 0x3); // courtesy of Chris Frost
	}

	return c;
}