]> andersk Git - libfaim.git/blame - utils/faimtest/faimtest.c
Initial revision
[libfaim.git] / utils / faimtest / faimtest.c
CommitLineData
9de3ca7e 1/*
2 * -----------------------------------------------------------
3 * ProtoFAIM: v1.xx.xxplxx
4 * -----------------------------------------------------------
5 *
6 * This is ProtoFAIM v1.xx.xxplxx!!! Its nearly completely
7 * different than that ugly thing called v0. This app is
8 * compatible with the latest version of the libfaim library.
9 * Work is continuing.
10 *
11 * ProtoFAIM should only be used for two things...
12 * 1) Testing the libfaim backend.
13 * 2) For reference on the libfaim API when developing clients.
14 *
15 * Its very ugly. Probably always will be. Nothing is more
16 * ugly than the backend itself, however.
17 *
18 * -----------------------------------------------------------
19 *
20 * I'm releasing this code and all it's associated linkage
21 * under the GNU General Public License. For more information,
22 * please refer to http://www.fsf.org. For any questions,
23 * please contact me at the address below.
24 *
25 * Most everything:
26 * (c) 1998 Adam Fritzler, PST, afritz@iname.com
27 *
28 * The password algorithms
29 * (c) 1998 Brock Wilcox, awwaiid@iname.com
30 *
31 * THERE IS NO CODE FROM AOL'S AIM IN THIS CODE, NOR
32 * WAS THERE ANY DISASSEMBLAGE TO DEFINE PROTOCOL. All
33 * information was gained through painstakingly comparing
34 * TCP dumps while the AIM Java client was running. Nothing
35 * more than that, except for a lot of experimenting.
36 *
37 * -----------------------------------------------------------
38 *
39 */
40
41/*
42 Current status:
43
44
45 */
46
47#define FAIMTEST_SCREENNAME "SN"
48#define FAIMTEST_PASSWORD "PASS"
49
50#include "aim.h" /* for struct defs, global ptrs, etc */
51
52int faimtest_parse_oncoming(struct command_rx_struct *, ...);
53int faimtest_parse_offgoing(struct command_rx_struct *, ...);
54int faimtest_parse_login_phase3d_f(struct command_rx_struct *, ...);
55int faimtest_auth_error(struct command_rx_struct *, ...);
56int faimtest_auth_success(struct command_rx_struct *, ...);
57int faimtest_parse_incoming_im(struct command_rx_struct *command, ...);
58int faimtest_parse_userinfo(struct command_rx_struct *command, ...);
59int faimtest_handleredirect(struct command_rx_struct *command, ...);
60int faimtest_authsvrready(struct command_rx_struct *command, ...);
61int faimtest_pwdchngdone(struct command_rx_struct *command, ...);
62int faimtest_serverready(struct command_rx_struct *command, ...);
63int faimtest_parse_misses(struct command_rx_struct *command, ...);
64int main(void)
65{
66
67#if 0
68 /*
69 specify your custom command handlers here. I recommend
70 at least overriding the login_phase3d_f handler so that
71 you can have your own buddy list and profile. The
72 rest are probably only useful to override for UI
73 reasons.
74 */
75 rxcallback_t faimtest_callbacks[] = {
76 faimtest_parse_incoming_im, /* incoming IM 0 */
77 faimtest_parse_oncoming, /* oncoming buddy 1 */
78 faimtest_parse_offgoing, /* offgoing buddy 2 */
79 faimtest_parse_misses, /* AIM_CB_MISSED_IM 3 */
80 faimtest_parse_misses, /* AIM_CB_MISSED_CALL 4 */
81 NULL, /* login phase 4 packet C command 1 -- depricated 5 */
82 NULL, /* login phase 4 packet C command 2 -- depricated 6 */
83 NULL, /* login phase 2, first resp -- depricated 7 */
84 faimtest_serverready, /* server ready -- **HANDLING REQUIRED** 8 */
85 NULL, /* login phase 3 packet B -- depricated 9 */
86 NULL, /* login phase 3D packet A -- depricated 10 */
87 NULL, /* login phase 3D packet B -- depricated 11 */
88 NULL, /* login phase 3D packet C -- depricated 12 */
89 NULL, /* login phase 3D packet D -- depricated 13 */
90 NULL, /* login phase 3D packet E -- depricated 14 */
91 faimtest_handleredirect, /* redirect -- **HANDLING REQUIRED** 15 */
92 faimtest_parse_misses, /* AIM_CB_RATECHANGE 16 */
93 faimtest_parse_misses, /* AIM_CB_USERERROR 17 */
94 NULL, /* completely unknown command 18 */
95 faimtest_parse_userinfo, /* user info response 19 */
96 NULL, /* user search by address response 20 */
97 NULL, /* user serach by name response 21 */
98 NULL, /* user search fail 22 */
99 faimtest_auth_error, /* 23 */
100 faimtest_auth_success, /* 24 */
101 faimtest_authsvrready, /* 25 */
102 NULL, /* 26 */
103 faimtest_pwdchngdone, /* 27 */
104 faimtest_serverready, /* 28 */
105 0x00 /* terminating NULL -- REQUIRED 29 */
106 };
107#endif
108
109 struct client_info_s info = {"FAIMtest (Hi guys!)", 3, 90, 42, "us", "en"};
110 struct aim_conn_t *authconn = NULL;
111 int stayconnected = 1;
112
113 aim_connrst(); /* reset connection array -- there's a better place for this*/
114 /* register our callback array (optional) */
115 //aim_register_callbacks(faimtest_callbacks);
116
117 enter:
118 authconn = aim_newconn(AIM_CONN_TYPE_AUTH, FAIM_LOGIN_SERVER);
119
120 if (authconn == NULL)
121 {
122 fprintf(stderr, "faimtest: internal connection error while in aim_login. bailing out.\n");
123 return -1;
124 }
125 else if (authconn->fd == -1)
126 {
127 if (authconn->status & AIM_CONN_STATUS_RESOLVERR)
128 fprintf(stderr, "faimtest: could not resolve authorizer name\n");
129 else if (authconn->status & AIM_CONN_STATUS_CONNERR)
130 fprintf(stderr, "faimtest: could not connect to authorizer\n");
131 return -1;
132 }
133 else
134 {
135 aim_conn_addhandler(authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_ERROR, faimtest_auth_error, 0);
136 aim_conn_addhandler(authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS, faimtest_auth_success, 0);
137 aim_conn_addhandler(authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_authsvrready, 0);
138 aim_send_login(authconn, FAIMTEST_SCREENNAME, FAIMTEST_PASSWORD, &info);
139 }
140
141 while (aim_select(NULL) > (struct aim_conn_t *)0)
142 {
143 if (aim_queue_outgoing)
144 aim_tx_flushqueue();
145
146 if (aim_get_command() < 0)
147 {
148 printf("\afaimtest: connection error!\n");
149 }
150 else
151 aim_rxdispatch();
152 }
153
154 /* Close up */
155 printf("AIM just decided we didn't need to be here anymore, closing up.,,\n");
156
157 /* close up all connections, dead or no */
158 aim_logoff();
159
160 if (stayconnected)
161 {
162 printf("\nTrying to reconnect in 2 seconds...\n");
163 sleep(2);
164 goto enter;
165 }
166
167 /* Get out */
168 exit(0);
169}
170
171int faimtest_serverready(struct command_rx_struct *command, ...)
172{
173 switch (command->conn->type)
174 {
175 case AIM_CONN_TYPE_BOS:
176 aim_bos_reqrate(command->conn); /* request rate info */
177 aim_bos_ackrateresp(command->conn); /* ack rate info response -- can we say timing? */
178 aim_bos_setprivacyflags(command->conn, 0x00000003);
179
180#if 0
181 aim_bos_reqpersonalinfo(command->conn);
182#endif
183
184 aim_bos_reqservice(command->conn, AIM_CONN_TYPE_ADS); /* 0x05 == Advertisments */
185
186#if 0
187 aim_bos_reqrights(NULL);
188 aim_bos_reqbuddyrights(NULL);
189 aim_bos_reqlocaterights(NULL);
190 aim_bos_reqicbmparaminfo(NULL);
191#endif
192
193 /* set group permissions */
194 aim_bos_setgroupperm(NULL, 0x1f);
195 fprintf(stderr, "faimtest: done with BOS ServerReady\n");
196 break;
197 case AIM_CONN_TYPE_CHATNAV:
198 fprintf(stderr, "faimtest: chatnav: got server ready\n");
199 break;
200 default:
201 fprintf(stderr, "faimtest: unknown connection type on Server Ready\n");
202 }
203 return 1;
204}
205
206/*
207 handleredirect()...
208
209 This, of course, handles Service Redirects from OSCAR.
210
211 Should get passed in the following:
212 struct command_rx_struct *command
213 the raw command data
214 int serviceid
215 the destination service ID
216 char *serverip
217 the IP address of the service's server
218 char *cookie
219 the raw auth cookie
220 */
221int faimtest_handleredirect(struct command_rx_struct *command, ...)
222{
223 va_list ap;
224 int serviceid;
225 char *ip;
226 char *cookie;
227
228 /* this is the new buddy list */
229 char buddies[] = "Buddy1&Buddy2&";
230 /* this is the new profile */
231 char profile[] = "Hello";
232
233 va_start(ap, command);
234 serviceid = va_arg(ap, int);
235 ip = va_arg(ap, char *);
236 cookie = va_arg(ap, char *);
237 va_end(ap);
238
239 switch(serviceid)
240 {
241 case 0x0005: /* Advertisements */
242 /*
243 * The craziest explanation yet as to why we finish logging in when
244 * we get the advertisements redirect, of which we don't use anyway....
245 * IT WAS EASY!
246 */
247
248 /* send the buddy list and profile (required, even if empty) */
249 aim_bos_setbuddylist(command->conn, buddies);
250 aim_bos_setprofile(command->conn, profile);
251
252 /* send final login command (required) */
253 aim_bos_clientready(command->conn); /* tell BOS we're ready to go live */
254
255 /* you should now be ready to go */
256 printf("\nYou are now officially online. (%s)\n", ip);
257
258 break;
259 case 0x0007: /* Authorizer */
260 {
261 struct aim_conn_t *tstconn;
262 /* Open a connection to the Auth */
263 tstconn = aim_newconn(AIM_CONN_TYPE_AUTH, ip);
264 if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR) )
265 fprintf(stderr, "faimtest: unable to reconnect with authorizer\n");
266 else
267 /* Send the cookie to the Auth */
268 aim_auth_sendcookie(tstconn, cookie);
269
270 }
271 break;
272 case 0x000d: /* ChatNav */
273 {
274 struct aim_conn_t *tstconn = NULL;
275 tstconn = aim_newconn(AIM_CONN_TYPE_CHATNAV, ip);
276 if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
277 {
278 fprintf(stderr, "faimtest: unable to connect to chatnav server\n");
279 return 1;
280 }
281 aim_conn_addhandler(tstconn, AIM_CB_FAM_CTN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
282 aim_conn_addhandler(tstconn, AIM_CB_FAM_GEN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
283 aim_auth_sendcookie(tstconn, cookie);
284 fprintf(stderr, "\achatnav: connected\n");
285 }
286 break;
287 case 0x000e: /* Chat */
288 {
289#if 0
290 struct aim_conn_t *tstconn = NULL;
291 tstconn = aim_newconn(AIM_CONN_TYPE_CHAT, ip);
292 if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
293 {
294 fprintf(stderr, "faimtest: unable to connect to chat server\n");
295 return 1;
296 }
297 aim_auth_sendcookie(aim_getconn_type(AIM_CONN_TYPE_CHAT), cookie);
298 fprintf(stderr, "\achat: connected\n");
299#endif
300 }
301 break;
302 default:
303 printf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
304 /* dunno */
305 }
306
307 return 1;
308}
309
310int faimtest_auth_error(struct command_rx_struct *command, ...)
311{
312 va_list ap;
313 struct login_phase1_struct *logininfo;
314 char *errorurl;
315 short errorcode;
316
317 va_start(ap, command);
318 logininfo = va_arg(ap, struct login_phase1_struct *);
319 printf("Screen name: %s\n", logininfo->screen_name);
320 errorurl = va_arg(ap, char *);
321 printf("Error URL: %s\n", errorurl);
322 errorcode = va_arg(ap, short);
323 printf("Error code: 0x%02x\n", errorcode);
324 va_end(ap);
325
326 aim_conn_close(aim_getconn_type(AIM_CONN_TYPE_AUTH));
327 exit(0);
328
329 return 0;
330}
331
332int faimtest_auth_success(struct command_rx_struct *command, ...)
333{
334 va_list ap;
335 struct login_phase1_struct *logininfo;
336 struct aim_conn_t *bosconn = NULL;
337
338 va_start(ap, command);
339 logininfo = va_arg(ap, struct login_phase1_struct *);
340 va_end(ap);
341
342 printf("Screen name: %s\n", logininfo->screen_name);
343 printf("Reg status: %2d\n", logininfo->regstatus);
344 printf("Email: %s\n", logininfo->email);
345 printf("Cookie len: %d\n", sizeof(logininfo->cookie));
346 printf("BOS IP: %s\n", logininfo->BOSIP);
347
348 printf("Closing auth connection...\n");
349 aim_conn_close(command->conn);
350 bosconn = aim_newconn(AIM_CONN_TYPE_BOS, logininfo->BOSIP);
351 if (bosconn == NULL)
352 {
353 fprintf(stderr, "faimtest: could not connect to BOS: internal error\n");
354 }
355 else if (bosconn->status != 0)
356 {
357 fprintf(stderr, "faimtest: could not connect to BOS\n");
358 }
359 else
360 {
361 aim_conn_addhandler(bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
362 aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
363 aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
364 aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
365 aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, NULL, 0);
366 aim_conn_addhandler(bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, NULL, 0);
367 aim_conn_addhandler(bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
368 aim_conn_addhandler(bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
369 aim_conn_addhandler(bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
370 aim_conn_addhandler(bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_misses, 0);
371 aim_conn_addhandler(bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
372 aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_misses, 0);
373 aim_conn_addhandler(bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_misses, 0);
374 aim_conn_addhandler(bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
375
376 aim_conn_addhandler(bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 0);
377 aim_conn_addhandler(bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
378 aim_auth_sendcookie(bosconn, logininfo->cookie);
379 }
380 return 1;
381}
382
383int faimtest_parse_userinfo(struct command_rx_struct *command, ...)
384{
385 struct aim_userinfo_s *userinfo;
386 char *prof_encoding = NULL;
387 char *prof = NULL;
388
389 va_list ap;
390 va_start(ap, command);
391 userinfo = va_arg(ap, struct aim_userinfo_s *);
392 prof_encoding = va_arg(ap, char *);
393 prof = va_arg(ap, char *);
394 va_end(ap);
395
396 printf("faimtest: userinfo: sn: %s\n", userinfo->sn);
397 printf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
398 printf("faimtest: userinfo: class: 0x%04x = ", userinfo->class);
399
400 /*
401 * 00000000 (binary)
402 * 1 Trial
403 * 2 Unknown
404 * 3 AOL
405 * 4 Unknown
406 * 5 Free
407 *
408 * ORed together.
409 *
410 */
411
412 if (userinfo->class & 0x0001)
413 printf("TRIAL ");
414 if (userinfo->class & 0x0002)
415 printf("UNKNOWN_BIT2 ");
416 if (userinfo->class & 0x0004)
417 printf("AOL ");
418 if (userinfo->class & 0x0008)
419 printf("UNKNOWN_BIT4 ");
420 if (userinfo->class & 0x0010)
421 printf("FREE ");
422 printf("\n");
423
424 printf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
425 printf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
426 printf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
427
428 printf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
429 printf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
430
431 return 1;
432}
433
434/*
435 * The user-level Incoming ICBM callback.
436 *
437 * Arguments:
438 * struct command_rx_struct * command if you feel like doing it yourself
439 * char * srcsn the source name
440 * char * msg message
441 * int warnlevel warning/evil level
442 * int class user class
443 * ulong membersince time_t of date of signup
444 * ulong onsince time_t of date of singon
445 * int idletime min (sec?) idle
446 * int isautoreply TRUE if its an auto-response
447 *
448 */
449int faimtest_parse_incoming_im(struct command_rx_struct *command, ...)
450{
451 struct aim_userinfo_s *userinfo;
452 char *msg = NULL;
453 int isautoreply = 0;
454 va_list ap;
455 char *tmpstr = NULL;
456
457 va_start(ap, command);
458 userinfo = va_arg(ap, struct aim_userinfo_s *);
459 msg = va_arg(ap, char *);
460 isautoreply = va_arg(ap, int);
461 va_end(ap);
462
463 printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
464 printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
465 printf("faimtest: icbm: class = 0x%04x ", userinfo->class);
466 if (userinfo->class & 0x0010)
467 printf("(FREE)\n");
468 else if (userinfo->class & 0x0001)
469 printf("(TRIAL)\n");
470 else if (userinfo->class & 0x0004)
471 printf("(AOL)\n");
472 else
473 printf("(UNKNOWN)\n");
474 printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
475 printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
476 printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
477 printf("faimtest: icbm: isautoreply = %s\n", isautoreply ? "TRUE" : "FALSE");
478
479 printf("faimtest: icbm: message: %s\n", msg);
480
481 if (msg)
482 {
483 tmpstr = index(msg, '>');
484 if (tmpstr != NULL)
485 tmpstr+=1;
486 else
487 tmpstr = msg;
488
489 if ( (strlen(tmpstr) >= 10) &&
490 (!strncmp(tmpstr, "disconnect", 10)) )
491 {
492 aim_send_im(command->conn, "midendian", 0, "ta ta...");
493 aim_logoff();
494 }
495 else if (strstr(tmpstr, "goodday"))
496 {
497 printf("faimtest: icbm: sending response\n");
498 aim_send_im(command->conn, userinfo->sn, 0, "Good day to you too.");
499 }
500#if 0
501 else if (!strncmp(tmpstr, "joinchat", 8))
502 {
503 aim_chat_join(command->conn, "GoodDay");
504 }
505#endif
506 else
507 {
508#if 0
509 printf("faimtest: icbm: starting chat...\n");
510 aim_bos_reqservice(command->conn, AIM_CONN_TYPE_CHATNAV);
511#else
512 aim_bos_setidle(command->conn, 0x0ffffffe);
513#endif
514 }
515
516 }
517
518 printf("faimtest: icbm: done with ICBM handling\n");
519
520 return 1;
521}
522
523int faimtest_authsvrready(struct command_rx_struct *command, ...)
524{
525 printf("faimtest_authsvrready: called (contype: %d)\n", command->conn->type);
526 sleep(10);
527 /* should just be able to tell it we're ready too... */
528 aim_auth_clientready(command->conn);
529
530#if 0
531 /*
532 * This is where you'd really begin changing your password.
533 * However, this callback may get called for reasons other
534 * than you wanting to change your password. You should
535 * probably check that before actually doing it.
536 */
537 aim_auth_changepasswd(command->conn, "PWD1", "PWD2");
538#endif
539
540 return 1;
541}
542
543int faimtest_pwdchngdone(struct command_rx_struct *command, ...)
544{
545 printf("PASSWORD CHANGE SUCCESSFUL!!!\n");
546 return 1;
547}
548
549int faimtest_parse_oncoming(struct command_rx_struct *command, ...)
550{
551 struct aim_userinfo_s *userinfo;
552
553 va_list ap;
554 va_start(ap, command);
555 userinfo = va_arg(ap, struct aim_userinfo_s *);
556 va_end(ap);
557
558 printf("\n%s is now online\n", userinfo->sn);
559
560 return 1;
561}
562
563int faimtest_parse_offgoing(struct command_rx_struct *command, ...)
564{
565
566 printf("\n%s has left\n", &(command->data[11]));
567
568 return 1;
569}
570
571
572/*
573 * Handles callbacks for: AIM_CB_RATECHANGE, AIM_CB_USERERROR,
574 * AIM_CB_MISSED_IM, and AIM_CB_MISSED_CALL.
575 */
576int faimtest_parse_misses(struct command_rx_struct *command, ...)
577{
578 u_short family;
579 u_short subtype;
580
581 family = (command->data[0] << 8) + command->data[1];
582 subtype = (command->data[2] << 8) + command->data[3];
583
584 switch (family)
585 {
586 case 0x0001:
587 if (subtype == 0x000a) /* or AIM_CB_RATECHANGE */
588 printf("\n****STOP SENDING/RECIEVING MESSAGES SO FAST!****\n\n");
589 break;
590 case 0x0002:
591 if (subtype == 0x0001) /* or AIM_CB_USERERROR */
592 {
593 u_long snacid = 0x00000000;
594
595 snacid = aimutil_get32(&command->data[6]);
596
597 printf("Received unknown error in SNAC family 0x0002 (snacid = %08lx)\n", snacid);
598 }
599 break;
600 case 0x0004:
601 if (subtype == 0x0001) /* or AIM_CB_MISSED_IM */
602 printf("\n***LAST IM DIDN\'T MAKE IT BECAUSE THE BUDDY IS NOT ONLINE***\n\n");
603 else if (subtype == 0x000a) /* or AIM_CB_MISSED_CALL */
604 printf("You missed some messages from %s because they were sent too fast\n", &(command->data[13]));
605 break;
606 }
607
608 return 0;
609}
610
611
612
613
614
This page took 0.165976 seconds and 5 git commands to generate.