Annotation of capa/capa51/pProj/capaCommon.c, revision 1.2
1.1 albertel 1: /* =||>|===================== capaCommon.c =====================|<||= */
2: /* created 1994 by Isaac Tsai */
3: /* 1994, 1995, 1996, 1997, 1998, 1999 copyrighted by Isaac Tsai */
4: /* TODO: restructure capa_check_ans*() calls into one */
5: /* =||>|===================== capaCommon.c =====================|<||= */
6: #include <ctype.h>
7: #if defined(__sun) || defined(linux) || defined(__alpha) || defined(hpux) || defined(AIX) || defined(IRIX)
8: #include <unistd.h> /* lockf() */
9: #endif
10: #include <sys/types.h>
11: #include <sys/stat.h>
12: #include <fcntl.h>
13: #include "capaParser.h"
14: #include "capaToken.h"
15: #include "capaCommon.h"
16: #include "ranlib.h"
17:
18:
19: /*----------------------------------------------------------*/
20: /* flock() in SUN is in BSD compatibility lib */
21: /* #include <sys/file.h> */
22: /*----------------------------------------------------------*/
23:
24: int yyparse();
25: extern FILE *yyin;
26: extern void yyrestart();
27:
28: /*----------------------------------------------------------*/
29: /* RETURN: -1 file error */
30: /* 0 success */
31: /* INPUT: if section == 0, for all students in class */
32: /* set : 1, 2, 3, ... */
33: /* prob: 1, 2, 3, ... */
34: /*----------------------------------------------------------*/
35: int
36: capa_excuse(int set,int prob,int section)
37: {
38: int nq;
39: T_header header;
40: T_entry entry;
41: T_student *student_p, *s1_p;
42: char tmp_number[MAX_STUDENT_NUMBER+1];
43: long offset;
44: int num_students;
45:
46: /* Calculate parameters */
47: if (capa_get_header(&header,set)) return (-1);
48: sscanf(header.num_questions,"%d", &nq);
49:
50: if( ( prob > nq ) || (section < 0 ) || (section > MAX_SECTION_COUNT) ) return (-1);
51: num_students= 0;
52: if ( (num_students = capa_get_section(&student_p, section))== -1 ) return (-1);
53: for ( s1_p = student_p ; s1_p ; s1_p = (s1_p->s_next)) {
54: sprintf(tmp_number,"%s",s1_p->s_sn);
55: offset = capa_get_entry(&entry,tmp_number,set);
56: if(offset < 0 ) offset = -offset;
57: switch(entry.answers[prob-1]) {
1.2 ! albertel 58: case '0':
1.1 albertel 59: case '-': entry.answers[prob-1] = 'E'; break;
60: case 'N': entry.answers[prob-1] = 'E'; break;
61: case 'n': entry.answers[prob-1] = 'e'; break;
1.2 ! albertel 62: case '1': case '2': case '3': case '4': case '5':
! 63: case '6': case '7': case '8': case '9':
! 64: if (entry.answers[prob-1] < header.weight[prob-1]) {
! 65: entry.answers[prob-1] = 'E';
! 66: }
! 67: break;
1.1 albertel 68: default : break;
69: }
70: capa_set_entry(&entry,tmp_number,set,offset);
71: capa_mfree(entry.answers); entry.answers = NULL;
72: capa_mfree(entry.tries); entry.tries = NULL;
73: }
1.2 ! albertel 74: capa_mfree(header.weight);
! 75: capa_mfree(header.partial_credit);
1.1 albertel 76: free_students(student_p);
77: return (0);
78: }
79:
80: /*----------------------------------------------------------*/
81: /* Lock file shared */
82: /* lock the file specified by file stream pointer sp */
83: /*----------------------------------------------------------*/
84: int
85: flockstream_sh(sp) FILE *sp;
86: {
87: int fd;
88:
89: fd = fileno(sp);
90:
91: #if defined(__sun) || defined(hpux) || defined(AIX)
92: return ( lockf(fd,F_LOCK, 0L) );
93: #else
94: return (flock(fd,LOCK_SH));
95: #endif
96: }
97: /*----------------------------------------------------------*/
98: int
99: flockstream(sp) FILE *sp;
100: {
101: int fd;
102:
103: fd = fileno(sp);
104:
105: #if defined(__sun) || defined(hpux) || defined(AIX)
106: return ( lockf(fd,F_LOCK, 0L) );
107: #else
108: return (flock(fd,LOCK_EX));
109: #endif
110: }
111: /*----------------------------------------------------------*/
112: int
113: funlockstream(sp) FILE *sp;
114: {
115: int fd;
116:
117: fd = fileno(sp);
118:
119: #if defined(__sun) || defined(hpux) || defined(AIX)
120: return ( lockf(fd,F_ULOCK, 0L) );
121: #else
122: return ( flock(fd,LOCK_UN) );
123: #endif
124: }
125:
126: int
127: inquery_a_lock(sp,cmd,type,offset,whence,len)
128: FILE *sp;int cmd;off_t offset;int whence;off_t len;
129: {
130: struct flock lock;
131: int fd;
132: lock.l_type = type; lock.l_start = offset;
133: lock.l_whence = whence; lock.l_len = len;
134: fd=fileno(sp);
135: return (fcntl(fd,cmd,&lock));
136: }
137: #define Blocked_Write_Lock(sp) \
138: inquery_a_lock(sp,F_SETLK,F_WRLCK,0,0,0)
139:
140: #define Blocked_Write_Lock(sp) \
141: inquery_a_lock(sp,F_SETLK,F_WRLCK,0,0,0)
142:
143: #define Un_Lock(sp) \
144: inquery_a_lock(sp,F_SETLK,F_UNLCK,0,0,0)
145:
146:
147: /*----------------------------------------------------------*/
148: /* INPUT: set problem set number */
149: /* RETURN: -1 no records/setX.db file or file error */
150: /* 0 success */
151: /* OUTPUT: header pointer to T_header structure */
152: /*----------------------------------------------------------*/
153: int
154: capa_set_header(header, set) T_header *header;int set;
155: {
156: FILE *fp;
157: char *big_buf=NULL, filename[FILE_NAME_LENGTH], cr=0, oneline[TMP_LINE_LENGTH];
158: int nq, len, errcode, fd, item_cnt, exists=1;
159: T_header oldheader;
160: long orig_size, new_size, big_buf_size;
161:
162: sprintf(filename,"records/set%d.db",set);
163: if ((fp=fopen(filename,"r+"))==NULL) {
164: exists=0;
165: if ((fp=fopen(filename,"w"))==NULL) { /* create if non-existant */
166: /*printf("Error: can't open %s\n",filename);*/ return (-1);
167: }
168: }
169: sscanf(header->num_questions,"%d",&nq);
170: /* sprintf(oneline,"%d,%s,%s,%s\n",nq,header->open_date,header->due_date,header->answer_date); */
171: sprintf(oneline,"%d\n",nq);
172: len = strlen(oneline);
173: flockstream(fp); errcode = 0;
174:
175: if (exists) {
176: /*get file size*/
177: fseek(fp,0L,SEEK_END);
178: orig_size = ftell(fp);
179: big_buf_size = orig_size; /*the amt we need to read is less then the file's size*/
180: big_buf = capa_malloc(big_buf_size,1);
181: fseek(fp,0L,SEEK_SET);
182:
183: /*read in old header*/
184: fscanf(fp,"%d",&nq);
185: while ( cr != '\n' && cr != EOF ) { cr=fgetc(fp); }
186: oldheader.weight=capa_malloc(nq+1,1);
187: oldheader.partial_credit=capa_malloc(nq+1,1);
188: if (!fread(oldheader.weight, sizeof(char), nq, fp)) errcode = -2;
189: if (EOF==(cr=fgetc(fp))) errcode = -3;
190: if (!fread(oldheader.partial_credit, sizeof(char), nq, fp)) errcode = -4;
191: if (EOF==(cr=fgetc(fp))) errcode = -5;
192: capa_mfree(oldheader.weight);
193: capa_mfree(oldheader.partial_credit);
194:
195: /*read rest of file*/
196: item_cnt=fread(big_buf,1,big_buf_size, fp);
197: }
198:
199: /*write new header*/
200: fseek(fp,0L,SEEK_SET);
201: if (!fwrite(oneline, len, 1, fp)) {errcode = -6;}
202: if ( header->weight != NULL ) {
203: if (!fwrite((char *)(header->weight), strlen(header->weight), 1, fp)) errcode=-7;
204: }
205:
206: if (EOF==(!fputc('\n', fp))) errcode = -8;
207: if (header->partial_credit != NULL) {
208: if (!fwrite((char *)(header->partial_credit), strlen(header->partial_credit),
209: 1, fp)) { errcode = -9; }
210: }
211: if (EOF==(!fputc('\n', fp))) errcode = -10;
212:
213: if (exists) {
214: /*write out rest of file*/
215: if (item_cnt >= 0 ) {
216: big_buf[item_cnt]=0;
217: if (!fwrite(big_buf,item_cnt,1,fp) ) errcode= -11;
218: new_size = ftell(fp);
219: if (new_size < orig_size ) {
220: fd = fileno(fp);
221: ftruncate(fd,new_size);
222: }
223: }
224: }
225:
226: fflush(fp);
227: funlockstream(fp); fclose(fp);
228: if (big_buf!=NULL) capa_mfree(big_buf);
229: return (errcode);
230: }
231:
232: /*----------------------------------------------------------*/
233: /* INPUT: set problem set number */
234: /* RETURN: -1 file error */
235: /* 0 success */
236: /* OUTPUT: header pointer to T_header structure */
237: /* Note: allocates space for the partial_credit and weight */
238: /* fields of the passed in header, caller needs to */
239: /* eventually free them with capa_mfree */
240: /*----------------------------------------------------------*/
241: int
242: capa_get_header(header, set) T_header *header;int set;
243: {
244: FILE *fp;
245: char filename[FILE_NAME_LENGTH];
246: char cr;
247: int nq=0, errcode;
248:
249: sprintf(filename,"records/set%d.db",set);
250: if ((fp=fopen(filename,"r"))==NULL) {
251: /*printf("Error capa_get_header(): can't open %s\n",filename);*/
252: return (-1);
253: }
254:
255: flockstream(fp); errcode = 0;
256: fscanf(fp,"%d",&nq);
257: cr='\0';
258: while ( cr != '\n' && cr != EOF ) { cr=fgetc(fp); }
259: header->weight=capa_malloc(nq+1,1);
260: header->partial_credit=capa_malloc(nq+1,1);
261: if (nq > 0 ) {
262: if (!fread(header->weight, sizeof(char), nq, fp)) errcode = -1;
263: }
264: if (EOF==(cr=fgetc(fp))) errcode = -1;
265: if (nq > 0 ) {
266: if (!fread(header->partial_credit, sizeof(char), nq, fp)) errcode = -1;
267: }
268:
269: funlockstream(fp); fclose(fp);
270: header->weight[nq]='\0'; header->partial_credit[nq]='\0';
271: sprintf(header->num_questions,"%d",nq);
272: return (errcode);
273: }
274: /*----------------------------------------------------------*/
275: /* ----------- previous version, obsolete as of May 1997
276: int
277: capa_set_entry(entry, student_number, set, offset)
278: T_entry *entry;
279: char *student_number;
280: int set;
281: long offset;
282: {
283: FILE *fp;
284: int errcode=0;
285: int len;
286: char filename[FILE_NAME_LENGTH];
287: char a_line[TMP_LINE_LENGTH];
288:
289: sprintf(filename,"records/set%d.db",set);
290: if ((fp=fopen(filename,"r+"))==NULL) {
291: return (-1);
292: }
293: sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
294: len = strlen(a_line);
295: flockstream(fp);
296: fseek(fp,offset,0);
297: if (!fwrite(a_line,len,1,fp) ) {
298: printf("Error writing data to file\n");
299: errcode= (-1);
300: }
301: fflush(fp);
302: funlockstream(fp);
303: fclose(fp);
304: return (errcode);
305: }
306: ---------- */
307:
308: int
309: capa_set_entry(entry, student_number, set, offset)
310: T_entry *entry;
311: char *student_number;
312: int set;
313: long offset;
314: {
315: FILE *fp;
316: int fd;
317: int errcode=0;
318: int done, len, new_len, item_cnt;
319: long next_r, orig_size, new_size, big_buf_size;
320: char filename[FILE_NAME_LENGTH];
321: char *a_line, tmpline[TMP_LINE_LENGTH],
322: tmp_sn[MAX_STUDENT_NUMBER+1], fmtbuf[SMALL_LINE_BUFFER];
323: char *big_buf;
324:
325: sprintf(filename,"records/set%d.db",set);
326: if ((fp=fopen(filename,"r+"))==NULL) {
327: /* printf("Error capa_set_entry(): can't open %s\n",filename); */ return (-1);
328: }
329: /* entry->answers*3 == entry->tries, + fudge factor*/
330: a_line=capa_malloc(strlen(entry->tries)*5+MAX_STUDENT_NUMBER,1);
331: sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
332: new_len = strlen(a_line);
333: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
334: flockstream(fp); /* <==== lock the setX.db file */
335: fseek(fp,0L,SEEK_END);
336: orig_size = ftell(fp);
337: big_buf_size = orig_size + new_len;
338: big_buf = capa_malloc(big_buf_size,1);
339: fseek(fp,0L,SEEK_SET); /* rewind to beginning of file */
340: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* skip weight line, including \n */
341: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* hand grading */
342: done = 0;
343: while(!done) {
344: done = !fgets(tmpline,TMP_LINE_LENGTH-1,fp); len = strlen(tmpline);
345: if( !done ) {
346: sscanf(tmpline,fmtbuf,tmp_sn);
347: if( !strncasecmp(tmp_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */
348: next_r = ftell(fp); offset = next_r - len; done = 1;
349: item_cnt=fread(big_buf,1,big_buf_size, fp); /* read remaining lines into buffer */
350: if(item_cnt >= 0 ) { /* no error reading remaining lines */
351: big_buf[item_cnt]=0; /* terminate the buffer, for sure */
352: fseek(fp,offset,SEEK_SET); /* reposition file pointer to the record */
353: if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */
354: /* printf("Error writing data to file\n"); */
355: errcode= (-1);
356: }
357: if (item_cnt != 0) {
358: if (!fwrite(big_buf,item_cnt,1,fp) ){/*write out the remainings*/
359: /* printf("Error writing data to file\n"); */
360: errcode= (-1);
361: }
362: }
363: new_size = ftell(fp);
364: if(new_size < orig_size ) {
365: fd = fileno(fp);
366: ftruncate(fd,new_size);
367: }
368: }
369: }
370: } else { /* end of file */
371: fseek(fp,0L,SEEK_END);
372: offset = ftell(fp); /* last byte, if last byte is cr, back up one */
373: fseek(fp,-1L,SEEK_END);
374: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
375: offset = offset +2; /* last char and cr */
376: done=1;
377: fseek(fp,offset,SEEK_SET);
378: if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */
379: /* printf("Error writing data to file\n"); */
380: errcode= (-1);
381: }
382: }
383: }
384: fflush(fp);
385: funlockstream(fp); /* <======= unlock the file */
386: fclose(fp);
387: capa_mfree(big_buf); /* free up the buffer */
388: return (errcode);
389: }
390:
391: /* for all elements in entry->answers that aren't ? it changes the
392: file to have the new values (except if student has a Y and for all
393: entries in entry->tries that don't have the value -1 it changes the
394: file to have the new value */
395:
396: int
397: capa_change_entry(entry, student_number, set)
398: T_entry *entry;
399: char *student_number;
400: int set;
401: {
402: FILE *fp;
403: int fd;
404: int errcode=0,offset=0;
405: int done, len, new_len, item_cnt,i,j;
406: long next_r, orig_size, new_size, big_buf_size;
407: char filename[FILE_NAME_LENGTH];
408: char *a_line, tmpline[TMP_LINE_LENGTH],
409: tmp_sn[MAX_STUDENT_NUMBER+1], fmtbuf[SMALL_LINE_BUFFER];
410: char *big_buf;
411:
412: sprintf(filename,"records/set%d.db",set);
413: if ((fp=fopen(filename,"r+"))==NULL) {
414: /* printf("Error capa_set_entry(): can't open %s\n",filename); */ return (-1);
415: }
416: /* entry->answers*3 == entry->tries, + fudge factor*/
417: a_line=capa_malloc(strlen(entry->tries)*5+MAX_STUDENT_NUMBER,1);
418: sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
419: new_len = strlen(a_line);
420: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
421: flockstream(fp); /* <==== lock the setX.db file */
422: fseek(fp,0L,SEEK_END);
423: orig_size = ftell(fp);
424: big_buf_size = orig_size + new_len;
425: big_buf = capa_malloc(big_buf_size,1);
426: fseek(fp,0L,SEEK_SET); /* rewind to beginning of file */
427: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* skip weight line, including \n */
428: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* hand grading */
429: done = 0;
430: while(!done) {
431: done = !fgets(tmpline,TMP_LINE_LENGTH-1,fp); len = strlen(tmpline);
432: if( !done ) {
433: sscanf(tmpline,fmtbuf,tmp_sn);
434: if( !strncasecmp(tmp_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */
435: next_r = ftell(fp); offset = next_r - len; done = 1;
436: item_cnt=fread(big_buf,1,big_buf_size,fp); /*read remaining lines into buffer*/
437: if(item_cnt >= 0 ) { /* no error reading remaining lines */
438: big_buf[item_cnt]=0; /* terminate the buffer, for sure */
439: fseek(fp,offset,SEEK_SET); /* reposition file pointer to the record */
440: for(i=0;i<entry->e_probs;i++) {
441: /*if entry has been updated, and student doesn't have a Y yet*/
442: if ((entry->answers[i]!='?') &&
443: (tmpline[MAX_STUDENT_NUMBER+1+i]!='Y'))
444: tmpline[MAX_STUDENT_NUMBER+1+i]=entry->answers[i];
445: j = atoi(&(entry->tries[i*3]));
446: if ( j > -1 ) {
447: tmpline[MAX_STUDENT_NUMBER+1+entry->e_probs+1+i*3]=entry->tries[i*3];
448: tmpline[MAX_STUDENT_NUMBER+1+entry->e_probs+1+i*3+1]=entry->tries[i*3+1];
449: }
450: }
451: if (!fwrite(tmpline,new_len,1,fp) ) { errcode= (-1); }
452: if (item_cnt != 0) {
453: if (!fwrite(big_buf,item_cnt,1,fp) ){/*write out the remainings*/
454: /* printf("Error writing data to file\n"); */
455: errcode= (-1);
456: }
457: }
458: new_size = ftell(fp);
459: if(new_size < orig_size ) {
460: fd = fileno(fp);
461: ftruncate(fd,new_size);
462: }
463: }
464: }
465: } else { /* end of file */
466: fseek(fp,0L,SEEK_END);
467: offset = ftell(fp); /* last byte, if last byte is cr, back up one */
468: fseek(fp,-1L,SEEK_END);
469: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
470: offset = offset +2; /* last char and cr */
471: done=1;
472: fseek(fp,offset,SEEK_SET);
473: if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */
474: /* printf("Error writing data to file\n"); */
475: errcode= (-1);
476: }
477: }
478: }
479: fflush(fp);
480: funlockstream(fp); /* <======= unlock the file */
481: fclose(fp);
482: capa_mfree(big_buf); /* free up the buffer */
483: return (errcode);
484: }
485:
486: /* -------------------------------------------------- */
487: /* append a entry record to the very end of the file */
488: long
489: capa_append_entry(entry, student_number, set)
490: T_entry *entry;
491: char *student_number;
492: int set;
493: {
494: FILE *fp;
495: int len;
496: char filename[FILE_NAME_LENGTH];
497: char a_line[TMP_LINE_LENGTH];
498: long offset;
499:
500: sprintf(filename,"records/set%d.db",set);
501: if ((fp=fopen(filename,"r+"))==NULL) {
502: /* printf("Error capa_set_entry(): can't open %s\n",filename); */
503: return (-1);
504: }
505: sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
506: len = strlen(a_line);
507:
508: flockstream(fp); /* <==== lock the setX.db file */
509: fseek(fp,0L,SEEK_END);
510: offset = ftell(fp);
511: fseek(fp,-1L,SEEK_END);
512: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
513: offset = offset +2;
514: fseek(fp,offset,SEEK_SET);
515: if (!fwrite(a_line,len,1,fp) ) {
516: /* printf("Error writing data to file\n"); */
517: return (-1);
518: }
519: fflush(fp);
520: funlockstream(fp);
521: fclose(fp);
522: return (offset);
523: }
524:
525: /*----------------------------------------------------------*/
526:
527: long /* RETURNS: byte offset to start of record, 0 if error,
528: -offset if not found & newly created */
529: capa_get_entry(entry, student_number, set)
530: T_entry *entry;
531: char *student_number;
532: int set;
533: {
534: char filename[FILE_NAME_LENGTH];
535: FILE *fp;
536: int len, nq;
537: char *ans_p, *tries_p, oneline[TMP_LINE_LENGTH],fmtbuf[SMALL_LINE_BUFFER];
538: long offset = 0, next_r;
539: int ii, done, found = 0;
540: char a_sn[MAX_STUDENT_NUMBER+1];
541:
542: sprintf(filename,"records/set%d.db",set);
543: if ((fp=fopen(filename,"r"))==NULL) {
544: /*printf("Error capa_get_entry(): can't open %s\n",filename);*/
545: return (0);
546: }
547: sprintf(entry->student_number,"%s",student_number);
548: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
549: flockstream(fp);
550: fgets(oneline,TMP_LINE_LENGTH-1,fp); len = strlen(oneline); sscanf(oneline,"%d",&nq);
551: fgets(oneline,TMP_LINE_LENGTH-1,fp); /* skip weight line, including \n */
552: fgets(oneline,TMP_LINE_LENGTH-1,fp); /* hand grading */
553: done = 0;
554: while(!done) {
555: done = !fgets(oneline,TMP_LINE_LENGTH-1,fp); len = strlen(oneline);
556: if( !done ) {
557: sscanf(oneline,fmtbuf,a_sn);
558: if( !strncasecmp(a_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */
559: next_r = ftell(fp); offset = next_r - len; done = 1; found = 1;
560: }
561: } else { /* end of file */
562: fseek(fp,0L,SEEK_END);
563: offset = ftell(fp); /* last byte, if last bye is cr, back up one */
564: fseek(fp,-1L,SEEK_END);
565: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
566: offset = offset +2; /* last char and cr */
567: found = 0; done=1;
568: }
569: }
570: funlockstream(fp); fclose(fp);
571: if(!found) {
572: ans_p = capa_malloc(nq+1,1);
573: tries_p = capa_malloc(3*nq+2,1); /* space and \0 */
574: for(ii=0;ii<nq;ii++) { /* Initialize answer string and tries string */
575: ans_p[ii] = '-'; tries_p[3*ii] = ' '; tries_p[3*ii + 1] = '0';
576: if(ii < nq-1) tries_p[3*ii + 2] = ',';
577: }
578: entry->answers = ans_p;
579: entry->tries = tries_p;
580: entry->e_probs = nq;
581: offset = capa_append_entry(entry,student_number,set);
582: } else { /* grows records shorter than nq to nq in length*/
583: char *comma;
584: int length;
585: comma=index(oneline,',');
586: length=((int)(comma-oneline))-(MAX_STUDENT_NUMBER+1);
587: if (length < nq) {
588: ans_p = capa_malloc(nq+1,1);
589: tries_p = capa_malloc(3*nq+2,1); /* space and \0 */
590: } else {
591: ans_p = capa_malloc(length+1,1);
592: tries_p = capa_malloc(3*length+2,1); /* space and \0 */
593: }
594: sprintf(fmtbuf, "%%%dc",length);
595: sscanf(oneline + MAX_STUDENT_NUMBER+1,fmtbuf,ans_p);
596: sprintf(fmtbuf, "%%%dc",(3*length-1));
597: sscanf(oneline + MAX_STUDENT_NUMBER+1+length+1,fmtbuf,tries_p);
598: entry->answers = ans_p;
599: entry->tries = tries_p;
600: entry->e_probs = nq;
601: if (length < nq) {
602: for(ii=length;ii<nq;ii++) {
603: ans_p[ii] = '-'; tries_p[3*ii] = ' '; tries_p[3*ii + 1] = '0';
604: if(ii < nq-1) tries_p[3*ii + 2] = ',';
605: }
606: ans_p[nq]='\0';tries_p[3*(nq)+2]='\0';tries_p[3*length-1]=',';
607: }
608: }
609: return (offset);
610: }
611: /*----------------------------------------------------------*/
612: /* Constants defining the column number for each fields */
613: /* in classl file */
614: /*----------------------------------------------------------*/
615: #define SECTION_BEGIN_COLUMN 10
616: #define SN_BEGIN_COLUMN 14
617: #define NAME_BEGIN_COLUMN 24
618: #define EMAIL_BEGIN_COLUMN 60
619: #define CAPAID_BEGIN_COLUMN 100
620: /*----------------------------------------------------------*/
621: /* Retrieve a linked list of students with specified */
622: /* section in classl file */
623: /* If the input section number is 0, students in the whole */
624: /* classl will be retrieved. */
625: /* The resulting linked list is ordered according to the */
626: /* order in classl */
627: /* Remember to use free_students() to free up the linked */
628: /* list once done with it. */
629: /*----------------------------------------------------------*/
630: /* INPUT: section section number */
631: /* 0 means to load the whole class */
632: /* OUTPUT: student_pp */
633: /* pointer to pointer of structure T_student */
634: /* RETURN: number of students in specified section */
635: /*----------------------------------------------------------*/
636: int
637: capa_get_section(student_pp, section)
638: T_student **student_pp;
639: int section;
640: {
641: FILE *fp;
642: char line[SMALL_LINE_BUFFER],fmtbuf[SMALL_LINE_BUFFER], *cp;
643: int i, line_len;
644: int tmp_sec, student_cnt, tmp_capaid;
645: T_student *s1_p, *s2_p, *s3_p;
646:
647: if ((fp=fopen("classl","r"))==NULL) {
648: /*printf("Error: Can't open classlist file\n");*/
649: return (-1);
650: }
651: student_cnt = 0; s1_p = s2_p = s3_p = (T_student *)NULL;
652: while (fgets(line,SMALL_LINE_BUFFER-1,fp)) {
653: line_len = strlen(line);
654: if(line_len > 25 ) { /* contains valid information, instead of only cr */
655: sscanf(line+SECTION_BEGIN_COLUMN,"%d", &tmp_sec);
656: if (!section || tmp_sec == section) {
657: s3_p = (T_student *)capa_malloc(sizeof(T_student),1);
658: s3_p->s_sec = tmp_sec;
659: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
660: sscanf(line+SN_BEGIN_COLUMN,fmtbuf,s3_p->s_sn);
661: cp = (char *)&line[NAME_BEGIN_COLUMN];
662: for(i=0;i<MAX_NAME_CHAR;i++) s3_p->s_nm[i]=' ';
663: i=0;
664: while( (i < MAX_NAME_CHAR) &&
665: ( isalnum(cp[i]) || cp[i] == ',' || cp[i] == '.' || cp[i] == '\'' ||
666: cp[i] == ' ' || cp[i] == '\t'|| cp[i] == '-' ) ) {
667: s3_p->s_nm[i]=cp[i]; i++;
668: }
669: s3_p->s_nm[MAX_NAME_CHAR]='\0';
670: s3_p->s_email[0]=0;
671: if( line_len > EMAIL_BEGIN_COLUMN ) { /* contains email */
672: cp = (char *)&line[EMAIL_BEGIN_COLUMN];
673: for(i=0;i<MAX_EMAIL_CHAR;i++) s3_p->s_email[i]=' ';
674: i=0;
675: while( (i < MAX_EMAIL_CHAR) &&
676: ( isalnum(cp[i]) || cp[i] == '@' || cp[i] == '.' ) ) {
677: s3_p->s_email[i]=cp[i]; i++;
678: }
679: s3_p->s_email[i]='\0'; /* terminate the email string with the string length */
680: if( line_len > CAPAID_BEGIN_COLUMN ) { /* contains capa id */
681: sscanf(line+CAPAID_BEGIN_COLUMN,"%d", &tmp_capaid);
682: if(tmp_capaid > 0 ) {
683: s3_p->s_capaid = tmp_capaid;
684: }
685: }
686: }
687: if( student_cnt == 0 ) {
688: s1_p = s3_p;
689: s3_p->s_prev = s3_p; s3_p->s_next = (T_student *)NULL;
690: s2_p = s3_p;
691: } else {
692: s3_p->s_prev = s2_p; s3_p->s_next = (T_student *)NULL;
693: s2_p->s_next = s3_p;
694: s2_p = s3_p;
695: }
696: student_cnt++;
697: }
698: }
699: }
700: fclose(fp);
701: *student_pp = s1_p;
702: return (student_cnt);
703: }
704: /*----------------------------------------------------------*/
705: /*----------------------------------------------------------*/
706: /* Retrieve a linked list of students with specified */
707: /* section in classl file */
708: /* If the input section number is 0, students in the whole */
709: /* classl will be retrieved. */
710: /* The resulting linked list is ordered according to */
711: /* student name */
712: /* Remember to use free_students() to free up the linked */
713: /* list once done with it. */
714: /*----------------------------------------------------------*/
715: /* INPUT: section section number */
716: /* 0 means to load the whole class */
717: /* OUTPUT: student_pp */
718: /* pointer to pointer of structure T_student */
719: /* RETURN: number of students in specified section */
720: /*----------------------------------------------------------*/
721:
722: int
723: capa_sorted_section(student_pp, section)
724: T_student **student_pp;
725: int section;
726: {
727: int student_cnt;
728: T_student *student_p, *c_sp;
729:
730: student_cnt = capa_get_section(&student_p,section);
731: if( student_cnt > 1 ) {
732: for(c_sp=student_p;c_sp;c_sp=c_sp->s_next){
733: strcpy(c_sp->s_key,c_sp->s_nm);
734: }
735: msort_main(&student_p);
736: }
737: *student_pp = student_p;
738: return (student_cnt);
739: }
740:
741: /*----------------------------------------------------------*/
742: /* INPUT: address of a pointer to T_student structure */
743: /* OUTPUT: address of a pointer to T_student structure */
744: /* */
745: /* RETURN: none */
746: /*----------------------------------------------------------*/
747: void
748: msort_main(head_pp) T_student **head_pp;
749: {
750: T_student *right_p, *out_sp;
751:
752: if( (*head_pp != NULL) && ((*head_pp)->s_next != NULL) ) {
753: msort_split( *head_pp, &right_p);
754: msort_main(head_pp); msort_main(&right_p);
755: msort_merge(*head_pp, right_p, &out_sp);
756: *head_pp = out_sp;
757: }
758: }
759: /*----------------------------------------------------------*/
760: /* INPUT: a_sp pointer to T_student structur */
761: /* OUTPUT: a_sp */
762: /* b_pp address of a pointer to T_student structure */
763: /* */
764: /* RETURN: none */
765: /*----------------------------------------------------------*/
766: void
767: msort_split(a_sp, b_pp) T_student *a_sp; T_student **b_pp;
768: {
769: T_student *c_sp;
770:
771: *b_pp = a_sp;
772: c_sp = a_sp->s_next;
773: c_sp = c_sp->s_next;
774: while( c_sp != NULL ) {
775: c_sp = c_sp->s_next;
776: *b_pp = (*b_pp)->s_next;
777: if( c_sp != NULL ) c_sp = c_sp->s_next;
778: }
779: c_sp = (*b_pp)->s_next;
780: (*b_pp)->s_next = NULL;
781: *b_pp = c_sp;
782: }
783: /*----------------------------------------------------------*/
784: /* INPUT: a_sp pointer to T_student structur */
785: /* b_sp pointer to T_student structur */
786: /* OUTPUT: c_pp address of a pointer to T_student structure */
787: /* */
788: /* RETURN: none */
789: /*----------------------------------------------------------*/
790: void
791: msort_merge(a_sp, b_sp, c_pp) T_student *a_sp, *b_sp, **c_pp;
792: {
793: T_student *d_sp;
794:
795: if( a_sp == NULL || b_sp == NULL ) {
796:
797: } else {
798: if( strcmp(a_sp->s_key, b_sp->s_key) <= 0 ) {
799: *c_pp = a_sp;
800: a_sp = a_sp->s_next;
801: } else {
802: *c_pp = b_sp;
803: b_sp = b_sp->s_next;
804: }
805: d_sp = *c_pp;
806: while( (a_sp != NULL) && (b_sp != NULL) ) {
807: if( strcmp(a_sp->s_key, b_sp->s_key) <= 0) {
808: d_sp->s_next = a_sp;
809: d_sp = a_sp;
810: a_sp = a_sp->s_next;
811: } else {
812: d_sp->s_next = b_sp;
813: d_sp = b_sp;
814: b_sp = b_sp->s_next;
815: }
816: }
817: if( a_sp == NULL ) {
818: d_sp->s_next = b_sp;
819: } else {
820: d_sp->s_next = a_sp;
821: }
822: }
823: }
824:
825: /*----------------------------------------------------------*/
826: /* INPUT: head_p pointer to T_student structure */
827: /* OUTPUT: head_p pointed to sorted linked list */
828: /* */
829: /* RETURN: none */
830: /*----------------------------------------------------------*/
831: void
832: insert_sort(head_p) T_student *head_p;
833: {
834: T_student *tail_p, *i_p, *p_p, *r_p;
835:
836: if( head_p != NULL ) {
837: tail_p = head_p;
838: while( tail_p->s_next != NULL ) {
839: i_p = tail_p->s_next;
840: if( strcmp( i_p->s_key, head_p->s_key) < 0 ) {
841: tail_p->s_next = i_p->s_next;
842: i_p->s_next = head_p;
843: head_p = i_p;
844: } else {
845: r_p = head_p;
846: p_p = r_p->s_next;
847: while( strcmp(i_p->s_key, p_p->s_key) > 0 ) {
848: r_p = p_p;
849: p_p = r_p->s_next;
850: }
851: if( i_p == p_p ) {
852: tail_p = i_p;
853: } else {
854: tail_p->s_next = i_p->s_next;
855: i_p->s_next = p_p;
856: r_p->s_next = i_p;
857: }
858: }
859: }
860: }
861: }
862: /*----------------------------------------------------------*/
863: /* The purpose of this routine is to free up all spaces */
864: /* in the linked list */
865: /*----------------------------------------------------------*/
866: /* INPUT: student_p pointer to T_student structure */
867: /* OUTPUT: none */
868: /* */
869: /* RETURN: none */
870: /*----------------------------------------------------------*/
871:
872: void
873: free_students(student_p) T_student *student_p;
874: {
875: T_student *s_p,*next_p;
876:
877: for (s_p=student_p; s_p; s_p=next_p) {
878: next_p = (s_p->s_next);
879: capa_mfree((char *)s_p);
880: }
881: }
882:
883: /*----------------------------------------------------------*/
884: /* The purpose of this routine is to free up all spaces */
885: /* in the linked list */
886: /*----------------------------------------------------------*/
887: /* INPUT: student_p pointer to T_student structur */
888: /* OUTPUT: none */
889: /* */
890: /* RETURN: -2 file error */
891: /* -1 never login */
892: /* >= 0 score for that set */
893: /*----------------------------------------------------------*/
894: int
895: capa_get_score(student_number,set,valid_scores,answers_pp)
896: char *student_number;int set;int *valid_scores;char **answers_pp;
897: {
898: T_entry a_record;
899: T_header a_header;
900: long offset;
901: int set_scores, set_valids=0, probs_cnt;
902: int ii=0, never_login=1;
903:
904: if( (offset = capa_get_entry(&a_record,student_number,set) ) == 0 ) {
905: return (-2);
906: }
907: probs_cnt = a_record.e_probs;
908: if( capa_get_header(&a_header,set) < 0 ) { return (-2); }
909: if( offset < 0 ) {
910: for(set_valids=0,ii=0;ii<probs_cnt;ii++) {
911: set_valids += (a_header.weight[ii] - '0');
912: }
913: set_scores = -1;
914: *answers_pp = a_record.answers;
915: capa_mfree(a_record.tries); a_record.tries = NULL;
916: } else {
917: for(set_scores=0,ii=0, never_login=1;ii<probs_cnt;ii++) {
918: switch(a_record.answers[ii]) {
919: case 'Y': case 'y': never_login = 0;
920: set_scores += (a_header.weight[ii] - '0');
921: set_valids += (a_header.weight[ii] - '0'); break;
922: case '-': case 'N': case 'n':
923: set_valids += (a_header.weight[ii] - '0'); break;
924: case 'E': case 'e': break;
925: default : if( a_record.answers[ii] >= '0' &&
926: a_record.answers[ii] <= '9' ) {
927: set_scores += (a_record.answers[ii] - '0');
928: set_valids += (a_header.weight[ii] - '0');
929: never_login = 0;
930: } break;
931: }
932: }
933: *answers_pp = a_record.answers;
934: capa_mfree(a_record.tries); a_record.tries = NULL;
935: }
936: capa_mfree(a_header.weight);
937: capa_mfree(a_header.partial_credit);
938: *valid_scores = set_valids;
939: if(never_login) set_scores = -1;
940: return (set_scores);
941: }
942: /*----------------------------------------------------------*/
943: /* Reads the classl file and returns the number of students */
944: /* for each section in cnt_arry[] */
945: /* In cnt_arry[0] is the maximum section number that */
946: /* has at least one student */
947: /*----------------------------------------------------------*/
948: /* INPUT: cnt_arry[] integer array */
949: /* OUTPUT: cnt_arry[] */
950: /* */
951: /* */
952: /* RETURN: -1 file error */
953: /*----------------------------------------------------------*/
954: int
955: capa_get_section_count(cnt_arry) int cnt_arry[];
956: {
957: FILE *fp;
958: char filename[FILE_NAME_LENGTH];
959: char line[TMP_LINE_LENGTH];
960: int sec_num, cnt, i, max;
961:
962: sprintf(filename,"classl");
963: if ((fp=fopen(filename,"r"))==NULL) {
964: /*printf("Error: can't open %s\n",filename);*/
965: return (-1);
966: }
967: for(i=0;i<MAX_SECTION_COUNT;i++) cnt_arry[i]=0;
968: max = 0;
969: while ( fgets(line,TMP_LINE_LENGTH-1,fp) && (strlen(line) != 0) ) {
970: sec_num=0;
971: sscanf(line+SECTION_BEGIN_COLUMN,"%d", &sec_num);
972: if( sec_num != 0 ) {
973: max = MAX(sec_num,max);
974: cnt_arry[sec_num]++;
975: }
976: }
977: fclose(fp);
978: cnt = 0;
979: for(i=1; i <= max; i++) {
980: if(cnt_arry[i]) cnt++;
981: }
982: cnt_arry[0] = max;
983: return (cnt);
984: }
985: /*----------------------------------------------------------*/
986: /* lookup student information from classl file by */
987: /* student number */
988: /*----------------------------------------------------------*/
989: /* INPUT: student_number char array of student number */
990: /* OUTPUT: student_p pointer to a T_student structure */
991: /* that contains the student name, */
992: /* student number, section number */
993: /* of the student inquired */
994: /* */
995: /* RETURN: -1 file error */
996: /* 0 no such student */
997: /* >0 success (line number in classl of student)*/
998: /*----------------------------------------------------------*/
999: int
1000: capa_get_student(student_number, student_p)
1001: char *student_number;
1002: T_student *student_p;
1003: {
1004: FILE *fp;
1005: char line[SMALL_LINE_BUFFER],fmtbuf[SMALL_LINE_BUFFER],
1006: sNumber[MAX_STUDENT_NUMBER+1],
1007: aNumber[MAX_STUDENT_NUMBER+1];
1008: int i,found,line_len,tmp_capaid,linenum=0;
1009: char *cp;
1010:
1011: strncpy(sNumber, student_number,MAX_STUDENT_NUMBER+1);
1012: if ((fp=fopen("classl","r"))==NULL) {
1013: /*printf("Error: Can't open classlist file\n");*/
1014: return (-1);
1015: }
1016: found = 0;
1017: while (!found && fgets(line,SMALL_LINE_BUFFER-1,fp)) {
1018: linenum++;
1019: line_len = strlen(line);
1020: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
1021: sscanf(line+SN_BEGIN_COLUMN,fmtbuf,aNumber);
1022: if(!strncasecmp(sNumber,aNumber, MAX_STUDENT_NUMBER)) {
1023: found = 1;
1024: i=0;
1025: strncpy(student_p->s_sn, student_number,MAX_STUDENT_NUMBER+1);
1026: cp = (char *)&line[NAME_BEGIN_COLUMN];
1027: while( (i< MAX_NAME_CHAR) &&
1028: (isalnum(cp[i]) || cp[i] == ',' || cp[i] == '.' || cp[i] == '\'' ||
1029: cp[i] == ' ' || cp[i] == '\t'|| cp[i] == '-' || cp[i] == '_' || cp[i] == '~' ) ) {
1030: student_p->s_nm[i]=cp[i]; i++;
1031: }
1032: student_p->s_nm[i]='\0';
1033: sscanf(line+SECTION_BEGIN_COLUMN,"%d", &(student_p->s_sec));
1034: student_p->s_email[0]=0;
1035: if( line_len > EMAIL_BEGIN_COLUMN ) { /* contains email */
1036: cp = (char *)&line[EMAIL_BEGIN_COLUMN];
1037: for(i=0;i<MAX_EMAIL_CHAR;i++) student_p->s_email[i]=' ';
1038: i=0;
1039: while( (i < MAX_EMAIL_CHAR) &&
1040: ( isalnum(cp[i]) || cp[i] == '@' || cp[i] == '.' || cp[i] == '!' || cp[i] == '=' ||
1041: cp[i] == '_' || cp[i] == '-' || cp[i] == '+' || cp[i] == '^' || cp[i] == '|' ) ) {
1042: student_p->s_email[i]=cp[i]; i++;
1043: }
1044: student_p->s_email[i]='\0'; /* terminate the email string with the string length */
1045: if( line_len > CAPAID_BEGIN_COLUMN ) { /* contains capa id */
1046: sscanf(line+CAPAID_BEGIN_COLUMN,"%d", &tmp_capaid);
1047: if(tmp_capaid > 0 ) {
1048: student_p->s_capaid = tmp_capaid;
1049: }
1050: }
1051: }
1052: }
1053: }
1054: fclose(fp);
1055: if (found > 0) found=linenum;
1056: return (found);
1057: }
1058: /*----------------------------------------------------------*/
1059: /* lookup student information from classl file by */
1060: /* student name */
1061: /*----------------------------------------------------------*/
1062: /* INPUT: student_name char array of student name */
1063: /* OUTPUT: student_p pointer to a T_student structure */
1064: /* that contains the student name, */
1065: /* student number, section number */
1066: /* of the student inquired */
1067: /* */
1068: /* RETURN: -1 file error */
1069: /* 0 no such student */
1070: /* 1 success */
1071: /*----------------------------------------------------------*/
1072: int
1073: capa_student_byname(student_name, student_p)
1074: char *student_name;
1075: T_student *student_p;
1076: {
1077: FILE *fp;
1078: char line[SMALL_LINE_BUFFER],fmtbuf[SMALL_LINE_BUFFER],
1079: sName[MAX_NAME_CHAR+1],
1080: aName[MAX_NAME_CHAR+1];
1081: int i,found, len, line_len,tmp_capaid;
1082: char *cp;
1083:
1084: len = strlen(student_name);
1085: strncpy(sName, student_name,MAX_NAME_CHAR+1);
1086: if ((fp=fopen("classl","r"))==NULL) {
1087: /*printf("Error: Can't open classlist file\n");*/
1088: return (-1);
1089: }
1090: found = 0;
1091: while (fgets(line,SMALL_LINE_BUFFER-1,fp)) {
1092: i=0;
1093: cp = (char *)&line[NAME_BEGIN_COLUMN];
1094: while( (i < MAX_NAME_CHAR) &&
1095: (isalnum(cp[i]) || cp[i] == ',' || cp[i] == '.' || cp[i] == '\'' ||
1096: cp[i] == ' ' || cp[i] == '\t' || cp[i] == '-' || cp[i] == '_' || cp[i] == '~') ) {
1097: aName[i]=cp[i]; i++;
1098: }
1099: aName[i]='\0';
1100: if(!strncasecmp(sName,aName,len)) {
1101: found = 1;
1102: strcpy(student_p->s_nm,aName);
1103: sscanf(line+SECTION_BEGIN_COLUMN,"%d", &(student_p->s_sec));
1104: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
1105: sscanf(line+SN_BEGIN_COLUMN,fmtbuf,student_p->s_sn);
1106: student_p->s_email[0]=0;
1107: line_len=strlen(line);
1108: if( line_len > EMAIL_BEGIN_COLUMN ) { /* contains email */
1109: cp = (char *)&line[EMAIL_BEGIN_COLUMN];
1110: for(i=0;i<MAX_EMAIL_CHAR;i++) student_p->s_email[i]=' ';
1111: i=0;
1112: while( (i < MAX_EMAIL_CHAR) &&
1113: ( isalnum(cp[i]) || cp[i] == '@' || cp[i] == '.' || cp[i] == '!' || cp[i] == '=' ||
1114: cp[i] == '_' || cp[i] == '-' || cp[i] == '+' || cp[i] == '^' || cp[i] == '|' ) ) {
1115: student_p->s_email[i]=cp[i]; i++;
1116: }
1117: student_p->s_email[i]='\0'; /* terminate the email string with the string length */
1118: if( line_len > CAPAID_BEGIN_COLUMN ) { /* contains capa id */
1119: sscanf(line+CAPAID_BEGIN_COLUMN,"%d", &tmp_capaid);
1120: if(tmp_capaid > 0 ) {
1121: student_p->s_capaid = tmp_capaid;
1122: }
1123: }
1124: }
1125: }
1126: }
1127: fclose(fp);
1128: return (found);
1129: }
1130: /*----------------------------------------------------------*/
1131: /* Randomly selected a student from classl file specified */
1132: /* by section */
1133: /*----------------------------------------------------------*/
1134: /* INPUT: section section number */
1135: /* OUTPUT: student_p pointer to a T_student structure */
1136: /* that contains the student name, */
1137: /* student number, section number */
1138: /* of the student inquired */
1139: /* */
1140: /* RETURN: -1 file error */
1141: /* 0 no such student */
1142: /* 1 success */
1143: /*----------------------------------------------------------*/
1144: int
1145: capa_pick_student(section, student_p)
1146: int section;
1147: T_student *student_p;
1148: {
1149: T_student *s1_p, *s2_p;
1150: int student_cnt, idx, pick=-1;
1151:
1152: student_cnt = capa_get_section(&s1_p,section);
1153: if(student_cnt > 0 ) {
1154: srand(time(NULL));
1155: pick = rand() % student_cnt;
1156: for(s2_p = s1_p, idx=0; s2_p && idx < pick; idx++) {
1157: s2_p = s2_p->s_next;
1158: }
1159: strcpy(student_p->s_sn,s2_p->s_sn);
1160: strcpy(student_p->s_nm,s2_p->s_nm);
1161: strcpy(student_p->s_email,s2_p->s_email);
1162: student_p->s_capaid=s2_p->s_capaid;
1163: student_p->s_sec = s2_p->s_sec;
1164: free_students(s1_p);
1165: }
1166: return (pick);
1167: }
1168: /* -------------------------------------------------- */
1169: /* add a student to the class file */
1170: /* check duplicated student id */
1171: /* student name? */
1172: /* Returns: 0 success */
1173: /* 1 there is an duplicate entry */
1174: /* -------------------------------------------------- */
1175: int
1176: capa_add_student(student_p)
1177: T_student *student_p;
1178: {
1179: FILE *fp;
1180: char line[SMALL_LINE_BUFFER], fmtbuf1[SMALL_LINE_BUFFER],
1181: tmp_nm[MAX_STUDENT_NUMBER+1],
1182: tmp_nu[MAX_NAME_CHAR+1];
1183: int i,found, len;
1184: char *class, *cp;
1185: char cid[4],cn[4];
1186: #if defined(NeXT)
1187: char cwd[FILE_NAME_LENGTH];
1188: #endif
1189:
1190: #if defined(NeXT)
1191: class = getwd(cwd);
1192: if( class == NULL ) { class = cwd; }
1193: #else
1194: class = getcwd(NULL,255);
1195: #endif
1196:
1197: if( class == NULL ) { printf("capa_add_student(): Current working directory unknown!\n"); }
1198: len=strlen(class); cp=class; cp=cp+(len-8);
1199: for(i=0;i<3;i++) {
1200: cid[i] = cp[i+3];
1201: cn[i] = cp[i];
1202: }
1203: cid[3]=cn[3]=0;
1204: if ((fp=fopen("classl","r+"))==NULL) {
1205: /*printf("Error: Can't open classlist file\n");*/
1206: return (-1);
1207: }
1208: found = 0;
1209: sprintf(fmtbuf1, "%%%dc",MAX_STUDENT_NUMBER);
1210: while (fgets(line,SMALL_LINE_BUFFER-1,fp)) {
1211: sscanf(line+SN_BEGIN_COLUMN,fmtbuf1,tmp_nu);
1212: tmp_nu[MAX_STUDENT_NUMBER]='\0';
1213: if(!strncasecmp(student_p->s_sn,tmp_nu, MAX_STUDENT_NUMBER)) {
1214: found = 1; break;
1215: }
1216: i=0; cp = (char *)&line[NAME_BEGIN_COLUMN];
1217: while( (i < MAX_NAME_CHAR) &&
1218: (isalnum(cp[i]) || cp[i] == ',' || cp[i] == '.' || cp[i] == '\'' ||
1219: cp[i] == ' ' || cp[i] == '\t'|| cp[i] == '-' || cp[i] == '_' || cp[i] == '~') ) {
1220: tmp_nm[i]=cp[i]; i++;
1221: }
1222: tmp_nm[i]='\0';
1223: len=strlen(tmp_nm);
1224: if(!strncasecmp(student_p->s_nm,tmp_nm,len)) {
1225: found = 1; break;
1226: }
1227: }
1228: if(!found) {
1229: sprintf(line,"%s %s %03d %s %s\n",
1230: cn,cid,student_p->s_sec,student_p->s_sn,student_p->s_nm);
1231: len = strlen(line);
1232: fseek(fp,0L,SEEK_END);
1233: if (!fwrite(line,len,1,fp) ) {
1234: /*printf("Error writing data to file\n");*/
1235: found = -1;
1236: }
1237: fflush(fp);
1238: }
1239: fclose(fp);
1240: free(class);
1241: return (found);
1242: }
1243: /*----------------------------------------------------------*/
1244: /* INPUT: student_number char array of student number */
1245: /* set the X in logX.db */
1246: /* OUTPUT: none */
1247: /* */
1248: /* RETURN: -1 file error */
1249: /* 0 no login */
1250: /* >0 number of logins in that logX.db file */
1251: /*----------------------------------------------------------*/
1252: int
1253: capa_get_login_count(student_number,set)
1254: char *student_number;
1255: int set;
1256: {
1257: char filename[FILE_NAME_LENGTH],
1258: sNumber[MAX_STUDENT_NUMBER+1],
1259: aNumber[MAX_STUDENT_NUMBER+1];
1260: FILE *fp;
1261: char line[MAX_BUFFER_SIZE],fmtbuf[MAX_BUFFER_SIZE];
1262: int num;
1263:
1264: strncpy(sNumber, student_number,MAX_STUDENT_NUMBER+1);
1265: sprintf(filename,"records/log%d.db",set);
1266: if( !capa_access(filename, F_OK) ) {
1267: if ((fp=fopen(filename,"r"))==NULL) {
1268: /*printf("Error: can't open %s\n",filename);*/
1269: return (-1);
1270: }
1271: } else {
1272: return (-1);
1273: }
1274: num = 0;
1275: while (fgets(line,MAX_BUFFER_SIZE-1,fp)) {
1276: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
1277: sscanf(line,fmtbuf,aNumber);
1278: if(!strncasecmp(sNumber,aNumber, MAX_STUDENT_NUMBER)) num++;
1279: }
1280: fclose(fp);
1281: return (num);
1282: }
1283: /*----------------------------------------------------------*/
1284: /* INPUT: set the X in logX.db */
1285: /* OUTPUT: none */
1286: /* */
1287: /* RETURN: -1 file error */
1288: /* 0 no login */
1289: /* >0 number of logins in that logX.db file */
1290: /*----------------------------------------------------------*/
1291: #define ANSWER_BEGIN_COLUMN 35
1292: int
1293: capa_get_login_db(login_item,num_probs,set)
1294: T_entry login_item[];
1295: int *num_probs;
1296: int set;
1297: {
1298: FILE *fp;
1299: char filename[FILE_NAME_LENGTH];
1300: char line[MAX_BUFFER_SIZE],fmtbuf[SMALL_LINE_BUFFER];
1301: T_header header;
1302: int num_q, count, len;
1303:
1304: if(capa_get_header(&header,set)) return (0);
1305: sscanf(header.num_questions,"%d",&num_q);
1306: *num_probs = num_q;
1307: capa_mfree(header.weight);
1308: capa_mfree(header.partial_credit);
1309:
1310: sprintf(filename,"records/log%d.db",set);
1311: if((fp=fopen(filename,"r"))==NULL) {
1312: /*printf("Error: can't open %s\n",filename);*/
1313: return (-1);
1314: }
1315: count=0;
1316: while ( fgets(line,MAX_BUFFER_SIZE,fp) && (strlen(line) != 0 )) {
1317: len = strlen(line);
1318: if(len > ANSWER_BEGIN_COLUMN ) {
1319: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
1320: sscanf(line,fmtbuf, login_item[count].student_number);
1321: login_item[count].answers = capa_malloc(num_q,1);
1322: sprintf(fmtbuf, "%%%dc",num_q);
1323: sscanf(line+ANSWER_BEGIN_COLUMN,fmtbuf, login_item[count].answers);
1324: count++;
1325: }
1326: }
1327: fclose(fp);
1328: return (count);
1329: }
1330:
1331: /*----------------------------------------------------------*/
1332: /* INPUT: option the option the check */
1333: /* set the X in dateX.db */
1334: /* section which section to check for */
1335: /* */
1336: /* OUTPUT: none */
1337: /* */
1338: /* RETURN: -2 invalid option */
1339: /* -1 capa_get_section_dates error */
1340: /* 0 no */
1341: /* 1 yes */
1342: /*----------------------------------------------------------*/
1343: int capa_check_option(int option,int set,int section)
1344: {
1345: T_dates* dates;
1346: int result;
1347:
1348: result=capa_get_section_dates(section,set,&dates);
1349: if (result < 0) return -1;
1350: switch(option) {
1351: case OPTION_INHIBIT_RESPONSE: result=dates->inhibit_response;break;
1352: case OPTION_VIEW_PROBLEMS_AFTER_DUE: result=dates->view_problems_after_due;break;
1353: default: result=-2;
1354: }
1355: capa_mfree((char*)dates);
1356: return result;
1357: }
1358:
1359: /*----------------------------------------------------------*/
1360: /* INPUT: set the X in logX.db */
1361: /* OUTPUT: none */
1362: /* */
1363: /* RETURN: -1 file error */
1364: /* 0 no login */
1365: /* >0 number of logins in that logX.db file */
1366: /*----------------------------------------------------------*/
1367: int
1368: compare_datetime(time,datetime)
1369: time_t time;
1370: char *datetime;
1371: {
1372: char dateStr[16], timeStr[16];
1373: time_t time2;
1374: char *t_ptr;
1375: int idx;
1376:
1377: /* sscanf(datetime,"%s %s",dateStr,timeStr); */
1378: t_ptr = index(datetime,' '); t_ptr++; /*** hpux complained */
1379: for(idx=0;idx<10;idx++) dateStr[idx] = datetime[idx];
1380: dateStr[10] = 0;
1381: for(idx=0;idx<5;idx++) timeStr[idx] = t_ptr[idx];
1382: timeStr[5] = 0;
1383: time2 = convertTime(dateStr,timeStr);
1384: if(time == time2 ) return (0);
1385: return ( (time > time2)? 1 : -1 );
1386: }
1387:
1388: /* --------------------------------- */
1389: /* check if records/dateX.db exists */
1390: /* read the section open date, answer date, due date info */
1391: /* What if: [7,3] date_info */
1392: /* [3,7] date_info */
1393: /* 4 date_info */
1394:
1395: int capa_check_date(int which,char *student_number, int section,int set)
1396: {
1397: int result;
1398: char date_str[TMP_LINE_LENGTH];
1399: time_t curtime;
1400:
1401: time(&curtime);
1402:
1403: result = capa_get_date(which,student_number,section,set,date_str);
1404: if ( result == 1 ) { result = compare_datetime(curtime,date_str); }
1405: return result;
1406: }
1407:
1408: time_t capa_convert_duration(char *duration)
1409: {
1410: int hour, minute;
1411: sscanf(duration,"%d:%d",&hour,&minute);
1412: return ((hour*60)+minute)*60;
1413: }
1414:
1415: void capa_get_due_date(char *date_str,T_dates *current,char *student_number,int set)
1416: {
1417: time_t duration=capa_convert_duration(current->duration);
1418: time_t duetime=0;
1419: time_t logintime;
1420: struct tm *due_time_tm;
1421: if ((duration > 0) && (student_number!=NULL)) {
1422: if (capa_get_login_time(student_number,set,&logintime)==1) {
1423: duetime=logintime+duration;
1424: due_time_tm=localtime(&duetime);
1425: sprintf(date_str,"%04d/%02d/%02d %02d:%02d",((due_time_tm->tm_year)+1900),
1426: due_time_tm->tm_mon+1,due_time_tm->tm_mday,due_time_tm->tm_hour,
1427: due_time_tm->tm_min);
1428: return;
1429: }
1430: }
1431: strncpy(date_str,current->due_date,DATE_BUFFER);
1432: }
1433:
1434: /* student_number can be NULL, if it isn't NULL it is used by get_due_date */
1435: /* to assign a due date based on the time the student first accessed the */
1436: /* set if duration is non-zero */
1437: int
1438: capa_get_date(int which,char *student_number,int section,int set,char *date_str)
1439: {
1440: T_dates *current;
1441: int result;
1442: result=capa_get_section_dates(section,set,¤t);
1443: if (result<0) return result;
1444: result=1;
1445: switch(which) {
1446: case CHECK_OPEN_DATE: strncpy(date_str,current->open_date,DATE_BUFFER); break;
1447: case CHECK_DUE_DATE: capa_get_due_date(date_str,current,student_number,set); break;
1448: case CHECK_ANS_DATE: strncpy(date_str,current->answer_date,DATE_BUFFER); break;
1449: default: strncpy(date_str,current->open_date,DATE_BUFFER); result=-4;break;
1450: }
1451: capa_mfree((char*)current);
1452: return result;
1453: }
1454:
1455: int
1456: capa_get_duration(char *student_number,int section,int set)
1457: {
1458: T_dates *current;
1459: int duration=0,result;
1460: result=capa_get_section_dates(section,set,¤t);
1461: if (result<0) return result;
1462: duration=capa_convert_duration(current->duration);
1463: capa_mfree((char*)current);
1464: return duration;
1465: }
1466:
1467: int
1468: capa_get_section_dates(int section,int set,T_dates** dates)
1469: {
1470: register int c;
1471: FILE *fp;
1472: int result = 0, done;
1473: int tmp_low, tmp_high, sec_mode;
1474: char filename[FILE_NAME_LENGTH], tmpline[TMP_LINE_LENGTH],
1475: default_line[TMP_LINE_LENGTH];
1476:
1477: sprintf(filename,"records/date%d.db",set);
1478: if( capa_access(filename, F_OK) != 0 ) { result = -2; } else {
1479: if ((fp=fopen(filename,"r")) == NULL) { result = -2; } else {
1480: done = 0; result = -3;
1481: /* first non-comment line is assumed to be the default line */
1482: c_gettype(fp); c_ignorewhite(fp); fgets(default_line,TMP_LINE_LENGTH-1,fp);
1483: do {
1484: c_ignorewhite(fp); c = getc(fp); ungetc(c,fp);
1485: if( c != EOF ) {
1486: sec_mode = c_getsec_range(fp,&tmp_low,&tmp_high);
1487: if( sec_mode > 0 ) { /* no error */
1488: c_ignorewhite(fp); fgets(tmpline,TMP_LINE_LENGTH-1,fp);
1489: if( sec_mode == 1 ) { /* form: sec date_info */
1490: if((result == -3) && (tmp_low == section)) {
1491: result=-4;
1492: *dates=add_date_info(tmp_low,tmp_low,tmpline);
1493: if ( *dates != NULL ) { done = 1; result = 1; }
1494: }
1495: } else { /* form : [low,high] date_info */
1496: if( (result == -3) && ((section>=tmp_low)&&(section<=tmp_high)) ) {
1497: result = -4;
1498: *dates=add_date_info(tmp_low,tmp_high,tmpline);
1499: if ( *dates != NULL ) { done = 1; result = 1; }
1500: }
1501: }
1502: } else { /* error in specify section date */
1503: while ( ((c = getc(fp)) != '\n') && ( c != EOF) ); /* skip to end of line */
1504: }
1505: } else { /* EOF encountered */
1506: done = 1;
1507: }
1508: } while (!done);
1509: /* need to deal with those sections not show up in the dateX.db file */
1510: if( result == -3 ) { /* section not in the dateX.db file, use default */
1511: result = -4;
1512: *dates=add_date_info(DATE_DEFAULTS,DATE_DEFAULTS,default_line);
1513: if ( *dates != NULL ) { result = 1; }
1514: }
1515: }
1516: fclose(fp);
1517: }
1518: return (result);
1519: }
1520:
1521: T_dates* add_date_info(int lowsec,int highsec, char *dateinfo)
1522: {
1523: T_dates *dates;
1524: int result;
1525: dates=(T_dates*)capa_malloc(sizeof(T_dates),1);
1526: result=sscanf(dateinfo,"%16c,%16c,%16c,%s %d,%d",dates->open_date,dates->due_date,
1527: dates->answer_date,dates->duration,&(dates->inhibit_response),
1528: &(dates->view_problems_after_due));
1529: if (result != 6) {
1530: capa_mfree((char*)dates);
1531: dates=NULL;
1532: } else {
1533: dates->section_start=lowsec;
1534: dates->section_end=highsec;
1535: dates->s_next=NULL;
1536: }
1537: return dates;
1538: }
1539: /*----------------------------------------------------------*/
1540: /* INPUT: set the X in dateX.db */
1541: /* dates a pointer to the dates pointer */
1542: /* ACTION: builds a linked list of T_dates containing */
1543: /* the login information */
1544: /* RETURN: <0 file error */
1545: /* >0 success (number of lines successfully */
1546: /* proccessed) */
1547: /*----------------------------------------------------------*/
1548: int capa_get_all_dates (int set,T_dates **dates)
1549: {
1550: T_dates *current;
1551: FILE *fp;
1552: int result = 0, done, tmp_low, tmp_high, sec_mode, c, num=0;
1553: char filename[FILE_NAME_LENGTH], tmpline[TMP_LINE_LENGTH];
1554:
1555: sprintf(filename,"records/date%d.db",set);
1556: if ( ((fp=fopen(filename,"r")) == NULL)) { result = -2; } else {
1557: done = 0; result = -3;
1558: /* first non-comment line is assumed to be the default line */
1559: c_gettype(fp); c_ignorewhite(fp); fgets(tmpline,TMP_LINE_LENGTH-1,fp);
1560: *dates=add_date_info(DATE_DEFAULTS,DATE_DEFAULTS,tmpline);
1561: num++;
1562: if ( NULL == (current=*dates) ) {
1563: result = -3;
1564: } else {
1565: while(1) {
1566: c_ignorewhite(fp); c = getc(fp); ungetc(c,fp);
1567: if( c == EOF ) { break; }
1568: sec_mode = c_getsec_range(fp,&tmp_low,&tmp_high);
1569: if( sec_mode > 0 ) { /* no error */
1570: c_ignorewhite(fp); fgets(tmpline,TMP_LINE_LENGTH-1,fp);
1571: if( sec_mode == 1 ) { /* form: sec date_info */
1572: current->s_next=add_date_info(tmp_low,tmp_low,tmpline);
1573: } else { /* form : [low,high] date_info */
1574: current->s_next=add_date_info(tmp_low,tmp_high,tmpline);
1575: }
1576: current=current->s_next;
1577: num++;
1578: } else { /* error in specify section date */
1579: while ( ((c = getc(fp)) != '\n') && ( c != EOF) ); /* skip to end of line */
1580: }
1581: }
1582: result=num;
1583: }
1584: fclose(fp);
1585: }
1586: return (result);
1587: }
1588:
1589: /*----------------------------------------------------------*/
1590: /* INPUT: dates a pointer to the dates pointer */
1591: /* ACTION: frees a linked list of T_dates */
1592: /*----------------------------------------------------------*/
1593: void free_dates(T_dates *dates)
1594: {
1595: T_dates *current = dates,*next;
1596: while ( current != NULL ) {
1597: next = current->s_next;
1598: capa_mfree((char*)current);
1599: current = next;
1600: }
1601: }
1602:
1603: /*----------------------------------------------------------*/
1604: /* INPUT: set the X in dateX.db */
1605: /* dates a pointer to the dates pointer */
1606: /* ACTION: takes a linked list of date information and */
1607: /* and writes the info to a file */
1608: /* RETURN: -1 file error */
1609: /* 1 success */
1610: /*----------------------------------------------------------*/
1611: int capa_set_all_dates (int set,T_dates *dates)
1612: {
1613: T_dates *current = dates;
1614: int result;
1615: FILE* fp;
1616: char filename[FILE_NAME_LENGTH];
1617:
1618: sprintf(filename,"records/date%d.db",set);
1619: if ( ((fp=fopen(filename,"w")) == NULL) ) { result = -1; } else {
1620: result=1;
1621: while ( current != NULL ) {
1622: if ( current->section_start == DATE_DEFAULTS ) {
1623: fprintf(fp,"<< DEFAULTS >> ");
1624: } else {
1625: fprintf(fp,"[%d, %d] ", current->section_start,current->section_end);
1626: }
1627: fprintf(fp,"%s,%s,%s,%s %d,%d\n", current->open_date,current->due_date,
1628: current->answer_date,current->duration,current->inhibit_response,
1629: current->view_problems_after_due);
1630: current = current->s_next;
1631: }
1632: fclose(fp);
1633: }
1634: return result;
1635: }
1636:
1637: /*----------------------------------------------------------*/
1638: /* INPUT: set the X in logX.db */
1639: /* OUTPUT: none */
1640: /* */
1641: /* RETURN: -1 file error */
1642: /* 0 no login */
1643: /* >0 number of logins in that logX.db file */
1644: /*----------------------------------------------------------*/
1645:
1646: #define FIFTEEN_MINUTES (15*60)
1647: #define TEN_MINUTES (600)
1648: #define ONE_DAY (86400)
1649: int /* RETURNS: 1 first time login, 2 second time login, 0 not ok, -1 file error */
1650: login_check(student_number) /* ARGUMENTS: */
1651: char *student_number; /* Student # */
1652: { /* LOCALS: */
1653: FILE *fp;
1654:
1655: int errcode=0;
1656: int found;
1657: char filename[FILE_NAME_LENGTH];
1658: char line[SMALL_LINE_BUFFER], new_line[SMALL_LINE_BUFFER];
1659: struct tm *theDT;
1660: time_t login_time, record_time;
1661: long offsetL, offsetR, offsetEnd,left_leng;
1662: char s_number[MAX_STUDENT_NUMBER+1];
1663: char tty_name[FILE_NAME_LENGTH];
1664: int log_tries, p_id;
1665: int month, day, year, hour, min, sec;
1666: char *tmp_buffer;
1667:
1668: sprintf(filename,"records/active.log");
1669:
1670: if( capa_access(filename,F_OK) < 0 ) { /*<------------- File not exist */
1671: if ((fp=fopen(filename,"w"))==NULL) { /* create if non-existant */
1672: /*printf("Error: can't create %s\n",filename);*/
1673: return (-1);
1674: }
1675: fclose(fp);
1676: }
1677: if ((fp=fopen(filename,"r"))==NULL) {
1678: /*printf("Error: can't open %s\n",filename);*/
1679: return (-1);
1680: }
1681: flockstream(fp); /* lock exclusively and perform read/write operation */
1682:
1683: found = 0;
1684: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
1685: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
1686: }
1687: offsetR = ftell(fp);
1688: offsetL = offsetR - strlen(line);
1689: funlockstream(fp); fclose(fp);
1690:
1691: if( found && (strlen(line) != 0) ) {
1692: /* printf("FOUND:%slen=%d\n",line,strlen(line)); */
1693: sscanf(line,"%s , %d , %d , /dev/%s ,(%d/%d/%d %d:%d:%d)\n", s_number,&log_tries,&p_id,tty_name,&month,&day,&year,&hour,&min,&sec);
1694: record_time = time(NULL);
1695: theDT = localtime(&record_time);
1696: theDT->tm_sec = sec; theDT->tm_min = min;
1697: theDT->tm_hour = hour; theDT->tm_mday = day;
1698: theDT->tm_mon = month-1; theDT->tm_year = year;
1699: theDT->tm_wday = weekday(year,month,day);
1700: theDT->tm_yday = julianday(year,month,day);
1701: record_time = mktime( theDT );
1702: time(&login_time); theDT = localtime(&login_time);
1703: switch(log_tries) {
1704: case 0: log_tries = 1; errcode = 1; break;
1705: case 1: log_tries = 2; errcode = 2;
1706: break;
1707: case 2: log_tries = 3; errcode = 0; break;
1708: case 3: if( (login_time - record_time) >= TEN_MINUTES ) {
1709: log_tries = 1; errcode = 1;
1710: } else {
1711: log_tries = 3; errcode = 2;
1712: return (0);
1713: }
1714: break;
1715: default: printf("ERROR: Number of logins UNKNOWN\n");
1716: log_tries = 1; errcode = 1;
1717: break;
1718: }
1719: sprintf(new_line,"%s , %2d , %5d , %s ,(%02d/%02d/%02d %02d:%02d:%02d)\n", student_number, log_tries, getpid(),ttyname(0), theDT->tm_mon + 1, theDT->tm_mday, theDT->tm_year, theDT->tm_hour, theDT->tm_min ,theDT->tm_sec);
1720: if ((fp=fopen(filename,"r+"))==NULL) {
1721: /*printf("Error: can't open %s\n",filename);*/
1722: return (-1);
1723: }
1724: flockstream(fp);
1725: tmp_buffer = (char *)malloc(8*1024*56);
1726: found = 0;
1727: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
1728: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
1729: }
1730: offsetR = ftell(fp); offsetL = offsetR - strlen(line);
1731: fseek(fp,0L,SEEK_END); offsetEnd = ftell(fp);
1732: left_leng = offsetEnd - offsetR;
1733: fseek(fp,offsetR,SEEK_SET);
1734: left_leng = fread(tmp_buffer, 1, left_leng+1, fp);
1735: tmp_buffer[left_leng] = 0;
1736: fseek(fp,offsetL,SEEK_SET);
1737: if ( fprintf(fp,"%s%s",new_line,tmp_buffer) < 0 ) {
1738: /*printf("Error: cannot write active.log\n");*/
1739: errcode = -1;
1740: }
1741: fflush(fp);
1742: free( (char *)tmp_buffer);
1743: funlockstream(fp);
1744: fclose(fp);
1745: } else { /********************************** First time login */
1746: if ((fp=fopen(filename,"a+"))==NULL) {
1747: /*printf("Error: can't open %s\n",filename);*/
1748: return (-1);
1749: }
1750: log_tries = 1;
1751: time(&login_time);
1752: theDT = localtime(&login_time);
1753: sprintf(line,"%s , %2d , %5d , %s ,(%02d/%02d/%02d %02d:%02d:%02d)\n", student_number, log_tries, getpid(),ttyname(0), theDT->tm_mon + 1, theDT->tm_mday, theDT->tm_year, theDT->tm_hour, theDT->tm_min ,theDT->tm_sec);
1754: /*
1755: leng = strlen(line);
1756: for(idx = 0, len_idx = 0; idx<(leng-1); idx++) {
1757: if(line[idx] == '\n' && line[idx+1] == '\n') {
1758: line[idx+1] = 0;
1759: }
1760: }
1761: */
1762: flockstream(fp);
1763: if ( !fwrite((char *)line, strlen(line), 1, fp) ) {
1764: /*printf("ERROR: cannot write active.log\n");*/
1765: errcode = -1;
1766: } else {
1767: errcode = 1;
1768: }
1769: fflush(fp);
1770: funlockstream(fp);
1771: fclose(fp);
1772: }
1773: return (errcode);
1774:
1775: }
1776:
1777: /******************************************************************************/
1778: /* Logout check */
1779: /******************************************************************************/
1780: int /* RETURNS: 1 successful, 0 otherwise, -1 file error */
1781: logout_check(student_number) /* ARGUMENTS: */
1782: char *student_number; /* Student # */
1783: { /* LOCALS: */
1784: FILE *fp;
1785:
1786: int errcode=0;
1787: int found;
1788: char filename[FILE_NAME_LENGTH];
1789: char line[SMALL_LINE_BUFFER];
1790: long offsetL, offsetR, offsetEnd,left_leng;
1791: char s_number[MAX_STUDENT_NUMBER+1];
1792: char tty_name[FILE_NAME_LENGTH];
1793: int log_tries, p_id;
1794: int month, day, year, hour, min, sec;
1795: char *tmp_buffer;
1796:
1797:
1798: sprintf(filename,"records/active.log");
1799: if ((fp=fopen(filename,"r"))==NULL) {
1800: /*printf("Error: can't open %s\n",filename);*/
1801: return (-1);
1802: }
1803: flockstream(fp); /* lock exclusively and perform read/write operation */
1804:
1805: found = 0;
1806: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
1807: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
1808: }
1809: offsetR = ftell(fp);
1810: offsetL = offsetR - strlen(line);
1811:
1812: funlockstream(fp);
1813: fclose(fp);
1814:
1815: if( found ) {
1816: #ifdef __alpha
1817: sscanf(line,"%s , %d , %d , /dev/%s ,(%d/%d/%d %d:%d:%d)\n", s_number,&log_tries,&p_id,tty_name,&month,&day,&year,&hour,&min,&sec);
1818: #else
1819: sscanf(line,"%s , %d , %d , /dev/%s ,(%d/%d/%d %d:%d:%d)\n", \
1820: s_number,&log_tries,&p_id,tty_name,&month,&day,&year,&hour,&min,&sec);
1821: #endif
1822: switch(log_tries) {
1823: case 0: log_tries = 0;
1824: break;
1825: case 1: log_tries = 0;
1826: break;
1827: case 2: log_tries = 0;
1828: break;
1829: default: printf("ERROR: Number of logins UNKNOWN\n");
1830: log_tries = 0;
1831: break;
1832: }
1833: #ifdef __alpha
1834: sprintf(line,"%s , %2d , %5d , /dev/%s ,(%02d/%02d/%02d %02d:%02d:%02d)\n", s_number,log_tries, p_id, tty_name, month, day, year, hour, min, sec);
1835: #else
1836: sprintf(line,"%s , %2d , %5d , /dev/%s ,(%02d/%02d/%02d %02d:%02d:%02d)\n", \
1837: s_number,log_tries, p_id, tty_name, month, day, year, hour, min, sec);
1838: #endif
1839:
1840: if ((fp=fopen(filename,"r+"))==NULL) {
1841: /*printf("Error: can't open %s\n",filename);*/
1842: return (-1);
1843: }
1844: flockstream(fp);
1845: tmp_buffer = (char *)malloc(8*1024*56);
1846: fseek(fp,0L,SEEK_END);
1847: offsetEnd = ftell(fp);
1848: left_leng = offsetEnd - offsetR;
1849: fseek(fp,offsetR,SEEK_SET);
1850: fread(tmp_buffer, left_leng, 1, fp);
1851: tmp_buffer[left_leng] = 0;
1852: /*
1853: for(idx=0, l_idx = 0; idx< (left_leng-1); idx++) {
1854: if( tmp_buffer[idx] == '/n' && tmp_buffer[idx+1] == '/n' ) {
1855: }
1856: }
1857: */
1858: fseek(fp,offsetL,SEEK_SET);
1859: if ( fprintf(fp,"%s%s",line,tmp_buffer) < 0 ) {
1860: /*printf("Error: write error\n");*/
1861: errcode = -1;
1862: } else {
1863: errcode = 1;
1864: }
1865: fflush(fp);
1866: free( (char *)tmp_buffer);
1867: funlockstream(fp);
1868: fclose(fp);
1869: } else {
1870: errcode = -1;
1871: }
1872: return (errcode);
1873:
1874: }
1875: /*********************************************/
1876: /* SIZE of char =1, int=4, long=4, double=8 */
1877: void
1878: capa_seed(seed1,seed2,student_number)long *seed1;long *seed2;char *student_number;
1879: {
1880: int class_pin1, class_pin2;
1881: int s_pin1, s_pin2, s_pin3;
1882: int i;
1883: char dest[16], tmpSN[MAX_STUDENT_NUMBER+1];
1884: char *class,*capadefault="capadefault";
1885: long part1, part2;
1886: #if defined(NeXT)
1887: char cwd[FILE_NAME_LENGTH];
1888: #endif
1889: int big_endian;
1890:
1891: big_endian = endian(); /* determine what type of CPU we are on */
1892:
1893: #if defined(NeXT)
1894: class = getwd(cwd);
1895: if( class == NULL ) { class = cwd; }
1896: #else
1897: class = getcwd(NULL,255);
1898: #endif
1899: class_pin1 = class_pin2 = 2;
1900: s_pin1 = s_pin2 = s_pin3 = 2;
1901:
1902: if( class == NULL ) {
1903: printf("capa_seed(): Current working directory unknown! Using capadefault\n");
1904: class=capa_malloc(strlen(capadefault)+1,1);
1905: strcpy(class,capadefault);
1906: }
1907: if( big_endian ) {
1908: for(i=0;i<4;i++) dest[i] = class[strlen(class)-8+i];
1909: for(i=4;i<8;i++) dest[i] = 0;
1910: memcpy((char *)(&class_pin1), dest, 4);
1911: for(i=0;i<4;i++) dest[i] = class[strlen(class)-4+i];
1912: for(i=4;i<8;i++) dest[i] = 0;
1913: memcpy((char *)(&class_pin2), dest, 4);
1914: } else {
1915: for(i=0;i<4;i++) dest[i] = class[strlen(class)-i-5];
1916: for(i=4;i<8;i++) dest[i] = 0;
1917: memcpy((char *)(&class_pin1), dest, 4);
1918: for(i=0;i<4;i++) dest[i] = class[strlen(class)-i-1];
1919: for(i=4;i<8;i++) dest[i] = 0;
1920: memcpy((char *)(&class_pin2), dest, 4);
1921: }
1922: for(i=0;i<MAX_STUDENT_NUMBER;i++) {
1923: if(islower(student_number[i])) {
1924: tmpSN[i] = toupper(student_number[i]);
1925: } else {
1926: tmpSN[i] = student_number[i];
1927: }
1928: }
1929: tmpSN[MAX_STUDENT_NUMBER] = 0;
1930:
1931: if( big_endian ) { /* big endian ** SUN, BlackNeXT 68xxx , PowerPC */
1932: for(i=0;i<4;i++) dest[i] = tmpSN[i];
1933: for(i=4;i<8;i++) dest[i] = 0;
1934: memcpy((char *)(&s_pin1), dest, 4); /* 012345678 -> "0123" */
1935: for(i=0;i<4;i++) dest[i] = tmpSN[i+2];
1936: for(i=4;i<8;i++) dest[i] = 0;
1937: memcpy((char *)(&s_pin2), dest, 4); /* 012345678 -> "2345" */
1938: for(i=0;i<4;i++) dest[i] = tmpSN[i+5];
1939: for(i=4;i<8;i++) dest[i] = 0;
1940: memcpy((char *)(&s_pin3), dest, 4); /* 012345678 -> "5678" */
1941: } else { /* Intel 386, 486 */
1942: for(i=0;i<4;i++) dest[i] = tmpSN[3-i];
1943: for(i=4;i<8;i++) dest[i] = 0;
1944: memcpy((char *)(&s_pin1), dest, 4); /* 012345678 -> "0123" */
1945: for(i=0;i<4;i++) dest[i] = tmpSN[5-i];
1946: for(i=4;i<8;i++) dest[i] = 0;
1947: memcpy((char *)(&s_pin2), dest, 4); /* 012345678 -> "2345" */
1948: for(i=0;i<4;i++) dest[i] = tmpSN[8-i];
1949: for(i=4;i<8;i++) dest[i] = 0;
1950: memcpy((char *)(&s_pin3), dest, 4); /* 012345678 -> "5678" */
1951: }
1952:
1953:
1954: part1 = s_pin1 + s_pin3+ class_pin2; if(part1 < 0) part1 = part1 * (-1);
1955: part2 = s_pin2 + class_pin1; if(part2 < 0) part2 = part2 * (-1);
1956:
1957: #ifdef SEED_DBG
1958: printf("S_PIN(%d,%d, %d) C_PIN(%d,%d)\n",s_pin1, s_pin2, s_pin3, class_pin1, class_pin2);
1959: printf("SEED(%ld,%ld)\n",part1, part2);
1960: #endif
1961: {
1962: extern void gsrgs(long getset,long *qvalue);
1963: static long qrgnin;
1964: gsrgs(0L,&qrgnin);
1965: if(!qrgnin)
1966: setall(part1, part2);
1967: }
1968: (*seed1) = part1;
1969: (*seed2) = part2;
1970: free(class);
1971: }
1972: /* ======================================================= PIN number */
1973: /* pin should only called once for each student. */
1974: /* if not called at the beginning of problem set, try to call it automatically */
1975:
1976: int /* RETURNS: pin number for login set */
1977: capa_PIN(student_number, set, guess) /* ARGUMENTS: */
1978: char *student_number;
1979: int set; /* Problem set number */
1980: int guess;
1981: { /* LOCALS: */
1982: int current=0, /* Current pin for set */
1983: i,j, /* Array indices */
1984: nope,
1985: correct=0,
1986: all_pins[ONE_K];
1987: long part1, part2;
1988: long orig_gen, new_gen;
1989:
1990: capa_seed(&part1, &part2, student_number);
1991: gscgn(GET_GENERATOR, &orig_gen);
1992: new_gen = PIN_G;
1993: gscgn(SET_GENERATOR, &new_gen);
1994: setsd(part1, part2);
1995: /* Generate 4-digit pin (1000-9999) */
1996: for (i=1; i<=set; i++) {
1997: current=1000+ignlgi()%9000;
1998: do {
1999: nope=0;
2000: for (j=1; j<i; j++) {
2001: if (current == all_pins[j]) {
2002: current=1000+ignlgi()%9000;
2003: nope++;
2004: }
2005: }
2006: } while (nope);
2007: all_pins[i]=current;
2008: if (guess && guess==current) correct=i;
2009: }
2010: gscgn(SET_GENERATOR, &orig_gen);
2011: if (guess) return (correct);
2012: return (current);
2013: }
2014:
2015: /* -------------------------------------------------------------------- */
2016: /* returns a longer pin, the first four characters are the same as the */
2017: /* normal capaId, additionally the result is a capa_malloc string */
2018: /* containing the number */
2019: /* NOTE!-> the result is a string of letters where A=1..I=9,J=0 */
2020: /* -------------------------------------------------------------------- */
2021: char*
2022: capa_id_plus(student_number, set, plus)
2023: char *student_number;
2024: int set;
2025: int plus;
2026: {
2027: long part1,part2,orig_gen,new_gen,pin,rout,k,i;
2028: char *result;
2029: char letters[10]={'J','A','B','C','D','E','F','G','H','I'};
2030: capa_seed(&part1, &part2, student_number);
2031: gscgn(GET_GENERATOR, &orig_gen);
2032: new_gen = PIN_G;
2033: gscgn(SET_GENERATOR, &new_gen);
2034: setsd(part1, part2);
2035: pin=capa_PIN(student_number,set,0);
2036: result=(char *)capa_malloc(sizeof(char), plus+MAX_PIN_CHAR+1);
2037: k=1;
2038: for(i=1;i<=MAX_PIN_CHAR;i++) {
2039: result[MAX_PIN_CHAR-i] = letters[(pin%(k*10))/k];
2040: k*=10;
2041: }
2042: for(i=MAX_PIN_CHAR;i<MAX_PIN_CHAR+plus;i++) {
2043: rout = ignlgi()%10;
2044: result[i] = letters[rout];
2045: }
2046: result[i] = '\0';
2047: gscgn(SET_GENERATOR, &orig_gen);
2048: return result;
2049: }
2050: /* -------------------------------------------------------------------- */
2051: /* need to set problem_p = NULL after this call */
2052: /* -------------------------------------------------------------------- */
2053: void
2054: free_problems(problem_p) Problem_t *problem_p;
2055: {
2056: Problem_t *p, *next;
2057:
2058: for (p=problem_p; p!=NULL ; p=next) {
2059: next=p->next;
2060: if (p->question != NULL) capa_mfree(p->question);
2061: if (p->answer != NULL) capa_mfree(p->answer);
2062: if (p->ans_cnt > 1 ) { AnswerInfo_t *a,*b;
2063: for(a = p->ans_list; a != NULL ; a = b) {
2064: b = a->ans_next;
2065: if (a->ans_str != NULL) capa_mfree(a->ans_str);
2066: if (a->ans_id_list != NULL ) capa_mfree(a->ans_id_list);
2067: if (a->ans_pts_list) {
2068: free_ptslist(a->ans_pts_list);
2069: }
2070: if (a->ans_unit) {
2071: freelist_unit_e(a->ans_unit->u_list);
2072: if (a->ans_unit != NULL) capa_mfree((char *)a->ans_unit);
2073: }
2074: capa_mfree((char *)a);
2075: }
2076: }
2077: if (p->id_list != NULL ) capa_mfree(p->id_list);
2078: if (p->pts_list!= NULL ) {
2079: free_ptslist(p->pts_list);
2080: }
2081: if (p->hint != NULL ) capa_mfree(p->hint);
2082: if (p->explain != NULL ) capa_mfree(p->explain);
2083: if (p->ans_unit !=NULL ) {
2084: freelist_unit_e(p->ans_unit->u_list);
2085: capa_mfree((char *)p->ans_unit);
2086: }
2087: capa_mfree((char *)p);
2088: p=NULL;
2089: }
2090: problem_p=NULL;
2091: }
2092:
2093: /******************************************************************************/
2094: /* PARSE SOURCE FILE AND RETURN BLOCKS OF TEXT */
2095: /******************************************************************************/
2096: int
2097: capa_parse(set,problem,student_number,num_questions,func_ptr)
2098: int set;Problem_t **problem;char *student_number;int *num_questions;
2099: void (*func_ptr)();
2100: {
2101: char filename[QUARTER_K];
2102: int errcode;
2103: FILE *fp;
2104: extern FILE *Input_stream[MAX_OPENED_FILE];
2105: extern char Opened_filename[MAX_OPENED_FILE][QUARTER_K];
2106: extern int Lexi_line;
2107: extern int Lexi_qnum;
2108: extern Problem_t *FirstProblem_p;
2109: extern Problem_t *LastProblem_p;
2110: extern Problem_t *LexiProblem_p;
2111: extern char *StartText_p;
2112: extern char *EndText_p;
2113: extern char *ErrorMsg_p;
2114: extern int ErrorMsg_count;
2115: extern char Parse_class[QUARTER_K];
2116: extern int Parse_section;
2117: extern int Parse_set;
2118: extern char Parse_name[MAX_NAME_CHAR+1];
2119: extern char Parse_student_number[MAX_STUDENT_NUMBER+1];
2120: extern int Symb_count;
2121: extern int first_run;
2122: extern int Stop_Parser;
2123: extern void (*Status_Func)();
2124: long seed1, seed2;
2125: T_student a_student;
2126: char *class, *classname, warn_msg[WARN_MSG_LENGTH];
2127: #if defined(NeXT)
2128: char cwd[FILE_NAME_LENGTH];
2129:
2130: class = getwd(cwd);
2131: if( class == NULL ) { class = cwd; }
2132: #else
2133: class = getcwd(NULL,255);
2134:
2135: #endif
2136:
2137: if(class == NULL) { /* printf("capa_parse(): Current working directory unknown!"); */ return (-1); }
2138: classname = rindex(class,'/'); classname++; /*** hpux complained */
2139: sprintf(Parse_class,"%s", classname);
2140: free(class);
2141: if( capa_get_student(student_number, &a_student) < 1 ) {
2142: /*printf("Error: capa_parse() encountered a student which is not in classl file\n"); */
2143: return (-1);
2144: }
2145: sprintf(filename,"capa.config");
2146: if ((fp=fopen(filename,"r"))==NULL) {
2147: /* printf("Error: can't open %s\n",filename);*/
2148: return (-1);
2149: }
2150: u_getunit(fp);
2151: fclose(fp);
2152: strncpy(Parse_name,a_student.s_nm,MAX_NAME_CHAR+1);
2153: strncpy(Parse_student_number,student_number,MAX_STUDENT_NUMBER+1);
2154: Parse_section = a_student.s_sec;
2155: if(ErrorMsg_p) { capa_mfree(ErrorMsg_p); ErrorMsg_p = NULL; }
2156: if(EndText_p) { capa_mfree(EndText_p); EndText_p = NULL; }
2157: if(StartText_p) { capa_mfree(StartText_p); StartText_p = NULL; }
2158: ErrorMsg_p = NULL; first_run = 1; EndText_p = NULL;
2159: free_symtree(); Symb_count = ErrorMsg_count = Lexi_line = Lexi_qnum = 0;
2160: FirstProblem_p = LastProblem_p = NULL;
2161: LexiProblem_p = (Problem_t *)capa_malloc(sizeof(Problem_t),1);
2162: problem_default(LexiProblem_p);
2163: /*LexiProblem_p->capaidplus=NULL;*/
2164: Parse_set = set;
2165: Status_Func=func_ptr;
2166: sprintf(filename,"set%d.qz",set);
2167: #ifdef AVOIDYYINPUT
2168: yyin=fopen(filename,"r");
2169: #else
2170: if ( (Input_stream[0]=fopen(filename,"r")) == NULL) {
2171: /* printf("Error: can't open %s\n",filename);*/
2172: sprintf(warn_msg,"capa_parse(): CANNOT OPEN FILE\"%s\", file does not exist or is not readable.\n", filename);
2173: capa_msg(MESSAGE_ERROR,warn_msg);
2174: return (-1);
2175: }
2176: #endif
2177: sprintf(Opened_filename[0],"%s",filename);
2178:
2179: capa_seed(&seed1, &seed2, student_number); setall(seed1,seed2);
2180:
2181: yyrestart(yyin);
2182: Stop_Parser=0;
2183: if ( !yyparse() ) { errcode = Lexi_qnum; } else { errcode = 0; }
2184: /* fclose(Input_stream[0]);*/ /* The Lexer handles closing this */
2185: /* print_symb_stat(); */
2186: free_symtree();
2187: /*
2188: capa_mfree((char *)LexiProblem_p);
2189: LexiProblem_p = NULL;
2190: */
2191: (*problem) = FirstProblem_p;
2192: (*num_questions) = Lexi_qnum;
2193: return (errcode);
2194: }
2195:
2196: /******************************************************************************/
2197: /* PARSE SOURCE FILE AND RETURN BLOCKS OF TEXT, unlike capa_parse_student */
2198: /******************************************************************************/
2199: int
2200: capa_parse_student(set,problem,a_student,num_questions,func_ptr)
2201: int set;Problem_t **problem;T_student *a_student;int *num_questions;
2202: void (*func_ptr)();
2203: {
2204: char filename[QUARTER_K];
2205: int errcode;
2206: FILE *fp;
2207: extern FILE *Input_stream[MAX_OPENED_FILE];
2208: extern char Opened_filename[MAX_OPENED_FILE][QUARTER_K];
2209: extern int Lexi_line;
2210: extern int Lexi_qnum;
2211: extern Problem_t *FirstProblem_p;
2212: extern Problem_t *LastProblem_p;
2213: extern Problem_t *LexiProblem_p;
2214: extern char *StartText_p;
2215: extern char *EndText_p;
2216: extern char *ErrorMsg_p;
2217: extern int ErrorMsg_count;
2218: extern char Parse_class[QUARTER_K];
2219: extern int Parse_section;
2220: extern int Parse_set;
2221: extern char Parse_name[MAX_NAME_CHAR+1];
2222: extern char Parse_student_number[MAX_STUDENT_NUMBER+1];
2223: extern int Symb_count;
2224: extern int first_run;
2225: extern void (*Status_Func)();
2226: long seed1, seed2;
2227: char *class, *classname, warn_msg[WARN_MSG_LENGTH];
2228:
2229: #if defined(NeXT)
2230: char cwd[FILE_NAME_LENGTH];
2231:
2232: class = getwd(cwd);
2233: if( class == NULL ) { class = cwd; }
2234: #else
2235: class = getcwd(NULL,255);
2236:
2237: #endif
2238:
2239: if(class == NULL) { /* printf("capa_parse(): Current working directory unknown!"); */ return (-1); }
2240: classname = rindex(class,'/'); classname++; /*** hpux complained */
2241: sprintf(Parse_class,"%s", classname);
2242: free(class);
2243:
2244: sprintf(filename,"capa.config");
2245: if ((fp=fopen(filename,"r"))==NULL) {
2246: /* printf("Error: can't open %s\n",filename);*/
2247: sprintf(warn_msg,"capa_parse(): CANNOT OPEN FILE\"%s\", file does not exist or is not readable.\n", filename);
2248: capa_msg(MESSAGE_ERROR,warn_msg);
2249: return (-1);
2250: }
2251: u_getunit(fp);
2252: fclose(fp);
2253: strncpy(Parse_name,a_student->s_nm,MAX_NAME_CHAR+1);
2254: strncpy(Parse_student_number,a_student->s_sn,MAX_STUDENT_NUMBER+1);
2255: Parse_section = a_student->s_sec;
2256: if(ErrorMsg_p) { capa_mfree(ErrorMsg_p); ErrorMsg_p = NULL; }
2257: if(EndText_p) { capa_mfree(EndText_p); EndText_p = NULL; }
2258: if(StartText_p) { capa_mfree(StartText_p); StartText_p = NULL; }
2259: ErrorMsg_p = NULL; first_run = 1; EndText_p = NULL;
2260: free_symtree(); Symb_count = ErrorMsg_count = Lexi_line = Lexi_qnum = 0;
2261: FirstProblem_p = LastProblem_p = NULL;
2262: LexiProblem_p = (Problem_t *)capa_malloc(sizeof(Problem_t),1);
2263: problem_default(LexiProblem_p);
2264: /*LexiProblem_p->capaidplus=NULL;*/
2265: Parse_set = set;
2266: Status_Func=func_ptr;
2267: sprintf(filename,"set%d.qz",set);
2268: #ifdef AVOIDYYINPUT
2269: yyin=fopen(filename,"r");
2270: #else
2271: if ( (Input_stream[0]=fopen(filename,"r")) == NULL) {
2272: /* printf("Error: can't open %s\n",filename);*/
2273: sprintf(warn_msg,"capa_parse(): CANNOT OPEN FILE\"%s\", file does not exist or is not readable.\n", filename);
2274: capa_msg(MESSAGE_ERROR,warn_msg);
2275: return (-1);
2276: }
2277: #endif
2278: sprintf(Opened_filename[0],"%s",filename);
2279:
2280: capa_seed(&seed1, &seed2, a_student->s_sn); setall(seed1,seed2);
2281:
2282: yyrestart(yyin);
2283: if ( !yyparse() ) { errcode = Lexi_qnum; } else { errcode = 0; }
2284: /* fclose(Input_stream[0]);*/ /*The Lexer handles closing this*/
2285: /* print_symb_stat(); */
2286: free_symtree();
2287: /*
2288: capa_mfree((char *)LexiProblem_p);
2289: LexiProblem_p = NULL;
2290: */
2291: (*problem) = FirstProblem_p;
2292: (*num_questions) = Lexi_qnum;
2293: return (errcode);
2294: }
2295:
2296: /* =================================================================== */
2297: /* A utility method to convert a date string and time string to time_t */
2298: /* dateStr: yyyy/mm/dd */
2299: /* timeStr: hh:mm */
2300: time_t
2301: convertTime(dateStr,timeStr)char *dateStr; char *timeStr;
2302: {
2303: struct tm *theTimeData;
2304: time_t result;
2305: int dateTime[5];
2306: int year, month, day, mm, hh;
2307:
2308: sscanf(dateStr,"%4d/%2d/%2d",&year,&month,&day);
2309: dateTime[0] = month;
2310: dateTime[1] = day;
2311: dateTime[2] = year;
2312: sscanf(timeStr,"%2d:%2d",&hh,&mm);
2313: dateTime[3] = hh;
2314: dateTime[4] = mm;
2315: result = time(NULL);
2316: theTimeData = localtime(&result);
2317: theTimeData->tm_sec = 0;
2318: theTimeData->tm_min = dateTime[4];
2319: theTimeData->tm_hour = dateTime[3];
2320: theTimeData->tm_mday = dateTime[1];
2321: theTimeData->tm_mon = dateTime[0]-1;
2322: theTimeData->tm_year = dateTime[2]-1900;/* tm_year is years since 1900 */
2323: /* these fields are ignored by mktime
2324: theTimeData->tm_wday = weekday(year,month,day);
2325: theTimeData->tm_yday = julianday(year,month,day);
2326: */
2327: result = mktime( theTimeData );
2328: return (result);
2329: }
2330:
2331: int
2332: weekday( year, month, day) int year; int month; int day;
2333: {
2334: register int dow;
2335: #if defined(hpux)
2336: int juldays[13];
2337: juldays[0]=0;juldays[1]=0;juldays[2]=31;juldays[3]=59;
2338: juldays[4]=90;juldays[5]=120;juldays[6]=151;juldays[7]=181;
2339: juldays[8]=212;juldays[9]=243;juldays[10]=273;juldays[11]=304;juldays[12]=334;
2340: #else
2341: int juldays[13] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
2342: #endif
2343:
2344: dow = 7 + year + year/4 - year/100 + year/400 + juldays[month] + day;
2345: if( (month < 3) && ( leap_year(year) ) ) dow--;
2346: dow %= 7;
2347: return (dow);
2348: } /* weekday */
2349:
2350: int
2351: julianday( year, month, day)int year;int month;int day;
2352: {
2353: register int doy;
2354: #if defined(hpux)
2355: int juldays[13];
2356: juldays[0]=0;juldays[1]=0;juldays[2]=31;juldays[3]=59;
2357: juldays[4]=90;juldays[5]=120;juldays[6]=151;juldays[7]=181;
2358: juldays[8]=212;juldays[9]=243;juldays[10]=273;juldays[11]=304;juldays[12]=334;
2359: #else
2360: int juldays[13] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
2361: #endif
2362:
2363: doy = juldays[month];
2364: if((month > 2) && (leap_year(year)) ) doy++;
2365: doy += day;
2366: return (doy);
2367: } /* julianday */
2368:
2369: int
2370: check_int( an_int ) char *an_int;
2371: {
2372: int ii, leng;
2373: int result=0;
2374:
2375: if( (an_int[0] == '-') || (an_int[0]== '+') ) an_int++;
2376: leng = strlen(an_int);
2377: for(ii=0;ii<leng;ii++) {
2378: if( !isdigit(an_int[ii]) ) result = 1;
2379: }
2380: return (result);
2381: }
2382: /* --------------------------- */
2383: /* 0 OK , 1 NOT a real number */
2384: int
2385: check_real( a_real ) char *a_real;
2386: {
2387: int ii, leng;
2388: int result=0;
2389:
2390: if( (a_real[0] == '-') || (a_real[0]== '+') ) a_real++;
2391: leng = strlen(a_real);
2392: for(ii=0;ii<leng;ii++) {
2393: if( (!isdigit(a_real[ii])) && (a_real[ii]!='e') && (a_real[ii]!='E') &&
2394: (a_real[ii]!='.') && (a_real[ii]!='+') && (a_real[ii]!='-') ) result = 1;
2395: }
2396: return (result);
2397: }
2398:
2399: int
2400: check_input_usymb(u_symb)char *u_symb;
2401: {
2402: int result=0;
2403:
2404:
2405: return (result);
2406: }
2407:
2408: /* <== This routine determine emperically where to split a character */
2409: /* string into two portions, one for numerical answer and the */
2410: /* other for units */
2411: /* ----------------------------------------------------------------- */
2412: /* inputs : buf : answer string */
2413: /* outputs: num : the numerical part */
2414: /* num_p : the numerical part in string */
2415: /* unit_p : the unit string */
2416: /* num_p is used to calculate sig figs */
2417: /* return : 0 empty string */
2418: /* 1 number without units */
2419: /* 2 empty number with units */
2420: /* 3 number with units */
2421: /* */
2422: int split_num_unit(buf,num,num_p,unit_p)
2423: char *buf;double *num; char *num_p; char *unit_p;
2424: {
2425: char num_str[ANSWER_STRING_LENG], unit_str[ANSWER_STRING_LENG];
2426: char base_str[ANSWER_STRING_LENG], exp_str[ANSWER_STRING_LENG];
2427: int idx=0, errcode=0;
2428: int len, ii, n_idx=0, b_idx=0, e_idx=0, u_idx=0;
2429: double n_part, x_part, b_part, e_part, result;
2430:
2431: unit_str[0]=0; /* initialize unit_str[] */
2432: len = strlen(buf);
2433: while( isspace(buf[idx]) ) { idx++; } /* ignore white spaces */
2434: num_str[n_idx]=0; /* initialize number string */
2435: if( buf[idx] == '+' || buf[idx] == '-' ) {
2436: /* the first char is either '+' or '-' */
2437: num_str[n_idx++]= buf[idx++];
2438: }
2439: /* skip over alphabet char and those that are not '.' */
2440: while( (!isdigit( buf[idx] )) && buf[idx] != '.' ) { idx++; }
2441: while( isdigit( buf[idx] ) || buf[idx] == '.' ) { /* collect decimal numbers */
2442: num_str[n_idx++]= buf[idx++];
2443: }
2444: num_str[n_idx] = 0; /* end the string with a '\0' */
2445: sprintf(num_p,"%s",num_str); /* put the collected numerical string in num_p */
2446: /* skip over white spaces */
2447: while( isspace(buf[idx]) ) { idx++; }
2448: if( buf[idx] == 'e' || buf[idx] == 'E' ) { /* optional e or E part */
2449: /* peek further one char to see if it belongs to one of the following */
2450: if( buf[idx+1] == '-' || buf[idx+1] == '+' || isspace(buf[idx+1]) || isdigit(buf[idx+1])) {
2451: num_str[n_idx++] = buf[idx++]; /* should be 'e' or 'E' */
2452: while( isspace(buf[idx]) ) { idx++; } /* skip over spaces */
2453: num_str[n_idx++] = buf[idx++]; /* the second char '-', '+' or digit */
2454: while( isdigit(buf[idx]) ) { /* only integer is allowed, not '.' */
2455: num_str[n_idx++] = buf[idx++];
2456: }
2457: }
2458: num_str[n_idx] = 0; /* terminiate the numerical string */
2459: while( isspace(buf[idx]) ) { idx++; }
2460: sscanf(num_str, "%lg", &result); /* put the numerical value into a double variable */
2461: errcode = errcode | 1;
2462: } else if( buf[idx] == 'x' || buf[idx] == 'X') { /* optional x or X part */
2463: idx++; /* skip x or X */
2464: while( isspace(buf[idx]) ) { idx++; }
2465:
2466: e_part = 1.0; /* default power */
2467: base_str[b_idx] = 0; /* initialize base_str[] */
2468: while( isdigit(buf[idx]) || buf[idx] == '.' ) { /* should start with a digit or . */
2469: base_str[b_idx++] = buf[idx++];
2470: }
2471: base_str[b_idx] = 0; /* terminate base_str[] */
2472: while( isspace(buf[idx]) ) { idx++; } /* skip over white spaces */
2473: if( buf[idx] == '^' ) { /* power */
2474: idx++;
2475: exp_str[e_idx] = 0; /* initialize exp_str[] */
2476: while( isspace(buf[idx]) ) { idx++; }
2477: if( buf[idx] == '{'|| buf[idx] == '(' ) { /* matching right bracket */
2478: idx++;
2479: }
2480: while( isspace(buf[idx]) ) { idx++; }
2481: if( isdigit(buf[idx]) || buf[idx] == '+' || buf[idx] == '-' ) {
2482: exp_str[e_idx] = 0; /* initialize exp_str[], again */
2483: while( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-' ) {
2484: exp_str[e_idx++] = buf[idx++];
2485: }
2486: exp_str[e_idx] = 0; /* terminate exp_str[] */
2487: }
2488: while( isspace(buf[idx]) ) { idx++; }
2489: if( buf[idx] == '}' || buf[idx] == ')' ) {
2490: idx++;
2491: }
2492: sscanf(exp_str, "%lg", &e_part);
2493: }
2494: if( strlen(base_str) > 0 ) {
2495: sscanf(base_str, "%lg", &b_part);
2496: x_part = pow(b_part, e_part);
2497: } else {
2498: x_part = 0.0;
2499: }
2500: if( strlen(num_str) > 0 ) {
2501: sscanf(num_str, "%lg", &n_part);
2502: } else {
2503: n_part=0.0;
2504: }
2505: result = n_part * x_part;
2506: errcode = errcode | 1;
2507: } else if ( buf[idx] == '^' ) { /* number ^ */
2508: idx++;
2509: e_part = 1.0;
2510: while( isspace(buf[idx]) ) { idx++; }
2511: if( buf[idx] == '{'|| buf[idx] == '(' ) { /* matching right bracket */
2512: idx++;
2513: }
2514: while( isspace(buf[idx]) ) { idx++; }
2515: if( isdigit(buf[idx]) || buf[idx] == '+' || buf[idx] == '-' ) {
2516: exp_str[e_idx] = 0;
2517: while( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-' ) {
2518: exp_str[e_idx++] = buf[idx++];
2519: }
2520: exp_str[e_idx] = 0;
2521: }
2522: while( isspace(buf[idx]) ) { idx++; }
2523: if( buf[idx] == '}' || buf[idx] == ')' ) {
2524: idx++;
2525: }
2526: sscanf(exp_str, "%lg", &e_part);
2527: sscanf(num_str, "%lg", &n_part);
2528: result = pow(n_part,e_part);
2529: errcode = errcode | 1;
2530: } else { /* number unit */
2531: if( strlen(num_str) > 0 ) {
2532: sscanf(num_str, "%lg", &result);
2533: errcode = errcode | 1;
2534: }
2535: }
2536:
2537: if( idx < len ) { /* collect the rest as unit string */
2538: for(ii=idx;ii< len; ii++ ) {
2539:
2540: unit_str[u_idx++] = buf[ii];
2541: }
2542: unit_str[u_idx]=0; /* terminate unit_str[] */
2543: if(u_idx>0) {
2544: errcode = errcode | 2;
2545: }
2546: }
2547: if( strlen(num_str) > 0 ) {
2548: *num = result;
2549: } else { /* empty number string */
2550: *num = 0.0;
2551: }
2552: sprintf(unit_p,"%s", unit_str);
2553: return (errcode);
2554: }
2555:
2556: char *
2557: answers_string(mode, p)int mode;Problem_t *p;
2558: {
2559: char *fmted_ans, lower[ANSWER_STRING_LENG], upper[ANSWER_STRING_LENG];
2560: char *str_aa, *str_bb, *str_cc, *ans_str, *sub_ans_str, *tmp_str;
2561: int len_aa=0, len_bb=0, len_cc=0,len_dd=0, total_len, num_answer;
2562: double d_answer;
2563:
2564: if( p->ans_type == ANSWER_IS_SUBJECTIVE ) {
2565: char *a="Subjective Answer\n";
2566: ans_str = (char *)capa_malloc(strlen(a)+1,1);
2567: strcpy(ans_str,a);
2568: return (ans_str);
2569: }
2570: num_answer = calc_ansrange(p->ans_type,p->calc, p->answer, p->ans_fmt, p->tol_type,
2571: p->tolerance, lower, upper);
2572:
2573: if( p->ans_type == ANSWER_IS_FLOAT ) {
2574: fmted_ans = capa_malloc(SMALL_LINE_BUFFER,1);
2575: d_answer = (double)atof(p->answer);
2576: sprintf(fmted_ans,p->ans_fmt,d_answer);
2577: } else {
2578: fmted_ans = capa_malloc(strlen(p->answer)+2,1);
2579: strcpy(fmted_ans,p->answer);
2580: }
2581:
2582: len_aa = strlen(fmted_ans);
2583: if (lower != NULL ) len_bb = strlen(lower); else len_bb = 0;
2584: if (upper != NULL ) len_cc = strlen(upper); else len_cc = 0;
2585: if ( p->unit_str != NULL ) len_dd = strlen(p->unit_str); else len_dd = 0;
2586:
2587: switch(mode) {
2588: case TeX_MODE:
2589: if(num_answer==2) {
2590: /* 16 is by adding up characters ' [,] \n\n' and others */
2591: str_aa = format_toTeX(fmted_ans);
2592: total_len = strlen(str_aa) + len_dd + 16;
2593: str_bb = format_toTeX(lower);
2594: total_len += strlen(str_bb);
2595: str_cc = format_toTeX(upper);
2596: total_len += strlen(str_cc);
2597: ans_str = (char *)capa_malloc(total_len,1);
2598: if(len_dd == 0 ) { /* no unit_str */
2599: sprintf(ans_str," %s [%s,%s]\n\n", str_aa,str_bb,str_cc);
2600: } else {
2601: sprintf(ans_str," %s [%s,%s] $%s$\n\n", str_aa,str_bb,str_cc,p->unit_str);
2602: }
2603: capa_mfree((char *)str_aa);
2604: capa_mfree((char *)str_bb);
2605: capa_mfree((char *)str_cc);
2606: } else { /* only one answer */
2607: if ( (p->ans_type == ANSWER_IS_INTEGER) ||
2608: (p->ans_type == ANSWER_IS_FLOAT )) {
2609: str_bb = format_toTeX(lower);
2610: } else { /* answer could be string, choice */
2611: str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
2612: if (p->ans_type == ANSWER_IS_FORMULA || 1)
2613: sprintf(str_bb,"\\begin{verbatim}%s\\end{verbatim}",lower);
2614: else
2615: strcpy(str_bb,lower);
2616: }
2617: total_len = strlen(str_bb) + len_dd + 8;
2618: /* 4 is by adding up characters ' \\\n' plus four */
2619: ans_str = (char *)capa_malloc(sizeof(char),total_len);
2620: if(len_dd == 0 ) { /* no unit_str */
2621: sprintf(ans_str," %s\n", str_bb);
2622: } else {
2623: sprintf(ans_str," %s $%s$\n", str_bb,p->unit_str);
2624: }
2625: capa_mfree((char *)str_bb);
2626: }
2627: break;
2628: case ASCII_MODE:
2629: total_len = len_aa + len_bb + len_cc + len_dd + 8;
2630: /* 8 is by adding up characters ' [,] \n\n' plus one */
2631: ans_str = (char *)capa_malloc(sizeof(char),total_len);
2632: if(num_answer==2) {
2633: if(len_dd == 0 ) { /* no unit_str */
2634: sprintf(ans_str,"%s [%s,%s]\n\n", fmted_ans,lower,upper);
2635: } else {
2636: sprintf(ans_str,"%s [%s,%s] %s\n\n", fmted_ans,lower,upper,p->unit_str);
2637: }
2638: } else {
2639: if(len_dd == 0 ) { /* no unit_str */
2640: sprintf(ans_str,"%s\n\n", lower);
2641: } else {
2642: sprintf(ans_str,"%s %s\n\n", lower,p->unit_str);
2643: }
2644: }
2645: break;
2646: case ANSWER_STRING_MODE:
2647: total_len = len_aa + len_bb + len_cc + len_dd + 8;
2648: /* 8 is by adding up characters ' [,] \n\n' plus one */
2649: ans_str = (char *)capa_malloc(sizeof(char),total_len);
2650: if(num_answer==2) {
2651: if(len_dd == 0 ) { /* no unit_str */
2652: sprintf(ans_str,"%s", fmted_ans);
2653: } else {
2654: sprintf(ans_str,"%s %s", fmted_ans,p->unit_str);
2655: }
2656: } else {
2657: if(len_dd == 0 ) { /* no unit_str */
2658: sprintf(ans_str,"%s", lower);
2659: } else {
2660: sprintf(ans_str,"%s %s", lower,p->unit_str);
2661: }
2662: }
2663: break;
2664: case HTML_MODE:
2665: if(num_answer==2) { /* this indicates that answer should be either float or int
2666: */
2667: str_aa = format_toHTML(fmted_ans);
2668: total_len = strlen(str_aa) + len_dd + 8;
2669: str_bb = format_toHTML(lower);
2670: total_len += strlen(str_bb);
2671: str_cc = format_toHTML(upper);
2672: total_len += strlen(str_cc);
2673: /* 8 is by adding up characters ' [,] \n\n' plus one */
2674: ans_str = (char *)capa_malloc(sizeof(char),total_len);
2675: if(len_dd == 0 ) { /* no unit_str */
2676: sprintf(ans_str,"%s [%s,%s]\n\n", str_aa,str_bb,str_cc);
2677: } else {
2678: sprintf(ans_str,"%s [%s,%s] %s\n\n", str_aa,str_bb,str_cc,p->unit_str);
2679: }
2680: capa_mfree((char *)str_aa); capa_mfree((char *)str_bb); capa_mfree((char
2681: *)str_cc);
2682: } else {
2683: if ( (p->ans_type == ANSWER_IS_INTEGER) ||
2684: (p->ans_type == ANSWER_IS_FLOAT )) {
2685: str_bb = format_toHTML(lower);
2686: } else { /* answer could be string, choice */
2687: str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
2688: if (p->ans_type == ANSWER_IS_FORMULA || 1)
2689: sprintf(str_bb,"<PRE>\n%s\n</PRE>",lower);
2690: else
2691: strcpy(str_bb,lower);
2692: }
2693: total_len = strlen(str_bb) + len_dd + 4;
2694: /* 4 is by adding up characters ' \n\n' plus one */
2695: ans_str = (char *)capa_malloc(sizeof(char),total_len);
2696: if(len_dd == 0 ) { /* no unit_str */
2697: sprintf(ans_str,"%s\n\n", str_bb);
2698: } else {
2699: sprintf(ans_str,"%s %s\n\n", str_bb,p->unit_str);
2700: }
2701: capa_mfree((char *)str_bb);
2702: }
2703: break;
2704: }
2705: capa_mfree(fmted_ans);
2706:
2707: if( p->ans_cnt > 1 ) {
2708: AnswerInfo_t *ai;
2709: for( ai = p->ans_list; ai; ai = ai->ans_next) {
2710: num_answer = calc_ansrange(ai->ans_type,ai->ans_calc, ai->ans_str, ai->ans_fmt,
2711: ai->ans_tol_type,ai->ans_tol,lower,upper);
2712: if( ai->ans_type == ANSWER_IS_FLOAT ) {
2713: fmted_ans = capa_malloc(SMALL_LINE_BUFFER,1);
2714: d_answer = (double)atof(ai->ans_str);
2715: sprintf(fmted_ans,ai->ans_fmt,d_answer);
2716: } else {
2717: fmted_ans = capa_malloc(strlen(ai->ans_str)+2,1);
2718: strcpy(fmted_ans,ai->ans_str);
2719: }
2720: len_aa = strlen(fmted_ans);
2721: len_bb = strlen(lower);
2722: len_cc = strlen(upper);
2723: len_dd = strlen(ai->ans_unit_str);
2724: switch(mode) {
2725: case TeX_MODE:
2726: if(num_answer==2) {
2727: /* 16 is by adding up characters ' [,] \n\n' and others */
2728:
2729: str_aa = format_toTeX(fmted_ans);
2730: total_len = strlen(str_aa) + len_dd + 16;
2731: str_bb = format_toTeX(lower);
2732: total_len += strlen(str_bb);
2733: str_cc = format_toTeX(upper);
2734: total_len += strlen(str_cc);
2735:
2736: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
2737:
2738: if(len_dd == 0 ) { /* no unit_str */
2739: sprintf(sub_ans_str," %s [%s,%s]\n\n", str_aa,str_bb,str_cc);
2740: } else {
2741: sprintf(sub_ans_str," %s [%s,%s] $%s$\n\n",
2742: str_aa,str_bb,str_cc,ai->ans_unit_str);
2743: }
2744: capa_mfree((char *)str_aa); capa_mfree((char *)str_bb); capa_mfree((char *)str_cc);
2745: } else { /* only one answer */
2746: if ( (ai->ans_type == ANSWER_IS_INTEGER) ||
2747: (ai->ans_type == ANSWER_IS_FLOAT )) {
2748: str_bb = format_toTeX(lower);
2749: } else { /* answer could be string, choice */
2750: str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
2751: if (ai->ans_type == ANSWER_IS_FORMULA || 1)
2752: sprintf(str_bb,"\\begin{verbatim}%s\\end{verbatim}",lower);
2753: else
2754: strcpy(str_bb,lower);
2755: }
2756: total_len = strlen(str_bb) + len_dd + 8;
2757: /* 4 is by adding up characters ' \\\n' plus four */
2758: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
2759: if(len_dd == 0 ) { /* no unit_str */
2760: sprintf(sub_ans_str," %s\n", str_bb);
2761: } else {
2762: sprintf(sub_ans_str," %s $%s$\n", str_bb,ai->ans_unit_str);
2763: }
2764: capa_mfree((char *)str_bb);
2765: }
2766: break;
2767: case ASCII_MODE:
2768: total_len = len_aa + len_bb + len_cc + len_dd + 8;
2769: /* 8 is by adding up characters ' [,] \n\n' plus one */
2770: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
2771: if(num_answer==2) {
2772: if(len_dd == 0 ) { /* no unit_str */
2773: sprintf(sub_ans_str,"%s [%s,%s]\n\n", fmted_ans,lower,upper);
2774: } else {
2775: sprintf(sub_ans_str,"%s [%s,%s] %s\n\n",
2776: fmted_ans,lower,upper,ai->ans_unit_str);
2777: }
2778: } else {
2779: if(len_dd == 0 ) { /* no unit_str */
2780: sprintf(sub_ans_str,"%s\n\n", lower);
2781: } else {
2782: sprintf(sub_ans_str,"%s %s\n\n", lower,ai->ans_unit_str);
2783: }
2784: }
2785: break;
2786: case ANSWER_STRING_MODE:
2787: total_len = len_aa + len_bb + len_cc + len_dd + 8;
2788: /* 8 is by adding up characters ' [,] \n\n' plus one */
2789: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
2790: if(num_answer==2) {
2791: if(len_dd == 0 ) { /* no unit_str */
2792: sprintf(sub_ans_str,", %s", fmted_ans);
2793: } else {
2794: sprintf(sub_ans_str,", %s %s", fmted_ans,ai->ans_unit_str);
2795: }
2796: } else {
2797: if(len_dd == 0 ) { /* no unit_str */
2798: sprintf(sub_ans_str,", %s", lower);
2799: } else {
2800: sprintf(sub_ans_str,", %s %s", lower,ai->ans_unit_str);
2801: }
2802: }
2803: break;
2804: case HTML_MODE:
2805: if(num_answer==2) {
2806: str_aa = format_toHTML(fmted_ans);
2807: total_len = strlen(str_aa) + len_dd + 8;
2808: str_bb = format_toHTML(lower);
2809: total_len += strlen(str_bb);
2810: str_cc = format_toHTML(upper);
2811: total_len += strlen(str_cc);
2812: /* 8 is by adding up characters ' [,] \n\n' plus one */
2813: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
2814: if(len_dd == 0 ) { /* no unit_str */
2815: sprintf(sub_ans_str,"%s [%s,%s]\n\n", str_aa,str_bb,str_cc);
2816: } else {
2817: sprintf(sub_ans_str,"%s [%s,%s] %s\n\n",
2818: str_aa,str_bb,str_cc,ai->ans_unit_str);
2819: }
2820: capa_mfree((char *)str_aa); capa_mfree((char *)str_bb); capa_mfree((char
2821: *)str_cc);
2822: } else {
2823: if ( (ai->ans_type == ANSWER_IS_INTEGER) ||
2824: (ai->ans_type == ANSWER_IS_FLOAT )) {
2825: str_bb = format_toHTML(lower);
2826: } else { /* answer could be string, choice */
2827: str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
2828: if (ai->ans_type == ANSWER_IS_FORMULA || 1)
2829: sprintf(str_bb,"<PRE>\n%s\n</PRE>",lower);
2830: else
2831: strcpy(str_bb,lower);
2832: }
2833: total_len = strlen(str_bb) + len_dd + 4;
2834: /* 4 is by adding up characters ' \n\n' plus one */
2835: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
2836: if(len_dd == 0 ) { /* no unit_str */
2837: sprintf(sub_ans_str,"%s\n\n", str_bb);
2838: } else {
2839: sprintf(sub_ans_str,"%s %s\n\n", str_bb,ai->ans_unit_str);
2840: }
2841: capa_mfree((char *)str_bb);
2842: }
2843: break;
2844: } /* end of switch */
2845: total_len = strlen(ans_str);
2846: total_len += (strlen(sub_ans_str) + 1);
2847: tmp_str = (char *)capa_malloc(sizeof(char),total_len);
2848: strncpy(tmp_str, ans_str, strlen(ans_str)+1);
2849: strcat(tmp_str, sub_ans_str);
2850: capa_mfree(ans_str); capa_mfree(sub_ans_str);
2851: capa_mfree(fmted_ans);
2852: ans_str = tmp_str;
2853: } /* end of for */
2854: } /* end of if */
2855:
2856: return (ans_str); /* the calling routing needs to deallocate it */
2857: }
2858:
2859:
2860:
2861: /* ------------------------------ called from capalogin */
2862: /* impose stronger checking on the user input string *answer */
2863: /* */
2864:
2865: /* <== This routine checks user input string *ans against correct answer *s ==> */
2866: int
2867: capa_check_ans(ai,ans) AnswerInfo_t *ai; char *ans;
2868: {
2869: int t; /* ans_type */
2870: char *s; /* ans_str */
2871: int c; /* ans_calc */
2872: int tt; /* ans_tol_type */
2873: double to; /* ans_tol */
2874: int su; /* ans_sig_ub */
2875: int sl; /* ans_sig_lb */
2876: char *fm; /* ans_fmt */
2877: char *us; /* ans_unit_str */
2878: Unit_t *u_p; /* ans_unit */
2879: int input_len, all_alphabet = 1, idx, ii, type;
2880: int outcome, result = INCORRECT;
2881: int sig, corr_len;
2882: int choice[ANSWER_STRING_LENG];
2883: char num_str[ANSWER_STRING_LENG], unit_str[ANSWER_STRING_LENG];
2884: char fmted[ANSWER_STRING_LENG], correct[ANSWER_STRING_LENG], answer[ANSWER_STRING_LENG];
2885: double n_part;
2886: double given, target, ratio, fmted_target, target_u, target_l, scale=1.0;
2887: double delta;
2888:
2889: t = ai->ans_type; s = ai->ans_str; c = ai->ans_calc;
2890: tt = ai->ans_tol_type; to = ai->ans_tol;
2891: su = ai->ans_sig_ub; sl = ai->ans_sig_lb;
2892: fm = ai->ans_fmt;
2893: us = ai->ans_unit_str; u_p = ai->ans_unit;
2894:
2895: switch(t) {
2896: case ANSWER_IS_INTEGER:
2897: case ANSWER_IS_FLOAT:
2898: {
2899: input_len = strlen(ans);
2900: all_alphabet = 1;
2901: for(idx=0;idx<input_len;idx++) {
2902: if( isdigit(ans[idx]) ) {
2903: all_alphabet = 0;
2904: }
2905: }
2906: if( !all_alphabet ) { /* answer string is not all alphabets */
2907: outcome = split_num_unit(ans,&n_part,num_str,unit_str);
2908: if( outcome > 1 ) { /* with both num and unit parts or only unit part */
2909: if( u_p != NULL ) {
2910: result = check_correct_unit(unit_str,u_p,&scale);
2911: } else { /* what to do when no unit is specified but student entered a unit? */
2912: result = UNIT_NOTNEEDED;
2913: }
2914: } else {
2915: if( u_p != NULL ) {
2916: result = NO_UNIT;
2917: }
2918: }
2919: if( (result != NO_UNIT) && (result != UNIT_FAIL) && ( result != UNIT_NOTNEEDED) ) {
2920: if( t == ANSWER_IS_FLOAT ) {
2921: target = (double)atof(s); /* real number */
2922: } else {
2923: target = (double)atol(s); /* Integer answer */
2924: }
2925: given = n_part * scale; /* convert the given answer into proper scale for units */
2926: sig = calc_sig( num_str );
2927: if( (sig < sl) || (sig > su) ) {
2928: result = SIG_FAIL;
2929: } else {
2930: switch( tt ) { /* tolerence type */
2931: case TOL_ABSOLUTE:
2932: fmted_target = target; /* if answer type is integer */
2933: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
2934: sprintf(fmted, fm, target);
2935: fmted_target = (double)atof(fmted);
2936: }
2937: to = fabs(to); /* tol must be positive */
2938: if( c == CALC_FORMATED) {
2939: target_l = fmted_target - to; target_u = fmted_target + to;
2940: } else {
2941: target_l = target - to; target_u = target + to;
2942: }
2943: if( (given >= target_l) && (given <= target_u) ) {
2944: result = APPROX_ANS;
2945: } else { result = INCORRECT; }
2946: break;
2947: case TOL_PERCENTAGE:
2948: if( target != 0.0 ) {
2949: ratio = (double)(to / 100.0);
2950: fmted_target = target; /* if answer type is integer */
2951: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
2952: sprintf(fmted, fm, target);
2953: fmted_target = (double)atof(fmted);
2954: }
2955: delta = (double)fabs((double)ratio*target);
2956: if( c == CALC_FORMATED) {
2957: target_l = fmted_target - delta; target_u = fmted_target + delta;
2958: } else {
2959: target_l = target - delta; target_u = target + delta;
2960: }
2961: } else { target_l = target_u = target; }
2962: if ( (given >= target_l) && (given <= target_u) ) {
2963: result = APPROX_ANS;
2964: } else { result = INCORRECT; }
2965: break;
2966: }
2967: } /* end sig check */
2968: } /* end if unit check */
2969: } else { /* user entered alphabets, but no number */
2970: result = INCORRECT;
2971: }
2972: }
2973: break;
2974: case ANSWER_IS_CHOICE:
2975: {
2976: corr_len = strlen(s); input_len = strlen(ans);
2977: if( corr_len == input_len ) {
2978: for(idx=0;idx<ANSWER_STRING_LENG;idx++) choice[idx] = 0;
2979: result = EXACT_ANS;
2980: for(ii=0;ii<corr_len; ii++) {
2981: idx = toupper(correct[ii]) - 'A'; choice[idx] = 1;
2982: }
2983: for(ii=0;ii<input_len;ii++) {
2984: idx = toupper(answer[ii]) - 'A';
2985: if(choice[idx] != 1 ) result = INCORRECT;
2986: }
2987: } else { result = INCORRECT; }
2988: break;
2989: }
2990: case ANSWER_IS_STRING_CI:
2991: if (strcasecmp(ans, s)) { result = INCORRECT; } else { result = EXACT_ANS; }
2992: break;
2993: case ANSWER_IS_STRING_CS:
2994: if (strcmp(ans, s)) { result = INCORRECT; } else { result = EXACT_ANS; }
2995: break;
2996: case ANSWER_IS_FORMULA:
2997: result = check_formula_ans(s,ans,ai->ans_id_list,ai->ans_pts_list,tt,to);
2998: break;
2999: case ANSWER_IS_EXTERNAL: /* Not yet implemented */
3000: break;
3001: }
3002: return (result);
3003: }
3004:
3005: /* =============================================================================== */
3006: /* calling sequence capa_check_answers() --> capa_check_answer() */
3007: /* --> capa_check_ans() */
3008:
3009:
3010: /* How we check the correct answer against user input string */
3011: /*
3012: If the correct answer is a number (either integer or real number)
3013: check if user input string consists of only alphabet characters
3014: use split_num_unit() heuristic function to split the input string into two parts
3015: numerical part and units part.
3016: if the outcome contains units, check if the units is correct or not
3017:
3018: */
3019:
3020:
3021: int
3022: capa_check_answer(p, answer) Problem_t *p; char *answer;
3023: {
3024: int type;
3025: char *correct;
3026: char input[ANSWER_STRING_LENG], unit_str[ANSWER_STRING_LENG];
3027: int tol_type, calc_type;
3028: double tol, n_part;
3029: int sig_l;
3030: int sig_u;
3031: char *fmt;
3032: int choice[ANSWER_STRING_LENG], ii, idx, corr_len, input_len;
3033: int result = INCORRECT, sig, outcome, all_alphabet;
3034: char fmted[FORMAT_STRING_LENG];
3035: double given, target, ratio, fmted_target, target_u, target_l, scale=1.0;
3036: double delta;
3037:
3038: type = p->ans_type;
3039: correct = p->answer;
3040: tol_type = p->tol_type;
3041: tol = p->tolerance;
3042: sig_l = p->sig_lbound;
3043: sig_u = p->sig_ubound;
3044: fmt = p->ans_fmt;
3045: calc_type = p->calc;
3046: unit_str[0]=0;
3047:
3048: switch(type) {
3049: case ANSWER_IS_INTEGER:
3050: case ANSWER_IS_FLOAT:
3051: {
3052: input_len = strlen(answer);
3053: all_alphabet = 1;
3054: for(idx=0;idx<input_len;idx++) {
3055: if( isdigit(answer[idx]) ) {
3056: all_alphabet = 0;
3057: }
3058: }
3059: if( !all_alphabet ) {
3060: outcome = split_num_unit(answer,&n_part,input,unit_str);
3061: if( outcome > 1 ) { /* with both num and unit parts or only unit part */
3062: if( p->ans_unit != NULL ) {
3063: result = check_correct_unit(unit_str,p->ans_unit,&scale);
3064:
3065: } else { /* what to do when no unit is specified but student entered a unit? */
3066: result = UNIT_NOTNEEDED;
3067: }
3068: } else {
3069: if( p->ans_unit != NULL ) {
3070: result = NO_UNIT;
3071: }
3072: }
3073: if( (result != NO_UNIT) && (result != UNIT_FAIL) && ( result != UNIT_NOTNEEDED) ) {
3074: if( type == ANSWER_IS_FLOAT ) {
3075: target = (double)atof(correct); /* real number */
3076: } else {
3077: target = (double)atol(correct); /* Integer answer */
3078: }
3079: given = n_part * scale; /* convert the given answer into proper scale for units */
3080: sig = calc_sig( input );
3081: if( (sig < sig_l) || (sig > sig_u) ) {
3082: result = SIG_FAIL;
3083: } else {
3084: switch( tol_type ) {
3085: case TOL_ABSOLUTE:
3086: fmted_target = target; /* if answer type is integer */
3087: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
3088: sprintf(fmted, fmt, target);
3089: fmted_target = (double)atof(fmted);
3090: }
3091: tol = fabs(tol); /* tol must be positive */
3092: if( calc_type == CALC_FORMATED) {
3093: target_l = fmted_target - tol; target_u = fmted_target + tol;
3094: } else {
3095: target_l = target - tol; target_u = target + tol;
3096: }
3097: if( (given >= target_l) && (given <= target_u) ) {
3098: result = APPROX_ANS;
3099: } else { result = INCORRECT; }
3100: break;
3101: case TOL_PERCENTAGE:
3102: if( target != 0.0 ) {
3103: ratio = (double)(tol / 100.0);
3104: fmted_target = target; /* if answer type is integer */
3105: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
3106: sprintf(fmted, fmt, target);
3107: fmted_target = (double)atof(fmted);
3108: }
3109: delta = (double)fabs((double)ratio*target);
3110: if( calc_type == CALC_FORMATED) {
3111: target_l = fmted_target - delta; target_u = fmted_target + delta;
3112: } else {
3113: target_l = target - delta; target_u = target + delta;
3114: }
3115: } else { target_l = target_u = target; }
3116: if ( (given >= target_l) && (given <= target_u) ) {
3117: result = APPROX_ANS;
3118: } else { result = INCORRECT; }
3119: break;
3120: }
3121: } /* end sig check */
3122: } /* end if unit check */
3123: } else { /* user entered alphabet, but no number */
3124: result = INCORRECT;
3125: }
3126: }
3127: break;
3128: case ANSWER_IS_CHOICE:
3129: {
3130: corr_len = strlen(correct); input_len = strlen(answer);
3131: if( corr_len == input_len ) {
3132: for(ii=0;ii<ANSWER_STRING_LENG;ii++) choice[ii] = 0; result = EXACT_ANS;
3133: for(ii=0;ii<corr_len; ii++) {
3134: idx = toupper(correct[ii]) - 'A'; choice[idx] = 1;
3135: }
3136: for(ii=0;ii<input_len;ii++) {
3137: idx = toupper(answer[ii]) - 'A';
3138: if(choice[idx] != 1 ) result = INCORRECT;
3139: }
3140: } else { result = INCORRECT; }
3141: break;
3142: }
3143: case ANSWER_IS_STRING_CI:
3144: if (strcasecmp(answer, correct)) { result = INCORRECT; } else { result = EXACT_ANS; }
3145: break;
3146: case ANSWER_IS_STRING_CS:
3147: if (strcmp(answer, correct)) { result = INCORRECT; } else { result = EXACT_ANS; }
3148: break;
3149: case ANSWER_IS_FORMULA:
3150: result = check_formula_ans(correct,answer,p->id_list,p->pts_list,tol_type,tol);
3151: break;
3152: case ANSWER_IS_EXTERNAL: /* not yet implemented */
3153: break;
3154:
3155: }
3156: return (result);
3157: }
3158:
3159: /* ----------------------------------------------------------------------------------- */
3160: /* assumming the formula is *fml_str and the student input is *input_str */
3161: /* according to the type of tolerance, we form the final formula as */
3162: /* absolute tolerance: (*fml_str) - (*input_str) */
3163: /* relative tolerance: (*input_str) / (*fml_str) */
3164: int
3165: check_formula_ans(fml_str,input_str,var_list,pts_list,tol_type,tol)
3166: char *fml_str;char *input_str;char *var_list;PointsList_t *pts_list;int tol_type; double tol;
3167: {
3168: char *check_fml_str;
3169: int f_len, i_len, outcome, error_code;
3170: PointsList_t *pt, *next;
3171: double formula_val, diff;
3172:
3173: f_len = strlen(fml_str);
3174: i_len = strlen(input_str);
3175:
3176: check_fml_str = (char *)capa_malloc((f_len + i_len + 16), sizeof(char));
3177: if( tol_type == TOL_ABSOLUTE ) {
3178: sprintf(check_fml_str,"abs((%s) - (%s))",fml_str, input_str);
3179: } else {
3180: sprintf(check_fml_str,"(%s) / (%s)",input_str,fml_str);
3181: }
3182: outcome = APPROX_ANS;
3183: for(pt= pts_list; pt!=NULL ; pt=next) {
3184: next=pt->pts_next;
3185: error_code = f_eval_formula(&formula_val,check_fml_str, var_list, pt->pts_str);
3186: if( ! error_code ) {
3187: if( tol_type == TOL_ABSOLUTE ) {
3188: diff = tol - formula_val;
3189: if( diff < 0.0 ) {
3190: outcome = INCORRECT;
3191: }
3192: } else {
3193: diff = abs(1.0 - formula_val) * 100.0 ;
3194: if( diff < tol ) {
3195: outcome = INCORRECT;
3196: }
3197: }
3198: } else {
3199: outcome = BAD_FORMULA;
3200: break;
3201: }
3202: }
3203: capa_mfree((char *)check_fml_str);
3204:
3205: return (outcome);
3206:
3207: }
3208: /* inputs: type :: answer type, calc_type :: input string format string tolerance type */
3209: /* returns: lower upper */
3210:
3211: int
3212: calc_ansrange(type, calc_type, input, fmt, tol_type, tol, lower, upper)
3213: int type;int calc_type;char *input;char *fmt;
3214: int tol_type;double tol;char *lower;char *upper;
3215: {
3216: int result = 2, leng;
3217: char fmted[ANSWER_STRING_LENG];
3218: double target, fmted_target, ratio, target_l, target_u, tmp, delta;
3219:
3220:
3221: if( (type == ANSWER_IS_FORMULA) ||
3222: (type == ANSWER_IS_EXTERNAL ) ) {
3223: strcpy(lower, input);
3224: result = 1;
3225: return (result);
3226: } else {
3227: if( tol == 0.0 ) { /* answer could be ANSWER_IS_FLOAT ANSWER_IS_INTEGER,
3228: ANSWER_IS_STRING_CI ANSWER_IS_STRING_CS
3229: ANSWER_IS_CHOICE
3230: */
3231: result = 1; /* only one answer */
3232: if( type == ANSWER_IS_FLOAT ) {
3233: target = (double)atof(input);
3234: sprintf(fmted, fmt, target);
3235: leng = strlen(fmted)+1;
3236:
3237: strcpy(lower, fmted);
3238: } else { /* could be integer, choice, string ci, string cs */
3239: strcpy(lower, input);
3240: }
3241: } else { /* we have tolerence */
3242:
3243: target = (double)atof(input);
3244: switch( tol_type ) {
3245: case TOL_ABSOLUTE:
3246: fmted_target = target; /* if answer type is integer */
3247: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
3248: sprintf(fmted, fmt, target);
3249: fmted_target = (double)atof(fmted);
3250: }
3251: tol = fabs(tol); /* tol must be positive */
3252: if( calc_type == CALC_FORMATED) {
3253: target_l = fmted_target - tol; target_u = fmted_target + tol;
3254: } else {
3255: target_l = target - tol; target_u = target + tol;
3256: }
3257: if(type == ANSWER_IS_FLOAT) {
3258: sprintf(fmted, fmt, target_l ); strcpy(lower, fmted);
3259: sprintf(fmted, fmt, target_u ); strcpy(upper, fmted);
3260: } else {
3261: sprintf(fmted, "%.15g", target_l ); strcpy(lower, fmted);
3262: sprintf(fmted, "%.15g", target_u ); strcpy(upper, fmted);
3263: }
3264: break;
3265: case TOL_PERCENTAGE:
3266: if( target != 0.0 ) {
3267: ratio = (double)(tol / 100.0);
3268: fmted_target = target; /* if answer type is integer */
3269: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
3270: sprintf(fmted, fmt, target);
3271: fmted_target = (double)atof(fmted);
3272: }
3273: delta = (double)fabs((double)ratio*target);
3274: if( calc_type == CALC_FORMATED) {
3275: target_l = fmted_target - delta; target_u = fmted_target + delta;
3276: } else {
3277: target_l = target - delta; target_u = target + delta;
3278: }
3279: if( target_l > target_u ) { tmp = target_u; target_u = target_l; target_l = tmp; }
3280: if(type == ANSWER_IS_FLOAT) {
3281: sprintf(fmted, fmt, target_l ); strcpy(lower, fmted);
3282: sprintf(fmted, fmt, target_u ); strcpy(upper, fmted);
3283: } else {
3284: sprintf(fmted, "%.15g", target_l ); strcpy(lower, fmted);
3285: sprintf(fmted, "%.15g", target_u ); strcpy(upper, fmted);
3286: }
3287: } else { strcpy(lower, "0.0"); strcpy(upper, "0.0"); result = 1;}
3288: break;
3289: }
3290: }
3291: }
3292:
3293: return (result);
3294: }
3295:
3296: /* Algorithms : check ALL units first */
3297: /* sig figs second */
3298: /* numerical, string comparisons last */
3299: /* result from capa_check_ans() could be */
3300:
3301: /* New check answers routine checks the /AND and /OR group of answers */
3302: /* use array of char pointers char **a */
3303: int
3304: capa_check_answers(p,answers,cnt) Problem_t *p; char **answers; int cnt;
3305: {
3306: AnswerInfo_t *ai;
3307: int ii, done, result;
3308: int *outcomes;
3309:
3310: if(p->ans_op == ANS_AND) { /* ans /and ans */
3311: if( (cnt != p->ans_cnt) ) { return (ANS_CNT_NOT_MATCH); }
3312: if( cnt == 1 ) { return (capa_check_answer(p, answers[0])); } /* there is only one answer */
3313: outcomes = (int *)capa_malloc(sizeof(int),cnt);
3314: for(ii=0;ii<cnt;ii++) outcomes[ii]=0; /* initialize the outcomes array */
3315: outcomes[0] = capa_check_answer(p, answers[0]);
3316: for(ii=1, ai = p->ans_list; ai; ii++,ai = ai->ans_next ) {
3317: outcomes[ii] = capa_check_ans(ai,answers[ii]);
3318: }
3319: done = ii = 0;
3320: result = 0;
3321: while( !done ) { /* check if any of the outcome has failed on units */
3322: if( (outcomes[ii] == UNIT_FAIL) ||
3323: (outcomes[ii] == NO_UNIT) ||
3324: (outcomes[ii] == UNIT_NOTNEEDED) ) {
3325: result = outcomes[ii];
3326: done = 1;
3327: }
3328: ii++;
3329: if(ii==cnt) done = 1;
3330: }
3331: if( result == 0 ) { /* check if any of the outcome has failed on sig figs */
3332: done = ii = 0;
3333: while( !done ) {
3334: if( outcomes[ii] == SIG_FAIL ) {
3335: result = outcomes[ii];
3336: done = 1;
3337: }
3338: ii++;
3339: if(ii==cnt) done = 1;
3340: }
3341: }
3342: if( result == 0 ) { /* check if any of the outcome is incorrect */
3343: done = ii = 0;
3344: while( !done ) {
3345: if( outcomes[ii] == INCORRECT ) {
3346: result = outcomes[ii];
3347: done = 1;
3348: }
3349: ii++;
3350: if(ii==cnt) done = 1;
3351: }
3352: }
3353: capa_mfree((char *)outcomes);
3354: if( result == 0 ) {
3355: result = APPROX_ANS; /* all answers are correct */
3356: }
3357: } else { /* should be ANS_OR , user answer count should always be 1 */
3358: if( cnt != 1 ) { return (ANS_CNT_NOT_MATCH); }
3359: if( p->ans_cnt == 1 ) { return (capa_check_answer(p, answers[0])); }
3360: result = capa_check_answer(p, answers[0]);
3361: ii = 1; ai = p->ans_list;
3362: while( (ii<p->ans_cnt) && ( (result != EXACT_ANS) && (result != APPROX_ANS) ) ) {
3363: result = capa_check_ans(ai,answers[0]);
3364: ai = ai->ans_next; ii++;
3365: }
3366: }
3367: return (result);
3368: }
3369:
3370:
3371:
3372:
3373:
3374:
3375:
3376:
3377: /* ========================================================================= */
3378: int w_getclassdir(cpath_p, cown_p, class)
3379: char **cpath_p; char **cown_p; char *class;
3380: {
3381: FILE *fp;
3382: char filename[SMALL_LINE_BUFFER];
3383: char *cname_p;
3384: int done;
3385: char c;
3386:
3387: sprintf(filename,"class.conf");
3388: if ((fp=fopen(filename,"r"))==NULL) {
3389: sprintf(filename,"../class.conf");
3390: if ((fp=fopen(filename,"r"))==NULL) {
3391: printf("Error: can't open %s\n",filename);
3392: exit (1);
3393: }
3394: }
3395: do {
3396: c_ignorewhite(fp);
3397: c = getc(fp); ungetc(c,fp);
3398: if( c != EOF ) {
3399: cname_p = c_getword(fp);
3400: *cpath_p = c_getword(fp);
3401: *cown_p = c_getword(fp);
3402: throwaway_line(fp);
3403: if( ! strcasecmp(cname_p, class) ) {
3404: done = 1;
3405: } else {
3406: free(cname_p); free(*cpath_p); free(*cown_p);
3407: done = 0;
3408: }
3409: } else {
3410: done = 1;
3411: }
3412: } while ( ! done );
3413: fclose(fp);
3414: free(cname_p);
3415: return (1);
3416: }
3417:
3418: /* ----------------------------------------------------------------- */
3419: /* read_capa_config gets a value out of the capa.config file
3420: in the read resultant string all " are removed expect for \" occurances"
3421: in fact all case of \ then another character become just the last
3422: character
3423:
3424: inputs : key_word - a string that is searched for on the lefthand side
3425: of an equals sign
3426: outputs : value - a char pointer that the value of the key_word as defined
3427: in the config file is copied into
3428: return : -1 - unable to find or acces the capa.config file
3429: 0 - the requested keyword was not found
3430: >0 - length of the string that was returned in value
3431: */
3432: /* ----------------------------------------------------------------- */
3433: int read_capa_config(key_word,value)
3434: char *key_word;char *value;
3435: {
3436: FILE *fp;
3437: char filename[SMALL_LINE_BUFFER];
3438: char left[MAX_BUFFER_SIZE],right[MAX_BUFFER_SIZE],c;
3439: int failed=0,done=0,num=0,result=-1,found=0,returnVal=0,i,j;
3440:
3441: sprintf(filename,"capa.config");
3442: if ((fp=fopen(filename,"r"))==NULL) {
3443: return (-1);
3444: }
3445: do {
3446: num = fscanf(fp,"%[^ \n\t#] = %[^\n]",left,right);
3447: if (num == 2) { result = strcasecmp(left,key_word); }
3448: if (result==0) { done=1; }
3449: if (num==EOF) { failed=1; }
3450: if (num!=2) {
3451: found=0;
3452: while(1) {
3453: c=fgetc(fp);
3454: if (found) {
3455: if (c!='\n') {
3456: ungetc(c,fp);
3457: break;
3458: }
3459: }
3460: if (c=='\n') found=1;
3461: if (((char)c)==((char)EOF)) break;
3462: }
3463: }
3464: } while (!done && !failed);
3465:
3466: fclose(fp);
3467:
3468: if (done) {
3469: for(i=0,j=0;i<(strlen(right)+1);i++) {
3470: value[j]='\0';
3471: if (right[i] == '\\' && (i < (strlen(right))) ) {
3472: i++;value[j]=right[i];j++;
3473: } else if (right[i] != '\"' ) {
3474: value[j]=right[i];j++;
3475: }
3476: }
3477: value[j]='\0';
3478: returnVal=j;
3479: }
3480: return returnVal;
3481: }
3482:
3483: int capa_access(const char *pathname, int mode)
3484: {
3485: pid_t euid,egid;
3486: struct stat status;
3487:
3488: euid=geteuid();
3489: egid=getegid();
3490: if ( -1 == stat(pathname,&status) ) { return -1; }
3491: /*printf("mode:%x F_OK:%x mode&F_OK:%x\n",mode,F_OK,(mode&F_OK));*/
3492: /*printf("st_mode:%x S_IFMT:%x st_mode&S_IFMT:%x\n",
3493: status.st_mode,S_IFMT,(status.st_mode&S_IFMT));*/
3494: if (!(status.st_mode & S_IFMT)) { return -1; }
3495: /*printf("euid: %d\t egid: %d\tstatus.st_uid: %d\tstatus.st_gid: %d\n",
3496: euid,egid,status.st_uid,status.st_gid);*/
3497: /*printf("mode:%x R_OK:%x mode&R_OK:%x\n",mode,R_OK,(mode&R_OK));*/
3498: /*printf("mode:%x W_OK:%x mode&W_OK:%x\n",mode,R_OK,(mode&R_OK));*/
3499: /*printf("mode:%x X_OK:%x mode&X_OK:%x\n",mode,R_OK,(mode&R_OK));*/
3500: if (euid==status.st_uid) {
3501: /*printf("here1\n");*/
3502: if ((mode & R_OK) && (!(status.st_mode & S_IRUSR))) { return -1; }
3503: if ((mode & W_OK) && (!(status.st_mode & S_IWUSR))) { return -1; }
3504: if ((mode & X_OK) && (!(status.st_mode & S_IXUSR))) { return -1; }
3505: } else {
3506: if (egid==status.st_gid) {
3507: /*printf("here2\n");*/
3508: if ((mode & R_OK) && (!(status.st_mode & S_IRGRP))) { return -1; }
3509: if ((mode & W_OK) && (!(status.st_mode & S_IWGRP))) { return -1; }
3510: if ((mode & X_OK) && (!(status.st_mode & S_IXGRP))) { return -1; }
3511: } else {
3512: /*printf("here3\n");*/
3513: if ((mode & R_OK) && (!(status.st_mode & S_IROTH))) { return -1; }
3514: if ((mode & W_OK) && (!(status.st_mode & S_IWOTH))) { return -1; }
3515: if ((mode & X_OK) && (!(status.st_mode & S_IXOTH))) { return -1; }
3516: }
3517: }
3518: return 0;
3519: }
3520:
3521: /*checks if the string is all whitespace*/
3522: /*returns 0 if it isn't */
3523: /*returns 1 if it is */
3524: int is_all_ws(char* answer)
3525: {
3526: int length,result=1,i;
3527: if (answer!=NULL) {
3528: length=strlen(answer);
3529: for(i=0;i<length;i++) {
3530: if (!isspace(answer[i])) {result=0;break;}
3531: }
3532: }
3533: return result;
3534: }
3535:
3536: void trim_response_ws(char* answer)
3537: {
3538: char *temp;
3539: int i,j=0,length;
3540: length=strlen(answer);
3541: temp=capa_malloc(length+1,1);
3542: strcpy(temp,answer);
3543: for(i=0; i<length;i++) if (!(isspace(temp[i]))) break;
3544: for(j=length-1;j>=0;j--) if (!(isspace(temp[j]))) break;
3545: temp[++j]='\0';
3546: strcpy(answer,&temp[i]);
3547: }
3548:
3549: void throwaway_line(FILE* fp)
3550: {
3551: int c;
3552: do {
3553: c = getc(fp);
3554: } while ( (c != '\n') && (c != EOF) );
3555: }
3556:
3557: char* capa_get_seat(char* studentnum,char* seatfile)
3558: {
3559: FILE* fp;
3560: T_student student;
3561: char *result,*defaultseatfile="seatingchart";
3562: char line[TMP_LINE_LENGTH],*lineend;
3563: int stuline=0,seatline=0;
3564:
3565: stuline = capa_get_student(studentnum,&student);
3566: if (stuline < 1 ) goto error;
3567: if (seatfile == NULL) seatfile=defaultseatfile;
3568: if ((fp=fopen(seatfile,"r"))==NULL) goto error;
3569: while( (stuline>seatline) && (fgets(line,TMP_LINE_LENGTH-1,fp)) ) seatline++;
3570: if (seatline< stuline) goto error;
3571: if ((lineend=index(line,' '))!=NULL) lineend='\0';
3572: result=capa_malloc(strlen(line)+1,1);
3573: strcpy(result,line);
3574: return result;
3575:
3576: error:
3577: result= capa_malloc(8,1);
3578: sprintf(result,"No Seat");
3579: return result;
3580:
3581: }
3582:
3583: void protect_log_string(char* log_string)
3584: {
3585: int i,len=strlen(log_string);
3586: for(i=0;i<len;i++) {
3587: switch (log_string[i]) {
3588: case '\n': case '\t': case '\r':
3589: log_string[i]=' ';
3590: break;
3591: }
3592: }
3593: }
3594:
3595: int capa_get_login_time(char *student_number,int set,time_t *logintime)
3596: {
3597: FILE *fp;
3598: int found,temp=0;
3599: char filename[FILE_NAME_LENGTH],line[SMALL_LINE_BUFFER];
3600:
3601: *logintime=0;
3602: sprintf(filename,"records/access%d.log",set);
3603:
3604: if ((fp=fopen(filename,"r"))==NULL) return (-1);
3605: found = 0;
3606: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
3607: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
3608: }
3609: fclose(fp);
3610: if (found) sscanf(rindex(line,':'),":%d",&temp);
3611: *logintime=(time_t)temp;
3612: return found;
3613: }
3614:
3615: /*----------------------------------------------------------*/
3616: /* INPUT: set the X in logX.db */
3617: /* OUTPUT: creates the accessX.log file if it doesn't exist */
3618: /* and inserts stunum:time(NULL) if stunum isn't */
3619: /* in ther already. */
3620: /* */
3621: /* RETURN: -1 file error */
3622: /* 0 already set */
3623: /* 1 succesfully logged a login time */
3624: /*----------------------------------------------------------*/
3625: int capa_set_login_time(char *student_number,int set)
3626: {
3627: FILE *fp;
3628: int errcode=0;
3629: int found=0;
3630: char filename[FILE_NAME_LENGTH],line[SMALL_LINE_BUFFER];
3631:
3632: sprintf(filename,"records/access%d.log",set);
3633:
3634: if ((fp=fopen(filename,"r"))!=NULL) {
3635: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
3636: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
3637: }
3638: fclose(fp);
3639: }
3640:
3641: if (found) return 0;
3642:
3643: sprintf(line,"%s:%d\n", student_number,(int)time(NULL));
3644: if ((fp=fopen(filename,"a+"))==NULL) return (-1);
3645: flockstream(fp);
3646: fseek(fp,0L,SEEK_END);
3647: if ( !fwrite((char *)line, strlen(line), 1, fp) ) {
3648: errcode = -1;
3649: } else {
3650: errcode = 1;
3651: }
3652: fflush(fp);
3653: funlockstream(fp);
3654: fclose(fp);
3655: return (errcode);
3656: }
3657: /* =||>|===================== End of capaCommon.c =====================|<||= */
3658:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>