Example #1
0
void dstrprepend(dstr_t *ds, const char *str)
{
    dstr_t *copy = create_dstr();
    dstrcpy(copy, ds->data);
    dstrcpy(ds, str);
    dstrcatf(ds, "%s", copy->data);
    free_dstr(copy);
}
Example #2
0
void G_GetActionBindings(char *buff, char *action)
{
    int     i;
    char    *p;
    
    p = buff;
    *p = 0;
    for(i = 0; i < NUMKEYS; i++)
    {
        if(IsSameAction(action, KeyActions[i]))
        {
            if(p != buff)
                *(p++) = ',';

            M_GetKeyName(p, i);

            p += dstrlen(p);

            if(p - buff >= MAX_MENUACTION_LENGTH)
                return;
        }
    }
    for(i = 0; i < MOUSE_BUTTONS; i++)
    {
        if(IsSameAction(action, MouseActions[i]))
        {
            if(p != buff)
                *(p++) = ',';

            if(i < MOUSE_BUTTONS-2)
            {
                dstrcpy(p, "mouse?");
                p[5] = i + '1';
                p += 6;
            }

            if(p - buff >= MAX_MENUACTION_LENGTH)
                return;
        }
        if(IsSameAction(action, Mouse2Actions[i]))
        {
            if(p != buff)
                *(p++) = ',';
            dstrcpy(p, "mouse2?");
            p[6] = i + '1';
            p += 7;
            if(p - buff >= MAX_MENUACTION_LENGTH)
                return;
        }
    }
}
Example #3
0
void G_UnregisterAction(char *name)
{
    action_t    *action;
    action_t    *tree;
    char        buff[256];
    
    dstrcpy(buff, name);
    dstrlwr(buff);

    action = FindAction(buff);

    if(!action)
        return;

    if(!action->children[0])
    {
        ReplaceActionWith(action, action->children[1]);
    }
    else if(!action->children[1])
    {
        ReplaceActionWith(action, action->children[0]);
    }
    else
    {
        tree = action->children[1];
        while(tree->children[0])
            tree = tree->children[0];

        tree->children[0] = action->children[0];

        action->children[0]->parent = tree;
        G_OptimizeActionTree();
    }
    G_FreeAction(action);
}
Example #4
0
t_tree mFuncCallExpr(t_tree pActuals, const char *pFuncName, int pLineNr)
{
   t_tree node = allocateNode(kFuncCallExpr, pLineNr);
   node->Node.FuncCallExpr.Actuals = pActuals;
   node->Node.FuncCallExpr.FuncName = dstrcpy(pFuncName);
   return node;
}
Example #5
0
char *(Z_Strdup) (const char *s, int tag, void *user, const char *file,
		  int line) {
#ifdef ZONEFILE
	Z_LogPrintf("* Z_Strdup(file=%s:%d)\n", file, line);
#endif
	return dstrcpy((Z_Malloc) (dstrlen(s) + 1, tag, user, file, line), s);
}
Example #6
0
t_tree mRead(const char *pId, int pLineNr)
{
   t_tree node = allocateNode(kRead, pLineNr);
   node->Node.Read.Next = NULL;
   node->Node.Read.Id = dstrcpy(pId);
   return node;
}
Example #7
0
static void TrapProcessCreateHandler(uint32 *trapArgs, int sysmode)
{
  char allargs[SIZE_ARG_BUFF];
  char name[100];
  int i=0, j=0, k=0;
  uint32 args[MAX_ARGS];
  char *destination;
  // The first argument is the name of the executable file

  i=0;
  for(i=0;i<100; i++)
    allargs[i] = 0;
  i=0;
  if(!sysmode)
  {
    //Get the arguments into the sytem space
    MemoryCopyUserToSystem (currentPCB, trapArgs, args, sizeof (args));
    do {
      MemoryCopyUserToSystem (currentPCB,((char*)args[0])+i,name+i,1);
      i++;
    } while ((i < sizeof (name)) && (name[i-1] != '\0'));
  } else {
    bcopy (trapArgs, args, sizeof (args));
    dstrncpy ((char *)args[0], name, sizeof (name));
  }
  name[sizeof(name)-1] = '\0';	// null terminate the name
  i=0;
  if(!sysmode)
  {
    //Copy the rest of the arguments to the system space
    for(j=0; (j<11)&&(args[j]!=0); j++)
    {
      k=0;
      do 
      {
        MemoryCopyUserToSystem (currentPCB,((char*)args[j])+k,allargs+i,1);
        i++; k++;
      } while ((i<sizeof(allargs)) && (allargs[i-1]!='\0'));
    }
  }
  else 
  {
    destination = &allargs[0];
    for(j=0; (j<11)&&(args[j]!=0); j++)
    {
      k = dstrlen((char *)args[j]);  //length of the argument
      if(&destination[k]-allargs>100)
      {
        printf("Fatal: Cumulative length of all arguments > 100\n");
	exitsim();
      }
      dstrcpy(destination, (char *)args[j]);
      destination[k] = '\0';
    }
  }
  allargs[sizeof(allargs)-1] = '\0';	// null terminate the name

  ProcessFork(0, (uint32)allargs, name, 1);
}
Example #8
0
t_tree mFuncCallStmnt(t_tree pActuals, const char *pFuncName, int pLineNr)
{
   t_tree node = allocateNode(kFuncCallStmnt, pLineNr);
   node->Node.FuncCallStmnt.Next = NULL;
   node->Node.FuncCallStmnt.Actuals = pActuals;
   node->Node.FuncCallStmnt.FuncName = dstrcpy(pFuncName);
   return node;
}
Example #9
0
t_tree mAssign(const char *pId , t_tree pExpr, int pLineNr)
{
   t_tree node = allocateNode(kAssign, pLineNr);
   node->Node.Assign.Next = NULL;
   node->Node.Assign.Id = dstrcpy(pId);
   node->Node.Assign.Expr = pExpr;
   return node;
}
Example #10
0
t_tree mVariable(vKind pVarKind, const char *pName, eType pType, int pLineNr)
{
   t_tree node = allocateNode(kVariable, pLineNr);
   node->Node.Variable.Next = NULL;
   node->Node.Variable.VarKind = pVarKind;
   node->Node.Variable.Name = dstrcpy(pName);
   node->Node.Variable.Type = pType;
   return node;
}
Example #11
0
t_tree mFunction(t_tree pVariables, t_tree pStmnts, const char *pName, eType pType, int pLineNr)
{
   t_tree node = allocateNode(kFunction, pLineNr);
   node->Node.Function.Next = NULL;
   node->Node.Function.Variables = pVariables;
   node->Node.Function.Stmnts = pStmnts;
   node->Node.Function.Name = dstrcpy(pName);
   node->Node.Function.Type = pType;
   return node;
}
Example #12
0
void G_UnbindAction(char *action)
{
    int i;

    for(i = 0; i < NUMKEYS; i++)
    {
        if(IsSameAction(action, KeyActions[i]))
        {
            char p[16];

            M_GetKeyName(p, i);
            Unbind(p);
            return;
        }
    }
    for(i = 0; i < MOUSE_BUTTONS; i++)
    {
        if(IsSameAction(action, MouseActions[i]))
        {
            char p[16];

            if(i < MOUSE_BUTTONS-2)
            {
                dstrcpy(p, "mouse?");
                p[5] = i + '1';
            }

            Unbind(p);
            return;
        }
        if(IsSameAction(action, Mouse2Actions[i]))
        {
            char p[16];

            dstrcpy(p, "mouse2?");
            p[6] = i + '1';
            
            Unbind(p);
            return;
        }
    }
}
Example #13
0
char *
dstrcat (char *onto, const char *addn)
{
  char	*konto = onto;

  while (*onto != '\0') {
    onto++;
  }
  dstrcpy (onto, addn);
  return (konto);
}
Example #14
0
void CON_CvarRegister(cvar_t *variable)
{
    char *oldstr;
    
    // first check to see if it has allready been defined
    if(CON_CvarGet(variable->name))
    {
        CON_Printf(WHITE, "CON_CvarRegister: Can't register variable %s, already defined\n", variable->name);
        return;
    }
    
    // copy the value off, because future sets will Z_Free it
    oldstr = variable->string;
    variable->string = Z_Malloc(dstrlen(variable->string)+1, PU_STATIC, 0);	
    dstrcpy(variable->string, oldstr);
    variable->value = datof(variable->string);
    variable->defvalue = Z_Malloc(dstrlen(variable->string)+1, PU_STATIC, 0);
    dstrcpy(variable->defvalue, variable->string);
    
    // link the variable in
    variable->next = cvarcap;
    cvarcap = variable;
}
Example #15
0
extern void symtab_add(t_symtab *symtab, const char *s)
{
   t_symrec *symrec = calloc(sizeof(t_symrec), 1);
   if (symrec == NULL) {
      error_message("Out of memory when creating a symbol table record");
      exit(-1);
   }
   symrec->symtab = symtab;
   symrec->s = dstrcpy(s);
   llist_insert_last(symtab->list, symrec);
   if (symtab->lookup_table) {
      hash_insert(symtab->lookup_table, symrec->s, symrec);
   }
}
Example #16
0
///
/// BuildKeywordString
static char *BuildKeywordString(void)
{
  char *keywords = NULL;
  ULONG i;

  ENTER();

  dstrcpy(&keywords, C->AttachmentKeywords);

  for(i=0; IntMimeTypeArray[i].ContentType != NULL; i++)
  {
    if(IsStrEmpty(IntMimeTypeArray[i].Extension) == FALSE)
    {
      char *copy;

      // split the space separated extensions and build a string of
      // comma separated extensions with leading '.'
      if((copy = strdup(IntMimeTypeArray[i].Extension)) != NULL)
      {
        char *ext = copy;

        do
        {
          char *e;

          if((e = strpbrk(ext, " ")) != NULL)
            *e++ = '\0';

          if(dstrlen(keywords) != 0)
            dstrcat(&keywords, ",");

          dstrcat(&keywords, ".");
          dstrcat(&keywords, ext);

          ext = e;
        }
        while(ext != NULL);

        free(copy);
      }
    }
  }
  D(DBF_GUI, "build keyword string '%s'", keywords);

  RETURN(keywords);
  return keywords;
}
Example #17
0
void G_OutputBindings(FILE *fh)
{
    int         i;
    alist_t     *al;
    char        name[MAX_KEY_NAME_LENGTH];
    cvar_t      *var;
    
    for(i = 0; i < NUMKEYS; i++)
    {
        al = KeyActions[i];
        if(!al)
            continue;

        M_GetKeyName(name, i);
        OutputActions(fh, al, name);
    }

    dstrcpy(name, "mouse");

    for(i = 0; i < MOUSE_BUTTONS; i++)
    {
        al = MouseActions[i];
        if(al)
        {
            name[5] = i+'1';
            name[6] = 0;
            OutputActions(fh, al, name);
        }
    }
    for(i = 0; i< MOUSE_BUTTONS; i++)
    {
        al = Mouse2Actions[i];
        if(al)
        {
            name[5] = '2';
            name[6] = i+'1';
            name[7] = 0;
            OutputActions(fh, al, name);
        }
    }
    
    // cvars
    for(var = cvarcap; var; var = var->next)
        fprintf(fh, "seta \"%s\" \"%s\"\n", var->name, var->string);
}
Example #18
0
int M_GetKeyName(char *buff, int key)
{
	keyinfo_t *pkey;

	if (((key >= 'a') && (key <= 'z')) || ((key >= '0') && (key <= '9'))) {
		buff[0] = (char)toupper(key);
		buff[1] = 0;
		return true;
	}
	for (pkey = Keys; pkey->name; pkey++) {
		if (pkey->code == key) {
			dstrcpy(buff, pkey->name);
			return true;
		}
	}
	sprintf(buff, "Key%02x", key);
	return false;
}
Example #19
0
/*
 * Replace the first occurrence of 'find' after the index 'start' with 'repl'
 * Returns the position right after the replaced string
 */
int dstrreplace(dstr_t *ds, const char *find, const char *repl, int start)
{
    char *p;
    dstr_t *copy = create_dstr();
    int end = -1;

    dstrcpy(copy, ds->data);

    if ((p = strstr(&copy->data[start], find)))
    {
        dstrncpy(ds, copy->data, p - copy->data);
        dstrcatf(ds, "%s", repl);
        end = ds->len;
        dstrcatf(ds, "%s", p + strlen(find));
    }

    free_dstr(copy);
    return end;
}
Example #20
0
void TryActions(alist_t *al, dboolean up)
{
    if(!al)
        return;
    
    if(up)
    {
        action_t    *action;
        char        buff[256];
        
        if(al->next || (al->cmd[0] != '+'))
            return;
        
        dstrcpy(buff, al->cmd);
        buff[0] = '-';
        action = FindAction(buff);
        if(action)
            action->proc(action->data, al->param);
        return;
    }

    AddActions(DoRunActions(al, false));
}
Example #21
0
void CON_CvarSet(char *var_name, char *value)
{
    cvar_t	*var;
    dboolean changed;
    
    var = CON_CvarGet(var_name);
    if(!var)
    {	// there is an error in C code if this happens
        CON_Printf(WHITE, "CON_CvarSet: variable %s not found\n", var_name);
        return;
    }
    
    changed = dstrcmp(var->string, value);
    
    Z_Free(var->string);	// free the old value string
    
    var->string = Z_Malloc(dstrlen(value)+1, PU_STATIC, 0);
    dstrcpy(var->string, value);
    var->value = datof(var->string);

    if(var->callback)
        var->callback(var);
}
Example #22
0
//----------------------------------------------------------------------
//
//	main
//
//	This routine is called when the OS starts up.  It allocates a
//	PCB for the first process - the one corresponding to the initial
//	thread of execution.  Note that the stack pointer is already
//	set correctly by _osinit (assembly language code) to point
//	to the stack for the 0th process.  This stack isn't very big,
//	though, so it should be replaced by the system stack of the
//	currently running process.
//
//----------------------------------------------------------------------
void main (int argc, char *argv[])
{
  int		i,j;
  int		n;
  char	buf[120];
  char		*userprog = (char *)0;
  int base=0;
  int numargs=0;
  char allargs[SIZE_ARG_BUFF];
  int allargs_offset = 0;
  
  debugstr[0] = '\0';

  printf ("Got %d arguments.\n", argc);
  printf ("Available memory: 0x%x -> 0x%x.\n", (int)lastosaddress, MemoryGetSize ());
  printf ("Argument count is %d.\n", argc);
  for (i = 0; i < argc; i++) {
    printf ("Argument %d is %s.\n", i, argv[i]);
  }

  FsModuleInit ();
  for (i = 0; i < argc; i++) 
  {
    if (argv[i][0] == '-') 
    {
      switch (argv[i][1]) 
      {
      case 'D':
	dstrcpy (debugstr, argv[++i]);
	break;
      case 'i':
	n = dstrtol (argv[++i], (void *)0, 0);
	ditoa (n, buf);
	printf ("Converted %s to %d=%s\n", argv[i], n, buf);
	break;
      case 'f':
      {
	int	start, codeS, codeL, dataS, dataL, fd, j;
	int	addr = 0;
	static unsigned char buf[200];
	fd = ProcessGetCodeInfo (argv[++i], &start, &codeS, &codeL, &dataS,
				 &dataL);
	printf ("File %s -> start=0x%08x\n", argv[i], start);
	printf ("File %s -> code @ 0x%08x (size=0x%08x)\n", argv[i], codeS,
		codeL);
	printf ("File %s -> data @ 0x%08x (size=0x%08x)\n", argv[i], dataS,
		dataL);
	while ((n = ProcessGetFromFile (fd, buf, &addr, sizeof (buf))) > 0) 
	{
	  for (j = 0; j < n; j += 4) 
	  {
	    printf ("%08x: %02x%02x%02x%02x\n", addr + j - n, buf[j], buf[j+1],
		    buf[j+2], buf[j+3]);
	  }
	}
	close (fd);
	break;
      }
      case 'u':
	userprog = argv[++i];
        base = i; // Save the location of the user program's name 
	break;
      default:
	printf ("Option %s not recognized.\n", argv[i]);
	break;
      }
      if(userprog)
        break;
    }
  }
  dbprintf ('i', "About to initialize queues.\n");
  AQueueModuleInit ();
  dbprintf ('i', "After initializing queues.\n");
  MemoryModuleInit ();
  dbprintf ('i', "After initializing memory.\n");

  ProcessModuleInit ();
  dbprintf ('i', "After initializing processes.\n");
  SynchModuleInit ();
  dbprintf ('i', "After initializing synchronization tools.\n");
  KbdModuleInit ();
  dbprintf ('i', "After initializing keyboard.\n");
  ClkModuleInit ();
  dbprintf ('i', "After initializing clock.\n");
  for (i = 0; i < 100; i++) {
    buf[i] = 'a';
  }
  i = FsOpen ("vm", FS_MODE_WRITE);
  dbprintf ('i', "VM Descriptor is %d\n", i);
  FsSeek (i, 0, FS_SEEK_SET);
  FsWrite (i, buf, 80);
  FsClose (i);

  // Setup command line arguments
  if (userprog != (char *)0) {
    numargs=0;
    allargs_offset = 0;
    // Move through each of the argv addresses
    for(i=0; i<argc-base; i++) {
      // At each argv address, copy the string into allargs, including the '\0'
      for(j=0; allargs_offset < SIZE_ARG_BUFF; j++) {
        allargs[allargs_offset++] = argv[i+base][j];
        if (argv[i+base][j] == '\0') break; // end of this string
      }
      numargs++;
    }
    allargs[SIZE_ARG_BUFF-1] = '\0'; // set last char to NULL for safety
    ProcessFork(0, (uint32)allargs, userprog, 1);
  } else {
    dbprintf('i', "No user program passed!\n");
  }
  ClkStart();
  dbprintf ('i', "Set timer quantum to %d, about to run first process.\n",
	    processQuantum);
  intrreturn ();
  // Should never be called because the scheduler exits when there
  // are no runnable processes left.
  exitsim();	// NEVER RETURNS!
}
Example #23
0
//--------------------------------------------------------------------
//
// int process_create(char *exec_name, ...);
//
// Here we support reading command-line arguments.  Maximum MAX_ARGS 
// command-line arguments are allowed.  Also the total length of the 
// arguments including the terminating '\0' should be less than or 
// equal to SIZE_ARG_BUFF.
//
//--------------------------------------------------------------------
static void TrapProcessCreateHandler(uint32 *trapArgs, int sysmode) {
  char allargs[SIZE_ARG_BUFF];  // Stores full string of arguments (unparsed)
  char name[PROCESS_MAX_NAME_LENGTH]; // Local copy of name of executable (100 chars or less)
  char *username=NULL;          // Pointer to user-space address of exec_name string
  int i=0, j=0;                 // Loop index variables
  char *args[MAX_ARGS];         // All parsed arguments (char *'s)
  int allargs_position = 0;     // Index into current "position" in allargs
  char *userarg = NULL;         // Current pointer to user argument string
  int numargs = 0;              // Number of arguments passed on command line

  dbprintf('p', "TrapProcessCreateHandler: function started\n");
  // Initialize allargs string to all NULL's for safety
  for(i=0;i<SIZE_ARG_BUFF; i++) {
    allargs[i] = '\0';
  }

  // First deal with user-space addresses
  if(!sysmode) {
    dbprintf('p', "TrapProcessCreateHandler: creating user process\n");
    // Get the known arguments into the kernel space.
    // Argument 0: user-space pointer to name of executable
    MemoryCopyUserToSystem (currentPCB, (char *)(trapArgs+0), (char *)&username, sizeof(char *));

    // Copy the user-space string at user-address "username" into kernel space
    for(i=0; i<PROCESS_MAX_NAME_LENGTH; i++) {
      MemoryCopyUserToSystem(currentPCB, (char *)(username+i), (char *)&(name[i]), sizeof(char));
      // Check for end of user-space string
      if (name[i] == '\0') break;
    }
    dbprintf('p', "TrapProcessCreateHandler: just parsed executable name (%s) from trapArgs\n", name);
    if (i == PROCESS_MAX_NAME_LENGTH) {
      printf("TrapProcessCreateHandler: length of executable filename longer than allowed!\n");
      exitsim();
    }

    // Copy the program name into "allargs", since it has to be the first argument (i.e. argv[0])
    allargs_position = 0;
    dstrcpy(&(allargs[allargs_position]), name);
    allargs_position += dstrlen(name) + 1; // The "+1" is so we're pointing just beyond the NULL

    // Rest of arguments: a series of char *'s until we hit NULL or MAX_ARGS
    for(i=0; i<MAX_ARGS; i++) {
      // First, must copy the char * itself into kernel space in order to read its value
      MemoryCopyUserToSystem(currentPCB, (char *)(trapArgs+1+i), (char *)&userarg, sizeof(char *));
      // If this is a NULL in the set of char *'s, this is the end of the list
      if (userarg == NULL) break;
      // Store a pointer to the kernel-space location where we're copying the string
      args[i] = &(allargs[allargs_position]);
      // Copy the string into the allargs, starting where we left off last time through this loop
      for (j=0; j<SIZE_ARG_BUFF; j++) {
        MemoryCopyUserToSystem(currentPCB, (char *)(userarg+j), (char *)&(allargs[allargs_position]), sizeof(char));
        // Move current character in allargs to next spot
        allargs_position++;
        // Check that total length of arguments is still ok
        if (allargs_position == SIZE_ARG_BUFF) {
          printf("TrapProcessCreateHandler: strlen(all arguments) > maximum length allowed!\n");
          exitsim();
        }
        // Check for end of user-space string
        if (allargs[allargs_position-1] == '\0') break;
      }
    }
    if (i == MAX_ARGS) {
      printf("TrapProcessCreateHandler: too many arguments on command line (did you forget to pass a NULL?)\n");
      exitsim();
    }
    numargs = i+1;
    // Arguments are now setup
  } else {
    // Addresses are already in kernel space, so just copy into our local variables 
    // for simplicity
    // Argument 0: (char *) name of program
    dstrncpy(name, (char *)(trapArgs[0]), PROCESS_MAX_NAME_LENGTH);
    // Copy the program name into "allargs", since it has to be the first argument (i.e. argv[0])
    allargs_position = 0;
    dstrcpy(&(allargs[allargs_position]), name);
    allargs_position += dstrlen(name) + 1;  // The "+1" is so that we are now pointing just beyond the "null" in the name
    allargs_position = 0;
    for (i=0; i<MAX_ARGS; i++) {
      userarg = (char *)(trapArgs[i+1]);
      if (userarg == NULL) break; // found last argument
      // Store the address of where we're copying the string
      args[i] = &(allargs[allargs_position]);
      // Copy string into allargs
      for(j=0; j<SIZE_ARG_BUFF; j++) {
        allargs[allargs_position] = userarg[j];
        allargs_position++;
        if (allargs_position == SIZE_ARG_BUFF) {
          printf("TrapProcessCreateHandler: strlen(all arguments) > maximum length allowed!\n");
          exitsim();
        }
        // Check for end of user-space string
        if (allargs[allargs_position-1] == '\0') break;
      }
    }
    if (i == MAX_ARGS) {
      printf("TrapProcessCreateHandler: too many arguments on command line (did you forget to pass a NULL?)\n");
      exitsim();
    }
    numargs = i+1;
  }

  ProcessFork(0, (uint32)allargs, name, 1);
}
Example #24
0
size_t dstrfreadl(dstring_t dest, FILE *fp) {

   char     *start;                 /* points to beginning of buffer */
   char     *bufpos;                /* our current position in DSTRBUF(dest) */
   char     *status;                /* tests for NULL when we encounter EOF */
   ptrdiff_t bufcount = 0;          /* how many characters we've read so far */

   dstring_t temp;                  /* temporary dstring_t object */

   /* make sure dest is initialized */
   if (NULL == dest) {
      _setdstrerrno(DSTR_UNINITIALIZED);
      return 0;
   }

   /* make sure fp is an opened file */
   if (NULL == fp) {
      _setdstrerrno(DSTR_UNOPENED_FILE);
      return 0;
   }

   /* allocate space for temp */
   if (DSTR_SUCCESS != dstrnalloc(&temp, dstrallocsize(dest))) {
      return 0;
   }

   bufpos = start = DSTRBUF(temp);

   /* *start = '\0'; */

   /* loop until we've read a whole line */
   while (1) {

      status = fgets(bufpos, DSTRBUFLEN(temp) - bufcount, fp);

      /* EOF or read error encountered */
      if (status == NULL) {

         /* if we read something, we should keep it */
         if (dstrlen(temp) > 0) {
            break;
         }

         /* there's nothing to read */
         if (feof(fp)) {
            _setdstrerrno(DSTR_EOF);
         } else {
            _setdstrerrno(DSTR_FILE_ERROR);
         }

         dstrfree(&temp);
         return 0;
      }

      /* make sure bufpos points to our current position */
      bufpos = start + dstrlen(temp);

      /* we're done */
      if ('\n' == bufpos[-1]) {
         break;
      }

      /* if we can't get more memory, we can't finish the line */
      if (DSTR_SUCCESS != dstrealloc(&temp, DSTRBUFLEN(temp) * 2)) {
         dstrfree(&temp);
         return 0;
      }

      /* make sure you update start, lest you suffer the wrath of glibc... */
      start = DSTRBUF(temp);
      bufpos = start + dstrlen(temp);

      /* the +1 at the end is to make sure the '\0' is counted */
      bufcount = bufpos - start + 1;
   }

   /* copy our new string into dest only if we read something */
   if (dstrlen(temp) > 0) {
      /* does dest need more space than it already has? */
      if (DSTRBUFLEN(dest) < dstrlen(temp) + 1) {
         if (DSTR_SUCCESS != dstrealloc(&dest, dstrlen(temp) + 1)) {
            dstrfree(&temp);
            return 0;
         }
      }
      dstrcpy(dest, temp);
      if (DSTR_SUCCESS != dstrerrno) {
         dstrfree(&temp);
         return 0;
      }
   }

   /* indicate success and return */
   _setdstrerrno(DSTR_SUCCESS);
   dstrfree(&temp);
   return dstrlen(dest);
}
Example #25
0
//----------------------------------------------------------------------
//
//	ProcessFork
//
//	Create a new process and make it runnable.  This involves the
//	following steps:
//	* Allocate resources for the process (PCB, memory, etc.)
//	* Initialize the resources
//	* Place the PCB on the runnable queue
//
//	NOTE: This code has been tested for system processes, but not
//	for user processes.
//
//----------------------------------------------------------------------
int ProcessFork (VoidFunc func, uint32 param, char *name, int isUser) {
  int i,j;                   // Loop index variable
  int fd, n;               // Used for reading code from files.
  int start, codeS, codeL; // Used for reading code from files.
  int dataS, dataL;        // Used for reading code from files.
  int addr = 0;            // Used for reading code from files.
  unsigned char buf[100];  // Used for reading code from files.
  uint32 *stackframe;      // Stores address of current stack frame.
  PCB *pcb;                // Holds pcb while we build it for this process.
  int intrs;               // Stores previous interrupt settings.
  uint32  initial_user_params[MAX_ARGS+2]; // Initial memory for user parameters (argc, argv)
                                           // initial_user_params[0] = argc
                                           // initial_user_params[1] = argv, points to initial_user_params[2]
                                           // initial_user_params[2] = address of string for argv[0]
                                           // initial_user_params[3] = address of string for argv[1]
                                           //                           ...
  uint32 argc=0;           // running counter for number of arguments
  uint32 offset;           // Used in parsing command line argument strings, holds offset (in bytes) from 
                           // beginning of the string to the current argument.
  uint32 initial_user_params_bytes;  // total number of bytes in initial user parameters array

  int newpage;
  int index;
  int *p;


  intrs = DisableIntrs ();
  dbprintf ('I', "ProcessFork-Old interrupt value was 0x%x.\n", intrs);
  dbprintf ('p', "ProcessFork-Entering ProcessFork args=0x%x 0x%x %s %d\n", (int)func,
	    param, name, isUser);
  // Get a free PCB for the new process
  if (AQueueEmpty(&freepcbs)) {
    printf ("ProcessFork-FATAL error: no free processes!\n");
    exitsim ();	// NEVER RETURNS!
  }
  pcb = (PCB *)AQueueObject(AQueueFirst (&freepcbs));
  dbprintf ('p', "ProcessFork-Got a link @ 0x%x\n", (int)(pcb->l));
  if (AQueueRemove (&(pcb->l)) != QUEUE_SUCCESS) {
    printf("ProcessFork-FATAL ERROR: could not remove link from freepcbsQueue in ProcessFork!\n");
    exitsim();
  }
  // This prevents someone else from grabbing this process
  ProcessSetStatus (pcb, PROCESS_STATUS_RUNNABLE);

  // At this point, the PCB is allocated and nobody else can get it.
  // However, it's not in the run queue, so it won't be run.  Thus, we
  // can turn on interrupts here.
  RestoreIntrs (intrs);

  // Copy the process name into the PCB.
  dstrcpy(pcb->name, name);

  //----------------------------------------------------------------------
  // This section initializes the memory for this process
  //----------------------------------------------------------------------
  // Allocate 1 page for system stack, 1 page for user stack (at top of
  // virtual address space), and 4 pages for user code and global data.

  //---------------------------------------------------------
  // STUDENT: allocate pages for a new process here.  The
  // code below assumes that you set the "stackframe" variable
  // equal to the last 4-byte-aligned address in physical page
  // for the system stack.
  //---------------------------------------------------------

  ////////////////////////////////////////////////////////////////
  // JSM, allocate 6 physical pages for new process

  // First, get L2 Page Table for index 0 of L1 Page Table
  index = MemoryAllocateL2PT();
	if (index == -1)
	{
		printf ("ProcessFork-FATAL: couldn't allocate L2 Page Table for index 0 of L1 Page Table - no free page tables!\n");
		exitsim ();	// NEVER RETURNS!
	}
  // Assign L1 entry to address of start of L2 Page Table
	pcb->pagetable[0] = (uint32)&level2_pt_block[index];

	p = (uint32 *)pcb->pagetable[0];//L2

  // Allocate 4 pages for code and data
  for(i = 0; i < 4; i++)
  {
		newpage = MemoryAllocatePage();
		if (newpage == 0)
		{
			printf ("ProcessFork-FATAL: couldn't allocate memory - no free pages!\n");
			exitsim ();	// NEVER RETURNS!
		}
		dbprintf('p', "ProcessFork-Allocating physical page #%d (Address 0x%.8X) for process virtual page #%d (data/code)\n", newpage, (newpage*MEM_PAGE_SIZE), i);

		*(p+i) = ((newpage*MEM_PAGE_SIZE) | MEM_PTE_VALID);
		dbprintf('p', "Contents at 0x%.8X: 0x%.8X\n\n", (int)(p+i), *(p+i));
  }
	/////////////////////////////////////////////////////
	//YF ADDED allocate page for heap
  // First, initialize the heapfree map
  for (j=0; j<MEM_MAX_HEAP_FREEMAP; j++){
  	pcb->HeapFreeMap[j] = 0;
  }
  for (j =0; j<MEM_MAX_HEAP_POINTER_ARRAY; j++){
  	pcb->HeapPtrSizes[j] = 0;
  }

  index = MemoryAllocateL2PT();
	if (index == -1)
	{
		printf ("ProcessFork-FATAL: couldn't allocate L2 Page Table for index 0 of L1 Page Table - no free page tables!\n");
		exitsim ();	// NEVER RETURNS!
	}
  // Assign L1 entry to address of start of L2 Page Table
	pcb->pagetable[0] = (uint32)&level2_pt_block[index];
	p = (uint32 *)pcb->pagetable[0];

	newpage = MemoryAllocatePage();
	if (newpage == 0)
	{
		printf ("ProcessFork-FATAL: couldn't allocate memory - no free pages!\n");
		exitsim ();	// NEVER RETURNS!
	}
	dbprintf('p', "ProcessFork-Allocating physical page #%d (Address 0x%.8X) for process virtual page #%d (Heap Allocation)\n", newpage, (newpage*MEM_PAGE_SIZE), i);
	//address for catch in Memory translate. UserHeap Address =0x4000 =
	*(p+i) = ((newpage*MEM_PAGE_SIZE) | MEM_PTE_VALID | MEM_PTE_HEAP); //TODO ProcessFork: marked as a heap.
	pcb->userHeapArea = (uint32 *)(newpage*MEM_PAGE_SIZE);
	dbprintf('p', "Heap area is at physical address:0x%.8X   L2 Address: 0x%.8X\n", (int)(newpage*MEM_PAGE_SIZE), *(p+i));
	dbprintf('p', "Contents at 0x%.8X: 0x%.8X\n\n", (int)(p+i), *(p+i));
	//Done with Heap allocation

///////////////////////////////////////////////////////////////////////////////////////////////////
  // Allocate page for user stack
  // First, get L2 Page Table for index 15 of L1 Page Table
  index = MemoryAllocateL2PT();
	if (index == -1)
	{
		printf ("ProcessFork-FATAL: couldn't allocate L2 Page Table for index 0 of L1 Page Table - no free page tables!\n");
		exitsim ();	// NEVER RETURNS!
	}
  // Assign L1 entry to address of start of L2 Page Table
	pcb->pagetable[MEM_L1_PAGE_TABLE_SIZE-1] = (uint32)&level2_pt_block[index];
	p = (uint32 *)pcb->pagetable[MEM_L1_PAGE_TABLE_SIZE-1];

	newpage = MemoryAllocatePage();
	if (newpage == 0)
	{
		printf ("ProcessFork-FATAL: couldn't allocate memory - no free pages!\n");
		exitsim ();	// NEVER RETURNS!
	}
	dbprintf('p', "ProcessFork-Allocating physical page #%d (Address 0x%.8X) for process virtual page #%d (user stack)\n\n", newpage, (newpage*MEM_PAGE_SIZE), (MEM_L1_PAGE_TABLE_SIZE*MEM_L2_PAGE_TABLE_SIZE)-1);

	*(p+(MEM_L2_PAGE_TABLE_SIZE-1)) = ((newpage*MEM_PAGE_SIZE) | MEM_PTE_VALID);
	dbprintf('p', "Contents at 0x%.8X: 0x%.8X\n\n", (int)(p+(MEM_L2_PAGE_TABLE_SIZE-1)), *(p+(MEM_L2_PAGE_TABLE_SIZE-1)));

  // Allocate page for system stack
	newpage = MemoryAllocatePage();
	if (newpage == 0)
	{
		printf ("ProcessFork-FATAL: couldn't allocate memory - no free pages!\n");
		exitsim ();	// NEVER RETURNS!
	}
	dbprintf('p', "ProcessFork-Allocating physical page #%d (Address 0x%.8X) for process system stack\n\n", newpage, (newpage*MEM_PAGE_SIZE));
	pcb->sysStackArea = newpage * MEM_PAGE_SIZE;
	stackframe = (uint32 *)(pcb->sysStackArea + (MEM_PAGE_SIZE-4));
	dbprintf('p', "ProcessFork-Initializing system stack pointer to 0x%.8X\n\n", (uint32)stackframe);

  ////////////////////////////////////////////////////////////////

  // Now that the stack frame points at the bottom of the system stack memory area, we need to
  // move it up (decrement it) by one stack frame size because we're about to fill in the
  // initial stack frame that will be loaded for this PCB when it gets switched in by 
  // ProcessSchedule the first time.
  stackframe -= PROCESS_STACK_FRAME_SIZE;

  // The system stack pointer is set to the base of the current interrupt stack frame.
  pcb->sysStackPtr = stackframe;
  // The current stack frame pointer is set to the same thing.
  pcb->currentSavedFrame = stackframe;

  //----------------------------------------------------------------------
  // This section sets up the stack frame for the process.  This is done
  // so that the frame looks to the interrupt handler like the process
  // was "suspended" right before it began execution.  The standard
  // mechanism of swapping in the registers and returning to the place
  // where it was "interrupted" will then work.
  //----------------------------------------------------------------------

  // The previous stack frame pointer is set to 0, meaning there is no
  // previous frame.
  dbprintf('m', "ProcessFork-ProcessFork: stackframe = 0x%x\n", (int)stackframe);
  stackframe[PROCESS_STACK_PREV_FRAME] = 0;

  //----------------------------------------------------------------------
  // STUDENT: setup the PTBASE, PTBITS, and PTSIZE here on the current
  // stack frame.
  //----------------------------------------------------------------------

  // JSM added PTBASE, PTBITS, and PTSIZE on stack frame
  //////////////////////////////////////////////////////////
  stackframe[PROCESS_STACK_PTBASE] = (uint32)&(pcb->pagetable[0]);
  dbprintf('p', "ProcessFork-PTBASE: 0x%.8X\n\n", (uint32)&(pcb->pagetable[0]));
  stackframe[PROCESS_STACK_PTSIZE] = MEM_L1_PAGE_TABLE_SIZE;
  dbprintf('p', "ProcessFork-PTSIZE: 0x%.8X\n\n", MEM_L1_PAGE_TABLE_SIZE);
  stackframe[PROCESS_STACK_PTBITS] = (MEM_L2FIELD_FIRST_BITNUM << 16) | MEM_L1FIELD_FIRST_BITNUM;
  dbprintf('p', "ProcessFork-PTBITS: 0x%.8X\n\n", (MEM_L2FIELD_FIRST_BITNUM << 16) | MEM_L1FIELD_FIRST_BITNUM);

  //////////////////////////////////////////////////////////

  if (isUser) {//user prog .dlx.obj
    dbprintf ('p', "ProcessFork-About to load %s\n", name);
    fd = ProcessGetCodeInfo (name, &start, &codeS, &codeL, &dataS, &dataL);
    if (fd < 0) {
      // Free newpage and pcb so we don't run out...
      ProcessFreeResources (pcb);
      return (-1);
    }

    dbprintf ('p', "ProcessFork-File %s -> start=0x%08x\n", name, start);
    dbprintf ('p', "ProcessFork-File %s -> code @ 0x%08x (size=0x%08x)\n", name, codeS,
	      codeL);
    dbprintf ('p', "ProcessFork-File %s -> data @ 0x%08x (size=0x%08x)\n", name, dataS,
	      dataL);

    while ((n = ProcessGetFromFile (fd, buf, &addr, sizeof (buf))) > 0) {
      dbprintf ('p', "ProcessFork-Placing %d bytes at vaddr %08x.\n", n, addr - n);
      // Copy the data to user memory.  Note that the user memory needs to
      // have enough space so that this copy will succeed!
      MemoryCopySystemToUser (pcb, buf, (char *)(addr - n), n);
    }
    FsClose (fd);
    stackframe[PROCESS_STACK_ISR] = PROCESS_INIT_ISR_USER;

    //----------------------------------------------------------------------
    // STUDENT: setup the initial user stack pointer here as the top
    // of the process's virtual address space (4-byte aligned).
    //----------------------------------------------------------------------

    // JSM initialized user stack pointer
    //////////////////////////////////////////////////////////
    stackframe[PROCESS_STACK_USER_STACKPOINTER] = (MEM_MAX_VIRTUAL_ADDRESS-3);
    dbprintf('p', "ProcessFork-USER_STACKPOINTER: 0x%.8X\n\n", stackframe[PROCESS_STACK_USER_STACKPOINTER]);
    //////////////////////////////////////////////////////////

    //--------------------------------------------------------------------
    // This part is setting up the initial user stack with argc and argv.
    //--------------------------------------------------------------------

    // Copy the entire set of strings of command line parameters onto the user stack.
    // The "param" variable is a pointer to the start of a sequenial set of strings,
    // each ending with its own '\0' character.  The final "string" of the sequence
    // must be an empty string to indicate that the sequence is done.  Since we
    // can't figure out how long the set of strings actually is in this scenario,
    // we have to copy the maximum possible string length and parse things manually.
    stackframe[PROCESS_STACK_USER_STACKPOINTER] -= SIZE_ARG_BUFF;
    MemoryCopySystemToUser (pcb, (char *)param, (char *)stackframe[PROCESS_STACK_USER_STACKPOINTER], SIZE_ARG_BUFF);

    // Now that the main string is copied into the user space, we need to setup
    // argv as an array of pointers into that string, and argc as the total
    // number of arguments found in the string.  The first call to get_argument
    // should return 0 as the offset of the first string.
    offset = get_argument((char *)param);
   
    // Compute the addresses in user space of where each string for the command line arguments
    // begins.  These addresses make up the argv array.
    for(argc=0; argc < MAX_ARGS; argc++) {
      // The "+2" is because initial_user_params[0] is argc, and initial_user_params[1] is argv.
      // The address can be found as the current stack pointer (which points to the start of
      // the params list) plus the byte offset of the parameter from the beginning of
      // the list of parameters.
      initial_user_params[argc+2] = stackframe[PROCESS_STACK_USER_STACKPOINTER] + offset;
      offset = get_argument(NULL);
      if (offset == 0) {
        initial_user_params[argc+2+1] = 0; // last entry should be a null value
        break;
      }
    }
    // argc is currently the index of the last command line argument.  We need it to instead
    // be the number of command line arguments, so we increment it by 1.
    argc++;

    // Now argc can be stored properly
    initial_user_params[0] = argc;

    // Compute where initial_user_params[3] will be copied in user space as the 
    // base of the array of string addresses.  The entire initial_user_params array
    // of uint32's will be copied onto the stack.  We'll move the stack pointer by
    // the necessary amount, then start copying the array.  Therefore, initial_user_params[3]
    // will reside at the current stack pointer value minus the number of command line
    // arguments (argc).
    initial_user_params[1] = stackframe[PROCESS_STACK_USER_STACKPOINTER] - (argc*sizeof(uint32));

    // Now copy the actual memory.  Remember that stacks grow down from the top of memory, so 
    // we need to move the stack pointer first, then do the copy.  The "+2", as before, is 
    // because initial_user_params[0] is argc, and initial_user_params[1] is argv.
    initial_user_params_bytes = (argc + 2) * sizeof(uint32);

    stackframe[PROCESS_STACK_USER_STACKPOINTER] -= initial_user_params_bytes;
    MemoryCopySystemToUser (pcb, (char *)initial_user_params, (char *)(stackframe[PROCESS_STACK_USER_STACKPOINTER]), initial_user_params_bytes);

    // Set the correct address at which to execute a user process.
    stackframe[PROCESS_STACK_IAR] = (uint32)start;

    // Flag this as a user process
    pcb->flags |= PROCESS_TYPE_USER;
  } else {
    // Don't worry about messing with any code here for kernel processes because
    // there aren't any kernel processes in DLXOS.

    // Set r31 to ProcessExit().  This will only be called for a system
    // process; user processes do an exit() trap.
    stackframe[PROCESS_STACK_IREG+31] = (uint32)ProcessExit;

    // Set the stack register to the base of the system stack.
    //stackframe[PROCESS_STACK_IREG+29]=pcb->sysStackArea + MEM_PAGESIZE;

    // Set the initial parameter properly by placing it on the stack frame
    // at the location pointed to by the "saved" stack pointer (r29).
    *((uint32 *)(stackframe[PROCESS_STACK_IREG+29])) = param;

    // Set up the initial address at which to execute.  This is done by
    // placing the address into the IAR slot of the stack frame.
    stackframe[PROCESS_STACK_IAR] = (uint32)func;

    // Set the initial value for the interrupt status register
    stackframe[PROCESS_STACK_ISR] = PROCESS_INIT_ISR_SYS;

    // Mark this as a system process.
    pcb->flags |= PROCESS_TYPE_SYSTEM;
  }

  // Place the PCB onto the run queue.
  intrs = DisableIntrs ();
  if ((pcb->l = AQueueAllocLink(pcb)) == NULL) {
    printf("FATAL ERROR: could not get link for forked PCB in ProcessFork!\n");
    exitsim();
  }
  if (AQueueInsertLast(&runQueue, pcb->l) != QUEUE_SUCCESS) {
    printf("FATAL ERROR: could not insert link into runQueue in ProcessFork!\n");
    exitsim();
  }
  RestoreIntrs (intrs);

  // If this is the first process, make it the current one
  if (currentPCB == NULL) {
    dbprintf ('p', "Setting currentPCB=0x%x, stackframe=0x%x\n",
	      (int)pcb, (int)(pcb->currentSavedFrame));
    currentPCB = pcb;
  }

  dbprintf ('p', "Leaving ProcessFork (%s)\n", name);
  // Return the process number (found by subtracting the PCB number
  // from the base of the PCB array).
  return (pcb - pcbs);
}
Example #26
0
int tun_read_ev(int idx, dbuf_t *d, void *p) {
  lua_State *L;
  http_parser_t *parser = &http_parser;
  http_parser_init(parser);
  L = lua_open();
  lua_init_state(L);
  if(http_parser_data(parser, d->buf, d->dsize)) {
    char *reply = "File not found!\n";
    char *content_type = "text/plain";
    char headers[512];
    char trailer[1024];
    char *xfile;
    size_t xfile_sz;

    debug(DBG_GLOBAL, 1, "Parser done. Method: '%s', URI: '%s'", parser->req_method, parser->req_uri);
    if(strstr(parser->req_uri, ".css")) {
      content_type = "text/css";
    } else if(strstr(parser->req_uri, ".html")) {
      content_type = "text/html";
    } else if(strstr(parser->req_uri, ".js")) {
      content_type = "application/javascript";
    } else if(strstr(parser->req_uri, ".png")) {
      content_type = "image/png";
    }
    memcpy(trailer, parser->end, parser->content_length);
    trailer[parser->content_length] = 0;
    debug(DBG_GLOBAL, 0, "Parser trailer: '%s'", trailer);

    xfile = mz_zip_extract_archive_file_to_heap("data.zip", parser->req_uri+1, &xfile_sz, 0);
    if(xfile) {
      debug(0, 0, "File '%s' => size is %d", parser->req_uri+1, xfile_sz);
      xfile[xfile_sz] = 0;
      if(strstr(parser->req_uri, ".lua")) {
        if(luaL_loadstring(L, xfile)) {
	  debug(0, 0, "Lua file load error: %s", lua_tostring(L,-1));
        } else {
          lua_pcall(L, 0, LUA_MULTRET, 0);
          lua_getglobal(L, "request");
	  lua_pushinteger(L, idx);
	  int err = lua_pcall(L, 1, 0, 0);
          if (err != 0) {
            debug(0,0,"%d: LUA error %s\n",getpid(), lua_tostring(L,-1));
          }
        }
      } else {
        snprintf(headers, sizeof(headers)-1, "HTTP/1.0 200 OK\r\nConnection: keep-alive\r\nContent-length: %d\r\nContent-type: %s\r\n\r\n", (int)xfile_sz, content_type);
        dunlock(sock_write_data(idx, dstrcpy(headers), NULL));
        dunlock(sock_write_data(idx, dalloc_ptr(xfile, xfile_sz), NULL));
	xfile = NULL;
      }
    } else {
      snprintf(headers, sizeof(headers)-1, "HTTP/1.0 404 Not Found\r\nConnection: keep-alive\r\nContent-length: %d\r\nContent-type: %s\r\n\r\n", (int)strlen(reply), content_type);
      dunlock(sock_send_data(idx, dstrcpy(headers), NULL));
      dunlock(sock_send_data(idx, dstrcpy(reply), NULL));
    }
    if(xfile) {
      free(xfile);
    }
    lua_close(L);
  } else {
    lua_close(L);
    return 0;
  }
  
  // printf("Got packet, sending back!\n");
  return -1;
}
Example #27
0
void G_PlayDemo(const char* name) {
    int i;
    int p;
    char filename[256];

    gameaction = ga_nothing;
    endDemo = false;

    p = M_CheckParm("-playdemo");
    if(p && p < myargc-1) {
        // 20120107 bkw: add .lmp extension if missing.
        if(dstrrchr(myargv[p+1], '.')) {
            dstrcpy(filename, myargv[p+1]);
        }
        else {
            dsprintf(filename, "%s.lmp", myargv[p+1]);
        }

        CON_DPrintf("--------Reading demo %s--------\n", filename);
        if(M_ReadFile(filename, &demobuffer) == -1) {
            gameaction = ga_exitdemo;
            return;
        }

        demo_p = demobuffer;
    }
    else {
        if(W_CheckNumForName(name) == -1) {
            gameaction = ga_exitdemo;
            return;
        }

        CON_DPrintf("--------Playing demo %s--------\n", name);
        demobuffer = demo_p = W_CacheLumpName(name, PU_STATIC);
    }
    
    if(strncmp((char*)demo_p, "DM64", 4)) {
        I_Error("G_PlayDemo: Mismatched demo header");
        return;
    }

    G_SaveDefaults();

    demo_p++;
    demo_p++;
    demo_p++;
    demo_p++;
    demo_p++;

    startskill      = *demo_p++;
    startmap        = *demo_p++;
    deathmatch      = *demo_p++;
    respawnparm     = *demo_p++;
    respawnitem     = *demo_p++;
    fastparm        = *demo_p++;
    nomonsters      = *demo_p++;
    consoleplayer   = *demo_p++;
    
    rngseed  = *demo_p++ & 0xff;
    rngseed <<= 8;
    rngseed += *demo_p++ & 0xff;
    rngseed <<= 8;
    rngseed += *demo_p++ & 0xff;
    rngseed <<= 8;
    rngseed += *demo_p++ & 0xff;
    
    gameflags  = *demo_p++ & 0xff;
    gameflags <<= 8;
    gameflags += *demo_p++ & 0xff;
    gameflags <<= 8;
    gameflags += *demo_p++ & 0xff;
    gameflags <<= 8;
    gameflags += *demo_p++ & 0xff;
    
    compatflags  = *demo_p++ & 0xff;
    compatflags <<= 8;
    compatflags += *demo_p++ & 0xff;
    compatflags <<= 8;
    compatflags += *demo_p++ & 0xff;
    compatflags <<= 8;
    compatflags += *demo_p++ & 0xff;

    for(i = 0; i < MAXPLAYERS; i++) {
        playeringame[i] = *demo_p++;
    }

    G_InitNew(startskill, startmap);

    if(playeringame[1]) {
        netgame = true;
        netdemo = true;
    }

    precache = true;
    usergame = false;
    demoplayback = true;

    G_RunGame();
    iwadDemo = false;
}
Example #28
0
//----------------------------------------------------------------------
//
//	ProcessFork
//
//	Create a new process and make it runnable.  This involves the
//	following steps:
//	* Allocate resources for the process (PCB, memory, etc.)
//	* Initialize the resources
//	* Place the PCB on the runnable queue
//
//	NOTE: This code has been tested for system processes, but not
//	for user processes.
//
//----------------------------------------------------------------------
int ProcessFork (VoidFunc func, uint32 param, char *name, int isUser) {
  int i;                   // Loop index variable
  int fd, n;               // Used for reading code from files.
  int start, codeS, codeL; // Used for reading code from files.
  int dataS, dataL;        // Used for reading code from files.
  int addr = 0;            // Used for reading code from files.
  unsigned char buf[100];  // Used for reading code from files.
  uint32 *stackframe;      // Stores address of current stack frame.
  PCB *pcb;                // Holds pcb while we build it for this process.
  int intrs;               // Stores previous interrupt settings.
  uint32  initial_user_params[MAX_ARGS+2]; // Initial memory for user parameters (argc, argv)
                                           // initial_user_params[0] = argc
                                           // initial_user_params[1] = argv, points to initial_user_params[2]
                                           // initial_user_params[2] = address of string for argv[0]
                                           // initial_user_params[3] = address of string for argv[1]
                                           //                           ...
  uint32 argc=0;           // running counter for number of arguments
  uint32 offset;           // Used in parsing command line argument strings, holds offset (in bytes) from
                           // beginning of the string to the current argument.
  uint32 initial_user_params_bytes;  // total number of bytes in initial user parameters array
  int newPage;


  intrs = DisableIntrs ();
  dbprintf ('I', "Old interrupt value was 0x%x.\n", intrs);
  dbprintf ('p', "Entering ProcessFork args=0x%x 0x%x %s %d\n", (int)func,
	    param, name, isUser);
  // Get a free PCB for the new process
  if (AQueueEmpty(&freepcbs)) {
    printf ("FATAL error: no free processes!\n");
    exitsim ();	// NEVER RETURNS!
  }
  pcb = (PCB *)AQueueObject(AQueueFirst (&freepcbs));
  dbprintf ('p', "Got a link @ 0x%x\n", (int)(pcb->l));
  if (AQueueRemove (&(pcb->l)) != QUEUE_SUCCESS) {
    printf("FATAL ERROR: could not remove link from freepcbsQueue in ProcessFork!\n");
    exitsim();
  }
  // This prevents someone else from grabbing this process
  ProcessSetStatus (pcb, PROCESS_STATUS_RUNNABLE);

  // At this point, the PCB is allocated and nobody else can get it.
  // However, it's not in the run queue, so it won't be run.  Thus, we
  // can turn on interrupts here.
  RestoreIntrs (intrs);

  // Copy the process name into the PCB.
  dstrcpy(pcb->name, name);

  //----------------------------------------------------------------------
  // This section initializes the memory for this process
  //----------------------------------------------------------------------
  // Allocate 1 page for system stack, 1 page for user stack (at top of
  // virtual address space), and 4 pages for user code and global data.
  //---------------------------------------------------------
  // STUDENT: allocate pages for a new process here.  The
  // code below assumes that you set the "stackframe" variable
  // equal to the last 4-byte-aligned address in physical page
  // for the system stack.
  //---------------------------------------------------------
  // Pages for code and global data and Heap
  pcb->npages = 5;
  for(i = 0; i < pcb->npages; i++) {
    newPage = MemoryAllocPage();
    if(newPage == MEM_FAIL) {
      printf ("FATAL: couldn't allocate memory - no free pages!\n");
      ProcessFreeResources (pcb);
      return PROCESS_FORK_FAIL;
    }
    pcb->pagetable[i] = MemorySetupPte (newPage);
  }
  // Initialize nodes in pool
  for (i = 1; i <= MEM_HEAP_MAX_NODES; i++) {
    pcb->htree_array[i].parent = NULL;
    pcb->htree_array[i].cleft = NULL;
    pcb->htree_array[i].crght = NULL;
    pcb->htree_array[i].index = i;
    pcb->htree_array[i].size = -1;
    pcb->htree_array[i].addr = -1;
    pcb->htree_array[i].inuse = 0;
    pcb->htree_array[i].order = -1;
  }
  // Initialize Heap tree
  pcb->htree_array[1].size = MEM_PAGESIZE;
  pcb->htree_array[1].addr = 0;
  pcb->htree_array[1].order = 7;
  // user stack
  pcb->npages += 1;
  newPage = MemoryAllocPage();
  if(newPage == MEM_FAIL) {
    printf ("FATAL: couldn't allocate user stack - no free pages!\n");
    ProcessFreeResources (pcb);
    return PROCESS_FORK_FAIL;
  }
  pcb->pagetable[MEM_ADDRESS_TO_PAGE(MEM_MAX_VIRTUAL_ADDRESS)] = MemorySetupPte (newPage);

  // for system stack
  newPage = MemoryAllocPage ();
  if(newPage == MEM_FAIL) {
    printf ("FATAL: couldn't allocate system stack - no free pages!\n");
    ProcessFreeResources (pcb);
    return PROCESS_FORK_FAIL;
  }

  pcb->sysStackArea = newPage * MEM_PAGESIZE;
  //----------------------------------------------------------------------
  // Stacks grow down from the top.  The current system stack pointer has
  // to be set to the bottom of the interrupt stack frame, which is at the
  // high end (address-wise) of the system stack.
  stackframe = (uint32 *)(pcb->sysStackArea + MEM_PAGESIZE - 4);
  dbprintf('p', "ProcessFork: SystemStack page=%d sysstackarea=0x%x\n", newPage, pcb->sysStackArea);

  // Now that the stack frame points at the bottom of the system stack memory area, we need to
  // move it up (decrement it) by one stack frame size because we're about to fill in the
  // initial stack frame that will be loaded for this PCB when it gets switched in by
  // ProcessSchedule the first time.
  stackframe -= PROCESS_STACK_FRAME_SIZE;

  // The system stack pointer is set to the base of the current interrupt stack frame.
  pcb->sysStackPtr = stackframe;
  // The current stack frame pointer is set to the same thing.
  pcb->currentSavedFrame = stackframe;

  dbprintf ('p', "Setting up PCB @ 0x%x (sys stack=0x%x, mem=0x%x, size=0x%x)\n",
    (int)pcb, pcb->sysStackArea, pcb->pagetable[0], pcb->npages * MEM_PAGESIZE);

  //----------------------------------------------------------------------
  // This section sets up the stack frame for the process.  This is done
  // so that the frame looks to the interrupt handler like the process
  // was "suspended" right before it began execution.  The standard
  // mechanism of swapping in the registers and returning to the place
  // where it was "interrupted" will then work.
  //----------------------------------------------------------------------

  // The previous stack frame pointer is set to 0, meaning there is no
  // previous frame.
  dbprintf('p', "ProcessFork: stackframe = 0x%x\n", (int)stackframe);
  stackframe[PROCESS_STACK_PREV_FRAME] = 0;

  //----------------------------------------------------------------------
  // STUDENT: setup the PTBASE, PTBITS, and PTSIZE here on the current
  // stack frame.
  //----------------------------------------------------------------------
  // Set the base of the level 1 page table.  If there's only one page
  // table level, this is it.  For 2-level page tables, put the address
  // of the level 1 page table here.  For 2-level page tables, we'll also
  // have to build up the necessary tables....
  stackframe[PROCESS_STACK_PTBASE] = (uint32)(&(pcb->pagetable[0]));

  // Set the size (maximum number of entries) of the level 1 page table.
  // In our case, it's just one page, but it could be larger.
  stackframe[PROCESS_STACK_PTSIZE] = MEM_PAGE_TBL_SIZE;

  // Set the number of bits for both the level 1 and level 2 page tables.
  // This can be changed on a per-process basis if desired.  For now,
  // though, it's fixed.
  stackframe[PROCESS_STACK_PTBITS] = (MEM_L1FIELD_FIRST_BITNUM << 16) + MEM_L1FIELD_FIRST_BITNUM;

  if (isUser) {
    dbprintf ('p', "About to load %s\n", name);
    fd = ProcessGetCodeInfo (name, &start, &codeS, &codeL, &dataS, &dataL);
    if (fd < 0) {
      // Free newPage and pcb so we don't run out...
      ProcessFreeResources (pcb);
      return (-1);
    }

    dbprintf ('p', "File %s -> start=0x%08x\n", name, start);
    dbprintf ('p', "File %s -> code @ 0x%08x (size=0x%08x)\n", name, codeS,
	      codeL);
    dbprintf ('p', "File %s -> data @ 0x%08x (size=0x%08x)\n", name, dataS,
	      dataL);

    while ((n = ProcessGetFromFile (fd, buf, &addr, sizeof (buf))) > 0) {
      dbprintf ('i', "Placing %d bytes at vaddr %08x.\n", n, addr - n);
      // Copy the data to user memory.  Note that the user memory needs to
      // have enough space so that this copy will succeed!
      MemoryCopySystemToUser (pcb, buf, (char *)(addr - n), n);
    }
    FsClose (fd);
    stackframe[PROCESS_STACK_ISR] = PROCESS_INIT_ISR_USER;

    //----------------------------------------------------------------------
    // STUDENT: setup the initial user stack pointer here as the top
    // of the process's virtual address space (4-byte aligned).
    //----------------------------------------------------------------------
    stackframe[PROCESS_STACK_USER_STACKPOINTER] = MEM_MAX_VIRTUAL_ADDRESS - 3;
    dbprintf('p', "ProcessFork: UserStack usrsp=0x%x\n", stackframe[PROCESS_STACK_USER_STACKPOINTER]);

    //--------------------------------------------------------------------
    // This part is setting up the initial user stack with argc and argv.
    //--------------------------------------------------------------------

    // Copy the entire set of strings of command line parameters onto the user stack.
    // The "param" variable is a pointer to the start of a sequenial set of strings,
    // each ending with its own '\0' character.  The final "string" of the sequence
    // must be an empty string to indicate that the sequence is done.  Since we
    // can't figure out how long the set of strings actually is in this scenario,
    // we have to copy the maximum possible string length and parse things manually.
    stackframe[PROCESS_STACK_USER_STACKPOINTER] -= SIZE_ARG_BUFF;
    MemoryCopySystemToUser (pcb, (char *)param, (char *)stackframe[PROCESS_STACK_USER_STACKPOINTER], SIZE_ARG_BUFF);

    // Now that the main string is copied into the user space, we need to setup
    // argv as an array of pointers into that string, and argc as the total
    // number of arguments found in the string.  The first call to get_argument
    // should return 0 as the offset of the first string.
    offset = get_argument((char *)param);

    // Compute the addresses in user space of where each string for the command line arguments
    // begins.  These addresses make up the argv array.
    for(argc=0; argc < MAX_ARGS; argc++) {
      // The "+2" is because initial_user_params[0] is argc, and initial_user_params[1] is argv.
      // The address can be found as the current stack pointer (which points to the start of
      // the params list) plus the byte offset of the parameter from the beginning of
      // the list of parameters.
      initial_user_params[argc+2] = stackframe[PROCESS_STACK_USER_STACKPOINTER] + offset;
      offset = get_argument(NULL);
      if (offset == 0) {
        initial_user_params[argc+2+1] = 0; // last entry should be a null value
        break;
      }
    }
    // argc is currently the index of the last command line argument.  We need it to instead
    // be the number of command line arguments, so we increment it by 1.
    argc++;

    // Now argc can be stored properly
    initial_user_params[0] = argc;

    // Compute where initial_user_params[3] will be copied in user space as the
    // base of the array of string addresses.  The entire initial_user_params array
    // of uint32's will be copied onto the stack.  We'll move the stack pointer by
    // the necessary amount, then start copying the array.  Therefore, initial_user_params[3]
    // will reside at the current stack pointer value minus the number of command line
    // arguments (argc).
    initial_user_params[1] = stackframe[PROCESS_STACK_USER_STACKPOINTER] - (argc*sizeof(uint32));

    // Now copy the actual memory.  Remember that stacks grow down from the top of memory, so
    // we need to move the stack pointer first, then do the copy.  The "+2", as before, is
    // because initial_user_params[0] is argc, and initial_user_params[1] is argv.
    initial_user_params_bytes = (argc + 2) * sizeof(uint32);

    stackframe[PROCESS_STACK_USER_STACKPOINTER] -= initial_user_params_bytes;
    MemoryCopySystemToUser (pcb, (char *)initial_user_params, (char *)(stackframe[PROCESS_STACK_USER_STACKPOINTER]), initial_user_params_bytes);

    // Set the correct address at which to execute a user process.
    stackframe[PROCESS_STACK_IAR] = (uint32)start;

    // Flag this as a user process
    pcb->flags |= PROCESS_TYPE_USER;
  } else {
    // Don't worry about messing with any code here for kernel processes because
    // there aren't any kernel processes in DLXOS.

    // Set r31 to ProcessExit().  This will only be called for a system
    // process; user processes do an exit() trap.
    stackframe[PROCESS_STACK_IREG+31] = (uint32)ProcessExit;

    // Set the stack register to the base of the system stack.
    //stackframe[PROCESS_STACK_IREG+29]=pcb->sysStackArea + MEM_PAGESIZE;

    // Set the initial parameter properly by placing it on the stack frame
    // at the location pointed to by the "saved" stack pointer (r29).
    *((uint32 *)(stackframe[PROCESS_STACK_IREG+29])) = param;

    // Set up the initial address at which to execute.  This is done by
    // placing the address into the IAR slot of the stack frame.
    stackframe[PROCESS_STACK_IAR] = (uint32)func;

    // Set the initial value for the interrupt status register
    stackframe[PROCESS_STACK_ISR] = PROCESS_INIT_ISR_SYS;

    // Mark this as a system process.
    pcb->flags |= PROCESS_TYPE_SYSTEM;
  }

  // Place the PCB onto the run queue.
  intrs = DisableIntrs ();
  if ((pcb->l = AQueueAllocLink(pcb)) == NULL) {
    printf("FATAL ERROR: could not get link for forked PCB in ProcessFork!\n");
    exitsim();
  }
  if (AQueueInsertLast(&runQueue, pcb->l) != QUEUE_SUCCESS) {
    printf("FATAL ERROR: could not insert link into runQueue in ProcessFork!\n");
    exitsim();
  }
  RestoreIntrs (intrs);

  // If this is the first process, make it the current one
  if (currentPCB == NULL) {
    dbprintf ('p', "Setting currentPCB=0x%x, stackframe=0x%x\n",
	      (int)pcb, (int)(pcb->currentSavedFrame));
    currentPCB = pcb;
  }

  dbprintf ('p', "Leaving ProcessFork (%s)\n", name);
  // Return the process number (found by subtracting the PCB number
  // from the base of the PCB array).
  return (pcb - pcbs);
}
Example #29
0
//----------------------------------------------------------------------
//
//	ProcessFork
//
//	Create a new process and make it runnable.  This involves the
//	following steps:
//	* Allocate resources for the process (PCB, memory, etc.)
//	* Initialize the resources
//	* Place the PCB on the runnable queue
//
//	NOTE: This code has been tested for system processes, but not
//	for user processes.
//
//----------------------------------------------------------------------
int
ProcessFork (VoidFunc func, uint32 param, int p_nice, int p_info,char *name, int isUser)
{
  int		i, j, fd, n;
  Link		*l;
  int		start, codeS, codeL, dataS, dataL;
  uint32	*stackframe;
  int		newPage;
  PCB		*pcb;
  int	addr = 0;
  int		intrs;
  unsigned char buf[100];
  uint32 dum[MAX_ARGS+8], count, offset;
  char *str;


  intrs = DisableIntrs ();
  dbprintf ('I', "Old interrupt value was 0x%x.\n", intrs);
  dbprintf ('p', "Entering ProcessFork args=0x%x 0x%x %s %d\n", func,
	    param, name, isUser);
  // Get a free PCB for the new process
  if (QueueEmpty (&freepcbs)) {
    printf ("FATAL error: no free processes!\n");
    exitsim ();	// NEVER RETURNS!
  }
  l = QueueFirst (&freepcbs);
  dbprintf ('p', "Got a link @ 0x%x\n", l);
  QueueRemove (l);
  pcb = (PCB *)(l->object);
  // This prevents someone else from grabbing this process
  ProcessSetStatus (pcb, PROCESS_STATUS_RUNNABLE);

  // At this point, the PCB is allocated and nobody else can get it.
  // However, it's not in the run queue, so it won't be run.  Thus, we
  // can turn on interrupts here.
  dbprintf ('I', "Before restore interrupt value is 0x%x.\n", CurrentIntrs());
  RestoreIntrs (intrs);
  dbprintf ('I', "New interrupt value is 0x%x.\n", CurrentIntrs());

  // Copy the process name into the PCB.
  dstrcpy (pcb->name, name);

  //----------------------------------------------------------------------
  // This section initializes the memory for this process
  //----------------------------------------------------------------------
  // For now, we'll use one user page and a page for the system stack.
  // For system processes, though, all pages must be contiguous.
  // Of course, system processes probably need just a single page for
  // their stack, and don't need any code or data pages allocated for them.
  pcb->npages = 1;
  newPage = MemoryAllocPage ();
  if (newPage == 0) {
    printf ("aFATAL: couldn't allocate memory - no free pages!\n");
    exitsim ();	// NEVER RETURNS!
  }
  pcb->pagetable[0] = MemorySetupPte (newPage);
  newPage = MemoryAllocPage ();
  if (newPage == 0) {
    printf ("bFATAL: couldn't allocate system stack - no free pages!\n");
    exitsim ();	// NEVER RETURNS!
  }
  pcb->sysStackArea = newPage * MEMORY_PAGE_SIZE;


  //---------------------------------------
  // Lab3: initialized pcb member for your scheduling algorithm here
  //--------------------------------------
  pcb->p_nice = p_nice < 0 ? 0 : p_nice;
  pcb->p_info = p_info;
  pcb->sleeptime = my_timer_get();
  pcb->estcpu = 0;
  pcb->prio = PUSER;
  pcb->processed = 1 - processedFlag;
  pcb->estcputime = 0;
  //----------------------------------------------------------------------
  // Stacks grow down from the top.  The current system stack pointer has
  // to be set to the bottom of the interrupt stack frame, which is at the
  // high end (address-wise) of the system stack.
  stackframe = ((uint32 *)(pcb->sysStackArea + MEMORY_PAGE_SIZE)) -
    (PROCESS_STACK_FRAME_SIZE + 8);
  // The system stack pointer is set to the base of the current interrupt
  // stack frame.
  pcb->sysStackPtr = stackframe;
  // The current stack frame pointer is set to the same thing.
  pcb->currentSavedFrame = stackframe;

  dbprintf ('p',
	    "Setting up PCB @ 0x%x (sys stack=0x%x, mem=0x%x, size=0x%x)\n",
	    pcb, pcb->sysStackArea, pcb->pagetable[0],
	    pcb->npages * MEMORY_PAGE_SIZE);

  //----------------------------------------------------------------------
  // This section sets up the stack frame for the process.  This is done
  // so that the frame looks to the interrupt handler like the process
  // was "suspended" right before it began execution.  The standard
  // mechanism of swapping in the registers and returning to the place
  // where it was "interrupted" will then work.
  //----------------------------------------------------------------------

  // The previous stack frame pointer is set to 0, meaning there is no
  // previous frame.
  stackframe[PROCESS_STACK_PREV_FRAME] = 0;

  // Set the base of the level 1 page table.  If there's only one page
  // table level, this is it.  For 2-level page tables, put the address
  // of the level 1 page table here.  For 2-level page tables, we'll also
  // have to build up the necessary tables....
  stackframe[PROCESS_STACK_PTBASE] = (uint32)&(pcb->pagetable[0]);

  // Set the size (maximum number of entries) of the level 1 page table.
  // In our case, it's just one page, but it could be larger.
  stackframe[PROCESS_STACK_PTSIZE] = pcb->npages;

  // Set the number of bits for both the level 1 and level 2 page tables.
  // This can be changed on a per-process basis if desired.  For now,
  // though, it's fixed.
  stackframe[PROCESS_STACK_PTBITS] = (MEMORY_L1_PAGE_SIZE_BITS
					  + (MEMORY_L2_PAGE_SIZE_BITS << 16));


  if (isUser) {
    dbprintf ('p', "About to load %s\n", name);
    fd = ProcessGetCodeInfo (name, &start, &codeS, &codeL, &dataS, &dataL);
    if (fd < 0) {
      // Free newpage and pcb so we don't run out...
      ProcessFreeResources (pcb);
      return (-1);
    }
    dbprintf ('p', "File %s -> start=0x%08x\n", name, start);
    dbprintf ('p', "File %s -> code @ 0x%08x (size=0x%08x)\n", name, codeS,
	      codeL);
    dbprintf ('p', "File %s -> data @ 0x%08x (size=0x%08x)\n", name, dataS,
	      dataL);
    while ((n = ProcessGetFromFile (fd, buf, &addr, sizeof (buf))) > 0) {
      dbprintf ('p', "Placing %d bytes at vaddr %08x.\n", n, addr - n);
      // Copy the data to user memory.  Note that the user memory needs to
      // have enough space so that this copy will succeed!
      MemoryCopySystemToUser (pcb, buf, addr - n, n);
    }
    FsClose (fd);
    stackframe[PROCESS_STACK_ISR] = PROCESS_INIT_ISR_USER;
    // Set the initial stack pointer correctly.  Currently, it's just set
    // to the top of the (single) user address space allocated to this
    // process.
    str = (char *)param;
    stackframe[PROCESS_STACK_IREG+29] = MEMORY_PAGE_SIZE - SIZE_ARG_BUFF;
    // Copy the initial parameter to the top of stack

    MemoryCopySystemToUser (pcb, (char *)str,
			    (char *)stackframe[PROCESS_STACK_IREG+29],
			    SIZE_ARG_BUFF-32);

    offset = get_argument((char *)param);

    dum[2] = MEMORY_PAGE_SIZE - SIZE_ARG_BUFF + offset;
    for(count=3;;count++)
    {
      offset=get_argument(NULL);
      dum[count] = MEMORY_PAGE_SIZE - SIZE_ARG_BUFF + offset;
      if(offset==0)
      {
        break;
      }
    }
    dum[0] = count-2;
    dum[1] = MEMORY_PAGE_SIZE - SIZE_ARG_BUFF - (count-2)*4;
    MemoryCopySystemToUser (pcb, (char *)dum,
			    (char *)(stackframe[PROCESS_STACK_IREG+29]-count*4),
			    (count)*sizeof(uint32));
    stackframe[PROCESS_STACK_IREG+29] -= 4*count;
    // Set the correct address at which to execute a user process.
    stackframe[PROCESS_STACK_IAR] = (uint32)start;
    pcb->flags |= PROCESS_TYPE_USER;
  } else {
    // Set r31 to ProcessExit().  This will only be called for a system
    // process; user processes do an exit() trap.
    stackframe[PROCESS_STACK_IREG+31] = (uint32)ProcessExit;

    // Set the stack register to the base of the system stack.
    stackframe[PROCESS_STACK_IREG+29]=pcb->sysStackArea + MEMORY_PAGE_SIZE-32;

    // Set the initial parameter properly by placing it on the stack frame
    // at the location pointed to by the "saved" stack pointer (r29).
    *((uint32 *)(stackframe[PROCESS_STACK_IREG+29])) = param;

    // Set up the initial address at which to execute.  This is done by
    // placing the address into the IAR slot of the stack frame.
    stackframe[PROCESS_STACK_IAR] = (uint32)func;

    // Set the initial value for the interrupt status register
    stackframe[PROCESS_STACK_ISR] = PROCESS_INIT_ISR_SYS;

    // Mark this as a system process.
    pcb->flags |= PROCESS_TYPE_SYSTEM;
  }

  // Place the PCB onto the run queue.
  intrs = DisableIntrs ();
  QueueInsertLast (&runQueue[pcb->prio/4], l);
  RestoreIntrs (intrs);

  // If this is the first process, make it the current one
  if (currentPCB == NULL) {
    dbprintf ('p', "Setting currentPCB=0x%x, stackframe=0x%x\n",
	      pcb, pcb->currentSavedFrame);
    currentPCB = pcb;
  }
  dbprintf ('p', "Leaving ProcessFork (%s)\n", name);
  // Return the process number (found by subtracting the PCB number
  // from the base of the PCB array).
  return (pcb - pcbs);
}
Example #30
0
//----------------------------------------------------------------------
//
//	main
//
//	This routine is called when the OS starts up.  It allocates a
//	PCB for the first process - the one corresponding to the initial
//	thread of execution.  Note that the stack pointer is already
//	set correctly by _osinit (assembly language code) to point
//	to the stack for the 0th process.  This stack isn't very big,
//	though, so it should be replaced by the system stack of the
//	currently running process.
//
//----------------------------------------------------------------------
main (int argc, char *argv[])
{
  int		i, j;
  int		n;
  char	buf[120];
  char		*userprog = (char *)0;
  static PCB	temppcb;
  uint32	addr;
  extern void	SysprocCreateProcesses ();
  char *param[12]={NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  	 	   NULL, NULL, NULL, NULL};
  int base;

  debugstr[0] = '\0';
  MyFuncRetZero();
  printf ("Got %d arguments.\n", argc);
  printf ("Available memory: 0x%x -> 0x%x.\n", lastosaddress,
	  MemoryGetSize ());
  printf ("Argument count is %d.\n", argc);
  for (i = 0; i < argc; i++) {
    printf ("Argument %d is %s.\n", i, argv[i]);
  }
//  *((int *)0xfff00100) = 't';
  FsModuleInit ();
  for (i = 0; i < argc; i++)
  {
    if (argv[i][0] == '-')
    {
      switch (argv[i][1])
      {
      case 'D':
	dstrcpy (debugstr, argv[++i]);
	break;
      case 'i':
	n = dstrtol (argv[++i], (void *)0, 0);
	ditoa (n, buf);
	printf ("Converted %s to %d=%s\n", argv[i], n, buf);
	break;
      case 'f':
      {
	int	start, codeS, codeL, dataS, dataL, fd, j;
	int	addr = 0;
	static unsigned char buf[200];
	fd = ProcessGetCodeInfo (argv[++i], &start, &codeS, &codeL, &dataS,
				 &dataL);
	printf ("File %s -> start=0x%08x\n", argv[i], start);
	printf ("File %s -> code @ 0x%08x (size=0x%08x)\n", argv[i], codeS,
		codeL);
	printf ("File %s -> data @ 0x%08x (size=0x%08x)\n", argv[i], dataS,
		dataL);
	while ((n = ProcessGetFromFile (fd, buf, &addr, sizeof (buf))) > 0)
	{
	  for (j = 0; j < n; j += 4)
	  {
	    printf ("%08x: %02x%02x%02x%02x\n", addr + j - n, buf[j], buf[j+1],
		    buf[j+2], buf[j+3]);
	  }
	}
	close (fd);
	break;
      }
      case 'u':
	userprog = argv[++i];
        base = i;
	break;
      default:
	printf ("Option %s not recognized.\n", argv[i]);
	break;
      }
      if(userprog)
        break;
    }
  }
  dbprintf ('i', "About to initialize queues.\n");
  QueueModuleInit ();
  dbprintf ('i', "After initializing queues.\n");
  MemoryModuleInit ();
  dbprintf ('i', "After initializing memory.\n");

  ProcessModuleInit ();
  dbprintf ('i', "After initializing processes.\n");
  ShareModuleInit ();
  dbprintf ('i', "After initializing shared memory.\n");
  SynchModuleInit ();
  dbprintf ('i', "After initializing synchronization tools.\n");
  KbdModuleInit ();
  dbprintf ('i', "After initializing keyboard.\n");
  for (i = 0; i < 100; i++) {
    buf[i] = 'a';
  }
  i = FsOpen ("vm", FS_MODE_WRITE);
  dbprintf ('i', "VM Descriptor is %d\n", i);
  FsSeek (i, 0, FS_SEEK_SET);
  FsWrite (i, buf, 80);
  FsClose (i);
  if (userprog != (char *)0) {
      for(i=base;i<argc&&i-base<11; i++)
      {
        param[i-base] = argv[i];
      }
      process_create(0,0,param[0], param[1], param[2], param[3], param[4],
      		     param[5], param[6], param[7], param[8], param[9],
		     param[10], param[11]);
//    ProcessFork (0, (uint32)"Help Me man!", userprog, 1);
  }
  SysprocCreateProcesses ();
  dbprintf ('i', "Created processes - about to set timer quantum.\n");
  TimerSet (processQuantum);
  dbprintf ('i', "Set timer quantum to %d, about to run first process.\n",
	    processQuantum);
  intrreturn ();
  // Should never be called because the scheduler exits when there
  // are no runnable processes left.
  exitsim();	// NEVER RETURNS!
}